Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / isolated_app_browsertest.cc
blob1f19e3668c89d343f9280bb3b9763e989d8c20e1
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/extensions/extension_apitest.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/browser_commands.h"
10 #include "chrome/browser/ui/tabs/tab_strip_model.h"
11 #include "chrome/common/url_constants.h"
12 #include "chrome/test/base/ui_test_utils.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/site_instance.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "extensions/browser/extension_host.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/browser/process_map.h"
21 #include "extensions/common/switches.h"
22 #include "net/base/escape.h"
23 #include "net/dns/mock_host_resolver.h"
24 #include "net/test/embedded_test_server/embedded_test_server.h"
25 #include "net/test/embedded_test_server/http_request.h"
26 #include "net/test/embedded_test_server/http_response.h"
28 using content::ExecuteScript;
29 using content::ExecuteScriptAndExtractString;
30 using content::NavigationController;
31 using content::RenderViewHost;
32 using content::WebContents;
34 namespace extensions {
36 namespace {
38 std::string WrapForJavascriptAndExtract(const char* javascript_expression) {
39 return std::string("window.domAutomationController.send(") +
40 javascript_expression + ")";
43 scoped_ptr<net::test_server::HttpResponse> HandleExpectAndSetCookieRequest(
44 const net::test_server::EmbeddedTestServer* test_server,
45 const net::test_server::HttpRequest& request) {
46 if (!base::StartsWith(request.relative_url, "/expect-and-set-cookie?",
47 base::CompareCase::SENSITIVE))
48 return scoped_ptr<net::test_server::HttpResponse>();
50 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
51 new net::test_server::BasicHttpResponse);
52 http_response->set_code(net::HTTP_OK);
54 std::string request_cookies;
55 std::map<std::string, std::string>::const_iterator it =
56 request.headers.find("Cookie");
57 if (it != request.headers.end())
58 request_cookies = it->second;
60 size_t query_string_pos = request.relative_url.find('?');
61 std::string query_string =
62 request.relative_url.substr(query_string_pos + 1);
63 url::Component query(0, query_string.length()), key_pos, value_pos;
64 bool expectations_satisfied = true;
65 std::vector<std::string> cookies_to_set;
66 while (url::ExtractQueryKeyValue(query_string.c_str(), &query, &key_pos,
67 &value_pos)) {
68 std::string escaped_key(query_string.substr(key_pos.begin, key_pos.len));
69 std::string escaped_value(
70 query_string.substr(value_pos.begin, value_pos.len));
72 std::string key =
73 net::UnescapeURLComponent(escaped_key,
74 net::UnescapeRule::NORMAL |
75 net::UnescapeRule::SPACES |
76 net::UnescapeRule::URL_SPECIAL_CHARS);
78 std::string value =
79 net::UnescapeURLComponent(escaped_value,
80 net::UnescapeRule::NORMAL |
81 net::UnescapeRule::SPACES |
82 net::UnescapeRule::URL_SPECIAL_CHARS);
84 if (key == "expect") {
85 if (request_cookies.find(value) == std::string::npos)
86 expectations_satisfied = false;
87 } else if (key == "set") {
88 cookies_to_set.push_back(value);
89 } else {
90 return nullptr;
94 if (expectations_satisfied) {
95 for (size_t i = 0; i < cookies_to_set.size(); i++)
96 http_response->AddCustomHeader("Set-Cookie", cookies_to_set[i]);
99 return http_response.Pass();
102 class IsolatedAppTest : public ExtensionBrowserTest {
103 public:
104 // Returns whether the given tab's current URL has the given cookie.
105 bool WARN_UNUSED_RESULT HasCookie(WebContents* contents, std::string cookie) {
106 int value_size;
107 std::string actual_cookie;
108 ui_test_utils::GetCookies(contents->GetURL(), contents, &value_size,
109 &actual_cookie);
110 return actual_cookie.find(cookie) != std::string::npos;
113 const Extension* GetInstalledApp(WebContents* contents) {
114 content::BrowserContext* browser_context = contents->GetBrowserContext();
115 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context);
116 std::set<std::string> extension_ids =
117 ProcessMap::Get(browser_context)->GetExtensionsInProcess(
118 contents->GetRenderViewHost()->GetProcess()->GetID());
119 for (std::set<std::string>::iterator iter = extension_ids.begin();
120 iter != extension_ids.end(); ++iter) {
121 const Extension* installed_app =
122 registry->enabled_extensions().GetByID(*iter);
123 if (installed_app && installed_app->is_app())
124 return installed_app;
126 return NULL;
129 private:
130 void SetUpCommandLine(base::CommandLine* command_line) override {
131 ExtensionBrowserTest::SetUpCommandLine(command_line);
132 command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
136 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, CrossProcessClientRedirect) {
137 host_resolver()->AddRule("*", "127.0.0.1");
138 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
140 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
141 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
143 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
144 GURL::Replacements replace_host;
145 replace_host.SetHostStr("localhost");
146 base_url = base_url.ReplaceComponents(replace_host);
147 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
149 // Redirect to app2.
150 GURL redirect_url(embedded_test_server()->GetURL(
151 "/extensions/isolated_apps/app2/redirect.html"));
152 ui_test_utils::NavigateToURL(browser(), redirect_url);
154 // Go back twice.
155 // If bug fixed, we cannot go back anymore.
156 // If not fixed, we will redirect back to app2 and can go back again.
157 EXPECT_TRUE(chrome::CanGoBack(browser()));
158 chrome::GoBack(browser(), CURRENT_TAB);
159 EXPECT_TRUE(chrome::CanGoBack(browser()));
160 chrome::GoBack(browser(), CURRENT_TAB);
161 EXPECT_FALSE(chrome::CanGoBack(browser()));
163 // We also need to test script-initialized navigation (document.location.href)
164 // happened after page finishes loading. This one will also triggered the
165 // willPerformClientRedirect hook in RenderViewImpl but should not replace
166 // the previous history entry.
167 ui_test_utils::NavigateToURLWithDisposition(
168 browser(), base_url.Resolve("non_app/main.html"),
169 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
171 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(1);
173 // Using JavaScript to navigate to app2 page,
174 // after the non_app page has finished loading.
175 content::WindowedNotificationObserver observer1(
176 content::NOTIFICATION_LOAD_STOP,
177 content::Source<NavigationController>(
178 &browser()->tab_strip_model()->GetActiveWebContents()->
179 GetController()));
180 std::string script = base::StringPrintf(
181 "document.location.href=\"%s\";",
182 base_url.Resolve("app2/main.html").spec().c_str());
183 EXPECT_TRUE(ExecuteScript(tab0, script));
184 observer1.Wait();
186 // This kind of navigation should not replace previous navigation entry.
187 EXPECT_TRUE(chrome::CanGoBack(browser()));
188 chrome::GoBack(browser(), CURRENT_TAB);
189 EXPECT_FALSE(chrome::CanGoBack(browser()));
192 // Tests that cookies set within an isolated app are not visible to normal
193 // pages or other apps.
195 // TODO(ajwong): Also test what happens if an app spans multiple sites in its
196 // extent. These origins should also be isolated, but still have origin-based
197 // separation as you would expect.
199 // This test is disabled due to being flaky. http://crbug.com/86562
200 #if defined(OS_WIN)
201 #define MAYBE_CookieIsolation DISABLED_CookieIsolation
202 #else
203 #define MAYBE_CookieIsolation CookieIsolation
204 #endif
205 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_CookieIsolation) {
206 host_resolver()->AddRule("*", "127.0.0.1");
207 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
209 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
210 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
212 // The app under test acts on URLs whose host is "localhost",
213 // so the URLs we navigate to must have host "localhost".
214 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
215 GURL::Replacements replace_host;
216 replace_host.SetHostStr("localhost");
217 base_url = base_url.ReplaceComponents(replace_host);
219 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
220 ui_test_utils::NavigateToURLWithDisposition(
221 browser(), base_url.Resolve("app2/main.html"),
222 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
223 ui_test_utils::NavigateToURLWithDisposition(
224 browser(), base_url.Resolve("non_app/main.html"),
225 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
227 ASSERT_EQ(3, browser()->tab_strip_model()->count());
229 // Ensure first two tabs have installed apps.
230 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(0);
231 WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(1);
232 WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(2);
233 ASSERT_TRUE(GetInstalledApp(tab0));
234 ASSERT_TRUE(GetInstalledApp(tab1));
235 ASSERT_TRUE(!GetInstalledApp(tab2));
237 // Check that tabs see cannot each other's localStorage even though they are
238 // in the same origin.
239 ASSERT_TRUE(ExecuteScript(
240 tab0, "window.localStorage.setItem('testdata', 'ls_app1');"));
241 ASSERT_TRUE(ExecuteScript(
242 tab1, "window.localStorage.setItem('testdata', 'ls_app2');"));
243 ASSERT_TRUE(ExecuteScript(
244 tab2, "window.localStorage.setItem('testdata', 'ls_normal');"));
246 const std::string& kRetrieveLocalStorage =
247 WrapForJavascriptAndExtract(
248 "window.localStorage.getItem('testdata') || 'badval'");
249 std::string result;
250 ASSERT_TRUE(ExecuteScriptAndExtractString(
251 tab0, kRetrieveLocalStorage.c_str(), &result));
252 EXPECT_EQ("ls_app1", result);
253 ASSERT_TRUE(ExecuteScriptAndExtractString(
254 tab1, kRetrieveLocalStorage.c_str(), &result));
255 EXPECT_EQ("ls_app2", result);
256 ASSERT_TRUE(ExecuteScriptAndExtractString(
257 tab2, kRetrieveLocalStorage.c_str(), &result));
258 EXPECT_EQ("ls_normal", result);
260 // Check that each tab sees its own cookie.
261 EXPECT_TRUE(HasCookie(tab0, "app1=3"));
262 EXPECT_TRUE(HasCookie(tab1, "app2=4"));
263 EXPECT_TRUE(HasCookie(tab2, "normalPage=5"));
265 // Check that app1 tab cannot see the other cookies.
266 EXPECT_FALSE(HasCookie(tab0, "app2"));
267 EXPECT_FALSE(HasCookie(tab0, "normalPage"));
269 // Check that app2 tab cannot see the other cookies.
270 EXPECT_FALSE(HasCookie(tab1, "app1"));
271 EXPECT_FALSE(HasCookie(tab1, "normalPage"));
273 // Check that normal tab cannot see the other cookies.
274 EXPECT_FALSE(HasCookie(tab2, "app1"));
275 EXPECT_FALSE(HasCookie(tab2, "app2"));
277 // Check that the non_app iframe cookie is associated with app1 and not the
278 // normal tab. (For now, iframes are always rendered in their parent
279 // process, even if they aren't in the app manifest.)
280 EXPECT_TRUE(HasCookie(tab0, "nonAppFrame=6"));
281 EXPECT_FALSE(HasCookie(tab2, "nonAppFrame"));
283 // Check that isolation persists even if the tab crashes and is reloaded.
284 chrome::SelectNumberedTab(browser(), 0);
285 content::CrashTab(tab0);
286 content::WindowedNotificationObserver observer(
287 content::NOTIFICATION_LOAD_STOP,
288 content::Source<NavigationController>(
289 &browser()->tab_strip_model()->GetActiveWebContents()->
290 GetController()));
291 chrome::Reload(browser(), CURRENT_TAB);
292 observer.Wait();
293 EXPECT_TRUE(HasCookie(tab0, "app1=3"));
294 EXPECT_FALSE(HasCookie(tab0, "app2"));
295 EXPECT_FALSE(HasCookie(tab0, "normalPage"));
298 // This test is disabled due to being flaky. http://crbug.com/145588
299 // Ensure that cookies are not isolated if the isolated apps are not installed.
300 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_NoCookieIsolationWithoutApp) {
301 host_resolver()->AddRule("*", "127.0.0.1");
302 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
304 // The app under test acts on URLs whose host is "localhost",
305 // so the URLs we navigate to must have host "localhost".
306 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
307 GURL::Replacements replace_host;
308 replace_host.SetHostStr("localhost");
309 base_url = base_url.ReplaceComponents(replace_host);
311 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
312 ui_test_utils::NavigateToURLWithDisposition(
313 browser(), base_url.Resolve("app2/main.html"),
314 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
315 ui_test_utils::NavigateToURLWithDisposition(
316 browser(), base_url.Resolve("non_app/main.html"),
317 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
319 ASSERT_EQ(3, browser()->tab_strip_model()->count());
321 // Check that tabs see each other's cookies.
322 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
323 "app2=4"));
324 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
325 "normalPage=5"));
326 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(0),
327 "nonAppFrame=6"));
328 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
329 "app1=3"));
330 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
331 "normalPage=5"));
332 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(1),
333 "nonAppFrame=6"));
334 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
335 "app1=3"));
336 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
337 "app2=4"));
338 EXPECT_TRUE(HasCookie(browser()->tab_strip_model()->GetWebContentsAt(2),
339 "nonAppFrame=6"));
341 // Check that all tabs share the same localStorage if they have the same
342 // origin.
343 WebContents* app1_wc = browser()->tab_strip_model()->GetWebContentsAt(0);
344 WebContents* app2_wc = browser()->tab_strip_model()->GetWebContentsAt(1);
345 WebContents* non_app_wc = browser()->tab_strip_model()->GetWebContentsAt(2);
346 ASSERT_TRUE(ExecuteScript(
347 app1_wc, "window.localStorage.setItem('testdata', 'ls_app1');"));
348 ASSERT_TRUE(ExecuteScript(
349 app2_wc, "window.localStorage.setItem('testdata', 'ls_app2');"));
350 ASSERT_TRUE(ExecuteScript(
351 non_app_wc, "window.localStorage.setItem('testdata', 'ls_normal');"));
353 const std::string& kRetrieveLocalStorage =
354 WrapForJavascriptAndExtract("window.localStorage.getItem('testdata')");
355 std::string result;
356 ASSERT_TRUE(ExecuteScriptAndExtractString(
357 app1_wc, kRetrieveLocalStorage.c_str(), &result));
358 EXPECT_EQ("ls_normal", result);
359 ASSERT_TRUE(ExecuteScriptAndExtractString(
360 app2_wc, kRetrieveLocalStorage.c_str(), &result));
361 EXPECT_EQ("ls_normal", result);
362 ASSERT_TRUE(ExecuteScriptAndExtractString(
363 non_app_wc, kRetrieveLocalStorage.c_str(), &result));
364 EXPECT_EQ("ls_normal", result);
367 // http://crbug.com/174926
368 #if (defined(OS_WIN) && !defined(NDEBUG)) || defined(OS_MACOSX)
369 #define MAYBE_SubresourceCookieIsolation DISABLED_SubresourceCookieIsolation
370 #else
371 #define MAYBE_SubresourceCookieIsolation SubresourceCookieIsolation
372 #endif // (defined(OS_WIN) && !defined(NDEBUG)) || defined(OS_MACOSX)
374 // Tests that subresource and media requests use the app's cookie store.
375 // See http://crbug.com/141172.
376 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_SubresourceCookieIsolation) {
377 embedded_test_server()->RegisterRequestHandler(
378 base::Bind(&HandleExpectAndSetCookieRequest, embedded_test_server()));
380 host_resolver()->AddRule("*", "127.0.0.1");
381 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
383 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
385 // The app under test acts on URLs whose host is "localhost",
386 // so the URLs we navigate to must have host "localhost".
387 GURL root_url = embedded_test_server()->GetURL("/");
388 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
389 GURL::Replacements replace_host;
390 replace_host.SetHostStr("localhost");
391 root_url = root_url.ReplaceComponents(replace_host);
392 base_url = base_url.ReplaceComponents(replace_host);
394 // First set cookies inside and outside the app.
395 ui_test_utils::NavigateToURL(
396 browser(), root_url.Resolve("expect-and-set-cookie?set=nonApp%3d1"));
397 WebContents* tab0 = browser()->tab_strip_model()->GetWebContentsAt(0);
398 ASSERT_FALSE(GetInstalledApp(tab0));
399 ui_test_utils::NavigateToURLWithDisposition(
400 browser(), base_url.Resolve("app1/main.html"),
401 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
402 WebContents* tab1 = browser()->tab_strip_model()->GetWebContentsAt(1);
403 ASSERT_TRUE(GetInstalledApp(tab1));
405 // Check that each tab sees its own cookie.
406 EXPECT_TRUE(HasCookie(tab0, "nonApp=1"));
407 EXPECT_FALSE(HasCookie(tab0, "app1=3"));
408 EXPECT_FALSE(HasCookie(tab1, "nonApp=1"));
409 EXPECT_TRUE(HasCookie(tab1, "app1=3"));
411 // Now visit an app page that loads subresources located outside the app.
412 // For both images and video tags, it loads two URLs:
413 // - One will set nonApp{Media,Image}=1 cookies if nonApp=1 is set.
414 // - One will set app1{Media,Image}=1 cookies if app1=3 is set.
415 // We expect only the app's cookies to be present.
416 // We must wait for the onload event, to allow the subresources to finish.
417 content::WindowedNotificationObserver observer(
418 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
419 content::Source<WebContents>(
420 browser()->tab_strip_model()->GetActiveWebContents()));
421 ui_test_utils::NavigateToURL(
422 browser(), base_url.Resolve("app1/app_subresources.html"));
423 observer.Wait();
424 EXPECT_FALSE(HasCookie(tab1, "nonAppMedia=1"));
425 EXPECT_TRUE(HasCookie(tab1, "app1Media=1"));
426 EXPECT_FALSE(HasCookie(tab1, "nonAppImage=1"));
427 EXPECT_TRUE(HasCookie(tab1, "app1Image=1"));
429 // Also create a non-app tab to ensure no new cookies were set in that jar.
430 ui_test_utils::NavigateToURLWithDisposition(
431 browser(), root_url,
432 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
433 WebContents* tab2 = browser()->tab_strip_model()->GetWebContentsAt(2);
434 EXPECT_FALSE(HasCookie(tab2, "nonAppMedia=1"));
435 EXPECT_FALSE(HasCookie(tab2, "app1Media=1"));
436 EXPECT_FALSE(HasCookie(tab2, "nonAppImage=1"));
437 EXPECT_FALSE(HasCookie(tab2, "app1Image=1"));
440 // Test is flaky on Windows.
441 // http://crbug.com/247667
442 #if defined(OS_WIN)
443 #define MAYBE_IsolatedAppProcessModel DISABLED_IsolatedAppProcessModel
444 #else
445 #define MAYBE_IsolatedAppProcessModel IsolatedAppProcessModel
446 #endif // defined(OS_WIN)
448 // Tests that isolated apps processes do not render top-level non-app pages.
449 // This is true even in the case of the OAuth workaround for hosted apps,
450 // where non-app popups may be kept in the hosted app process.
451 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, MAYBE_IsolatedAppProcessModel) {
452 host_resolver()->AddRule("*", "127.0.0.1");
453 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
455 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
457 // The app under test acts on URLs whose host is "localhost",
458 // so the URLs we navigate to must have host "localhost".
459 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
460 GURL::Replacements replace_host;
461 replace_host.SetHostStr("localhost");
462 base_url = base_url.ReplaceComponents(replace_host);
464 // Create three tabs in the isolated app in different ways.
465 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
466 ui_test_utils::NavigateToURLWithDisposition(
467 browser(), base_url.Resolve("app1/main.html"),
468 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
469 // For the third tab, use window.open to keep it in process with an opener.
470 OpenWindow(browser()->tab_strip_model()->GetWebContentsAt(0),
471 base_url.Resolve("app1/main.html"), true, NULL);
473 // In a fourth tab, use window.open to a non-app URL. It should open in a
474 // separate process, even though this would trigger the OAuth workaround
475 // for hosted apps (from http://crbug.com/59285).
476 OpenWindow(browser()->tab_strip_model()->GetWebContentsAt(0),
477 base_url.Resolve("non_app/main.html"), false, NULL);
479 // We should now have four tabs, the first and third sharing a process.
480 // The second one is an independent instance in a separate process.
481 ASSERT_EQ(4, browser()->tab_strip_model()->count());
482 int process_id_0 = browser()->tab_strip_model()->GetWebContentsAt(0)->
483 GetRenderProcessHost()->GetID();
484 int process_id_1 = browser()->tab_strip_model()->GetWebContentsAt(1)->
485 GetRenderProcessHost()->GetID();
486 EXPECT_NE(process_id_0, process_id_1);
487 EXPECT_EQ(process_id_0,
488 browser()->tab_strip_model()->GetWebContentsAt(2)->
489 GetRenderProcessHost()->GetID());
490 EXPECT_NE(process_id_0,
491 browser()->tab_strip_model()->GetWebContentsAt(3)->
492 GetRenderProcessHost()->GetID());
494 // Navigating the second tab out of the app should cause a process swap.
495 const GURL& non_app_url(base_url.Resolve("non_app/main.html"));
496 NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(1),
497 non_app_url);
498 EXPECT_NE(process_id_1,
499 browser()->tab_strip_model()->GetWebContentsAt(1)->
500 GetRenderProcessHost()->GetID());
503 // This test no longer passes, since we don't properly isolate sessionStorage
504 // for isolated apps. This was broken as part of the changes for storage
505 // partition support for webview tags.
506 // TODO(nasko): If isolated apps is no longer developed, this test should be
507 // removed. http://crbug.com/159932
508 IN_PROC_BROWSER_TEST_F(IsolatedAppTest, DISABLED_SessionStorage) {
509 host_resolver()->AddRule("*", "127.0.0.1");
510 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
512 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app1")));
513 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("isolated_apps/app2")));
515 // The app under test acts on URLs whose host is "localhost",
516 // so the URLs we navigate to must have host "localhost".
517 GURL base_url = embedded_test_server()->GetURL("/extensions/isolated_apps/");
518 GURL::Replacements replace_host;
519 replace_host.SetHostStr("localhost");
520 base_url = base_url.ReplaceComponents(replace_host);
522 // Enter some state into sessionStorage three times on the same origin, but
523 // for three URLs that correspond to app1, app2, and a non-isolated site.
524 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
525 ASSERT_TRUE(ExecuteScript(
526 browser()->tab_strip_model()->GetWebContentsAt(0),
527 "window.sessionStorage.setItem('testdata', 'ss_app1');"));
529 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app2/main.html"));
530 ASSERT_TRUE(ExecuteScript(
531 browser()->tab_strip_model()->GetWebContentsAt(0),
532 "window.sessionStorage.setItem('testdata', 'ss_app2');"));
534 ui_test_utils::NavigateToURL(
535 browser(), base_url.Resolve("non_app/main.html"));
536 ASSERT_TRUE(ExecuteScript(
537 browser()->tab_strip_model()->GetWebContentsAt(0),
538 "window.sessionStorage.setItem('testdata', 'ss_normal');"));
540 // Now, ensure that the sessionStorage is correctly partitioned, and persists
541 // when we navigate around all over the dang place.
542 const std::string& kRetrieveSessionStorage =
543 WrapForJavascriptAndExtract(
544 "window.sessionStorage.getItem('testdata') || 'badval'");
545 std::string result;
546 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app1/main.html"));
547 ASSERT_TRUE(ExecuteScriptAndExtractString(
548 browser()->tab_strip_model()->GetWebContentsAt(0),
549 kRetrieveSessionStorage.c_str(), &result));
550 EXPECT_EQ("ss_app1", result);
552 ui_test_utils::NavigateToURL(browser(), base_url.Resolve("app2/main.html"));
553 ASSERT_TRUE(ExecuteScriptAndExtractString(
554 browser()->tab_strip_model()->GetWebContentsAt(0),
555 kRetrieveSessionStorage.c_str(), &result));
556 EXPECT_EQ("ss_app2", result);
558 ui_test_utils::NavigateToURL(
559 browser(), base_url.Resolve("non_app/main.html"));
560 ASSERT_TRUE(ExecuteScriptAndExtractString(
561 browser()->tab_strip_model()->GetWebContentsAt(0),
562 kRetrieveSessionStorage.c_str(), &result));
563 EXPECT_EQ("ss_normal", result);
566 } // namespace
568 } // namespace extensions