blob: 763736b606a3a88be54a7fa252978de0bc9aea01 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <WebKit/WebKit.h>
#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/mac/foundation_util.h"
#import "base/test/ios/wait_util.h"
#import "ios/web/common/web_view_creation_util.h"
#include "ios/web/public/browser_state.h"
#import "ios/web/public/test/js_test_util.h"
#import "ios/web/test/web_int_test.h"
#import "net/base/mac/url_conversions.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using base::test::ios::kWaitForPageLoadTimeout;
using base::test::ios::WaitUntilConditionOrTimeout;
// A WKNavigationDelegate that is used to check if a WKWebView has finished
// a navigation. Used for testing purposes.
@interface FakeNavigationDelegate : NSObject<WKNavigationDelegate>
// YES if a navigation has finished.
@property (nonatomic, assign) BOOL didFinishNavigation;
@end
@implementation FakeNavigationDelegate
@synthesize didFinishNavigation = _didFinishNavigation;
- (void)webView:(WKWebView*)webView
didFinishNavigation:(WKNavigation*)navigation {
self.didFinishNavigation = YES;
}
@end
namespace web {
// A test fixture for testing that browsing data is partitioned between
// web views created with a non-OTR BrowserState and web views created with an
// OTR BrowserState.
class BrowserStateWebViewPartitionTest : public WebIntTest {
protected:
BrowserStateWebViewPartitionTest() = default;
void SetUp() override {
WebIntTest::SetUp();
otr_browser_state_.SetOffTheRecord(true);
RegisterDefaultHandlers(&server_);
ASSERT_TRUE(server_.Start());
}
// Sets a persistent cookie with key, value on |web_view|.
void SetCookie(NSString* key, NSString* value, WKWebView* web_view) {
NSString* set_cookie = [NSString
stringWithFormat:@"document.cookie='%@=%@;"
@"Expires=Tue, 05-May-9999 02:18:23 GMT; Path=/'",
key, value];
web::test::ExecuteJavaScript(web_view, set_cookie);
}
// Returns a csv list of all cookies from |web_view|.
NSString* GetCookies(WKWebView* web_view) {
id result = web::test::ExecuteJavaScript(web_view, @"document.cookie");
return base::mac::ObjCCastStrict<NSString>(result);
}
// Sets a localstorage key, value pair on |web_view|.
void SetLocalStorageItem(NSString* key,
NSString* value,
WKWebView* web_view) {
NSString* set_local_storage_item = [NSString
stringWithFormat:@"localStorage.setItem('%@', '%@')", key, value];
NSError* unused_error = nil;
web::test::ExecuteJavaScript(web_view, set_local_storage_item,
&unused_error);
}
// Returns the localstorage value associated with |key| from |web_view|.
id GetLocalStorageItem(NSString* key, WKWebView* web_view) {
NSString* get_local_storage_value =
[NSString stringWithFormat:@"localStorage.getItem('%@');", key];
return web::test::ExecuteJavaScript(web_view, get_local_storage_value);
}
// Loads a test web page (that contains a small string) in |web_view| and
// waits until the web view has finished the navigation.
bool LoadTestWebPage(WKWebView* web_view) WARN_UNUSED_RESULT {
FakeNavigationDelegate* navigation_delegate =
[[FakeNavigationDelegate alloc] init];
id old_navigation_delegate = web_view.navigationDelegate;
web_view.navigationDelegate = navigation_delegate;
NSURL* url = net::NSURLWithGURL(server_.GetURL("/echo"));
[web_view loadRequest:[NSURLRequest requestWithURL:url]];
bool result = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^bool {
return navigation_delegate.didFinishNavigation;
});
web_view.navigationDelegate = old_navigation_delegate;
return result;
}
protected:
net::EmbeddedTestServer server_;
TestBrowserState otr_browser_state_;
DISALLOW_COPY_AND_ASSIGN(BrowserStateWebViewPartitionTest);
};
// Tests that cookies are partitioned between web views created with a
// non-OTR BrowserState and an OTR BrowserState.
TEST_F(BrowserStateWebViewPartitionTest, Cookies) {
WKWebView* web_view_1 = BuildWKWebView(CGRectZero, GetBrowserState());
ASSERT_TRUE(LoadTestWebPage(web_view_1));
SetCookie(@"someCookieName1", @"someCookieValue1", web_view_1);
ASSERT_NSEQ(@"someCookieName1=someCookieValue1", GetCookies(web_view_1));
WKWebView* web_view_2 = BuildWKWebView(CGRectZero, &otr_browser_state_);
ASSERT_TRUE(LoadTestWebPage(web_view_2));
// Test that the cookie has not leaked over to |web_view_2|.
ASSERT_NSEQ(@"", GetCookies(web_view_2));
SetCookie(@"someCookieName2", @"someCookieValue2", web_view_2);
EXPECT_NSEQ(@"someCookieName2=someCookieValue2", GetCookies(web_view_2));
// Test that the cookie has not leaked over to |web_view_1|.
NSString* cookies = GetCookies(web_view_1);
EXPECT_FALSE([cookies containsString:@"someCookieName2"]);
}
// Tests that localStorage is partitioned between web views created with a
// non-OTR BrowserState and an OTR BrowserState.
TEST_F(BrowserStateWebViewPartitionTest, LocalStorage) {
WKWebView* web_view_1 = BuildWKWebView(CGRectZero, GetBrowserState());
ASSERT_TRUE(LoadTestWebPage(web_view_1));
SetLocalStorageItem(@"someKey1", @"someValue1", web_view_1);
EXPECT_NSEQ(@"someValue1", GetLocalStorageItem(@"someKey1", web_view_1));
WKWebView* web_view_2 = BuildWKWebView(CGRectZero, &otr_browser_state_);
ASSERT_TRUE(LoadTestWebPage(web_view_2));
// Test that LocalStorage has not leaked over to |web_view_2|.
EXPECT_NSEQ([NSNull null], GetLocalStorageItem(@"someKey1", web_view_2));
SetLocalStorageItem(@"someKey2", @"someValue2", web_view_2);
// Due to platform limitation, it's not possible to actually set localStorage
// item on an OTR BrowserState. Therefore, it's not possible to verify that a
// localStorage item has been correctly set.
// Look at
// http://stackoverflow.com/questions/14555347/html5-localstorage-error-with-safari-quota-exceeded-err-dom-exception-22-an
// for more details.
// Test that LocalStorage has not leaked over to |web_view_1|.
EXPECT_NSEQ([NSNull null], GetLocalStorageItem(@"someKey2", web_view_1));
}
} // namespace web