blob: 0da843adda61fbc6c31214fc8553d284428d9e03 [file] [log] [blame]
[email protected]c333e792012-01-06 16:57:391// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]3a8eecb2010-04-22 23:56:302// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]3a8eecb2010-04-22 23:56:305#include "chrome/browser/extensions/extension_apitest.h"
6#include "chrome/browser/extensions/extension_host.h"
[email protected]6f371442011-11-09 06:45:467#include "chrome/browser/extensions/extension_service.h"
8#include "chrome/browser/extensions/process_map.h"
[email protected]8ecad5e2010-12-02 21:18:339#include "chrome/browser/profiles/profile.h"
[email protected]7b5dc002010-11-16 23:08:1010#include "chrome/browser/ui/browser.h"
[email protected]d8748142012-05-16 21:13:4311#include "chrome/browser/ui/browser_finder.h"
[email protected]71b73f02011-04-06 15:57:2912#include "chrome/browser/ui/browser_list.h"
[email protected]d55c2382011-08-18 23:10:3613#include "chrome/browser/ui/browser_window.h"
[email protected]ae673742011-08-24 19:48:3714#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]884033e2012-04-16 19:38:4215#include "chrome/common/chrome_notification_types.h"
[email protected]3a8eecb2010-04-22 23:56:3016#include "chrome/common/chrome_switches.h"
[email protected]814a7bf0f2011-08-13 05:30:5917#include "chrome/common/extensions/extension.h"
[email protected]c2f36e3a2011-12-14 01:27:1918#include "chrome/common/extensions/extension_file_util.h"
[email protected]36a5c4c2011-12-14 16:34:5019#include "chrome/common/string_ordinal.h"
[email protected]af44e7fb2011-07-29 18:32:3220#include "chrome/test/base/ui_test_utils.h"
[email protected]ad23a092011-12-28 07:02:0421#include "content/public/browser/navigation_entry.h"
[email protected]ad50def52011-10-19 23:17:0722#include "content/public/browser/notification_service.h"
[email protected]c333e792012-01-06 16:57:3923#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3324#include "content/public/browser/render_view_host.h"
[email protected]6acde6352012-01-04 16:52:2025#include "content/public/browser/web_contents.h"
[email protected]88aae972011-12-16 01:14:1826#include "content/test/test_navigation_observer.h"
[email protected]3a8eecb2010-04-22 23:56:3027#include "net/base/mock_host_resolver.h"
28
[email protected]c5eed492012-01-04 17:07:5029using content::NavigationController;
[email protected]eaabba22012-03-07 15:02:1130using content::RenderViewHost;
[email protected]4ca15302012-01-03 05:53:2031using content::WebContents;
[email protected]1c321ee52012-05-21 03:02:3432using extensions::Extension;
[email protected]4ca15302012-01-03 05:53:2033
[email protected]7b54ca02012-03-02 18:06:5334class AppApiTest : public ExtensionApiTest {
35 protected:
36 // Gets the base URL for files for a specific test, making sure that it uses
37 // "localhost" as the hostname, since that is what the extent is declared
38 // as in the test apps manifests.
39 GURL GetTestBaseURL(std::string test_directory) {
40 GURL::Replacements replace_host;
41 std::string host_str("localhost"); // must stay in scope with replace_host
42 replace_host.SetHostStr(host_str);
43 GURL base_url = test_server()->GetURL(
44 "files/extensions/api_test/" + test_directory + "/");
45 return base_url.ReplaceComponents(replace_host);
46 }
47
48 // Pass flags to make testing apps easier.
49 void SetUpCommandLine(CommandLine* command_line) {
50 ExtensionApiTest::SetUpCommandLine(command_line);
51 CommandLine::ForCurrentProcess()->AppendSwitch(
52 switches::kDisablePopupBlocking);
53 CommandLine::ForCurrentProcess()->AppendSwitch(
54 switches::kAllowHTTPBackgroundPage);
55 }
56
57 // Helper function to test that independent tabs of the named app are loaded
58 // into separate processes.
59 void TestAppInstancesHelper(std::string app_name) {
60 LOG(INFO) << "Start of test.";
61
62 extensions::ProcessMap* process_map =
63 browser()->profile()->GetExtensionService()->process_map();
64
65 host_resolver()->AddRule("*", "127.0.0.1");
66 ASSERT_TRUE(test_server()->Start());
67
68 ASSERT_TRUE(LoadExtension(
69 test_data_dir_.AppendASCII(app_name)));
70
71 // Open two tabs in the app, one outside it.
72 GURL base_url = GetTestBaseURL(app_name);
73
74 // Test both opening a URL in a new tab, and opening a tab and then
75 // navigating it. Either way, app tabs should be considered extension
76 // processes, but they have no elevated privileges and thus should not
77 // have WebUI bindings.
78 ui_test_utils::NavigateToURLWithDisposition(
79 browser(), base_url.Resolve("path1/empty.html"), NEW_FOREGROUND_TAB,
80 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
81 LOG(INFO) << "Nav 1.";
82 EXPECT_TRUE(process_map->Contains(
83 browser()->GetWebContentsAt(1)->GetRenderProcessHost()->GetID()));
84 EXPECT_FALSE(browser()->GetWebContentsAt(1)->GetWebUI());
85
86 ui_test_utils::WindowedNotificationObserver tab_added_observer(
[email protected]884033e2012-04-16 19:38:4287 chrome::NOTIFICATION_TAB_ADDED,
[email protected]7b54ca02012-03-02 18:06:5388 content::NotificationService::AllSources());
89 browser()->NewTab();
90 tab_added_observer.Wait();
91 LOG(INFO) << "New tab.";
92 ui_test_utils::NavigateToURL(browser(),
93 base_url.Resolve("path2/empty.html"));
94 LOG(INFO) << "Nav 2.";
95 EXPECT_TRUE(process_map->Contains(
96 browser()->GetWebContentsAt(2)->GetRenderProcessHost()->GetID()));
97 EXPECT_FALSE(browser()->GetWebContentsAt(2)->GetWebUI());
98
99 // We should have opened 2 new extension tabs. Including the original blank
100 // tab, we now have 3 tabs. The two app tabs should not be in the same
101 // process, since they do not have the background permission. (Thus, we
102 // want to separate them to improve responsiveness.)
103 ASSERT_EQ(3, browser()->tab_count());
[email protected]19da16a92012-05-23 17:11:29104 WebContents* tab1 = browser()->GetWebContentsAt(1);
105 WebContents* tab2 = browser()->GetWebContentsAt(2);
106 EXPECT_NE(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
[email protected]7b54ca02012-03-02 18:06:53107
108 // Opening tabs with window.open should keep the page in the opener's
109 // process.
[email protected]d8748142012-05-16 21:13:43110 ASSERT_EQ(1u, browser::GetBrowserCount(browser()->profile()));
[email protected]19da16a92012-05-23 17:11:29111 OpenWindow(tab1, base_url.Resolve("path1/empty.html"), true, NULL);
[email protected]7b54ca02012-03-02 18:06:53112 LOG(INFO) << "WindowOpenHelper 1.";
[email protected]19da16a92012-05-23 17:11:29113 OpenWindow(tab2, base_url.Resolve("path2/empty.html"), true, NULL);
[email protected]7b54ca02012-03-02 18:06:53114 LOG(INFO) << "End of test.";
115 }
116};
117
118// Tests that hosted apps with the background permission get a process-per-app
119// model, since all pages need to be able to script the background page.
[email protected]19da16a92012-05-23 17:11:29120IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) {
[email protected]87c7c292011-10-27 16:16:41121 LOG(INFO) << "Start of test.";
[email protected]9b600832011-10-26 20:31:59122
[email protected]6f371442011-11-09 06:45:46123 extensions::ProcessMap* process_map =
124 browser()->profile()->GetExtensionService()->process_map();
[email protected]718eab62011-10-05 21:16:52125
[email protected]3a8eecb2010-04-22 23:56:30126 host_resolver()->AddRule("*", "127.0.0.1");
[email protected]95409e12010-08-17 20:07:11127 ASSERT_TRUE(test_server()->Start());
[email protected]3a8eecb2010-04-22 23:56:30128
[email protected]cbf4d1912010-08-12 18:24:57129 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
[email protected]3a8eecb2010-04-22 23:56:30130
[email protected]87c7c292011-10-27 16:16:41131 LOG(INFO) << "Loaded extension.";
132
[email protected]cbf4d1912010-08-12 18:24:57133 // Open two tabs in the app, one outside it.
[email protected]118d3122011-08-10 17:09:53134 GURL base_url = GetTestBaseURL("app_process");
[email protected]fe3048872010-10-18 14:58:59135
[email protected]f0e13332011-05-20 22:41:14136 // Test both opening a URL in a new tab, and opening a tab and then navigating
137 // it. Either way, app tabs should be considered extension processes, but
138 // they have no elevated privileges and thus should not have WebUI bindings.
139 ui_test_utils::NavigateToURLWithDisposition(
140 browser(), base_url.Resolve("path1/empty.html"), NEW_FOREGROUND_TAB,
141 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
[email protected]6f371442011-11-09 06:45:46142 EXPECT_TRUE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20143 browser()->GetWebContentsAt(1)->GetRenderProcessHost()->GetID()));
144 EXPECT_FALSE(browser()->GetWebContentsAt(1)->GetWebUI());
[email protected]87c7c292011-10-27 16:16:41145 LOG(INFO) << "Nav 1.";
146
147 ui_test_utils::NavigateToURLWithDisposition(
148 browser(), base_url.Resolve("path2/empty.html"), NEW_FOREGROUND_TAB,
149 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
[email protected]6f371442011-11-09 06:45:46150 EXPECT_TRUE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20151 browser()->GetWebContentsAt(2)->GetRenderProcessHost()->GetID()));
152 EXPECT_FALSE(browser()->GetWebContentsAt(2)->GetWebUI());
[email protected]87c7c292011-10-27 16:16:41153 LOG(INFO) << "Nav 2.";
154
155 ui_test_utils::WindowedNotificationObserver tab_added_observer(
[email protected]884033e2012-04-16 19:38:42156 chrome::NOTIFICATION_TAB_ADDED,
[email protected]87c7c292011-10-27 16:16:41157 content::NotificationService::AllSources());
[email protected]cbf4d1912010-08-12 18:24:57158 browser()->NewTab();
[email protected]87c7c292011-10-27 16:16:41159 tab_added_observer.Wait();
160 LOG(INFO) << "New tab.";
[email protected]cbf4d1912010-08-12 18:24:57161 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path3/empty.html"));
[email protected]87c7c292011-10-27 16:16:41162 LOG(INFO) << "Nav 3.";
[email protected]6f371442011-11-09 06:45:46163 EXPECT_FALSE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20164 browser()->GetWebContentsAt(3)->GetRenderProcessHost()->GetID()));
165 EXPECT_FALSE(browser()->GetWebContentsAt(3)->GetWebUI());
[email protected]3a8eecb2010-04-22 23:56:30166
[email protected]056ad2a2011-07-12 02:13:55167 // We should have opened 3 new extension tabs. Including the original blank
168 // tab, we now have 4 tabs. Because the app_process app has the background
169 // permission, all of its instances are in the same process. Thus two tabs
170 // should be part of the extension app and grouped in the same process.
[email protected]3a8eecb2010-04-22 23:56:30171 ASSERT_EQ(4, browser()->tab_count());
[email protected]19da16a92012-05-23 17:11:29172 WebContents* tab = browser()->GetWebContentsAt(1);
[email protected]cbf4d1912010-08-12 18:24:57173
[email protected]19da16a92012-05-23 17:11:29174 EXPECT_EQ(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20175 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]19da16a92012-05-23 17:11:29176 EXPECT_NE(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20177 browser()->GetWebContentsAt(3)->GetRenderProcessHost());
[email protected]3a8eecb2010-04-22 23:56:30178
179 // Now let's do the same using window.open. The same should happen.
[email protected]d8748142012-05-16 21:13:43180 ASSERT_EQ(1u, browser::GetBrowserCount(browser()->profile()));
[email protected]19da16a92012-05-23 17:11:29181 OpenWindow(tab, base_url.Resolve("path1/empty.html"), true, NULL);
[email protected]87c7c292011-10-27 16:16:41182 LOG(INFO) << "WindowOpenHelper 1.";
[email protected]19da16a92012-05-23 17:11:29183 OpenWindow(tab, base_url.Resolve("path2/empty.html"), true, NULL);
[email protected]87c7c292011-10-27 16:16:41184 LOG(INFO) << "WindowOpenHelper 2.";
[email protected]361a5f1f2011-10-05 20:11:15185 // TODO(creis): This should open in a new process (i.e., false for the last
[email protected]ea7b7d82012-05-25 17:29:17186 // argument), but we temporarily avoid swapping processes away from a hosted
187 // app if it has an opener, because some OAuth providers make script calls
188 // between non-app popups and non-app iframes in the app process.
[email protected]361a5f1f2011-10-05 20:11:15189 // See crbug.com/59285.
[email protected]19da16a92012-05-23 17:11:29190 OpenWindow(tab, base_url.Resolve("path3/empty.html"), true, NULL);
[email protected]87c7c292011-10-27 16:16:41191 LOG(INFO) << "WindowOpenHelper 3.";
[email protected]3a8eecb2010-04-22 23:56:30192
193 // Now let's have these pages navigate, into or out of the extension web
194 // extent. They should switch processes.
[email protected]9a1e6d42010-04-26 22:29:36195 const GURL& app_url(base_url.Resolve("path1/empty.html"));
196 const GURL& non_app_url(base_url.Resolve("path3/empty.html"));
[email protected]19da16a92012-05-23 17:11:29197 NavigateInRenderer(browser()->GetWebContentsAt(2), non_app_url);
[email protected]87c7c292011-10-27 16:16:41198 LOG(INFO) << "NavigateTabHelper 1.";
[email protected]19da16a92012-05-23 17:11:29199 NavigateInRenderer(browser()->GetWebContentsAt(3), app_url);
[email protected]87c7c292011-10-27 16:16:41200 LOG(INFO) << "NavigateTabHelper 2.";
[email protected]ea7b7d82012-05-25 17:29:17201 EXPECT_NE(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20202 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]19da16a92012-05-23 17:11:29203 EXPECT_EQ(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20204 browser()->GetWebContentsAt(3)->GetRenderProcessHost());
[email protected]08e94b82010-12-15 22:51:04205
206 // If one of the popup tabs navigates back to the app, window.opener should
207 // be valid.
[email protected]19da16a92012-05-23 17:11:29208 NavigateInRenderer(browser()->GetWebContentsAt(6), app_url);
[email protected]87c7c292011-10-27 16:16:41209 LOG(INFO) << "NavigateTabHelper 3.";
[email protected]19da16a92012-05-23 17:11:29210 EXPECT_EQ(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20211 browser()->GetWebContentsAt(6)->GetRenderProcessHost());
[email protected]08e94b82010-12-15 22:51:04212 bool windowOpenerValid = false;
213 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
[email protected]6acde6352012-01-04 16:52:20214 browser()->GetWebContentsAt(6)->GetRenderViewHost(), L"",
[email protected]08e94b82010-12-15 22:51:04215 L"window.domAutomationController.send(window.opener != null)",
216 &windowOpenerValid));
217 ASSERT_TRUE(windowOpenerValid);
[email protected]87c7c292011-10-27 16:16:41218
219 LOG(INFO) << "End of test.";
[email protected]3a8eecb2010-04-22 23:56:30220}
[email protected]faf407b2011-01-05 01:24:32221
[email protected]056ad2a2011-07-12 02:13:55222// Test that hosted apps without the background permission use a process per app
223// instance model, such that separate instances are in separate processes.
[email protected]19da16a92012-05-23 17:11:29224IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessInstances) {
[email protected]7b54ca02012-03-02 18:06:53225 TestAppInstancesHelper("app_process_instances");
226}
[email protected]87c7c292011-10-27 16:16:41227
[email protected]7b54ca02012-03-02 18:06:53228// Test that hosted apps with the background permission but that set
229// allow_js_access to false also use a process per app instance model.
230// Separate instances should be in separate processes.
[email protected]19da16a92012-05-23 17:11:29231IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessBackgroundInstances) {
[email protected]7b54ca02012-03-02 18:06:53232 TestAppInstancesHelper("app_process_background_instances");
[email protected]056ad2a2011-07-12 02:13:55233}
234
[email protected]15877ca2011-11-18 22:40:52235// Tests that bookmark apps do not use the app process model and are treated
236// like normal web pages instead. http://crbug.com/104636.
[email protected]19da16a92012-05-23 17:11:29237IN_PROC_BROWSER_TEST_F(AppApiTest, BookmarkAppGetsNormalProcess) {
[email protected]c2f36e3a2011-12-14 01:27:19238 ExtensionService* service = browser()->profile()->GetExtensionService();
239 extensions::ProcessMap* process_map = service->process_map();
[email protected]15877ca2011-11-18 22:40:52240
241 host_resolver()->AddRule("*", "127.0.0.1");
242 ASSERT_TRUE(test_server()->Start());
[email protected]15877ca2011-11-18 22:40:52243 GURL base_url = GetTestBaseURL("app_process");
244
[email protected]c2f36e3a2011-12-14 01:27:19245 // Load an app as a bookmark app.
246 std::string error;
247 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension(
248 test_data_dir_.AppendASCII("app_process"),
249 Extension::LOAD,
250 Extension::FROM_BOOKMARK,
251 &error));
[email protected]36a5c4c2011-12-14 16:34:50252 service->OnExtensionInstalled(extension, false,
253 StringOrdinal::CreateInitialOrdinal());
[email protected]c2f36e3a2011-12-14 01:27:19254 ASSERT_TRUE(extension.get());
255 ASSERT_TRUE(extension->from_bookmark());
256
[email protected]15877ca2011-11-18 22:40:52257 // Test both opening a URL in a new tab, and opening a tab and then navigating
258 // it. Either way, bookmark app tabs should be considered normal processes
259 // with no elevated privileges and no WebUI bindings.
260 ui_test_utils::NavigateToURLWithDisposition(
261 browser(), base_url.Resolve("path1/empty.html"), NEW_FOREGROUND_TAB,
262 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
263 EXPECT_FALSE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20264 browser()->GetWebContentsAt(1)->GetRenderProcessHost()->GetID()));
265 EXPECT_FALSE(browser()->GetWebContentsAt(1)->GetWebUI());
[email protected]15877ca2011-11-18 22:40:52266
267 ui_test_utils::WindowedNotificationObserver tab_added_observer(
[email protected]884033e2012-04-16 19:38:42268 chrome::NOTIFICATION_TAB_ADDED,
[email protected]15877ca2011-11-18 22:40:52269 content::NotificationService::AllSources());
270 browser()->NewTab();
271 tab_added_observer.Wait();
272 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path2/empty.html"));
273 EXPECT_FALSE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20274 browser()->GetWebContentsAt(2)->GetRenderProcessHost()->GetID()));
275 EXPECT_FALSE(browser()->GetWebContentsAt(2)->GetWebUI());
[email protected]15877ca2011-11-18 22:40:52276
277 // We should have opened 2 new bookmark app tabs. Including the original blank
278 // tab, we now have 3 tabs. Because normal pages use the
279 // process-per-site-instance model, each should be in its own process.
280 ASSERT_EQ(3, browser()->tab_count());
[email protected]19da16a92012-05-23 17:11:29281 WebContents* tab = browser()->GetWebContentsAt(1);
282 EXPECT_NE(tab->GetRenderProcessHost(),
[email protected]6acde6352012-01-04 16:52:20283 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]15877ca2011-11-18 22:40:52284
285 // Now let's do the same using window.open. The same should happen.
[email protected]d8748142012-05-16 21:13:43286 ASSERT_EQ(1u, browser::GetBrowserCount(browser()->profile()));
[email protected]19da16a92012-05-23 17:11:29287 OpenWindow(tab, base_url.Resolve("path1/empty.html"), true, NULL);
288 OpenWindow(tab, base_url.Resolve("path2/empty.html"), true, NULL);
[email protected]15877ca2011-11-18 22:40:52289
290 // Now let's have a tab navigate out of and back into the app's web
291 // extent. Neither navigation should switch processes.
292 const GURL& app_url(base_url.Resolve("path1/empty.html"));
293 const GURL& non_app_url(base_url.Resolve("path3/empty.html"));
[email protected]6acde6352012-01-04 16:52:20294 RenderViewHost* host2 = browser()->GetWebContentsAt(2)->GetRenderViewHost();
[email protected]19da16a92012-05-23 17:11:29295 NavigateInRenderer(browser()->GetWebContentsAt(2), non_app_url);
[email protected]9f76c1e2012-03-05 15:15:58296 EXPECT_EQ(host2->GetProcess(),
[email protected]6acde6352012-01-04 16:52:20297 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]19da16a92012-05-23 17:11:29298 NavigateInRenderer(browser()->GetWebContentsAt(2), app_url);
[email protected]9f76c1e2012-03-05 15:15:58299 EXPECT_EQ(host2->GetProcess(),
[email protected]6acde6352012-01-04 16:52:20300 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]15877ca2011-11-18 22:40:52301}
302
[email protected]faf407b2011-01-05 01:24:32303// Tests that app process switching works properly in the following scenario:
304// 1. navigate to a page1 in the app
305// 2. page1 redirects to a page2 outside the app extent (ie, "/server-redirect")
306// 3. page2 redirects back to a page in the app
307// The final navigation should end up in the app process.
308// See http://crbug.com/61757
[email protected]ea7b7d82012-05-25 17:29:17309IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessRedirectBack) {
[email protected]faf407b2011-01-05 01:24:32310 host_resolver()->AddRule("*", "127.0.0.1");
311 ASSERT_TRUE(test_server()->Start());
312
313 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
314
315 // Open two tabs in the app.
[email protected]118d3122011-08-10 17:09:53316 GURL base_url = GetTestBaseURL("app_process");
[email protected]faf407b2011-01-05 01:24:32317
318 browser()->NewTab();
319 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
320 browser()->NewTab();
[email protected]ea7b7d82012-05-25 17:29:17321 // Wait until the second tab finishes its redirect train (2 hops).
[email protected]4ad5d77d2011-12-03 02:00:48322 // 1. We navigate to redirect.html
323 // 2. Renderer navigates and finishes, counting as a load stop.
324 // 3. Renderer issues the meta refresh to navigate to server-redirect.
325 // 4. Renderer is now in a "provisional load", waiting for navigation to
326 // complete.
327 // 5. Browser sees a redirect response from server-redirect to empty.html, and
328 // transfers that to a new navigation, using RequestTransferURL.
[email protected]ea7b7d82012-05-25 17:29:17329 // 6. Renderer navigates to empty.html, and finishes loading, counting as the
330 // second load stop
[email protected]4ad5d77d2011-12-03 02:00:48331 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
[email protected]ea7b7d82012-05-25 17:29:17332 browser(), base_url.Resolve("path1/redirect.html"), 2);
[email protected]faf407b2011-01-05 01:24:32333
334 // 3 tabs, including the initial about:blank. The last 2 should be the same
335 // process.
336 ASSERT_EQ(3, browser()->tab_count());
[email protected]089e8c332011-01-06 21:37:29337 EXPECT_EQ("/files/extensions/api_test/app_process/path1/empty.html",
[email protected]6acde6352012-01-04 16:52:20338 browser()->GetWebContentsAt(2)->GetController().
[email protected]36fc0392011-12-25 03:59:51339 GetLastCommittedEntry()->GetURL().path());
[email protected]6acde6352012-01-04 16:52:20340 EXPECT_EQ(browser()->GetWebContentsAt(1)->GetRenderProcessHost(),
341 browser()->GetWebContentsAt(2)->GetRenderProcessHost());
[email protected]faf407b2011-01-05 01:24:32342}
[email protected]d292d8a2011-05-25 03:47:11343
344// Ensure that reloading a URL after installing or uninstalling it as an app
345// correctly swaps the process. (http://crbug.com/80621)
[email protected]28505fc2012-05-02 10:33:09346//
347// The test times out under AddressSanitizer, see http://crbug.com/103371
348#if defined(ADDRESS_SANITIZER)
349#define MAYBE_ReloadIntoAppProcess DISABLED_ReloadIntoAppProcess
350#else
351#define MAYBE_ReloadIntoAppProcess ReloadIntoAppProcess
352#endif
353IN_PROC_BROWSER_TEST_F(AppApiTest, MAYBE_ReloadIntoAppProcess) {
[email protected]6f371442011-11-09 06:45:46354 extensions::ProcessMap* process_map =
355 browser()->profile()->GetExtensionService()->process_map();
[email protected]718eab62011-10-05 21:16:52356
[email protected]d292d8a2011-05-25 03:47:11357 host_resolver()->AddRule("*", "127.0.0.1");
358 ASSERT_TRUE(test_server()->Start());
359
360 // The app under test acts on URLs whose host is "localhost",
361 // so the URLs we navigate to must have host "localhost".
[email protected]118d3122011-08-10 17:09:53362 GURL base_url = GetTestBaseURL("app_process");
[email protected]d292d8a2011-05-25 03:47:11363
364 // Load an app URL before loading the app.
365 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
[email protected]6acde6352012-01-04 16:52:20366 WebContents* contents = browser()->GetWebContentsAt(0);
[email protected]6f371442011-11-09 06:45:46367 EXPECT_FALSE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52368 contents->GetRenderProcessHost()->GetID()));
[email protected]d292d8a2011-05-25 03:47:11369
[email protected]8d3132f62011-10-12 07:13:42370 // Load app and navigate to the page.
[email protected]d292d8a2011-05-25 03:47:11371 const Extension* app =
372 LoadExtension(test_data_dir_.AppendASCII("app_process"));
373 ASSERT_TRUE(app);
374 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
[email protected]6f371442011-11-09 06:45:46375 EXPECT_TRUE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52376 contents->GetRenderProcessHost()->GetID()));
[email protected]d292d8a2011-05-25 03:47:11377
[email protected]8d3132f62011-10-12 07:13:42378 // Disable app and navigate to the page.
[email protected]d292d8a2011-05-25 03:47:11379 DisableExtension(app->id());
380 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
[email protected]6f371442011-11-09 06:45:46381 EXPECT_FALSE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52382 contents->GetRenderProcessHost()->GetID()));
[email protected]d292d8a2011-05-25 03:47:11383
[email protected]8d3132f62011-10-12 07:13:42384 // Enable app and reload the page.
385 EnableExtension(app->id());
386 ui_test_utils::WindowedNotificationObserver reload_observer(
387 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50388 content::Source<NavigationController>(
[email protected]6acde6352012-01-04 16:52:20389 &browser()->GetSelectedTabContentsWrapper()->web_contents()->
[email protected]f5fa20e2011-12-21 22:35:56390 GetController()));
[email protected]8d3132f62011-10-12 07:13:42391 browser()->Reload(CURRENT_TAB);
392 reload_observer.Wait();
[email protected]6f371442011-11-09 06:45:46393 EXPECT_TRUE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52394 contents->GetRenderProcessHost()->GetID()));
[email protected]8d3132f62011-10-12 07:13:42395
396 // Disable app and reload the page.
397 DisableExtension(app->id());
398 ui_test_utils::WindowedNotificationObserver reload_observer2(
399 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50400 content::Source<NavigationController>(
[email protected]6acde6352012-01-04 16:52:20401 &browser()->GetSelectedTabContentsWrapper()->web_contents()->
[email protected]f5fa20e2011-12-21 22:35:56402 GetController()));
[email protected]8d3132f62011-10-12 07:13:42403 browser()->Reload(CURRENT_TAB);
404 reload_observer2.Wait();
[email protected]6f371442011-11-09 06:45:46405 EXPECT_FALSE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52406 contents->GetRenderProcessHost()->GetID()));
[email protected]8d3132f62011-10-12 07:13:42407
[email protected]d292d8a2011-05-25 03:47:11408 // Enable app and reload via JavaScript.
409 EnableExtension(app->id());
[email protected]8d3132f62011-10-12 07:13:42410 ui_test_utils::WindowedNotificationObserver js_reload_observer(
411 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50412 content::Source<NavigationController>(
[email protected]6acde6352012-01-04 16:52:20413 &browser()->GetSelectedTabContentsWrapper()->web_contents()->
[email protected]f5fa20e2011-12-21 22:35:56414 GetController()));
[email protected]151a63d2011-12-20 22:32:52415 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(contents->GetRenderViewHost(),
[email protected]d292d8a2011-05-25 03:47:11416 L"", L"location.reload();"));
[email protected]8d3132f62011-10-12 07:13:42417 js_reload_observer.Wait();
[email protected]6f371442011-11-09 06:45:46418 EXPECT_TRUE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52419 contents->GetRenderProcessHost()->GetID()));
[email protected]d292d8a2011-05-25 03:47:11420
421 // Disable app and reload via JavaScript.
422 DisableExtension(app->id());
[email protected]8d3132f62011-10-12 07:13:42423 ui_test_utils::WindowedNotificationObserver js_reload_observer2(
424 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50425 content::Source<NavigationController>(
[email protected]6acde6352012-01-04 16:52:20426 &browser()->GetSelectedTabContentsWrapper()->web_contents()->
[email protected]f5fa20e2011-12-21 22:35:56427 GetController()));
[email protected]151a63d2011-12-20 22:32:52428 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(contents->GetRenderViewHost(),
[email protected]bcd904482012-02-01 01:54:22429 L"", L"location = location;"));
[email protected]8d3132f62011-10-12 07:13:42430 js_reload_observer2.Wait();
[email protected]6f371442011-11-09 06:45:46431 EXPECT_FALSE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52432 contents->GetRenderProcessHost()->GetID()));
[email protected]d292d8a2011-05-25 03:47:11433}
[email protected]118d3122011-08-10 17:09:53434
[email protected]118d3122011-08-10 17:09:53435// Tests that if we have a non-app process (path3/container.html) that has an
436// iframe with a URL in the app's extent (path1/iframe.html), then opening a
437// link from that iframe to a new window to a URL in the app's extent (path1/
438// empty.html) results in the new window being in an app process. See
439// http://crbug.com/89272 for more details.
[email protected]19da16a92012-05-23 17:11:29440IN_PROC_BROWSER_TEST_F(AppApiTest, OpenAppFromIframe) {
[email protected]6f371442011-11-09 06:45:46441 extensions::ProcessMap* process_map =
442 browser()->profile()->GetExtensionService()->process_map();
[email protected]718eab62011-10-05 21:16:52443
[email protected]118d3122011-08-10 17:09:53444 host_resolver()->AddRule("*", "127.0.0.1");
445 ASSERT_TRUE(test_server()->Start());
446
447 GURL base_url = GetTestBaseURL("app_process");
448
449 // Load app and start URL (not in the app).
450 const Extension* app =
451 LoadExtension(test_data_dir_.AppendASCII("app_process"));
452 ASSERT_TRUE(app);
[email protected]19da16a92012-05-23 17:11:29453
454 ui_test_utils::WindowedNotificationObserver popup_observer(
455 content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
456 content::NotificationService::AllSources());
457 ui_test_utils::NavigateToURL(browser(),
458 base_url.Resolve("path3/container.html"));
[email protected]6f371442011-11-09 06:45:46459 EXPECT_FALSE(process_map->Contains(
[email protected]6acde6352012-01-04 16:52:20460 browser()->GetWebContentsAt(0)->GetRenderProcessHost()->GetID()));
[email protected]19da16a92012-05-23 17:11:29461 popup_observer.Wait();
[email protected]118d3122011-08-10 17:09:53462
463 // Popup window should be in the app's process.
[email protected]19da16a92012-05-23 17:11:29464 RenderViewHost* popup_host =
465 content::Source<RenderViewHost>(popup_observer.source()).ptr();
466 EXPECT_TRUE(process_map->Contains(popup_host->GetProcess()->GetID()));
[email protected]118d3122011-08-10 17:09:53467}
[email protected]a09add52011-08-12 03:59:23468
[email protected]88aae972011-12-16 01:14:18469// Tests that if an extension launches an app via chrome.tabs.create with an URL
470// that's not in the app's extent but that redirects to it, we still end up with
471// an app process. See http://crbug.com/99349 for more details.
472IN_PROC_BROWSER_TEST_F(AppApiTest, OpenAppFromExtension) {
473 host_resolver()->AddRule("*", "127.0.0.1");
474 ASSERT_TRUE(StartTestServer());
475
476 LoadExtension(test_data_dir_.AppendASCII("app_process"));
477 const Extension* launcher =
478 LoadExtension(test_data_dir_.AppendASCII("app_launcher"));
479
480 // There should be three navigations by the time the app page is loaded.
481 // 1. The extension launcher page.
482 // 2. The URL that the extension launches, which redirects.
483 // 3. The app's URL.
484 TestNavigationObserver test_navigation_observer(
485 content::NotificationService::AllSources(),
486 NULL,
487 3);
488
489 // Load the launcher extension, which should launch the app.
490 ui_test_utils::NavigateToURLWithDisposition(
491 browser(),
492 launcher->GetResourceURL("main.html"),
493 CURRENT_TAB,
494 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
495
496 // Wait for app tab to be created and loaded.
497 test_navigation_observer.WaitForObservation(
498 base::Bind(&ui_test_utils::RunMessageLoop),
499 base::Bind(&MessageLoop::Quit,
500 base::Unretained(MessageLoopForUI::current())));
501
502 // App has loaded, and chrome.app.isInstalled should be true.
503 bool is_installed = false;
504 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
[email protected]4ca15302012-01-03 05:53:20505 browser()->GetSelectedWebContents()->GetRenderViewHost(), L"",
[email protected]88aae972011-12-16 01:14:18506 L"window.domAutomationController.send(chrome.app.isInstalled)",
507 &is_installed));
508 ASSERT_TRUE(is_installed);
509}
510
[email protected]d55c2382011-08-18 23:10:36511// Tests that if we have an app process (path1/container.html) with a non-app
512// iframe (path3/iframe.html), then opening a link from that iframe to a new
513// window to a same-origin non-app URL (path3/empty.html) should keep the window
514// in the app process.
515// This is in contrast to OpenAppFromIframe, since here the popup will not be
516// missing special permissions and should be scriptable from the iframe.
517// See http://crbug.com/92669 for more details.
[email protected]19da16a92012-05-23 17:11:29518IN_PROC_BROWSER_TEST_F(AppApiTest, OpenWebPopupFromWebIframe) {
[email protected]6f371442011-11-09 06:45:46519 extensions::ProcessMap* process_map =
520 browser()->profile()->GetExtensionService()->process_map();
[email protected]718eab62011-10-05 21:16:52521
[email protected]d55c2382011-08-18 23:10:36522 host_resolver()->AddRule("*", "127.0.0.1");
523 ASSERT_TRUE(test_server()->Start());
524
525 GURL base_url = GetTestBaseURL("app_process");
526
527 // Load app and start URL (in the app).
528 const Extension* app =
529 LoadExtension(test_data_dir_.AppendASCII("app_process"));
530 ASSERT_TRUE(app);
[email protected]19da16a92012-05-23 17:11:29531
532 ui_test_utils::WindowedNotificationObserver popup_observer(
533 content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
534 content::NotificationService::AllSources());
535 ui_test_utils::NavigateToURL(browser(),
536 base_url.Resolve("path1/container.html"));
[email protected]f3b1a082011-11-18 00:34:30537 content::RenderProcessHost* process =
[email protected]6acde6352012-01-04 16:52:20538 browser()->GetWebContentsAt(0)->GetRenderProcessHost();
[email protected]f3b1a082011-11-18 00:34:30539 EXPECT_TRUE(process_map->Contains(process->GetID()));
[email protected]d55c2382011-08-18 23:10:36540
[email protected]19da16a92012-05-23 17:11:29541 // Wait for popup window to appear.
542 popup_observer.Wait();
[email protected]d55c2382011-08-18 23:10:36543
544 // Popup window should be in the app's process.
[email protected]19da16a92012-05-23 17:11:29545 RenderViewHost* popup_host =
546 content::Source<RenderViewHost>(popup_observer.source()).ptr();
547 EXPECT_EQ(process, popup_host->GetProcess());
[email protected]d55c2382011-08-18 23:10:36548}
549
[email protected]a344b762012-03-16 18:53:49550// http://crbug.com/118502
551#if defined(OS_MACOSX) || defined(OS_LINUX)
552#define MAYBE_ReloadAppAfterCrash DISABLED_ReloadAppAfterCrash
553#else
554#define MAYBE_ReloadAppAfterCrash ReloadAppAfterCrash
555#endif
556IN_PROC_BROWSER_TEST_F(AppApiTest, MAYBE_ReloadAppAfterCrash) {
[email protected]6f371442011-11-09 06:45:46557 extensions::ProcessMap* process_map =
558 browser()->profile()->GetExtensionService()->process_map();
559
[email protected]a09add52011-08-12 03:59:23560 host_resolver()->AddRule("*", "127.0.0.1");
561 ASSERT_TRUE(test_server()->Start());
562
563 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
564
565 GURL base_url = GetTestBaseURL("app_process");
566
567 // Load the app, chrome.app.isInstalled should be true.
568 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html"));
[email protected]6acde6352012-01-04 16:52:20569 WebContents* contents = browser()->GetWebContentsAt(0);
[email protected]6f371442011-11-09 06:45:46570 EXPECT_TRUE(process_map->Contains(
[email protected]151a63d2011-12-20 22:32:52571 contents->GetRenderProcessHost()->GetID()));
[email protected]a09add52011-08-12 03:59:23572 bool is_installed = false;
573 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
[email protected]151a63d2011-12-20 22:32:52574 contents->GetRenderViewHost(), L"",
[email protected]a09add52011-08-12 03:59:23575 L"window.domAutomationController.send(chrome.app.isInstalled)",
576 &is_installed));
577 ASSERT_TRUE(is_installed);
578
579 // Crash the tab and reload it, chrome.app.isInstalled should still be true.
[email protected]4ca15302012-01-03 05:53:20580 ui_test_utils::CrashTab(browser()->GetSelectedWebContents());
[email protected]ae673742011-08-24 19:48:37581 ui_test_utils::WindowedNotificationObserver observer(
582 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50583 content::Source<NavigationController>(
[email protected]6acde6352012-01-04 16:52:20584 &browser()->GetSelectedTabContentsWrapper()->web_contents()->
[email protected]f5fa20e2011-12-21 22:35:56585 GetController()));
[email protected]a09add52011-08-12 03:59:23586 browser()->Reload(CURRENT_TAB);
[email protected]ae673742011-08-24 19:48:37587 observer.Wait();
[email protected]a09add52011-08-12 03:59:23588 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
[email protected]151a63d2011-12-20 22:32:52589 contents->GetRenderViewHost(), L"",
[email protected]a09add52011-08-12 03:59:23590 L"window.domAutomationController.send(chrome.app.isInstalled)",
591 &is_installed));
592 ASSERT_TRUE(is_installed);
593}