Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.
[chromium-blink-merge.git] / components / storage_monitor / storage_monitor_win.cc
blob95a6911552d83a20827bdd9bb29a876131652fc7
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.
5 #include "components/storage_monitor/storage_monitor_win.h"
7 #include <windows.h>
8 #include <dbt.h>
9 #include <fileapi.h>
10 #include <shlobj.h>
12 #include "base/win/wrapped_window_proc.h"
13 #include "components/storage_monitor/portable_device_watcher_win.h"
14 #include "components/storage_monitor/removable_device_constants.h"
15 #include "components/storage_monitor/storage_info.h"
16 #include "components/storage_monitor/volume_mount_watcher_win.h"
18 #define WM_USER_MEDIACHANGED (WM_USER + 5)
20 // StorageMonitorWin -------------------------------------------------------
22 namespace storage_monitor {
24 StorageMonitorWin::StorageMonitorWin(
25 VolumeMountWatcherWin* volume_mount_watcher,
26 PortableDeviceWatcherWin* portable_device_watcher)
27 : window_class_(0),
28 instance_(NULL),
29 window_(NULL),
30 shell_change_notify_id_(0),
31 volume_mount_watcher_(volume_mount_watcher),
32 portable_device_watcher_(portable_device_watcher) {
33 DCHECK(volume_mount_watcher_);
34 DCHECK(portable_device_watcher_);
35 volume_mount_watcher_->SetNotifications(receiver());
36 portable_device_watcher_->SetNotifications(receiver());
39 StorageMonitorWin::~StorageMonitorWin() {
40 if (shell_change_notify_id_)
41 SHChangeNotifyDeregister(shell_change_notify_id_);
42 volume_mount_watcher_->SetNotifications(NULL);
43 portable_device_watcher_->SetNotifications(NULL);
45 if (window_)
46 DestroyWindow(window_);
48 if (window_class_)
49 UnregisterClass(MAKEINTATOM(window_class_), instance_);
52 void StorageMonitorWin::Init() {
53 WNDCLASSEX window_class;
54 base::win::InitializeWindowClass(
55 L"Chrome_StorageMonitorWindow",
56 &base::win::WrappedWindowProc<StorageMonitorWin::WndProcThunk>,
57 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
58 &window_class);
59 instance_ = window_class.hInstance;
60 window_class_ = RegisterClassEx(&window_class);
61 DCHECK(window_class_);
63 window_ = CreateWindow(MAKEINTATOM(window_class_), 0, 0, 0, 0, 0, 0, 0, 0,
64 instance_, 0);
65 SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
66 volume_mount_watcher_->Init();
67 portable_device_watcher_->Init(window_);
68 MediaChangeNotificationRegister();
71 bool StorageMonitorWin::GetStorageInfoForPath(const base::FilePath& path,
72 StorageInfo* device_info) const {
73 DCHECK(device_info);
75 // TODO(gbillock): Move this logic up to StorageMonitor.
76 // If we already know the StorageInfo for the path, just return it.
77 // This will account for portable devices as well.
78 std::vector<StorageInfo> attached_devices = GetAllAvailableStorages();
79 size_t best_parent = attached_devices.size();
80 size_t best_length = 0;
81 for (size_t i = 0; i < attached_devices.size(); i++) {
82 if (!StorageInfo::IsRemovableDevice(attached_devices[i].device_id()))
83 continue;
84 base::FilePath relative;
85 if (base::FilePath(attached_devices[i].location()).AppendRelativePath(
86 path, &relative)) {
87 // Note: the relative path is longer for shorter shared path between
88 // the path and the device mount point, so we want the shortest
89 // relative path.
90 if (relative.value().size() < best_length) {
91 best_parent = i;
92 best_length = relative.value().size();
96 if (best_parent != attached_devices.size()) {
97 *device_info = attached_devices[best_parent];
98 return true;
101 return GetDeviceInfo(path, device_info);
104 void StorageMonitorWin::EjectDevice(
105 const std::string& device_id,
106 base::Callback<void(EjectStatus)> callback) {
107 StorageInfo::Type type;
108 if (!StorageInfo::CrackDeviceId(device_id, &type, NULL)) {
109 callback.Run(EJECT_FAILURE);
110 return;
113 if (type == StorageInfo::MTP_OR_PTP)
114 portable_device_watcher_->EjectDevice(device_id, callback);
115 else if (StorageInfo::IsRemovableDevice(device_id))
116 volume_mount_watcher_->EjectDevice(device_id, callback);
117 else
118 callback.Run(EJECT_FAILURE);
121 bool StorageMonitorWin::GetMTPStorageInfoFromDeviceId(
122 const std::string& storage_device_id,
123 base::string16* device_location,
124 base::string16* storage_object_id) const {
125 StorageInfo::Type type;
126 StorageInfo::CrackDeviceId(storage_device_id, &type, NULL);
127 return ((type == StorageInfo::MTP_OR_PTP) &&
128 portable_device_watcher_->GetMTPStorageInfoFromDeviceId(
129 storage_device_id, device_location, storage_object_id));
132 // static
133 LRESULT CALLBACK StorageMonitorWin::WndProcThunk(HWND hwnd, UINT message,
134 WPARAM wparam, LPARAM lparam) {
135 StorageMonitorWin* msg_wnd = reinterpret_cast<StorageMonitorWin*>(
136 GetWindowLongPtr(hwnd, GWLP_USERDATA));
137 if (msg_wnd)
138 return msg_wnd->WndProc(hwnd, message, wparam, lparam);
139 return ::DefWindowProc(hwnd, message, wparam, lparam);
142 LRESULT CALLBACK StorageMonitorWin::WndProc(HWND hwnd, UINT message,
143 WPARAM wparam, LPARAM lparam) {
144 switch (message) {
145 case WM_DEVICECHANGE:
146 OnDeviceChange(static_cast<UINT>(wparam), lparam);
147 return TRUE;
148 case WM_USER_MEDIACHANGED:
149 OnMediaChange(wparam, lparam);
150 return TRUE;
151 default:
152 break;
155 return ::DefWindowProc(hwnd, message, wparam, lparam);
158 void StorageMonitorWin::MediaChangeNotificationRegister() {
159 LPITEMIDLIST id_list;
160 if (SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &id_list) == NOERROR) {
161 SHChangeNotifyEntry notify_entry;
162 notify_entry.pidl = id_list;
163 notify_entry.fRecursive = TRUE;
164 shell_change_notify_id_ = SHChangeNotifyRegister(
165 window_, SHCNRF_ShellLevel, SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
166 WM_USER_MEDIACHANGED, 1, &notify_entry);
167 if (!shell_change_notify_id_)
168 DVLOG(1) << "SHChangeNotifyRegister FAILED";
169 } else {
170 DVLOG(1) << "SHGetSpecialFolderLocation FAILED";
174 bool StorageMonitorWin::GetDeviceInfo(const base::FilePath& device_path,
175 StorageInfo* info) const {
176 DCHECK(info);
178 // TODO(kmadhusu) Implement PortableDeviceWatcherWin::GetDeviceInfo()
179 // function when we have the functionality to add a sub directory of
180 // portable device as a media gallery.
181 return volume_mount_watcher_->GetDeviceInfo(device_path, info);
184 void StorageMonitorWin::OnDeviceChange(UINT event_type, LPARAM data) {
185 DVLOG(1) << "OnDeviceChange " << event_type << " " << data;
186 volume_mount_watcher_->OnWindowMessage(event_type, data);
187 portable_device_watcher_->OnWindowMessage(event_type, data);
190 void StorageMonitorWin::OnMediaChange(WPARAM wparam, LPARAM lparam) {
191 volume_mount_watcher_->OnMediaChange(wparam, lparam);
194 StorageMonitor* StorageMonitor::CreateInternal() {
195 return new StorageMonitorWin(new VolumeMountWatcherWin(),
196 new PortableDeviceWatcherWin());
199 } // namespace storage_monitor