Add ianwen to watch list for related projects
[chromium-blink-merge.git] / ios / web / browsing_data_partition_impl.mm
blobf15ac55786e951e4a3a2681b1fb39b7c14d89545
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/browsing_data_partition_impl.h"
7 #include "base/logging.h"
8 #include "ios/web/public/browser_state.h"
9 #import "ios/web/public/crw_browsing_data_store.h"
10 #include "ios/web/public/web_thread.h"
12 // A class that observes the |mode| changes in a CRWBrowsingDataStore using KVO.
13 // Maintains a count of all the CRWBrowsingDataStores whose mode is out of sync
14 // with their corresponding ActiveStateManager's active state.
15 @interface CRWBrowsingDataStoreModeObserver : NSObject
17 // The total count of the CRWBrowsingDataStores -- that are being observed --
18 // whose mode is out of sync with their associated ActiveStateManager's active
19 // state.
20 @property(nonatomic, assign) NSUInteger outOfSyncStoreCount;
22 // Adds |browsingDataStore| to the list of the CRWBrowsingDataStores that are
23 // being observed for KVO changes in the |mode| value. |browserState| cannot be
24 // null and the |browserState|'s associated CRWBrowsingDataStore must be
25 // |browsingDataStore|.
26 // The |browsingDataStore|'s mode must not already be |CHANGING|.
27 - (void)startObservingBrowsingDataStore:(CRWBrowsingDataStore*)browsingDataStore
28                            browserState:(web::BrowserState*)browserState;
30 // Stops observing |browsingDataStore| for its |mode| change.
31 // The |browsingDataStore|'s mode must not be |CHANGING|.
32 - (void)stopObservingBrowsingDataStore:(CRWBrowsingDataStore*)browsingDataStore;
33 @end
35 @implementation CRWBrowsingDataStoreModeObserver
37 @synthesize outOfSyncStoreCount = _outOfSyncStoreCount;
39 - (void)startObservingBrowsingDataStore:(CRWBrowsingDataStore*)browsingDataStore
40                            browserState:(web::BrowserState*)browserState {
41   web::BrowsingDataPartition* browsing_data_partition =
42       web::BrowserState::GetBrowsingDataPartition(browserState);
43   DCHECK(browsing_data_partition);
44   DCHECK_EQ(browsing_data_partition->GetBrowsingDataStore(), browsingDataStore);
45   DCHECK_NE(web::CHANGING, browsingDataStore.mode);
47   [browsingDataStore addObserver:self
48                       forKeyPath:@"mode"
49                          options:0
50                          context:browserState];
53 - (void)stopObservingBrowsingDataStore:
54         (CRWBrowsingDataStore*)browsingDataStore {
55   DCHECK_NE(web::CHANGING, browsingDataStore.mode);
57   [browsingDataStore removeObserver:self forKeyPath:@"mode"];
60 - (void)observeValueForKeyPath:(NSString*)keyPath
61                       ofObject:(CRWBrowsingDataStore*)browsingDataStore
62                         change:(NSDictionary*)change
63                        context:(void*)context {
64   DCHECK([keyPath isEqual:@"mode"]);
65   DCHECK([browsingDataStore isKindOfClass:[CRWBrowsingDataStore class]]);
66   DCHECK(context);
68   if (browsingDataStore.mode == web::CHANGING) {
69     ++self.outOfSyncStoreCount;
70     return;
71   }
72   web::BrowserState* browserState = static_cast<web::BrowserState*>(context);
73   web::ActiveStateManager* activeStateManager =
74       web::BrowserState::GetActiveStateManager(browserState);
75   DCHECK(activeStateManager);
76   bool activeState = activeStateManager->IsActive();
77   // Check if the |browsingDataStore|'s associated ActiveStateManager's active
78   // state is still out of sync.
79   if (activeState && browsingDataStore.mode == web::INACTIVE) {
80     [browsingDataStore makeActiveWithCompletionHandler:nil];
81   } else if (!activeState && browsingDataStore.mode == web::ACTIVE) {
82     [browsingDataStore makeInactiveWithCompletionHandler:nil];
83   }
85   DCHECK_GE(self.outOfSyncStoreCount, 1U);
86   --self.outOfSyncStoreCount;
87   // TODO(shreyasv): Have a BrowsingDataPartitionClient be informed when
88   // |self.outOfSyncStoreCount| goes down to 0. crbug.com/480654.
91 @end
93 namespace web {
95 namespace {
96 // The global observer that tracks the number of CRWBrowsingDataStores whose
97 // modes are out of sync with their associated ActiveStateManager's active
98 // state.
99 CRWBrowsingDataStoreModeObserver* g_browsing_data_store_mode_observer = nil;
100 }  // namespace
102 BrowsingDataPartitionImpl::BrowsingDataPartitionImpl(
103     BrowserState* browser_state)
104     : browser_state_(browser_state) {
105   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
106   DCHECK(browser_state);
108   active_state_manager_ = static_cast<ActiveStateManagerImpl*>(
109       BrowserState::GetActiveStateManager(browser_state));
110   DCHECK(active_state_manager_);
111   active_state_manager_->AddObserver(this);
114 BrowsingDataPartitionImpl::~BrowsingDataPartitionImpl() {
115   if (active_state_manager_) {
116     active_state_manager_->RemoveObserver(this);
117   }
118   DCHECK_NE(CHANGING, [browsing_data_store_ mode]);
119   [g_browsing_data_store_mode_observer
120       stopObservingBrowsingDataStore:browsing_data_store_];
123 // static
124 bool BrowsingDataPartition::IsSynchronized() {
125   return [g_browsing_data_store_mode_observer outOfSyncStoreCount] == 0U;
128 CRWBrowsingDataStore* BrowsingDataPartitionImpl::GetBrowsingDataStore() {
129   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
131   if (!browsing_data_store_) {
132     browsing_data_store_.reset(
133         [[CRWBrowsingDataStore alloc] initWithBrowserState:browser_state_]);
134     if (!g_browsing_data_store_mode_observer) {
135       g_browsing_data_store_mode_observer =
136           [[CRWBrowsingDataStoreModeObserver alloc] init];
137     }
138     [g_browsing_data_store_mode_observer
139         startObservingBrowsingDataStore:browsing_data_store_
140                            browserState:browser_state_];
141   }
142   return browsing_data_store_;
145 void BrowsingDataPartitionImpl::OnActive() {
146   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
148   [GetBrowsingDataStore() makeActiveWithCompletionHandler:nil];
151 void BrowsingDataPartitionImpl::OnInactive() {
152   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
154   [GetBrowsingDataStore() makeInactiveWithCompletionHandler:nil];
157 void BrowsingDataPartitionImpl::WillBeDestroyed() {
158   DCHECK_CURRENTLY_ON_WEB_THREAD(WebThread::UI);
160   active_state_manager_->RemoveObserver(this);
161   active_state_manager_ = nullptr;
164 }  // namespace web