1// Copyright 2014 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
5#include <vector>
6
7#include "base/files/scoped_temp_dir.h"
8#include "base/message_loop/message_loop.h"
9#include "base/message_loop/message_loop_proxy.h"
10#include "base/run_loop.h"
11#include "content/public/test/mock_special_storage_policy.h"
12#include "content/public/test/mock_storage_client.h"
13#include "net/base/net_util.h"
14#include "storage/browser/quota/quota_manager.h"
15#include "storage/browser/quota/quota_manager_proxy.h"
16#include "storage/browser/quota/storage_monitor.h"
17#include "storage/browser/quota/storage_observer.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using storage::HostStorageObservers;
21using storage::kQuotaErrorNotSupported;
22using storage::kQuotaStatusOk;
23using storage::kStorageTypePersistent;
24using storage::kStorageTypeTemporary;
25using storage::QuotaClient;
26using storage::QuotaManager;
27using storage::QuotaStatusCode;
28using storage::SpecialStoragePolicy;
29using storage::StorageMonitor;
30using storage::StorageObserver;
31using storage::StorageObserverList;
32using storage::StorageType;
33using storage::StorageTypeObservers;
34
35namespace content {
36
37namespace {
38
39const char kDefaultOrigin[] = "http://www.foo.com/";
40const char kAlternativeOrigin[] = "http://www.bar.com/";
41
42class MockObserver : public StorageObserver {
43 public:
44  const StorageObserver::Event& LastEvent() const {
45    CHECK(!events_.empty());
46    return events_.back();
47  }
48
49  int EventCount() const {
50    return events_.size();
51  }
52
53  // StorageObserver implementation:
54  virtual void OnStorageEvent(const StorageObserver::Event& event) OVERRIDE {
55    events_.push_back(event);
56  }
57
58 private:
59  std::vector<StorageObserver::Event> events_;
60};
61
62// A mock quota manager for overriding GetUsageAndQuotaForWebApps().
63class UsageMockQuotaManager : public QuotaManager {
64 public:
65  UsageMockQuotaManager(SpecialStoragePolicy* special_storage_policy)
66      : QuotaManager(
67            false,
68            base::FilePath(),
69            base::MessageLoopProxy::current().get(),
70            base::MessageLoopProxy::current().get(),
71            special_storage_policy),
72        callback_usage_(0),
73        callback_quota_(0),
74        callback_status_(kQuotaStatusOk),
75        initialized_(false) {
76  }
77
78  void SetCallbackParams(int64 usage, int64 quota, QuotaStatusCode status) {
79    initialized_ = true;
80    callback_quota_ = quota;
81    callback_usage_ = usage;
82    callback_status_ = status;
83  }
84
85  void InvokeCallback() {
86    delayed_callback_.Run(callback_status_, callback_usage_, callback_quota_);
87  }
88
89  virtual void GetUsageAndQuotaForWebApps(
90      const GURL& origin,
91      StorageType type,
92      const GetUsageAndQuotaCallback& callback) OVERRIDE {
93    if (initialized_)
94      callback.Run(callback_status_, callback_usage_, callback_quota_);
95    else
96      delayed_callback_ = callback;
97  }
98
99 protected:
100  virtual ~UsageMockQuotaManager() {}
101
102 private:
103  int64 callback_usage_;
104  int64 callback_quota_;
105  QuotaStatusCode callback_status_;
106  bool initialized_;
107  GetUsageAndQuotaCallback delayed_callback_;
108};
109
110}  // namespace
111
112class StorageMonitorTestBase : public testing::Test {
113 protected:
114  void DispatchPendingEvents(StorageObserverList& observer_list) {
115    observer_list.DispatchPendingEvent();
116  }
117
118  const StorageObserver::Event* GetPendingEvent(
119      const StorageObserverList& observer_list) {
120    return observer_list.notification_timer_.IsRunning()
121                ? &observer_list.pending_event_ : NULL;
122  }
123
124  const StorageObserver::Event* GetPendingEvent(
125      const HostStorageObservers& host_observers) {
126    return GetPendingEvent(host_observers.observers_);
127  }
128
129  int GetRequiredUpdatesCount(const StorageObserverList& observer_list) {
130    int count = 0;
131    for (StorageObserverList::StorageObserverStateMap::const_iterator it =
132            observer_list.observers_.begin();
133         it != observer_list.observers_.end(); ++it) {
134      if (it->second.requires_update)
135        ++count;
136    }
137
138    return count;
139  }
140
141  int GetRequiredUpdatesCount(const HostStorageObservers& host_observers) {
142    return GetRequiredUpdatesCount(host_observers.observers_);
143  }
144
145  void SetLastNotificationTime(StorageObserverList& observer_list,
146                               StorageObserver* observer) {
147    ASSERT_TRUE(observer_list.observers_.find(observer) !=
148                observer_list.observers_.end());
149
150    StorageObserverList::ObserverState& state =
151        observer_list.observers_[observer];
152    state.last_notification_time = base::TimeTicks::Now() - state.rate;
153  }
154
155  void SetLastNotificationTime(HostStorageObservers& host_observers,
156                               StorageObserver* observer) {
157    SetLastNotificationTime(host_observers.observers_, observer);
158  }
159
160  int GetObserverCount(const HostStorageObservers& host_observers) {
161    return host_observers.observers_.ObserverCount();
162  }
163};
164
165class StorageTestWithManagerBase : public StorageMonitorTestBase {
166 public:
167  virtual void SetUp() OVERRIDE {
168    storage_policy_ = new MockSpecialStoragePolicy();
169    quota_manager_ = new UsageMockQuotaManager(storage_policy_.get());
170  }
171
172  virtual void TearDown() OVERRIDE {
173    // This ensures the quota manager is destroyed correctly.
174    quota_manager_ = NULL;
175    base::RunLoop().RunUntilIdle();
176  }
177
178 protected:
179  base::MessageLoop message_loop_;
180  scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
181  scoped_refptr<UsageMockQuotaManager> quota_manager_;
182};
183
184// Tests for StorageObserverList:
185
186typedef StorageMonitorTestBase StorageObserverListTest;
187
188// Test dispatching events to one observer.
189TEST_F(StorageObserverListTest, DispatchEventToSingleObserver) {
190  // A message loop is required as StorageObserverList may schedule jobs.
191  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
192
193  StorageObserver::MonitorParams params(kStorageTypePersistent,
194                                        GURL(kDefaultOrigin),
195                                        base::TimeDelta::FromHours(1),
196                                        false);
197  MockObserver mock_observer;
198  StorageObserverList observer_list;
199  observer_list.AddObserver(&mock_observer, params);
200
201  StorageObserver::Event event;
202  event.filter = params.filter;
203
204  // Verify that the first event is dispatched immediately.
205  event.quota = 1;
206  event.usage = 1;
207  observer_list.OnStorageChange(event);
208  EXPECT_EQ(1, mock_observer.EventCount());
209  EXPECT_EQ(event, mock_observer.LastEvent());
210  EXPECT_EQ(NULL, GetPendingEvent(observer_list));
211  EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list));
212
213  // Verify that the next event is pending.
214  event.quota = 2;
215  event.usage = 2;
216  observer_list.OnStorageChange(event);
217  EXPECT_EQ(1, mock_observer.EventCount());
218  ASSERT_TRUE(GetPendingEvent(observer_list));
219  EXPECT_EQ(event, *GetPendingEvent(observer_list));
220  EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list));
221
222  // Fake the last notification time so that an event will be dispatched.
223  SetLastNotificationTime(observer_list, &mock_observer);
224  event.quota = 3;
225  event.usage = 3;
226  observer_list.OnStorageChange(event);
227  EXPECT_EQ(2, mock_observer.EventCount());
228  EXPECT_EQ(event, mock_observer.LastEvent());
229  EXPECT_EQ(NULL, GetPendingEvent(observer_list));
230  EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list));
231
232  // Remove the observer.
233  event.quota = 4;
234  event.usage = 4;
235  observer_list.RemoveObserver(&mock_observer);
236  observer_list.OnStorageChange(event);
237  EXPECT_EQ(2, mock_observer.EventCount());
238  EXPECT_EQ(NULL, GetPendingEvent(observer_list));
239}
240
241// Test dispatching events to multiple observers.
242TEST_F(StorageObserverListTest, DispatchEventToMultipleObservers) {
243  // A message loop is required as StorageObserverList may schedule jobs.
244  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
245
246  MockObserver mock_observer1;
247  MockObserver mock_observer2;
248  StorageObserverList observer_list;
249  StorageObserver::Filter filter(kStorageTypePersistent,
250                                 GURL(kDefaultOrigin));
251  observer_list.AddObserver(
252      &mock_observer1,
253      StorageObserver::MonitorParams(
254          filter, base::TimeDelta::FromHours(1), false));
255  observer_list.AddObserver(
256      &mock_observer2,
257      StorageObserver::MonitorParams(
258          filter, base::TimeDelta::FromHours(2), false));
259
260  StorageObserver::Event event;
261  event.filter = filter;
262
263  // Verify that the first event is dispatched immediately.
264  event.quota = 1;
265  event.usage = 1;
266  observer_list.OnStorageChange(event);
267  EXPECT_EQ(1, mock_observer1.EventCount());
268  EXPECT_EQ(1, mock_observer2.EventCount());
269  EXPECT_EQ(event, mock_observer1.LastEvent());
270  EXPECT_EQ(event, mock_observer2.LastEvent());
271  EXPECT_EQ(NULL, GetPendingEvent(observer_list));
272  EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list));
273
274  // Fake the last notification time so that observer1 will receive the next
275  // event, but it will be pending for observer2.
276  SetLastNotificationTime(observer_list, &mock_observer1);
277  event.quota = 2;
278  event.usage = 2;
279  observer_list.OnStorageChange(event);
280  EXPECT_EQ(2, mock_observer1.EventCount());
281  EXPECT_EQ(1, mock_observer2.EventCount());
282  EXPECT_EQ(event, mock_observer1.LastEvent());
283  ASSERT_TRUE(GetPendingEvent(observer_list));
284  EXPECT_EQ(event, *GetPendingEvent(observer_list));
285  EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list));
286
287  // Now dispatch the pending event to observer2.
288  SetLastNotificationTime(observer_list, &mock_observer2);
289  DispatchPendingEvents(observer_list);
290  EXPECT_EQ(2, mock_observer1.EventCount());
291  EXPECT_EQ(2, mock_observer2.EventCount());
292  EXPECT_EQ(event, mock_observer1.LastEvent());
293  EXPECT_EQ(event, mock_observer2.LastEvent());
294  EXPECT_EQ(NULL, GetPendingEvent(observer_list));
295  EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list));
296}
297
298// Ensure that the |origin| field in events match the origin specified by the
299// observer on registration.
300TEST_F(StorageObserverListTest, ReplaceEventOrigin) {
301  StorageObserver::MonitorParams params(kStorageTypePersistent,
302                                        GURL(kDefaultOrigin),
303                                        base::TimeDelta::FromHours(1),
304                                        false);
305  MockObserver mock_observer;
306  StorageObserverList observer_list;
307  observer_list.AddObserver(&mock_observer, params);
308
309  StorageObserver::Event dispatched_event;
310  dispatched_event.filter = params.filter;
311  dispatched_event.filter.origin = GURL("https://www.foo.com/bar");
312  observer_list.OnStorageChange(dispatched_event);
313
314  EXPECT_EQ(params.filter.origin, mock_observer.LastEvent().filter.origin);
315}
316
317// Tests for HostStorageObservers:
318
319typedef StorageTestWithManagerBase HostStorageObserversTest;
320
321// Verify that HostStorageObservers is initialized after the first usage change.
322TEST_F(HostStorageObserversTest, InitializeOnUsageChange) {
323  StorageObserver::MonitorParams params(kStorageTypePersistent,
324                                        GURL(kDefaultOrigin),
325                                        base::TimeDelta::FromHours(1),
326                                        false);
327  const int64 kUsage = 324554;
328  const int64 kQuota = 234354354;
329  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
330
331  MockObserver mock_observer;
332  HostStorageObservers host_observers(quota_manager_.get());
333  host_observers.AddObserver(&mock_observer, params);
334
335  // Verify that HostStorageObservers dispatches the first event correctly.
336  StorageObserver::Event expected_event(params.filter, kUsage, kQuota);
337  host_observers.NotifyUsageChange(params.filter, 87324);
338  EXPECT_EQ(1, mock_observer.EventCount());
339  EXPECT_EQ(expected_event, mock_observer.LastEvent());
340  EXPECT_TRUE(host_observers.is_initialized());
341
342  // Verify that HostStorageObservers handles subsequent usage changes
343  // correctly.
344  const int64 kDelta = 2345;
345  expected_event.usage += kDelta;
346  SetLastNotificationTime(host_observers, &mock_observer);
347  host_observers.NotifyUsageChange(params.filter, kDelta);
348  EXPECT_EQ(2, mock_observer.EventCount());
349  EXPECT_EQ(expected_event, mock_observer.LastEvent());
350}
351
352// Verify that HostStorageObservers is initialized after the adding the first
353// observer that elected to receive the initial state.
354TEST_F(HostStorageObserversTest, InitializeOnObserver) {
355  const int64 kUsage = 74387;
356  const int64 kQuota = 92834743;
357  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
358  HostStorageObservers host_observers(quota_manager_.get());
359
360  // |host_observers| should not be initialized after the first observer is
361  // added because it did not elect to receive the initial state.
362  StorageObserver::MonitorParams params(kStorageTypePersistent,
363                                        GURL(kDefaultOrigin),
364                                        base::TimeDelta::FromHours(1),
365                                        false);
366  MockObserver mock_observer1;
367  host_observers.AddObserver(&mock_observer1, params);
368  EXPECT_FALSE(host_observers.is_initialized());
369  EXPECT_EQ(0, mock_observer1.EventCount());
370
371  // |host_observers| should be initialized after the second observer is
372  // added.
373  MockObserver mock_observer2;
374  params.dispatch_initial_state = true;
375  host_observers.AddObserver(&mock_observer2, params);
376  StorageObserver::Event expected_event(params.filter, kUsage, kQuota);
377  EXPECT_EQ(0, mock_observer1.EventCount());
378  EXPECT_EQ(1, mock_observer2.EventCount());
379  EXPECT_EQ(expected_event, mock_observer2.LastEvent());
380  EXPECT_TRUE(host_observers.is_initialized());
381  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
382  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
383
384  // Verify that both observers will receive events after a usage change.
385  const int64 kDelta = 2345;
386  expected_event.usage += kDelta;
387  SetLastNotificationTime(host_observers, &mock_observer2);
388  host_observers.NotifyUsageChange(params.filter, kDelta);
389  EXPECT_EQ(1, mock_observer1.EventCount());
390  EXPECT_EQ(2, mock_observer2.EventCount());
391  EXPECT_EQ(expected_event, mock_observer1.LastEvent());
392  EXPECT_EQ(expected_event, mock_observer2.LastEvent());
393  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
394  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
395
396  // Verify that the addition of a third observer only causes an event to be
397  // dispatched to the new observer.
398  MockObserver mock_observer3;
399  params.dispatch_initial_state = true;
400  host_observers.AddObserver(&mock_observer3, params);
401  EXPECT_EQ(1, mock_observer1.EventCount());
402  EXPECT_EQ(2, mock_observer2.EventCount());
403  EXPECT_EQ(1, mock_observer3.EventCount());
404  EXPECT_EQ(expected_event, mock_observer3.LastEvent());
405}
406
407// Verify that negative usage and quota is changed to zero.
408TEST_F(HostStorageObserversTest, NegativeUsageAndQuota) {
409  StorageObserver::MonitorParams params(kStorageTypePersistent,
410                                        GURL(kDefaultOrigin),
411                                        base::TimeDelta::FromHours(1),
412                                        false);
413  const int64 kUsage = -324554;
414  const int64 kQuota = -234354354;
415  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
416
417  MockObserver mock_observer;
418  HostStorageObservers host_observers(quota_manager_.get());
419  host_observers.AddObserver(&mock_observer, params);
420
421  StorageObserver::Event expected_event(params.filter, 0, 0);
422  host_observers.NotifyUsageChange(params.filter, -87324);
423  EXPECT_EQ(expected_event, mock_observer.LastEvent());
424}
425
426// Verify that HostStorageObservers can recover from a bad initialization.
427TEST_F(HostStorageObserversTest, RecoverFromBadUsageInit) {
428  StorageObserver::MonitorParams params(kStorageTypePersistent,
429                                        GURL(kDefaultOrigin),
430                                        base::TimeDelta::FromHours(1),
431                                        false);
432  MockObserver mock_observer;
433  HostStorageObservers host_observers(quota_manager_.get());
434  host_observers.AddObserver(&mock_observer, params);
435
436  // Set up the quota manager to return an error status.
437  const int64 kUsage = 6656;
438  const int64 kQuota = 99585556;
439  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaErrorNotSupported);
440
441  // Verify that |host_observers| is not initialized and an event has not been
442  // dispatched.
443  host_observers.NotifyUsageChange(params.filter, 9438);
444  EXPECT_EQ(0, mock_observer.EventCount());
445  EXPECT_FALSE(host_observers.is_initialized());
446  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
447  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
448
449  // Now ensure that quota manager returns a good status.
450  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
451  host_observers.NotifyUsageChange(params.filter, 9048543);
452  StorageObserver::Event expected_event(params.filter, kUsage, kQuota);
453  EXPECT_EQ(1, mock_observer.EventCount());
454  EXPECT_EQ(expected_event, mock_observer.LastEvent());
455  EXPECT_TRUE(host_observers.is_initialized());
456}
457
458// Verify that HostStorageObservers handle initialization of the cached usage
459// and quota correctly.
460TEST_F(HostStorageObserversTest, AsyncInitialization) {
461  StorageObserver::MonitorParams params(kStorageTypePersistent,
462                                        GURL(kDefaultOrigin),
463                                        base::TimeDelta::FromHours(1),
464                                        false);
465  MockObserver mock_observer;
466  HostStorageObservers host_observers(quota_manager_.get());
467  host_observers.AddObserver(&mock_observer, params);
468
469  // Trigger initialization. Leave the mock quota manager uninitialized so that
470  // the callback is not invoked.
471  host_observers.NotifyUsageChange(params.filter, 7645);
472  EXPECT_EQ(0, mock_observer.EventCount());
473  EXPECT_FALSE(host_observers.is_initialized());
474  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
475  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
476
477  // Simulate notifying |host_observers| of a usage change before initialization
478  // is complete.
479  const int64 kUsage = 6656;
480  const int64 kQuota = 99585556;
481  const int64 kDelta = 327643;
482  host_observers.NotifyUsageChange(params.filter, kDelta);
483  EXPECT_EQ(0, mock_observer.EventCount());
484  EXPECT_FALSE(host_observers.is_initialized());
485  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
486  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
487
488  // Simulate an asynchronous callback from QuotaManager.
489  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
490  quota_manager_->InvokeCallback();
491  StorageObserver::Event expected_event(params.filter, kUsage + kDelta, kQuota);
492  EXPECT_EQ(1, mock_observer.EventCount());
493  EXPECT_EQ(expected_event, mock_observer.LastEvent());
494  EXPECT_TRUE(host_observers.is_initialized());
495  EXPECT_EQ(NULL, GetPendingEvent(host_observers));
496  EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers));
497}
498
499// Tests for StorageTypeObservers:
500
501typedef StorageTestWithManagerBase StorageTypeObserversTest;
502
503// Test adding and removing observers.
504TEST_F(StorageTypeObserversTest, AddRemoveObservers) {
505  StorageTypeObservers type_observers(quota_manager_.get());
506
507  StorageObserver::MonitorParams params1(kStorageTypePersistent,
508                                         GURL(kDefaultOrigin),
509                                         base::TimeDelta::FromHours(1),
510                                         false);
511  StorageObserver::MonitorParams params2(kStorageTypePersistent,
512                                         GURL(kAlternativeOrigin),
513                                         base::TimeDelta::FromHours(1),
514                                         false);
515  std::string host1 = net::GetHostOrSpecFromURL(params1.filter.origin);
516  std::string host2 = net::GetHostOrSpecFromURL(params2.filter.origin);
517
518  MockObserver mock_observer1;
519  MockObserver mock_observer2;
520  MockObserver mock_observer3;
521  type_observers.AddObserver(&mock_observer1, params1);
522  type_observers.AddObserver(&mock_observer2, params1);
523
524  type_observers.AddObserver(&mock_observer1, params2);
525  type_observers.AddObserver(&mock_observer2, params2);
526  type_observers.AddObserver(&mock_observer3, params2);
527
528  // Verify that the observers have been removed correctly.
529  ASSERT_TRUE(type_observers.GetHostObservers(host1));
530  ASSERT_TRUE(type_observers.GetHostObservers(host2));
531  EXPECT_EQ(2, GetObserverCount(*type_observers.GetHostObservers(host1)));
532  EXPECT_EQ(3, GetObserverCount(*type_observers.GetHostObservers(host2)));
533
534  // Remove an observer for a specific filter.
535  type_observers.RemoveObserverForFilter(&mock_observer1, params1.filter);
536  ASSERT_TRUE(type_observers.GetHostObservers(host1));
537  ASSERT_TRUE(type_observers.GetHostObservers(host2));
538  EXPECT_EQ(1, GetObserverCount(*type_observers.GetHostObservers(host1)));
539  EXPECT_EQ(3, GetObserverCount(*type_observers.GetHostObservers(host2)));
540
541  // Remove all instances of an observer.
542  type_observers.RemoveObserver(&mock_observer2);
543  ASSERT_TRUE(type_observers.GetHostObservers(host2));
544  EXPECT_EQ(2, GetObserverCount(*type_observers.GetHostObservers(host2)));
545  // Observers of host1 has been deleted as it is empty.
546  EXPECT_FALSE(type_observers.GetHostObservers(host1));
547}
548
549// Tests for StorageMonitor:
550
551class StorageMonitorTest : public StorageTestWithManagerBase {
552 public:
553  StorageMonitorTest()
554      : storage_monitor_(NULL),
555        params1_(kStorageTypeTemporary,
556                 GURL(kDefaultOrigin),
557                 base::TimeDelta::FromHours(1),
558                 false),
559        params2_(kStorageTypePersistent,
560                 GURL(kDefaultOrigin),
561                 base::TimeDelta::FromHours(1),
562                 false) {
563  }
564
565 protected:
566  virtual void SetUp() OVERRIDE {
567    StorageTestWithManagerBase::SetUp();
568
569    storage_monitor_ = quota_manager_->storage_monitor_.get();
570    host_ = net::GetHostOrSpecFromURL(params1_.filter.origin);
571
572    storage_monitor_->AddObserver(&mock_observer1_, params1_);
573    storage_monitor_->AddObserver(&mock_observer2_, params1_);
574
575    storage_monitor_->AddObserver(&mock_observer1_, params2_);
576    storage_monitor_->AddObserver(&mock_observer2_, params2_);
577    storage_monitor_->AddObserver(&mock_observer3_, params2_);
578  }
579
580  int GetObserverCount(StorageType storage_type) {
581    const StorageTypeObservers* type_observers =
582        storage_monitor_->GetStorageTypeObservers(storage_type);
583    return StorageMonitorTestBase::GetObserverCount(
584                *type_observers->GetHostObservers(host_));
585  }
586
587  void CheckObserverCount(int expected_temporary, int expected_persistent) {
588    ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers(
589                    kStorageTypeTemporary));
590    ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers(
591                    kStorageTypeTemporary)->GetHostObservers(host_));
592    EXPECT_EQ(expected_temporary, GetObserverCount(kStorageTypeTemporary));
593
594    ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers(
595                    kStorageTypePersistent));
596    ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers(
597                    kStorageTypePersistent)->GetHostObservers(host_));
598    EXPECT_EQ(expected_persistent, GetObserverCount(kStorageTypePersistent));
599  }
600
601  StorageMonitor* storage_monitor_;
602  StorageObserver::MonitorParams params1_;
603  StorageObserver::MonitorParams params2_;
604  MockObserver mock_observer1_;
605  MockObserver mock_observer2_;
606  MockObserver mock_observer3_;
607  std::string host_;
608};
609
610// Test adding storage observers.
611TEST_F(StorageMonitorTest, AddObservers) {
612  // Verify that the observers are added correctly.
613  CheckObserverCount(2, 3);
614}
615
616// Test dispatching events to storage observers.
617TEST_F(StorageMonitorTest, EventDispatch) {
618  // Verify dispatch of events.
619  const int64 kUsage = 5325;
620  const int64 kQuota = 903845;
621  quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk);
622  storage_monitor_->NotifyUsageChange(params1_.filter, 9048543);
623
624  StorageObserver::Event expected_event(params1_.filter, kUsage, kQuota);
625  EXPECT_EQ(1, mock_observer1_.EventCount());
626  EXPECT_EQ(1, mock_observer2_.EventCount());
627  EXPECT_EQ(0, mock_observer3_.EventCount());
628  EXPECT_EQ(expected_event, mock_observer1_.LastEvent());
629  EXPECT_EQ(expected_event, mock_observer2_.LastEvent());
630}
631
632// Test removing all instances of an observer.
633TEST_F(StorageMonitorTest, RemoveObserver) {
634  storage_monitor_->RemoveObserver(&mock_observer1_);
635  CheckObserverCount(1, 2);
636}
637
638// Test removing an observer for a specific filter.
639TEST_F(StorageMonitorTest, RemoveObserverForFilter) {
640  storage_monitor_->RemoveObserverForFilter(&mock_observer1_, params2_.filter);
641  CheckObserverCount(2, 2);
642}
643
644// Integration test for QuotaManager and StorageMonitor:
645
646class StorageMonitorIntegrationTest : public testing::Test {
647 public:
648  virtual void SetUp() OVERRIDE {
649    ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
650    storage_policy_ = new MockSpecialStoragePolicy();
651    quota_manager_ = new QuotaManager(
652        false,
653        data_dir_.path(),
654        base::MessageLoopProxy::current().get(),
655        base::MessageLoopProxy::current().get(),
656        storage_policy_.get());
657
658    client_ = new MockStorageClient(quota_manager_->proxy(),
659                                    NULL,
660                                    QuotaClient::kFileSystem,
661                                    0);
662
663    quota_manager_->proxy()->RegisterClient(client_);
664  }
665
666  virtual void TearDown() OVERRIDE {
667    // This ensures the quota manager is destroyed correctly.
668    quota_manager_ = NULL;
669    base::RunLoop().RunUntilIdle();
670  }
671
672 protected:
673  base::MessageLoop message_loop_;
674  base::ScopedTempDir data_dir_;
675  scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
676  scoped_refptr<QuotaManager> quota_manager_;
677  MockStorageClient* client_;
678};
679
680// This test simulates a usage change in a quota client and verifies that a
681// storage observer will receive a storage event.
682TEST_F(StorageMonitorIntegrationTest, NotifyUsageEvent) {
683  const StorageType kTestStorageType = kStorageTypePersistent;
684  const int64 kTestUsage = 234743;
685
686  // Register the observer.
687  StorageObserver::MonitorParams params(kTestStorageType,
688                                        GURL(kDefaultOrigin),
689                                        base::TimeDelta::FromHours(1),
690                                        false);
691  MockObserver mock_observer;
692  quota_manager_->AddStorageObserver(&mock_observer, params);
693
694  // Fire a usage change.
695  client_->AddOriginAndNotify(GURL(kDefaultOrigin),
696                              kTestStorageType,
697                              kTestUsage);
698  base::RunLoop().RunUntilIdle();
699
700  // Verify that the observer receives it.
701  ASSERT_EQ(1, mock_observer.EventCount());
702  const StorageObserver::Event& event = mock_observer.LastEvent();
703  EXPECT_EQ(params.filter, event.filter);
704  EXPECT_EQ(kTestUsage, event.usage);
705}
706
707}  // namespace content
708