Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Unified Diff: chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc

Issue 11419279: Implement systemInfo.storage.onChanged event (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: refine browser test and code comments Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
index 4aac3243ec9eb58433335777f15351688d62ac75..1617af99ea1719c2eefdc552df978acd9c7d001c 100644
--- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
+++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/extensions/api/system_info_storage/storage_info_provider.h"
+#include <cmath>
+
#include "base/stl_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
@@ -26,11 +28,14 @@ const char kStorageTypeRemovable[] = "removable";
} // namespace systeminfo
// Default watching interval is 1000 ms.
-const unsigned int kDefaultPollingIntervalMs = 1000;
+const int kDefaultPollingIntervalMs = 1000;
+
+// Default threshold for free space change.
+const int kDefaultThresholdBytes = 4096;
StorageInfoProvider::StorageInfoProvider()
: watching_timer_(NULL),
- observers_(new ObserverListThreadSafe<Observer>()),
+ observers_(new ObserverListThreadSafe<StorageInfoObserver>()),
watching_interval_(kDefaultPollingIntervalMs) {
registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources());
@@ -41,28 +46,31 @@ StorageInfoProvider::~StorageInfoProvider() {
registrar_.RemoveAll();
}
-void StorageInfoProvider::AddObserver(Observer* obs) {
+void StorageInfoProvider::AddObserver(StorageInfoObserver* obs) {
observers_->AddObserver(obs);
}
-void StorageInfoProvider::RemoveObserver(Observer* obs) {
+void StorageInfoProvider::RemoveObserver(StorageInfoObserver* obs) {
observers_->RemoveObserver(obs);
}
-void StorageInfoProvider::StartWatching(const std::string& id) {
+void StorageInfoProvider::StartWatching(const std::string& id, int threshold) {
+ if (threshold <= 0)
+ threshold = kDefaultThresholdBytes;
+
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&StorageInfoProvider::StartWatchingOnFileThread,
- base::Unretained(this), id));
+ base::Unretained(this), id, threshold));
}
-void StorageInfoProvider::StopWatching(const std::string& id) {
+void StorageInfoProvider::StopWatching(const std::string& id, int threshold) {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&StorageInfoProvider::StopWatchingOnFileThread,
- base::Unretained(this), id));
+ base::Unretained(this), id, threshold));
}
void StorageInfoProvider::Observe(
@@ -82,21 +90,28 @@ void StorageInfoProvider::Observe(
}
}
-void StorageInfoProvider::StartWatchingOnFileThread(const std::string& id) {
+void StorageInfoProvider::StartWatchingOnFileThread(const std::string& id,
+ int threshold) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- // If the storage |id| is already being watched.
- if (ContainsKey(storage_id_to_size_map_, id))
- return;
+
+ FreeSpaceWatcher watcher(id, threshold);
benwells 2012/12/11 04:40:40 This can move to line 111.
+ for (FreeSpaceWatchers::iterator it = id_to_watcher_map_[id].begin();
+ it != id_to_watcher_map_[id].end(); ++it) {
+ // Returns back if the same watcher is already existing.
+ if (it->threshold == threshold)
benwells 2012/12/11 04:40:40 What if two extensions start watching using the sa
Hongbo Min 2012/12/11 05:08:50 Good catch! It will lead to the second one can not
+ return;
+ }
StorageUnitInfo info;
- if (!QueryUnitInfo(id, &info))
+ if (!QueryUnitInfo(id, &info)) {
+ AbortWatching(id);
return;
+ }
- storage_id_to_size_map_[id] = info.available_capacity;
+ watcher.recent_free_space = info.available_capacity;
+ id_to_watcher_map_[id].push_back(watcher);
- // If it is the first storage to be watched, we need to start the watching
- // timer.
- if (storage_id_to_size_map_.size() == 1) {
+ if (!watching_timer_) {
watching_timer_ = new base::RepeatingTimer<StorageInfoProvider>();
watching_timer_->Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(watching_interval_),
@@ -104,39 +119,63 @@ void StorageInfoProvider::StartWatchingOnFileThread(const std::string& id) {
}
}
-void StorageInfoProvider::StopWatchingOnFileThread(const std::string& id) {
+void StorageInfoProvider::StopWatchingOnFileThread(const std::string& id,
+ int threshold) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (!ContainsKey(storage_id_to_size_map_, id))
+ if (!ContainsKey(id_to_watcher_map_, id))
return;
- storage_id_to_size_map_.erase(id);
+ for (FreeSpaceWatchers::iterator it = id_to_watcher_map_[id].begin();
+ it != id_to_watcher_map_[id].end(); ++it) {
+ if (it->threshold == threshold) {
+ id_to_watcher_map_[id].erase(it);
+ break;
+ }
+ }
+
+ if (id_to_watcher_map_[id].empty())
+ id_to_watcher_map_.erase(id);
// If there is no storage to be watched, we need to destroy the watching
// timer.
- if (storage_id_to_size_map_.size() == 0)
+ if (id_to_watcher_map_.empty())
DestroyWatchingTimer();
}
void StorageInfoProvider::CheckWatchedStorages() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(storage_id_to_size_map_.size() > 0);
+ DCHECK(!id_to_watcher_map_.empty());
- StorageIDToSizeMap::iterator it = storage_id_to_size_map_.begin();
- for (; it != storage_id_to_size_map_.end(); ++it) {
+ StorageIDToWatcherMap::iterator it = id_to_watcher_map_.begin();
+ for (; it != id_to_watcher_map_.end(); ++it) {
StorageUnitInfo info;
- if (!QueryUnitInfo(it->first, &info)) {
- storage_id_to_size_map_.erase(it);
- if (storage_id_to_size_map_.size() == 0) {
- DestroyWatchingTimer();
- return;
- }
- }
- if (it->second != info.available_capacity) {
- observers_->Notify(&Observer::OnStorageFreeSpaceChanged,
- it->first, /* storage id */
- it->second, /* old free space value */
- info.available_capacity /* new value */);
- it->second = info.available_capacity;
+ if (!QueryUnitInfo(it->first, &info))
+ AbortWatching(it->first);
+ NotifyFreeSpaceChangedIfNeeded(it->first, info.available_capacity);
+ }
+}
+
+void StorageInfoProvider::AbortWatching(const std::string& id) {
+ if (!ContainsKey(id_to_watcher_map_, id))
+ return;
+ id_to_watcher_map_.erase(id);
+ if (id_to_watcher_map_.empty())
+ DestroyWatchingTimer();
+}
+
+void StorageInfoProvider::NotifyFreeSpaceChangedIfNeeded(
+ const std::string& id, double latest_free_space) {
+ for (FreeSpaceWatchers::iterator it = id_to_watcher_map_[id].begin();
+ it != id_to_watcher_map_[id].end(); ++it) {
+ int delta = static_cast<int>(latest_free_space - it->recent_free_space);
+ if (it->recent_free_space != latest_free_space &&
+ it->threshold <= abs(delta)) {
+ observers_->Notify(&StorageInfoObserver::OnStorageFreeSpaceChanged,
+ it->id, /* storage id */
+ it->recent_free_space, /* old free space value */
+ latest_free_space /* new value */,
+ it->threshold /* change threshold */);
benwells 2012/12/11 04:40:40 Why do we pass the threshold back in the event?
Hongbo Min 2012/12/11 05:08:50 The SystemInfoEventRouter needs it to marshal the
+ it->recent_free_space = latest_free_space;
}
}
}

Powered by Google App Engine
This is Rietveld 408576698