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 "ios/web/test/web_test.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "testing/platform_test.h"
20 // An observer to observe the |mode| key changes to a CRWBrowsingDataStore.
21 // Used for testing purposes.
22 @interface CRWTestBrowsingDataStoreObserver : NSObject
23 // The number of times that the mode of the underlying CRWBrowsingDataStore
25 @property(nonatomic, assign) NSUInteger modeChangeCount;
27 // |browsingDataStore| cannot be null.
28 - (instancetype)initWithBrowsingDataStore:
29 (CRWBrowsingDataStore*)browsingDataStore NS_DESIGNATED_INITIALIZER;
30 - (instancetype)init NS_UNAVAILABLE;
33 @implementation CRWTestBrowsingDataStoreObserver {
34 // The underlying CRWBrowsingDataStore.
35 __weak CRWBrowsingDataStore* _browsingDataStore;
38 @synthesize modeChangeCount = _modeChangeCount;
40 - (instancetype)initWithBrowsingDataStore:
41 (CRWBrowsingDataStore*)browsingDataStore {
44 DCHECK(browsingDataStore);
45 [browsingDataStore addObserver:self
49 _browsingDataStore = browsingDataStore;
54 - (instancetype)init {
60 [_browsingDataStore removeObserver:self forKeyPath:@"mode"];
64 - (void)observeValueForKeyPath:(NSString*)keyPath
66 change:(NSDictionary*)change
67 context:(void*)context {
68 DCHECK([keyPath isEqual:@"mode"]);
69 DCHECK_EQ(_browsingDataStore, object);
71 ++self.modeChangeCount;
79 // A test fixture for testing CRWBrowsingDataStore.
80 class BrowsingDataStoreTest : public WebTest {
82 void SetUp() override {
85 BrowserState::GetActiveStateManager(GetBrowserState())->IsActive());
86 browsing_data_store_.reset(
87 [[CRWBrowsingDataStore alloc] initWithBrowserState:GetBrowserState()]);
90 // Sets the mode of the |browsing_data_store_| to |ACTIVE| and blocks until
91 // the mode has actually been changed.
93 [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
96 base::test::ios::WaitUntilCondition(^bool() {
97 return [browsing_data_store_ mode] == ACTIVE;
101 // Sets the mode of the |browsing_data_store_| to |INACTIVE| and blocks until
102 // the mode has actually been changed.
103 void MakeInactive() {
104 [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
107 base::test::ios::WaitUntilCondition(^bool() {
108 return [browsing_data_store_ mode] == INACTIVE;
112 // Removes browsing data of |browsingDataTypes| from the underlying
113 // CRWBrowsingDataStore and waits until the operation finished.
114 void RemoveDataOfTypes(web::BrowsingDataTypes browsing_data_types) {
115 __block BOOL block_was_called = NO;
116 [browsing_data_store_ removeDataOfTypes:browsing_data_types
118 block_was_called = YES;
120 base::test::ios::WaitUntilCondition(^bool() {
121 return block_was_called;
125 // The CRWBrowsingDataStore used for testing purposes.
126 base::scoped_nsobject<CRWBrowsingDataStore> browsing_data_store_;
131 // Tests that a CRWBrowsingDataStore's initial mode is set correctly and that it
132 // has no pending operations.
133 TEST_F(BrowsingDataStoreTest, InitialModeAndNoPendingOperations) {
134 if (!base::ios::IsRunningOnIOS8OrLater()) {
138 EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
139 EXPECT_FALSE([browsing_data_store_ hasPendingOperations]);
142 // Tests that CRWBrowsingDataStore handles several consecutive calls to
143 // |makeActive| and |makeInactive| correctly.
144 TEST_F(BrowsingDataStoreTest, MakeActiveAndInactiveOperations) {
145 if (!base::ios::IsRunningOnIOS8OrLater()) {
150 base::scoped_nsobject<CRWTestBrowsingDataStoreObserver> observer(
151 [[CRWTestBrowsingDataStoreObserver alloc]
152 initWithBrowsingDataStore:browsing_data_store_]);
153 EXPECT_EQ(0U, [observer modeChangeCount]);
155 __block int callbacks_received_count = 0;
156 void (^unsucessfullCallback)(BOOL) = ^(BOOL success) {
157 ASSERT_TRUE([NSThread isMainThread]);
158 ++callbacks_received_count;
159 BrowsingDataStoreMode mode = [browsing_data_store_ mode];
160 EXPECT_FALSE(success);
161 EXPECT_EQ(CHANGING, mode);
164 [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
165 EXPECT_EQ(0, callbacks_received_count);
166 unsucessfullCallback(success);
168 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
169 EXPECT_EQ(1U, [observer modeChangeCount]);
171 [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
172 EXPECT_EQ(1, callbacks_received_count);
173 unsucessfullCallback(success);
175 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
177 [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
178 EXPECT_EQ(2, callbacks_received_count);
179 unsucessfullCallback(success);
181 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
183 __block BOOL block_was_called = NO;
184 [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
185 ASSERT_TRUE([NSThread isMainThread]);
186 EXPECT_EQ(3, callbacks_received_count);
187 BrowsingDataStoreMode mode = [browsing_data_store_ mode];
188 EXPECT_TRUE(success);
189 EXPECT_EQ(INACTIVE, mode);
190 block_was_called = YES;
192 EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
194 base::test::ios::WaitUntilCondition(^bool{
195 return block_was_called;
198 EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);
199 EXPECT_EQ(2U, [observer modeChangeCount]);
202 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:|.
203 TEST_F(BrowsingDataStoreTest, RemoveDataOperations) {
204 if (!base::ios::IsRunningOnIOS8OrLater()) {
208 ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
209 // |removeDataOfTypes| is called when the mode was ACTIVE.
210 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
213 ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
214 // |removeDataOfTypes| is called when the mode was INACTIVE.
215 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
218 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
219 // a |makeActive| call.
220 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeActiveCall) {
221 if (!base::ios::IsRunningOnIOS8OrLater()) {
226 ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
228 [browsing_data_store_ makeActiveWithCompletionHandler:nil];
229 // |removeDataOfTypes| is called immediately after a |makeActive| call.
230 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
231 EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
234 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
235 // a |makeActive| call.
236 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeInactiveCall) {
237 if (!base::ios::IsRunningOnIOS8OrLater()) {
241 ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
243 [browsing_data_store_ makeInactiveWithCompletionHandler:nil];
244 // |removeDataOfTypes| is called immediately after a |makeInactive| call.
245 RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
246 EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);