| Index: chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.cc
|
| diff --git a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.cc b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.cc
|
| index 66a3ebb9dd4cbc5559d31af78cbe3f0f2acf7150..abc2f75621b10e572e0faa61b5e794f71f04b179 100644
|
| --- a/chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.cc
|
| +++ b/chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.cc
|
| @@ -2,15 +2,15 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "chrome/browser/extensions/api/system_info_storage/storage_info_provider.h"
|
| +#include "chrome/browser/extensions/api/system_info_storage/storage_info_provider_win.h"
|
|
|
| -#include "base/string_util.h"
|
| -#include "base/utf_string_conversions.h"
|
| #include <windows.h>
|
|
|
| -namespace extensions {
|
| +#include "base/memory/linked_ptr.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/media_gallery/media_storage_util.h"
|
|
|
| -namespace {
|
| +namespace extensions {
|
|
|
| using api::experimental_system_info_storage::StorageInfo;
|
| using api::experimental_system_info_storage::StorageUnitInfo;
|
| @@ -19,18 +19,15 @@ using api::experimental_system_info_storage::StorageUnitInfo;
|
| // L":", L"\" and a terminating null character.
|
| const unsigned long kMaxLogicalDriveString = 4 * 26;
|
|
|
| -// StorageInfoProvider implementation on Windows platform.
|
| -class StorageInfoProviderWin : public StorageInfoProvider {
|
| - public:
|
| - StorageInfoProviderWin() {}
|
| - virtual ~StorageInfoProviderWin() {}
|
| +StorageInfoProviderWin::StorageInfoProviderWin() {
|
| +}
|
|
|
| - virtual bool QueryInfo(StorageInfo* info) OVERRIDE;
|
| - virtual bool QueryUnitInfo(const std::string& id,
|
| - StorageUnitInfo* info) OVERRIDE;
|
| -};
|
| +StorageInfoProviderWin::~StorageInfoProviderWin() {
|
| +}
|
|
|
| bool StorageInfoProviderWin::QueryInfo(StorageInfo* info) {
|
| + if (info == NULL) return false;
|
| +
|
| info->units.clear();
|
|
|
| WCHAR logical_drive_strings[kMaxLogicalDriveString];
|
| @@ -44,23 +41,21 @@ bool StorageInfoProviderWin::QueryInfo(StorageInfo* info) {
|
| if (string_length == 0)
|
| return false;
|
|
|
| - // Iterate the drive string by 4 wchars each step
|
| for (unsigned int i = 0; i < string_length; i += 4) {
|
| linked_ptr<StorageUnitInfo> unit(new StorageUnitInfo());
|
| - if (QueryUnitInfo(WideToUTF8(&logical_drive_strings[i]), unit.get())) {
|
| + if (QueryUnitInfo(&logical_drive_strings[i], unit.get())) {
|
| info->units.push_back(unit);
|
| }
|
| }
|
| return true;
|
| }
|
|
|
| -bool StorageInfoProviderWin::QueryUnitInfo(const std::string& id,
|
| +bool StorageInfoProviderWin::QueryUnitInfo(const FilePath::StringType& path,
|
| StorageUnitInfo* info) {
|
| - DCHECK(info);
|
| - string16 drive = UTF8ToUTF16(id);
|
| + if (info == NULL) return false;
|
|
|
| std::string type;
|
| - DWORD ret = GetDriveType(drive.c_str());
|
| + DWORD ret = GetDriveType(path.c_str());
|
| switch (ret) {
|
| case DRIVE_FIXED:
|
| type = systeminfo::kStorageTypeHardDisk;
|
| @@ -82,9 +77,14 @@ bool StorageInfoProviderWin::QueryUnitInfo(const std::string& id,
|
| ULARGE_INTEGER total_bytes;
|
| ULARGE_INTEGER free_bytes;
|
|
|
| - if (GetDiskFreeSpaceEx(drive.c_str(), NULL, &total_bytes, &free_bytes)) {
|
| - info->id = id;
|
| + if (GetDiskFreeSpaceEx(path.c_str(), &free_bytes, &total_bytes, NULL)) {
|
| + // TODO(hongbo) We need to look up the real device id instead of using
|
| + // path as a fallback name. Here we call MakeDeviceId to align with the
|
| + // id conventions used in media_gallery.
|
| + info->id = chrome::MediaStorageUtil::MakeDeviceId(
|
| + chrome::MediaStorageUtil::OTHER_MASS_STORAGE, UTF16ToUTF8(path));
|
| info->type = type;
|
| + info->path = UTF16ToUTF8(path);
|
| info->capacity = static_cast<double>(total_bytes.QuadPart);
|
| info->available_capacity = static_cast<double>(free_bytes.QuadPart);
|
| return true;
|
| @@ -92,7 +92,82 @@ bool StorageInfoProviderWin::QueryUnitInfo(const std::string& id,
|
| return false;
|
| }
|
|
|
| -} // namespace
|
| +// TODO(hongbo): Need to consider storage device arrival/removal scenario
|
| +// for PlatformStartWatching and PlatformStopWatching implementations.
|
| +bool StorageInfoProviderWin::PlatformStartWatching(
|
| + StorageInfoProvider::Delegate* delegate) {
|
| + if (is_watching_) {
|
| + NOTREACHED() << "Already watching the storage info provider!";
|
| + return false;
|
| + }
|
| +
|
| + StorageInfo info;
|
| + if (QueryInfo(&info)) {
|
| + std::vector<linked_ptr<StorageUnitInfo> >::const_iterator iter;
|
| + for (iter = info.units.begin(); iter != info.units.end(); ++iter) {
|
| + string16 drive = UTF8ToUTF16((*iter)->path);
|
| + HANDLE handle = FindFirstChangeNotification(drive.c_str(),
|
| + TRUE,
|
| + FILE_NOTIFY_CHANGE_SIZE);
|
| + linked_ptr<StorageWatcherEntry> entry(new StorageWatcherEntry);
|
| +
|
| + if (entry->watcher.StartWatching(handle, this)) {
|
| + DLOG(INFO) << "Start watching: " << drive;
|
| + entry->path = drive;
|
| + storage_watchers_.insert(
|
| + std::pair<HANDLE, linked_ptr<StorageWatcherEntry> >(handle,
|
| + entry));
|
| + }
|
| + }
|
| + delegate_ = delegate;
|
| + is_watching_ = true;
|
| +
|
| + base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool StorageInfoProviderWin::PlatformStopWatching() {
|
| + if (!is_watching_) return false;
|
| +
|
| + is_watching_ = false;
|
| + delegate_ = NULL;
|
| +
|
| + for (StorageWatcherMap::iterator iter = storage_watchers_.begin();
|
| + iter != storage_watchers_.end();
|
| + ++iter) {
|
| + linked_ptr<StorageWatcherEntry> entry = iter->second;
|
| + entry->watcher.StopWatching();
|
| + }
|
| + storage_watchers_.clear();
|
| + base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// TODO(hongbo): Since the OnObjectSignaled may be called frequently, e.g.
|
| +// in case of unzip a package, we need to introduce an mechanism to control
|
| +// its frequency, for example, using a timer to poll and wait to be signaled.
|
| +void StorageInfoProviderWin::OnObjectSignaled(HANDLE object) {
|
| + StorageWatcherMap::iterator iter = storage_watchers_.find(object);
|
| + DCHECK(iter != storage_watchers_.end());
|
| +
|
| + linked_ptr<StorageWatcherEntry> entry = iter->second;
|
| +
|
| + StorageUnitInfo info;
|
| + if (QueryUnitInfo(entry->path, &info)) {
|
| + delegate_->OnStorageDeviceAvailableCapacityChanged(info.id,
|
| + info.available_capacity);
|
| + }
|
| + if (!FindNextChangeNotification(object)) {
|
| + NOTREACHED() << "FindNextChangeNotification failed: " << GetLastError();
|
| + return;
|
| + }
|
| +
|
| + // Continue to watch the object.
|
| + entry->watcher.StartWatching(object, this);
|
| +}
|
|
|
| // static
|
| StorageInfoProvider* StorageInfoProvider::Get() {
|
|
|