browser_state_web_view_partition_inttest.mm 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright 2015 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. #import <WebKit/WebKit.h>
  5. #include <memory>
  6. #include <string>
  7. #include "base/mac/foundation_util.h"
  8. #import "base/test/ios/wait_util.h"
  9. #import "ios/web/common/web_view_creation_util.h"
  10. #include "ios/web/public/browser_state.h"
  11. #import "ios/web/public/test/js_test_util.h"
  12. #import "ios/web/test/web_int_test.h"
  13. #import "net/base/mac/url_conversions.h"
  14. #include "net/test/embedded_test_server/default_handlers.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #import "testing/gtest_mac.h"
  17. #if !defined(__has_feature) || !__has_feature(objc_arc)
  18. #error "This file requires ARC support."
  19. #endif
  20. using base::test::ios::kWaitForPageLoadTimeout;
  21. using base::test::ios::WaitUntilConditionOrTimeout;
  22. // A WKNavigationDelegate that is used to check if a WKWebView has finished
  23. // a navigation. Used for testing purposes.
  24. @interface FakeNavigationDelegate : NSObject<WKNavigationDelegate>
  25. // YES if a navigation has finished.
  26. @property (nonatomic, assign) BOOL didFinishNavigation;
  27. @end
  28. @implementation FakeNavigationDelegate
  29. @synthesize didFinishNavigation = _didFinishNavigation;
  30. - (void)webView:(WKWebView*)webView
  31. didFinishNavigation:(WKNavigation*)navigation {
  32. self.didFinishNavigation = YES;
  33. }
  34. @end
  35. namespace web {
  36. // A test fixture for testing that browsing data is partitioned between
  37. // web views created with a non-OTR BrowserState and web views created with an
  38. // OTR BrowserState.
  39. class BrowserStateWebViewPartitionTest : public WebIntTest {
  40. protected:
  41. BrowserStateWebViewPartitionTest() = default;
  42. BrowserStateWebViewPartitionTest(const BrowserStateWebViewPartitionTest&) =
  43. delete;
  44. BrowserStateWebViewPartitionTest& operator=(
  45. const BrowserStateWebViewPartitionTest&) = delete;
  46. void SetUp() override {
  47. WebIntTest::SetUp();
  48. otr_browser_state_.SetOffTheRecord(true);
  49. RegisterDefaultHandlers(&server_);
  50. ASSERT_TRUE(server_.Start());
  51. }
  52. // Sets a persistent cookie with key, value on |web_view|.
  53. void SetCookie(NSString* key, NSString* value, WKWebView* web_view) {
  54. NSString* set_cookie = [NSString
  55. stringWithFormat:@"document.cookie='%@=%@;"
  56. @"Expires=Tue, 05-May-9999 02:18:23 GMT; Path=/'",
  57. key, value];
  58. web::test::ExecuteJavaScript(web_view, set_cookie);
  59. }
  60. // Returns a csv list of all cookies from |web_view|.
  61. NSString* GetCookies(WKWebView* web_view) {
  62. id result = web::test::ExecuteJavaScript(web_view, @"document.cookie");
  63. return base::mac::ObjCCastStrict<NSString>(result);
  64. }
  65. // Sets a localstorage key, value pair on |web_view|.
  66. void SetLocalStorageItem(NSString* key,
  67. NSString* value,
  68. WKWebView* web_view) {
  69. NSString* set_local_storage_item = [NSString
  70. stringWithFormat:@"localStorage.setItem('%@', '%@')", key, value];
  71. NSError* unused_error = nil;
  72. web::test::ExecuteJavaScript(web_view, set_local_storage_item,
  73. &unused_error);
  74. }
  75. // Returns the localstorage value associated with |key| from |web_view|.
  76. id GetLocalStorageItem(NSString* key, WKWebView* web_view) {
  77. NSString* get_local_storage_value =
  78. [NSString stringWithFormat:@"localStorage.getItem('%@');", key];
  79. return web::test::ExecuteJavaScript(web_view, get_local_storage_value);
  80. }
  81. // Loads a test web page (that contains a small string) in |web_view| and
  82. // waits until the web view has finished the navigation.
  83. [[nodiscard]] bool LoadTestWebPage(WKWebView* web_view) {
  84. FakeNavigationDelegate* navigation_delegate =
  85. [[FakeNavigationDelegate alloc] init];
  86. id old_navigation_delegate = web_view.navigationDelegate;
  87. web_view.navigationDelegate = navigation_delegate;
  88. NSURL* url = net::NSURLWithGURL(server_.GetURL("/echo"));
  89. [web_view loadRequest:[NSURLRequest requestWithURL:url]];
  90. bool result = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^bool {
  91. return navigation_delegate.didFinishNavigation;
  92. });
  93. web_view.navigationDelegate = old_navigation_delegate;
  94. return result;
  95. }
  96. protected:
  97. net::EmbeddedTestServer server_;
  98. FakeBrowserState otr_browser_state_;
  99. };
  100. // Tests that cookies are partitioned between web views created with a
  101. // non-OTR BrowserState and an OTR BrowserState.
  102. TEST_F(BrowserStateWebViewPartitionTest, Cookies) {
  103. WKWebView* web_view_1 = BuildWKWebView(CGRectZero, GetBrowserState());
  104. ASSERT_TRUE(LoadTestWebPage(web_view_1));
  105. SetCookie(@"someCookieName1", @"someCookieValue1", web_view_1);
  106. ASSERT_NSEQ(@"someCookieName1=someCookieValue1", GetCookies(web_view_1));
  107. WKWebView* web_view_2 = BuildWKWebView(CGRectZero, &otr_browser_state_);
  108. ASSERT_TRUE(LoadTestWebPage(web_view_2));
  109. // Test that the cookie has not leaked over to |web_view_2|.
  110. ASSERT_NSEQ(@"", GetCookies(web_view_2));
  111. SetCookie(@"someCookieName2", @"someCookieValue2", web_view_2);
  112. EXPECT_NSEQ(@"someCookieName2=someCookieValue2", GetCookies(web_view_2));
  113. // Test that the cookie has not leaked over to |web_view_1|.
  114. NSString* cookies = GetCookies(web_view_1);
  115. EXPECT_FALSE([cookies containsString:@"someCookieName2"]);
  116. }
  117. // Tests that localStorage is partitioned between web views created with a
  118. // non-OTR BrowserState and an OTR BrowserState.
  119. TEST_F(BrowserStateWebViewPartitionTest, LocalStorage) {
  120. WKWebView* web_view_1 = BuildWKWebView(CGRectZero, GetBrowserState());
  121. ASSERT_TRUE(LoadTestWebPage(web_view_1));
  122. SetLocalStorageItem(@"someKey1", @"someValue1", web_view_1);
  123. EXPECT_NSEQ(@"someValue1", GetLocalStorageItem(@"someKey1", web_view_1));
  124. WKWebView* web_view_2 = BuildWKWebView(CGRectZero, &otr_browser_state_);
  125. ASSERT_TRUE(LoadTestWebPage(web_view_2));
  126. // Test that LocalStorage has not leaked over to |web_view_2|.
  127. EXPECT_NSEQ([NSNull null], GetLocalStorageItem(@"someKey1", web_view_2));
  128. SetLocalStorageItem(@"someKey2", @"someValue2", web_view_2);
  129. // Due to platform limitation, it's not possible to actually set localStorage
  130. // item on an OTR BrowserState. Therefore, it's not possible to verify that a
  131. // localStorage item has been correctly set.
  132. // Look at
  133. // http://stackoverflow.com/questions/14555347/html5-localstorage-error-with-safari-quota-exceeded-err-dom-exception-22-an
  134. // for more details.
  135. // Test that LocalStorage has not leaked over to |web_view_1|.
  136. EXPECT_NSEQ([NSNull null], GetLocalStorageItem(@"someKey2", web_view_1));
  137. }
  138. } // namespace web