Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / isolated_app_browsertest.cc
blob4a24a0c9b318f21d2c8a052cec672f73501f92c2
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.
5 #include "base/strings/stringprintf.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "chrome/browser/automation/automation_util.h"
8 #include "chrome/browser/extensions/extension_apitest.h"
9 #include "chrome/browser/extensions/extension_host.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.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 "content/public/test/browser_test_utils.h"
22 #include "extensions/browser/process_map.h"
23 #include "extensions/common/switches.h"
24 #include "net/dns/mock_host_resolver.h"
25 #include "net/test/embedded_test_server/embedded_test_server.h"
26 #include "net/test/embedded_test_server/http_response.h"
27 #include "net/test/embedded_test_server/http_request.h"
29 using content::ExecuteScript;
30 using content::ExecuteScriptAndExtractString;
31 using content::NavigationController;
32 using content::WebContents;
33 using content::RenderViewHost;
35 namespace {
37 std::string WrapForJavascriptAndExtract(const char* javascript_expression) {
38 return std::string("window.domAutomationController.send(") +
39 javascript_expression + ")";
42 scoped_ptr<net::test_server::HttpResponse> HandleExpectAndSetCookieRequest(
43 const net::test_server::EmbeddedTestServer* test_server,
44 const net::test_server::HttpRequest& request) {
45 if (!StartsWithASCII(request.relative_url, "/expect-and-set-cookie?", true))
46 return scoped_ptr<net::test_server::HttpResponse>();
48 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
49 new net::test_server::BasicHttpResponse);
50 http_response->set_code(net::HTTP_OK);
52 std::string request_cookies;
53 std::map<std::string, std::string>::const_iterator it =
54 request.headers.find("Cookie");
55 if (it != request.headers.end())
56 request_cookies = it->second;
58 size_t query_string_pos = request.relative_url.find('?');
59 std::string query_string =
60 request.relative_url.substr(query_string_pos + 1);
61 url_parse::Component query(0, query_string.length()), key_pos, value_pos;
62 bool expectations_satisfied = true;
63 std::vector<std::string> cookies_to_set;
64 while (url_parse::ExtractQueryKeyValue(
65 query_string.c_str(), &query, &key_pos, &value_pos)) {
66 std::string escaped_key(query_string.substr(key_pos.begin, key_pos.len));
67 std::string escaped_value(
68 query_string.substr(value_pos.begin, value_pos.len));
70 std::string key =
71 net::UnescapeURLComponent(escaped_key,
72 net::UnescapeRule::NORMAL |
73 net::UnescapeRule::SPACES |
74 net::UnescapeRule::URL_SPECIAL_CHARS);
76 std::string value =
77 net::UnescapeURLComponent(escaped_value,
78 net::UnescapeRule::NORMAL |
79 net::UnescapeRule::SPACES |
80 net::UnescapeRule::URL_SPECIAL_CHARS);
82 if (key == "expect") {
83 if (request_cookies.find(value) == std::string::npos)
84 expectations_satisfied = false;
85 } else if (key == "set") {
86 cookies_to_set.push_back(value);
87 } else {
88 return scoped_ptr<net::test_server::HttpResponse>();
92 if (expectations_satisfied) {
93 for (size_t i = 0; i < cookies_to_set.size(); i++)
94 http_response->AddCustomHeader("Set-Cookie", cookies_to_set[i]);
97 return http_response.PassAs<net::test_server::HttpResponse>();
100 class IsolatedAppTest : public ExtensionBrowserTest {
101 public:
102 // Returns whether the given tab's current URL has the given cookie.
103 bool WARN_UNUSED_RESULT HasCookie(WebContents* contents, std::string cookie) {
104 int value_size;
105 std::string actual_cookie;
106 automation_util::GetCookies(contents->GetURL(), contents, &value_size,
107 &actual_cookie);
108 return actual_cookie.find(cookie) != std::string::npos;
111 const extensions::Extension* GetInstalledApp(WebContents* contents) {
112 const extensions::Extension* installed_app = NULL;
113 Profile* profile =
114 Profile::FromBrowserContext(contents->GetBrowserContext());
115 ExtensionService* service = profile->GetExtensionService();
116 if (service) {
117 std::set<std::string> extension_ids =
118 extensions::ProcessMap::Get(profile)->GetExtensionsInProcess(
119 contents->GetRenderViewHost()->GetProcess()->GetID());
120 for (std::set<std::string>::iterator iter = extension_ids.begin();
121 iter != extension_ids.end(); ++iter) {
122 installed_app = service->extensions()->GetByID(*iter);
123 if (installed_app && installed_app->is_app())
124 return installed_app;
127 return NULL;
130 private:
131 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
132 ExtensionBrowserTest::SetUpCommandLine(command_line);
133 command_line->AppendSwitch(
134 extensions::switches::kEnableExperimentalExtensionApis);
138 } // namespace
140 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, CrossProcessClientRedirect) {
141 host_resolver()->AddRule("*", "127.0.0.1");
142 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
144 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
145 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
147 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
148 GURL::Replacements replace_host;
149 std::string host_str("localhost"); // Must stay in scope with replace_host.
150 replace_host.SetHostStr(host_str);
151 base_url = base_url.ReplaceComponents(replace_host);
152 ui_test_utils::NavigateToURLWithDisposition(
153 browser(), base_url.Resolve("app1/main.html"),
154 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
156 // Redirect to app2.
157 GURL redirect_url(embedded_test_server()->GetURL(
158 "/extensions/isolated_apps/app2/redirect.html"));
159 ui_test_utils::NavigateToURLWithDisposition(
160 browser(), redirect_url,
161 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
163 // Go back twice.
164 // If bug fixed, we cannot go back anymore.
165 // If not fixed, we will redirect back to app2 and can go back again.
166 EXPECT_TRUE(chrome::CanGoBack(browser()));
167 chrome::GoBack(browser(), CURRENT_TAB);
168 EXPECT_TRUE(chrome::CanGoBack(browser()));
169 chrome::GoBack(browser(), CURRENT_TAB);
170 EXPECT_FALSE(chrome::CanGoBack(browser()));
172 // We also need to test script-initialized navigation (document.location.href)
173 // happened after page finishes loading. This one will also triggered the
174 // willPerformClientRedirect hook in RenderViewImpl but should not replace
175 // the previous history entry.
176 ui_test_utils::NavigateToURLWithDisposition(
177 browser(), base_url.Resolve("non_app/main.html"),
178 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
180 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(1);
182 // Using JavaScript to navigate to app2 page,
183 // after the non_app page has finished loading.
184 content::WindowedNotificationObserver observer1(
185 content::NOTIFICATION_LOAD_STOP,
186 content::Source<NavigationController>(
187 &browser()->tab_strip_model()->GetActiveWebContents()->
188 GetController()));
189 std::string script = base::StringPrintf(
190 "document.location.href=\"%s\";",
191 base_url.Resolve("app2/main.html").spec().c_str());
192 EXPECT_TRUE(ExecuteScript(tab0, script));
193 observer1.Wait();
195 // This kind of navigation should not replace previous navigation entry.
196 EXPECT_TRUE(chrome::CanGoBack(browser()));
197 chrome::GoBack(browser(), CURRENT_TAB);
198 EXPECT_FALSE(chrome::CanGoBack(browser()));
201 // Tests that cookies set within an isolated app are not visible to normal
202 // pages or other apps.
204 // TODO(ajwong): Also test what happens if an app spans multiple sites in its
205 // extent. These origins should also be isolated, but still have origin-based
206 // separation as you would expect.
208 // This test is disabled due to being flaky. http://crbug.com/86562
209 #if defined(OS_WIN)
210 #define MAYBE_CookieIsolation DISABLED_CookieIsolation
211 #else
212 #define MAYBE_CookieIsolation CookieIsolation
213 #endif
214 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_CookieIsolation) {
215 host_resolver()->AddRule("*", "127.0.0.1");
216 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
218 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
219 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
221 // The app under test acts on URLs whose host is "localhost",
222 // so the URLs we navigate to must have host "localhost".
223 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
224 GURL::Replacements replace_host;
225 std::string host_str("localhost"); // Must stay in scope with replace_host.
226 replace_host.SetHostStr(host_str);
227 base_url = base_url.ReplaceComponents(replace_host);
229 ui_test_utils::NavigateToURLWithDisposition(
230 browser(), base_url.Resolve("app1/main.html"),
231 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
232 ui_test_utils::NavigateToURLWithDisposition(
233 browser(), base_url.Resolve("app2/main.html"),
234 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
235 ui_test_utils::NavigateToURLWithDisposition(
236 browser(), base_url.Resolve("non_app/main.html"),
237 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
239 ASSERT_EQ(3, browser()->tab_strip_model()->count());
241 // Ensure first two tabs have installed apps.
242 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(0);
243 WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(1);
244 WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(2);
245 ASSERT_TRUE(GetInstalledApp(tab0));
246 ASSERT_TRUE(GetInstalledApp(tab1));
247 ASSERT_TRUE(!GetInstalledApp(tab2));
249 // Check that tabs see cannot each other's localStorage even though they are
250 // in the same origin.
251 ASSERT_TRUE(ExecuteScript(
252 tab0, "window.localStorage.setItem('testdata', 'ls_app1');"));
253 ASSERT_TRUE(ExecuteScript(
254 tab1, "window.localStorage.setItem('testdata', 'ls_app2');"));
255 ASSERT_TRUE(ExecuteScript(
256 tab2, "window.localStorage.setItem('testdata', 'ls_normal');"));
258 const std::string& kRetrieveLocalStorage =
259 WrapForJavascriptAndExtract(
260 "window.localStorage.getItem('testdata') || 'badval'");
261 std::string result;
262 ASSERT_TRUE(ExecuteScriptAndExtractString(
263 tab0, kRetrieveLocalStorage.c_str(), &result));
264 EXPECT_EQ("ls_app1", result);
265 ASSERT_TRUE(ExecuteScriptAndExtractString(
266 tab1, kRetrieveLocalStorage.c_str(), &result));
267 EXPECT_EQ("ls_app2", result);
268 ASSERT_TRUE(ExecuteScriptAndExtractString(
269 tab2, kRetrieveLocalStorage.c_str(), &result));
270 EXPECT_EQ("ls_normal", result);
272 // Check that each tab sees its own cookie.
273 EXPECT_TRUE(HasCookie(tab0, "app1=3"));
274 EXPECT_TRUE(HasCookie(tab1, "app2=4"));
275 EXPECT_TRUE(HasCookie(tab2, "normalPage=5"));
277 // Check that app1 tab cannot see the other cookies.
278 EXPECT_FALSE(HasCookie(tab0, "app2"));
279 EXPECT_FALSE(HasCookie(tab0, "normalPage"));
281 // Check that app2 tab cannot see the other cookies.
282 EXPECT_FALSE(HasCookie(tab1, "app1"));
283 EXPECT_FALSE(HasCookie(tab1, "normalPage"));
285 // Check that normal tab cannot see the other cookies.
286 EXPECT_FALSE(HasCookie(tab2, "app1"));
287 EXPECT_FALSE(HasCookie(tab2, "app2"));
289 // Check that the non_app iframe cookie is associated with app1 and not the
290 // normal tab. (For now, iframes are always rendered in their parent
291 // process, even if they aren't in the app manifest.)
292 EXPECT_TRUE(HasCookie(tab0, "nonAppFrame=6"));
293 EXPECT_FALSE(HasCookie(tab2, "nonAppFrame"));
295 // Check that isolation persists even if the tab crashes and is reloaded.
296 chrome::SelectNumberedTab(browser(), 0);
297 content::CrashTab(tab0);
298 content::WindowedNotificationObserver observer(
299 content::NOTIFICATION_LOAD_STOP,
300 content::Source<NavigationController>(
301 &browser()->tab_strip_model()->GetActiveWebContents()->
302 GetController()));
303 chrome::Reload(browser(), CURRENT_TAB);
304 observer.Wait();
305 EXPECT_TRUE(HasCookie(tab0, "app1=3"));
306 EXPECT_FALSE(HasCookie(tab0, "app2"));
307 EXPECT_FALSE(HasCookie(tab0, "normalPage"));
311 // This test is disabled due to being flaky. http://crbug.com/145588
312 // Ensure that cookies are not isolated if the isolated apps are not installed.
313 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_NoCookieIsolationWithoutApp) {
314 host_resolver()->AddRule("*", "127.0.0.1");
315 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
317 // The app under test acts on URLs whose host is "localhost",
318 // so the URLs we navigate to must have host "localhost".
319 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
320 GURL::Replacements replace_host;
321 std::string host_str("localhost"); // Must stay in scope with replace_host.
322 replace_host.SetHostStr(host_str);
323 base_url = base_url.ReplaceComponents(replace_host);
325 ui_test_utils::NavigateToURLWithDisposition(
326 browser(), base_url.Resolve("app1/main.html"),
327 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
328 ui_test_utils::NavigateToURLWithDisposition(
329 browser(), base_url.Resolve("app2/main.html"),
330 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
331 ui_test_utils::NavigateToURLWithDisposition(
332 browser(), base_url.Resolve("non_app/main.html"),
333 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
335 ASSERT_EQ(3, browser()->tab_strip_model()->count());
337 // Check that tabs see each other's cookies.
338 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
339 "app2=4"));
340 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
341 "normalPage=5"));
342 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
343 "nonAppFrame=6"));
344 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
345 "app1=3"));
346 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
347 "normalPage=5"));
348 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
349 "nonAppFrame=6"));
350 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
351 "app1=3"));
352 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
353 "app2=4"));
354 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
355 "nonAppFrame=6"));
357 // Check that all tabs share the same localStorage if they have the same
358 // origin.
359 WebContents* app1_wc = browser()->tab_strip_model()->GetWebContentsAt(0);
360 WebContents* app2_wc = browser()->tab_strip_model()->GetWebContentsAt(1);
361 WebContents* non_app_wc = browser()->tab_strip_model()->GetWebContentsAt(2);
362 ASSERT_TRUE(ExecuteScript(
363 app1_wc, "window.localStorage.setItem('testdata', 'ls_app1');"));
364 ASSERT_TRUE(ExecuteScript(
365 app2_wc, "window.localStorage.setItem('testdata', 'ls_app2');"));
366 ASSERT_TRUE(ExecuteScript(
367 non_app_wc, "window.localStorage.setItem('testdata', 'ls_normal');"));
369 const std::string& kRetrieveLocalStorage =
370 WrapForJavascriptAndExtract("window.localStorage.getItem('testdata')");
371 std::string result;
372 ASSERT_TRUE(ExecuteScriptAndExtractString(
373 app1_wc, kRetrieveLocalStorage.c_str(), &result));
374 EXPECT_EQ("ls_normal", result);
375 ASSERT_TRUE(ExecuteScriptAndExtractString(
376 app2_wc, kRetrieveLocalStorage.c_str(), &result));
377 EXPECT_EQ("ls_normal", result);
378 ASSERT_TRUE(ExecuteScriptAndExtractString(
379 non_app_wc, kRetrieveLocalStorage.c_str(), &result));
380 EXPECT_EQ("ls_normal", result);
383 // Test timing out on Windows debug bots.
384 // http://crbug.com/174926
385 #if defined(OS_WIN) && !defined(NDEBUG)
386 #define MAYBE_SubresourceCookieIsolation DISABLED_SubresourceCookieIsolation
387 #else
388 #define MAYBE_SubresourceCookieIsolation SubresourceCookieIsolation
389 #endif // defined(OS_WIN) && !defined(NDEBUG)
391 // Tests that subresource and media requests use the app's cookie store.
392 // See http://crbug.com/141172.
393 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_SubresourceCookieIsolation) {
394 embedded_test_server()->RegisterRequestHandler(
395 base::Bind(&HandleExpectAndSetCookieRequest, embedded_test_server()));
397 host_resolver()->AddRule("*", "127.0.0.1");
398 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
400 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
402 // The app under test acts on URLs whose host is "localhost",
403 // so the URLs we navigate to must have host "localhost".
404 GURL root_url = embedded_test_server()->GetURL("/");
405 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
406 GURL::Replacements replace_host;
407 std::string host_str("localhost"); // Must stay in scope with replace_host.
408 replace_host.SetHostStr(host_str);
409 root_url = root_url.ReplaceComponents(replace_host);
410 base_url = base_url.ReplaceComponents(replace_host);
412 // First set cookies inside and outside the app.
413 ui_test_utils::NavigateToURLWithDisposition(
414 browser(), root_url.Resolve("expect-and-set-cookie?set=nonApp%3d1"),
415 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
416 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(0);
417 ASSERT_FALSE(GetInstalledApp(tab0));
418 ui_test_utils::NavigateToURLWithDisposition(
419 browser(), base_url.Resolve("app1/main.html"),
420 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
421 WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(1);
422 ASSERT_TRUE(GetInstalledApp(tab1));
424 // Check that each tab sees its own cookie.
425 EXPECT_TRUE(HasCookie(tab0, "nonApp=1"));
426 EXPECT_FALSE(HasCookie(tab0, "app1=3"));
427 EXPECT_FALSE(HasCookie(tab1, "nonApp=1"));
428 EXPECT_TRUE(HasCookie(tab1, "app1=3"));
430 // Now visit an app page that loads subresources located outside the app.
431 // For both images and video tags, it loads two URLs:
432 // - One will set nonApp{Media,Image}=1 cookies if nonApp=1 is set.
433 // - One will set app1{Media,Image}=1 cookies if app1=3 is set.
434 // We expect only the app's cookies to be present.
435 // We must wait for the onload event, to allow the subresources to finish.
436 content::WindowedNotificationObserver observer(
437 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
438 content::Source<WebContents>(
439 browser()->tab_strip_model()->GetActiveWebContents()));
440 ui_test_utils::NavigateToURLWithDisposition(
441 browser(), base_url.Resolve("app1/app_subresources.html"),
442 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
443 observer.Wait();
444 EXPECT_FALSE(HasCookie(tab1, "nonAppMedia=1"));
445 EXPECT_TRUE(HasCookie(tab1, "app1Media=1"));
446 EXPECT_FALSE(HasCookie(tab1, "nonAppImage=1"));
447 EXPECT_TRUE(HasCookie(tab1, "app1Image=1"));
449 // Also create a non-app tab to ensure no new cookies were set in that jar.
450 ui_test_utils::NavigateToURLWithDisposition(
451 browser(), root_url,
452 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
453 WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(2);
454 EXPECT_FALSE(HasCookie(tab2, "nonAppMedia=1"));
455 EXPECT_FALSE(HasCookie(tab2, "app1Media=1"));
456 EXPECT_FALSE(HasCookie(tab2, "nonAppImage=1"));
457 EXPECT_FALSE(HasCookie(tab2, "app1Image=1"));
460 // Test is flaky on Windows.
461 // http://crbug.com/247667
462 #if defined(OS_WIN)
463 #define MAYBE_IsolatedAppProcessModel DISABLED_IsolatedAppProcessModel
464 #else
465 #define MAYBE_IsolatedAppProcessModel IsolatedAppProcessModel
466 #endif // defined(OS_WIN)
468 // Tests that isolated apps processes do not render top-level non-app pages.
469 // This is true even in the case of the OAuth workaround for hosted apps,
470 // where non-app popups may be kept in the hosted app process.
471 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_IsolatedAppProcessModel) {
472 host_resolver()->AddRule("*", "127.0.0.1");
473 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
475 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
477 // The app under test acts on URLs whose host is "localhost",
478 // so the URLs we navigate to must have host "localhost".
479 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
480 GURL::Replacements replace_host;
481 std::string host_str("localhost"); // Must stay in scope with replace_host.
482 replace_host.SetHostStr(host_str);
483 base_url = base_url.ReplaceComponents(replace_host);
485 // Create three tabs in the isolated app in different ways.
486 ui_test_utils::NavigateToURLWithDisposition(
487 browser(), base_url.Resolve("app1/main.html"),
488 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
489 ui_test_utils::NavigateToURLWithDisposition(
490 browser(), base_url.Resolve("app1/main.html"),
491 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
492 // For the third tab, use window.open to keep it in process with an opener.
493 OpenWindow(browser()->tab_strip_model()->GetWebContentsAt(0),
494 base_url.Resolve("app1/main.html"), true, NULL);
496 // In a fourth tab, use window.open to a non-app URL. It should open in a
497 // separate process, even though this would trigger the OAuth workaround
498 // for hosted apps (from http://crbug.com/59285).
499 OpenWindow(browser()->tab_strip_model()->GetWebContentsAt(0),
500 base_url.Resolve("non_app/main.html"), false, NULL);
502 // We should now have four tabs, the first and third sharing a process.
503 // The second one is an independent instance in a separate process.
504 ASSERT_EQ(4, browser()->tab_strip_model()->count());
505 int process_id_0 = browser()->tab_strip_model()->GetWebContentsAt(0)->
506 GetRenderProcessHost()->GetID();
507 int process_id_1 = browser()->tab_strip_model()->GetWebContentsAt(1)->
508 GetRenderProcessHost()->GetID();
509 EXPECT_NE(process_id_0, process_id_1);
510 EXPECT_EQ(process_id_0,
511 browser()->tab_strip_model()->GetWebContentsAt(2)->
512 GetRenderProcessHost()->GetID());
513 EXPECT_NE(process_id_0,
514 browser()->tab_strip_model()->GetWebContentsAt(3)->
515 GetRenderProcessHost()->GetID());
517 // Navigating the second tab out of the app should cause a process swap.
518 const GURL& non_app_url(base_url.Resolve("non_app/main.html"));
519 NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(1),
520 non_app_url);
521 EXPECT_NE(process_id_1,
522 browser()->tab_strip_model()->GetWebContentsAt(1)->
523 GetRenderProcessHost()->GetID());
526 // This test no longer passes, since we don't properly isolate sessionStorage
527 // for isolated apps. This was broken as part of the changes for storage
528 // partition support for webview tags.
529 // TODO(nasko): If isolated apps is no longer developed, this test should be
530 // removed. http://crbug.com/159932
531 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_SessionStorage) {
532 host_resolver()->AddRule("*", "127.0.0.1");
533 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
535 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
536 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
538 // The app under test acts on URLs whose host is "localhost",
539 // so the URLs we navigate to must have host "localhost".
540 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
541 GURL::Replacements replace_host;
542 std::string host_str("localhost"); // Must stay in scope with replace_host.
543 replace_host.SetHostStr(host_str);
544 base_url = base_url.ReplaceComponents(replace_host);
546 // Enter some state into sessionStorage three times on the same origin, but
547 // for three URLs that correspond to app1, app2, and a non-isolated site.
548 ui_test_utils::NavigateToURLWithDisposition(
549 browser(), base_url.Resolve("app1/main.html"),
550 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
551 ASSERT_TRUE(ExecuteScript(
552 browser()->tab_strip_model()->GetWebContentsAt(0),
553 "window.sessionStorage.setItem('testdata', 'ss_app1');"));
555 ui_test_utils::NavigateToURLWithDisposition(
556 browser(), base_url.Resolve("app2/main.html"),
557 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
558 ASSERT_TRUE(ExecuteScript(
559 browser()->tab_strip_model()->GetWebContentsAt(0),
560 "window.sessionStorage.setItem('testdata', 'ss_app2');"));
562 ui_test_utils::NavigateToURLWithDisposition(
563 browser(), base_url.Resolve("non_app/main.html"),
564 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
565 ASSERT_TRUE(ExecuteScript(
566 browser()->tab_strip_model()->GetWebContentsAt(0),
567 "window.sessionStorage.setItem('testdata', 'ss_normal');"));
569 // Now, ensure that the sessionStorage is correctly partitioned, and persists
570 // when we navigate around all over the dang place.
571 const std::string& kRetrieveSessionStorage =
572 WrapForJavascriptAndExtract(
573 "window.sessionStorage.getItem('testdata') || 'badval'");
574 std::string result;
575 ui_test_utils::NavigateToURLWithDisposition(
576 browser(), base_url.Resolve("app1/main.html"),
577 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
578 ASSERT_TRUE(ExecuteScriptAndExtractString(
579 browser()->tab_strip_model()->GetWebContentsAt(0),
580 kRetrieveSessionStorage.c_str(), &result));
581 EXPECT_EQ("ss_app1", result);
583 ui_test_utils::NavigateToURLWithDisposition(
584 browser(), base_url.Resolve("app2/main.html"),
585 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
586 ASSERT_TRUE(ExecuteScriptAndExtractString(
587 browser()->tab_strip_model()->GetWebContentsAt(0),
588 kRetrieveSessionStorage.c_str(), &result));
589 EXPECT_EQ("ss_app2", result);
591 ui_test_utils::NavigateToURLWithDisposition(
592 browser(), base_url.Resolve("non_app/main.html"),
593 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
594 ASSERT_TRUE(ExecuteScriptAndExtractString(
595 browser()->tab_strip_model()->GetWebContentsAt(0),
596 kRetrieveSessionStorage.c_str(), &result));
597 EXPECT_EQ("ss_normal", result);