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

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

Issue 16707002: [SystemInfo API] Rewrite storage info provider using storage monitor impl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add explicit destructors in UnitTestStorageInfoProvider to avoid build error. Created 7 years, 5 months 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 b29afa09bb4b775392070e88523654f633290cc6..581e02f509b9c360f2cdeeaf22fb103babe3dc53 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
@@ -6,6 +6,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
#include "content/public/browser/browser_thread.h"
@@ -13,7 +14,10 @@
namespace extensions {
using content::BrowserThread;
+using chrome::StorageMonitor;
using api::experimental_system_info_storage::StorageUnitInfo;
+using api::experimental_system_info_storage::STORAGE_UNIT_TYPE_FIXED;
+using api::experimental_system_info_storage::STORAGE_UNIT_TYPE_REMOVABLE;
namespace systeminfo {
@@ -21,127 +25,155 @@ const char kStorageTypeUnknown[] = "unknown";
const char kStorageTypeFixed[] = "fixed";
const char kStorageTypeRemovable[] = "removable";
+void BuildStorageUnitInfo(const chrome::StorageInfo& info,
+ StorageUnitInfo* unit) {
+ unit->id = StorageInfoProvider::Get()->GetTransientIdForDeviceId(
+ info.device_id());
+ unit->name = UTF16ToUTF8(info.name());
+ // TODO(hmin): Might need to take MTP device into consideration.
+ unit->type = chrome::StorageInfo::IsRemovableDevice(info.device_id()) ?
+ STORAGE_UNIT_TYPE_REMOVABLE : STORAGE_UNIT_TYPE_FIXED;
+ unit->capacity = static_cast<double>(info.total_size_in_bytes());
+ unit->available_capacity = 0;
+}
+
} // namespace systeminfo
const int kDefaultPollingIntervalMs = 1000;
const char kWatchingTokenName[] = "_storage_info_watching_token_";
StorageInfoProvider::StorageInfoProvider()
- : observers_(new ObserverListThreadSafe<StorageInfoObserver>()),
+ : observers_(new ObserverListThreadSafe<StorageFreeSpaceObserver>()),
watching_interval_(kDefaultPollingIntervalMs) {
- DCHECK(chrome::StorageMonitor::GetInstance());
- chrome::StorageMonitor::GetInstance()->AddObserver(this);
}
StorageInfoProvider::~StorageInfoProvider() {
- // Note that StorageInfoProvider is defined as a LazyInstance which would be
- // destroyed at process exiting, so its lifetime should be longer than the
- // StorageMonitor instance that would be destroyed before
- // StorageInfoProvider.
- if (chrome::StorageMonitor::GetInstance())
- chrome::StorageMonitor::GetInstance()->RemoveObserver(this);
}
-void StorageInfoProvider::AddObserver(StorageInfoObserver* obs) {
- observers_->AddObserver(obs);
+void StorageInfoProvider::StartQueryInfoImpl() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Register a callback to notify UI thread that StorageMonitor finishes the
+ // storage metadata retrieval on FILE thread. See the comments of
+ // StorageMonitor::Initialize about when the callback gets run.
+ StorageMonitor::GetInstance()->EnsureInitialized(
+ base::Bind(&StorageInfoProvider::QueryInfoImplOnUIThread, this));
}
-void StorageInfoProvider::RemoveObserver(StorageInfoObserver* obs) {
- observers_->RemoveObserver(obs);
+void StorageInfoProvider::QueryInfoImplOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // At this point, we can call StorageMonitor::GetAllAvailableStorages to
+ // get the correct results.
+ QueryInfo(&info_);
+ // The amount of available capacity should be queried on blocking pool.
+ PostQueryTaskToBlockingPool(FROM_HERE,
+ base::Bind(&StorageInfoProvider::QueryAvailableCapacityOnBlockingPool,
+ this));
}
-void StorageInfoProvider::OnRemovableStorageAttached(
- const chrome::StorageInfo& info) {
- // Since the storage API uses the location as identifier, e.g.
- // the drive letter on Windows while mount point on Posix. Here we has to
- // convert the |info.location| to UTF-8 encoding.
- //
- // TODO(hongbo): use |info.device_id| instead of using |info.location|
- // to keep the id persisting between device attachments, like
- // StorageMonitor does.
-#if defined(OS_POSIX)
- std::string id = info.location();
-#elif defined(OS_WIN)
- std::string id = UTF16ToUTF8(info.location());
-#endif
- // Post a task to blocking pool for querying the information.
- BrowserThread::PostBlockingPoolTask(FROM_HERE,
- base::Bind(&StorageInfoProvider::QueryAttachedStorageInfoOnBlockingPool,
- this, id));
-}
-
-void StorageInfoProvider::QueryAttachedStorageInfoOnBlockingPool(
- const std::string& id) {
+void StorageInfoProvider::QueryAvailableCapacityOnBlockingPool() {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+ for (StorageInfo::iterator it = info_.begin(); it != info_.end(); ++it) {
+ int64 amount = GetStorageFreeSpaceFromTransientId((*it)->id);
+ if (amount > 0)
+ (*it)->available_capacity = static_cast<double>(amount);
+ }
- StorageUnitInfo info;
- if (!QueryUnitInfo(id, &info))
- return;
- observers_->Notify(&StorageInfoObserver::OnStorageAttached,
- info.id,
- info.type,
- info.capacity,
- info.available_capacity);
+ // Notify UI thread that the querying operation has completed.
+ BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&StorageInfoProvider::OnQueryCompleted, this, true));
}
-void StorageInfoProvider::OnRemovableStorageDetached(
- const chrome::StorageInfo& info) {
- // TODO(hongbo): Use |info.device_id| instead. Same as the above.
-#if defined(OS_POSIX)
- std::string id = info.location();
-#elif defined(OS_WIN)
- std::string id = UTF16ToUTF8(info.location());
-#endif
- observers_->Notify(&StorageInfoObserver::OnStorageDetached, id);
+std::vector<chrome::StorageInfo> StorageInfoProvider::GetAllStorages() const {
+ return StorageMonitor::GetInstance()->GetAllAvailableStorages();
}
-void StorageInfoProvider::StartWatching(const std::string& id) {
+bool StorageInfoProvider::QueryInfo(StorageInfo* info) {
+ std::vector<chrome::StorageInfo> storage_list = GetAllStorages();
+ StorageInfo results;
+ std::vector<chrome::StorageInfo>::const_iterator it = storage_list.begin();
+ for (; it != storage_list.end(); ++it) {
+ linked_ptr<StorageUnitInfo> unit(new StorageUnitInfo());
+ systeminfo::BuildStorageUnitInfo(*it, unit.get());
+ results.push_back(unit);
+ }
+ info->swap(results);
+
+ return true;
+}
+
+void StorageInfoProvider::AddObserver(StorageFreeSpaceObserver* obs) {
+ observers_->AddObserver(obs);
+}
+
+void StorageInfoProvider::RemoveObserver(StorageFreeSpaceObserver* obs) {
+ observers_->RemoveObserver(obs);
+}
+
+void StorageInfoProvider::StartWatching(const std::string& transient_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
BrowserThread::PostBlockingPoolSequencedTask(
kWatchingTokenName,
FROM_HERE,
base::Bind(&StorageInfoProvider::AddWatchedStorageOnBlockingPool,
- this, id));
+ this, transient_id));
}
-void StorageInfoProvider::StopWatching(const std::string& id) {
+void StorageInfoProvider::StopWatching(const std::string& transient_id) {
+ base::FilePath mount_path;
BrowserThread::PostBlockingPoolSequencedTask(
kWatchingTokenName,
FROM_HERE,
base::Bind(&StorageInfoProvider::RemoveWatchedStorageOnBlockingPool,
- this, id));
+ this, transient_id));
+}
+
+int64 StorageInfoProvider::GetStorageFreeSpaceFromTransientId(
+ const std::string& transient_id) {
+ std::vector<chrome::StorageInfo> storage_list = GetAllStorages();
+ std::string device_id = GetDeviceIdForTransientId(transient_id);
+
+ // Lookup the matched storage info by |device_id|.
+ for (std::vector<chrome::StorageInfo>::const_iterator it =
+ storage_list.begin();
+ it != storage_list.end(); ++it) {
+ if (device_id == it->device_id())
+ return base::SysInfo::AmountOfFreeDiskSpace(
+ base::FilePath(it->location()));
+ }
+
+ return -1;
}
void StorageInfoProvider::AddWatchedStorageOnBlockingPool(
- const std::string& id) {
+ const std::string& transient_id) {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- // If the storage |id| is already being watched.
- if (ContainsKey(storage_id_to_size_map_, id))
+ // If the storage |transient_id| is already being watched.
+ if (ContainsKey(storage_transient_id_to_size_map_, transient_id))
return;
- StorageUnitInfo info;
- if (!QueryUnitInfo(id, &info))
+ int64 available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
+ if (available_bytes < 0)
return;
- storage_id_to_size_map_[id] = info.available_capacity;
+ storage_transient_id_to_size_map_[transient_id] = available_bytes;
// 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 (storage_transient_id_to_size_map_.size() == 1) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&StorageInfoProvider::StartWatchingTimerOnUIThread, this));
}
}
void StorageInfoProvider::RemoveWatchedStorageOnBlockingPool(
- const std::string& id) {
+ const std::string& transient_id) {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- if (!ContainsKey(storage_id_to_size_map_, id))
+ if (storage_transient_id_to_size_map_.erase(transient_id) == 0)
return;
- storage_id_to_size_map_.erase(id);
-
// Stop watching timer if there is no storage to be watched.
- if (storage_id_to_size_map_.empty()) {
+ if (storage_transient_id_to_size_map_.empty()) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
}
@@ -149,38 +181,52 @@ void StorageInfoProvider::RemoveWatchedStorageOnBlockingPool(
void StorageInfoProvider::CheckWatchedStorages() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostBlockingPoolSequencedTask(kWatchingTokenName, FROM_HERE,
- base::Bind(&StorageInfoProvider::CheckWatchedStoragesOnBlockingPool,
- this));
+ std::vector<chrome::StorageInfo> storage_list = GetAllStorages();
+
+ for (std::vector<chrome::StorageInfo>::iterator it = storage_list.begin();
+ it != storage_list.end(); ++it) {
+ BrowserThread::PostBlockingPoolSequencedTask(
+ kWatchingTokenName,
+ FROM_HERE,
+ base::Bind(&StorageInfoProvider::CheckWatchedStorageOnBlockingPool,
+ this, GetTransientIdForDeviceId(it->device_id())));
+ }
}
-void StorageInfoProvider::CheckWatchedStoragesOnBlockingPool() {
+void StorageInfoProvider::CheckWatchedStorageOnBlockingPool(
+ const std::string& transient_id) {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- for (StorageIDToSizeMap::iterator it = storage_id_to_size_map_.begin();
- it != storage_id_to_size_map_.end(); ) {
- StorageUnitInfo info;
- if (!QueryUnitInfo(it->first, &info)) {
- storage_id_to_size_map_.erase(it++);
- continue;
- }
- if (it->second != info.available_capacity) {
- observers_->Notify(&StorageInfoObserver::OnStorageFreeSpaceChanged,
- it->first, /* storage id */
- it->second, /* old free space value */
- info.available_capacity /* new value */);
- it->second = info.available_capacity;
+ if (!ContainsKey(storage_transient_id_to_size_map_, transient_id))
+ return;
+
+ double new_available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
+ double old_available_bytes = storage_transient_id_to_size_map_[transient_id];
+
+ // No free space change.
+ if (new_available_bytes == old_available_bytes)
+ return;
+
+ if (new_available_bytes < 0) {
+ // In case we can't establish the new free space value from |transient_id|,
+ // the |transient_id| is currently not available, so we need to remove it
+ // from |storage_transient_id_to_size_map_|.
+ storage_transient_id_to_size_map_.erase(transient_id);
+ if (storage_transient_id_to_size_map_.size() == 0) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
}
- ++it;
+ return;
}
- if (storage_id_to_size_map_.size() == 0) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread,
- this));
- return;
+ // Ignore free space change event if the old available capacity is 0.
+ if (old_available_bytes > 0) {
+ observers_->Notify(&StorageFreeSpaceObserver::OnFreeSpaceChanged,
+ transient_id,
+ old_available_bytes,
+ new_available_bytes);
}
- OnCheckWatchedStoragesFinishedForTesting();
+ storage_transient_id_to_size_map_[transient_id] = new_available_bytes;
}
void StorageInfoProvider::StartWatchingTimerOnUIThread() {
@@ -198,4 +244,19 @@ void StorageInfoProvider::StopWatchingTimerOnUIThread() {
watching_timer_.Stop();
}
+std::string StorageInfoProvider::GetTransientIdForDeviceId(
+ const std::string& device_id) const {
+ return StorageMonitor::GetInstance()->GetTransientIdForDeviceId(device_id);
+}
+
+std::string StorageInfoProvider::GetDeviceIdForTransientId(
+ const std::string& transient_id) const {
+ return StorageMonitor::GetInstance()->GetDeviceIdForTransientId(transient_id);
+}
+
+// static
+StorageInfoProvider* StorageInfoProvider::Get() {
+ return StorageInfoProvider::GetInstance<StorageInfoProvider>();
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698