1 // Copyright (c) 2012 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 #include "chrome/browser/storage_monitor/storage_monitor_win.h"
11 #include "base/win/wrapped_window_proc.h"
12 #include "chrome/browser/storage_monitor/portable_device_watcher_win.h"
13 #include "chrome/browser/storage_monitor/removable_device_constants.h"
14 #include "chrome/browser/storage_monitor/storage_info.h"
15 #include "chrome/browser/storage_monitor/volume_mount_watcher_win.h"
17 // StorageMonitorWin -------------------------------------------------------
19 StorageMonitorWin::StorageMonitorWin(
20 VolumeMountWatcherWin
* volume_mount_watcher
,
21 PortableDeviceWatcherWin
* portable_device_watcher
)
25 volume_mount_watcher_(volume_mount_watcher
),
26 portable_device_watcher_(portable_device_watcher
) {
27 DCHECK(volume_mount_watcher_
);
28 DCHECK(portable_device_watcher_
);
29 volume_mount_watcher_
->SetNotifications(receiver());
30 portable_device_watcher_
->SetNotifications(receiver());
33 StorageMonitorWin::~StorageMonitorWin() {
34 volume_mount_watcher_
->SetNotifications(NULL
);
35 portable_device_watcher_
->SetNotifications(NULL
);
38 DestroyWindow(window_
);
41 UnregisterClass(MAKEINTATOM(window_class_
), instance_
);
44 void StorageMonitorWin::Init() {
45 WNDCLASSEX window_class
;
46 base::win::InitializeWindowClass(
47 L
"Chrome_StorageMonitorWindow",
48 &base::win::WrappedWindowProc
<StorageMonitorWin::WndProcThunk
>,
49 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
,
51 instance_
= window_class
.hInstance
;
52 window_class_
= RegisterClassEx(&window_class
);
53 DCHECK(window_class_
);
55 window_
= CreateWindow(MAKEINTATOM(window_class_
), 0, 0, 0, 0, 0, 0, 0, 0,
57 SetWindowLongPtr(window_
, GWLP_USERDATA
, reinterpret_cast<LONG_PTR
>(this));
58 volume_mount_watcher_
->Init();
59 portable_device_watcher_
->Init(window_
);
62 bool StorageMonitorWin::GetStorageInfoForPath(const base::FilePath
& path
,
63 StorageInfo
* device_info
) const {
66 // TODO(gbillock): Move this logic up to StorageMonitor.
67 // If we already know the StorageInfo for the path, just return it.
68 // This will account for portable devices as well.
69 std::vector
<StorageInfo
> attached_devices
= GetAllAvailableStorages();
70 size_t best_parent
= attached_devices
.size();
71 size_t best_length
= 0;
72 for (size_t i
= 0; i
< attached_devices
.size(); i
++) {
73 if (!StorageInfo::IsRemovableDevice(attached_devices
[i
].device_id()))
75 base::FilePath relative
;
76 if (base::FilePath(attached_devices
[i
].location()).AppendRelativePath(
78 // Note: the relative path is longer for shorter shared path between
79 // the path and the device mount point, so we want the shortest
81 if (relative
.value().size() < best_length
) {
83 best_length
= relative
.value().size();
87 if (best_parent
!= attached_devices
.size()) {
88 *device_info
= attached_devices
[best_parent
];
92 return GetDeviceInfo(path
, device_info
);
95 void StorageMonitorWin::EjectDevice(
96 const std::string
& device_id
,
97 base::Callback
<void(EjectStatus
)> callback
) {
98 StorageInfo::Type type
;
99 if (!StorageInfo::CrackDeviceId(device_id
, &type
, NULL
)) {
100 callback
.Run(EJECT_FAILURE
);
104 if (type
== StorageInfo::MTP_OR_PTP
)
105 portable_device_watcher_
->EjectDevice(device_id
, callback
);
106 else if (StorageInfo::IsRemovableDevice(device_id
))
107 volume_mount_watcher_
->EjectDevice(device_id
, callback
);
109 callback
.Run(EJECT_FAILURE
);
112 bool StorageMonitorWin::GetMTPStorageInfoFromDeviceId(
113 const std::string
& storage_device_id
,
114 base::string16
* device_location
,
115 base::string16
* storage_object_id
) const {
116 StorageInfo::Type type
;
117 StorageInfo::CrackDeviceId(storage_device_id
, &type
, NULL
);
118 return ((type
== StorageInfo::MTP_OR_PTP
) &&
119 portable_device_watcher_
->GetMTPStorageInfoFromDeviceId(
120 storage_device_id
, device_location
, storage_object_id
));
124 LRESULT CALLBACK
StorageMonitorWin::WndProcThunk(HWND hwnd
, UINT message
,
125 WPARAM wparam
, LPARAM lparam
) {
126 StorageMonitorWin
* msg_wnd
= reinterpret_cast<StorageMonitorWin
*>(
127 GetWindowLongPtr(hwnd
, GWLP_USERDATA
));
129 return msg_wnd
->WndProc(hwnd
, message
, wparam
, lparam
);
130 return ::DefWindowProc(hwnd
, message
, wparam
, lparam
);
133 LRESULT CALLBACK
StorageMonitorWin::WndProc(HWND hwnd
, UINT message
,
134 WPARAM wparam
, LPARAM lparam
) {
136 case WM_DEVICECHANGE
:
137 OnDeviceChange(static_cast<UINT
>(wparam
), lparam
);
143 return ::DefWindowProc(hwnd
, message
, wparam
, lparam
);
146 bool StorageMonitorWin::GetDeviceInfo(const base::FilePath
& device_path
,
147 StorageInfo
* info
) const {
150 // TODO(kmadhusu) Implement PortableDeviceWatcherWin::GetDeviceInfo()
151 // function when we have the functionality to add a sub directory of
152 // portable device as a media gallery.
153 return volume_mount_watcher_
->GetDeviceInfo(device_path
, info
);
156 void StorageMonitorWin::OnDeviceChange(UINT event_type
, LPARAM data
) {
157 volume_mount_watcher_
->OnWindowMessage(event_type
, data
);
158 portable_device_watcher_
->OnWindowMessage(event_type
, data
);
161 StorageMonitor
* StorageMonitor::Create() {
162 return new StorageMonitorWin(new VolumeMountWatcherWin(),
163 new PortableDeviceWatcherWin());