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