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.
5 #import "ios/web/public/crw_browsing_data_store.h"
7 #include "base/ios/ios_util.h"
8 #include "base/logging.h"
9 #import "base/mac/scoped_nsobject.h"
10 #include "base/memory/scoped_ptr.h"
11 #import "base/test/ios/wait_util.h"
12 #include "ios/web/public/active_state_manager.h"
13 #include "ios/web/public/browser_state.h"
14 #include "ios/web/public/test/test_browser_state.h"
15 #include "ios/web/public/test/test_web_thread_bundle.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
19 // An observer to observe the |mode| key changes to a CRWBrowsingDataStore.
20 // Used for testing purposes.
21 @interface CRWTestBrowsingDataStoreObserver : NSObject
22 // Designated init. |browsingDataStore| cannot be null.
23 - (instancetype)initWithBrowsingDataStore:
24 (CRWBrowsingDataStore*)browsingDataStore NS_DESIGNATED_INITIALIZER;
25 - (instancetype)init NS_UNAVAILABLE;
26 // The number of times that the mode of the underlying CRWBrowsingDataStore
28 @property(nonatomic, assign) NSUInteger modeChangeCount;
31 @implementation CRWTestBrowsingDataStoreObserver {
32 // The underlying CRWBrowsingDataStore.
33 __weak CRWBrowsingDataStore* _browsingDataStore;
36 @synthesize modeChangeCount = _modeChangeCount;
38 - (instancetype)initWithBrowsingDataStore:
39 (CRWBrowsingDataStore*)browsingDataStore {
42 DCHECK(browsingDataStore);
43 [browsingDataStore addObserver:self
47 _browsingDataStore = browsingDataStore;
52 - (instancetype)init {
57 - (void)observeValueForKeyPath:(NSString*)keyPath
59 change:(NSDictionary*)change
60 context:(void*)context {
61 DCHECK([keyPath isEqual:@"mode"]);
62 DCHECK_EQ(_browsingDataStore, object);
64 ++self.modeChangeCount;
68 [_browsingDataStore removeObserver:self forKeyPath:@"mode"];
77 class BrowsingDataStoreTest : public PlatformTest {
79 void SetUp() override {
80 PlatformTest::SetUp();
81 browser_state_.reset(new TestBrowserState());
82 BrowserState::GetActiveStateManager(browser_state_.get())->SetActive(true);
83 browsing_data_store_.reset([[CRWBrowsingDataStore alloc]
84 initWithBrowserState:browser_state_.get()]);
86 void TearDown() override {
87 // The BrowserState needs to be destroyed first so that it is outlived by
88 // the WebThreadBundle.
89 BrowserState::GetActiveStateManager(browser_state_.get())->SetActive(false);
90 browser_state_.reset();
91 PlatformTest::TearDown();
94 // Sets the mode of the |browsing_data_store_| to |ACTIVE| and blocks until
95 // the mode has actually been changed.
97 [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
100 base::test::ios::WaitUntilCondition(^bool() {
101 return [browsing_data_store_ mode] == ACTIVE;
105 // Sets the mode of the |browsing_data_store_| to |INACTIVE| and blocks until
106 // the mode has actually been changed.
107 void MakeInactive() {
108 [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
111 base::test::ios::WaitUntilCondition(^bool() {
112 return [browsing_data_store_ mode] == INACTIVE;
116 // Removes browsing data of |browsingDataTypes| from the underlying
117 // CRWBrowsingDataStore and waits until the operation finished.
118 void RemoveDataOfTypes(web::BrowsingDataTypes browsing_data_types) {
119 __block BOOL block_was_called = NO;
120 [browsing_data_store_ removeDataOfTypes:browsing_data_types
122 block_was_called = YES;
124 base::test::ios::WaitUntilCondition(^bool() {
125 return block_was_called;
129 // The CRWBrowsingDataStore used for testing purposes.
130 base::scoped_nsobject<CRWBrowsingDataStore> browsing_data_store_;
133 // The WebThreadBundle used for testing purposes.
134 TestWebThreadBundle thread_bundle_;
135 // The BrowserState used for testing purposes.
136 scoped_ptr<BrowserState> browser_state_;
141 // Tests that a CRWBrowsingDataStore's initial mode is set correctly and that it
142 // has no pending operations.
143 TEST_F(BrowsingDataStoreTest, InitialModeAndNoPendingOperations) {
144 if (!base::ios::IsRunningOnIOS8OrLater()) {
148 EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
149 EXPECT_FALSE([browsing_data_store_ hasPendingOperations]);
152 // Tests that CRWBrowsingDataStore handles several consecutive calls to
153 // |makeActive| and |makeInactive| correctly.
154 // TODO(shreyasv): This test is flaky. http://crbug.com/504812
155 TEST_F(BrowsingDataStoreTest, FLAKY_MakeActiveAndInactiveOperations) {
156 if (!base::ios::IsRunningOnIOS8OrLater()) {
161 base::scoped_nsobject<CRWTestBrowsingDataStoreObserver> observer(
162 [[CRWTestBrowsingDataStoreObserver alloc]
163 initWithBrowsingDataStore:browsing_data_store_]);
164 EXPECT_EQ(0U, [observer modeChangeCount]);
166 id unsucessfullCallback = ^(BOOL success) {
167 ASSERT_TRUE([NSThread isMainThread]);
168 BrowsingDataStoreMode mode = [browsing_data_store_ mode];
169 EXPECT_FALSE(success);
170 EXPECT_EQ(CHANGING, mode);
172 [browsing_data_store_ makeActiveWithCompletionHandler:unsucessfullCallback];
173 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
174 EXPECT_EQ(1U, [observer modeChangeCount]);
176 [browsing_data_store_ makeInactiveWithCompletionHandler:unsucessfullCallback];
177 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
179 [browsing_data_store_ makeActiveWithCompletionHandler:unsucessfullCallback];
180 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
182 __block BOOL block_was_called = NO;
183 [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
184 ASSERT_TRUE([NSThread isMainThread]);
185 BrowsingDataStoreMode mode = [browsing_data_store_ mode];
186 EXPECT_TRUE(success);
187 EXPECT_EQ(INACTIVE, mode);
188 block_was_called = YES;
190 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
192 base::test::ios::WaitUntilCondition(^bool{
193 return block_was_called;
196 EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);
197 EXPECT_EQ(2U, [observer modeChangeCount]);
200 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:|.
201 TEST_F(BrowsingDataStoreTest, RemoveDataOperations) {
202 if (!base::ios::IsRunningOnIOS8OrLater()) {
206 ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
207 // |removeDataOfTypes| is called when the mode was ACTIVE.
208 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
211 ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
212 // |removeDataOfTypes| is called when the mode was INACTIVE.
213 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
216 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
217 // a |makeActive| call.
218 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeActiveCall) {
219 if (!base::ios::IsRunningOnIOS8OrLater()) {
224 ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
226 [browsing_data_store_ makeActiveWithCompletionHandler:nil];
227 // |removeDataOfTypes| is called immediately after a |makeActive| call.
228 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
229 EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
232 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
233 // a |makeActive| call.
234 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeInactiveCall) {
235 if (!base::ios::IsRunningOnIOS8OrLater()) {
239 ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
241 [browsing_data_store_ makeInactiveWithCompletionHandler:nil];
242 // |removeDataOfTypes| is called immediately after a |makeInactive| call.
243 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
244 EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);