[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / components / storage_monitor / storage_monitor_win.cc
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/storage_monitor/storage_monitor_win.h"
6
7 #include <windows.h>
8 #include <dbt.h>
9 #include <fileapi.h>
10 #include <shlobj.h>
11 #include <stddef.h>
12
13 #include <utility>
14 #include <vector>
15
16 #include "base/logging.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/win/wrapped_window_proc.h"
19 #include "components/storage_monitor/portable_device_watcher_win.h"
20 #include "components/storage_monitor/removable_device_constants.h"
21 #include "components/storage_monitor/storage_info.h"
22 #include "components/storage_monitor/volume_mount_watcher_win.h"
23
24 #define WM_USER_MEDIACHANGED (WM_USER + 5)
25
26 // StorageMonitorWin -------------------------------------------------------
27
28 namespace storage_monitor {
29
30 StorageMonitorWin::StorageMonitorWin(
31     std::unique_ptr<VolumeMountWatcherWin> volume_mount_watcher,
32     std::unique_ptr<PortableDeviceWatcherWin> portable_device_watcher)
33     : volume_mount_watcher_(std::move(volume_mount_watcher)),
34       portable_device_watcher_(std::move(portable_device_watcher)) {
35   DCHECK(volume_mount_watcher_);
36   DCHECK(portable_device_watcher_);
37   volume_mount_watcher_->SetNotifications(receiver());
38   portable_device_watcher_->SetNotifications(receiver());
39 }
40
41 StorageMonitorWin::~StorageMonitorWin() {
42   if (shell_change_notify_id_)
43     SHChangeNotifyDeregister(shell_change_notify_id_);
44   volume_mount_watcher_->SetNotifications(nullptr);
45   portable_device_watcher_->SetNotifications(nullptr);
46
47   if (window_)
48     DestroyWindow(window_);
49
50   if (window_class_)
51     UnregisterClass(MAKEINTATOM(window_class_), instance_);
52 }
53
54 void StorageMonitorWin::Init() {
55   WNDCLASSEX window_class;
56   base::win::InitializeWindowClass(
57       L"Chrome_StorageMonitorWindow",
58       &base::win::WrappedWindowProc<StorageMonitorWin::WndProcThunk>, 0, 0, 0,
59       nullptr, nullptr, nullptr, nullptr, nullptr, &window_class);
60   instance_ = window_class.hInstance;
61   window_class_ = RegisterClassEx(&window_class);
62   DCHECK(window_class_);
63
64   window_ = CreateWindow(MAKEINTATOM(window_class_), nullptr, 0, 0, 0, 0, 0,
65                          nullptr, nullptr, instance_, nullptr);
66   SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
67   volume_mount_watcher_->Init();
68   portable_device_watcher_->Init(window_);
69   MediaChangeNotificationRegister();
70 }
71
72 bool StorageMonitorWin::GetStorageInfoForPath(const base::FilePath& path,
73                                               StorageInfo* device_info) const {
74   DCHECK(device_info);
75
76   // TODO(gbillock): Move this logic up to StorageMonitor.
77   // If we already know the StorageInfo for the path, just return it.
78   // This will account for portable devices as well.
79   std::vector<StorageInfo> attached_devices = GetAllAvailableStorages();
80   size_t best_parent = attached_devices.size();
81   size_t best_length = 0;
82   for (size_t i = 0; i < attached_devices.size(); i++) {
83     if (!StorageInfo::IsRemovableDevice(attached_devices[i].device_id()))
84       continue;
85     base::FilePath relative;
86     if (base::FilePath(attached_devices[i].location()).AppendRelativePath(
87             path, &relative)) {
88       // Note: the relative path is longer for shorter shared path between
89       // the path and the device mount point, so we want the shortest
90       // relative path.
91       if (relative.value().size() < best_length) {
92         best_parent = i;
93         best_length = relative.value().size();
94       }
95     }
96   }
97   if (best_parent != attached_devices.size()) {
98     *device_info = attached_devices[best_parent];
99     return true;
100   }
101
102   return GetDeviceInfo(path, device_info);
103 }
104
105 void StorageMonitorWin::EjectDevice(
106     const std::string& device_id,
107     base::OnceCallback<void(EjectStatus)> callback) {
108   StorageInfo::Type type;
109   if (!StorageInfo::CrackDeviceId(device_id, &type, nullptr)) {
110     std::move(callback).Run(EJECT_FAILURE);
111     return;
112   }
113
114   if (type == StorageInfo::MTP_OR_PTP)
115     portable_device_watcher_->EjectDevice(device_id, std::move(callback));
116   else if (StorageInfo::IsRemovableDevice(device_id))
117     volume_mount_watcher_->EjectDevice(device_id, std::move(callback));
118   else
119     std::move(callback).Run(EJECT_FAILURE);
120 }
121
122 bool StorageMonitorWin::GetMTPStorageInfoFromDeviceId(
123     const std::string& storage_device_id,
124     std::wstring* device_location,
125     std::wstring* storage_object_id) const {
126   StorageInfo::Type type;
127   StorageInfo::CrackDeviceId(storage_device_id, &type, nullptr);
128   if (type != StorageInfo::MTP_OR_PTP)
129     return false;
130   return portable_device_watcher_->GetMTPStorageInfoFromDeviceId(
131       storage_device_id, device_location, storage_object_id);
132 }
133
134 // static
135 LRESULT CALLBACK StorageMonitorWin::WndProcThunk(HWND hwnd, UINT message,
136                                                  WPARAM wparam, LPARAM lparam) {
137   StorageMonitorWin* msg_wnd = reinterpret_cast<StorageMonitorWin*>(
138       GetWindowLongPtr(hwnd, GWLP_USERDATA));
139   if (msg_wnd)
140     return msg_wnd->WndProc(hwnd, message, wparam, lparam);
141   return ::DefWindowProc(hwnd, message, wparam, lparam);
142 }
143
144 LRESULT CALLBACK StorageMonitorWin::WndProc(HWND hwnd, UINT message,
145                                             WPARAM wparam, LPARAM lparam) {
146   switch (message) {
147     case WM_DEVICECHANGE:
148       OnDeviceChange(static_cast<UINT>(wparam), lparam);
149       return TRUE;
150     case WM_USER_MEDIACHANGED:
151       OnMediaChange(wparam, lparam);
152       return TRUE;
153     default:
154       break;
155   }
156
157   return ::DefWindowProc(hwnd, message, wparam, lparam);
158 }
159
160 void StorageMonitorWin::MediaChangeNotificationRegister() {
161   LPITEMIDLIST id_list;
162   if (SHGetSpecialFolderLocation(nullptr, CSIDL_DRIVES, &id_list) == NOERROR) {
163     SHChangeNotifyEntry notify_entry;
164     notify_entry.pidl = id_list;
165     notify_entry.fRecursive = TRUE;
166     shell_change_notify_id_ = SHChangeNotifyRegister(
167         window_, SHCNRF_ShellLevel, SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
168         WM_USER_MEDIACHANGED, 1, &notify_entry);
169     if (!shell_change_notify_id_)
170       DVLOG(1) << "SHChangeNotifyRegister FAILED";
171   } else {
172     DVLOG(1) << "SHGetSpecialFolderLocation FAILED";
173   }
174 }
175
176 bool StorageMonitorWin::GetDeviceInfo(const base::FilePath& device_path,
177                                       StorageInfo* info) const {
178   DCHECK(info);
179
180   // TODO(kmadhusu) Implement PortableDeviceWatcherWin::GetDeviceInfo()
181   // function when we have the functionality to add a sub directory of
182   // portable device as a media gallery.
183   return volume_mount_watcher_->GetDeviceInfo(device_path, info);
184 }
185
186 void StorageMonitorWin::OnDeviceChange(UINT event_type, LPARAM data) {
187   DVLOG(1) << "OnDeviceChange " << event_type << " " << data;
188   volume_mount_watcher_->OnWindowMessage(event_type, data);
189   portable_device_watcher_->OnWindowMessage(event_type, data);
190 }
191
192 void StorageMonitorWin::OnMediaChange(WPARAM wparam, LPARAM lparam) {
193   volume_mount_watcher_->OnMediaChange(wparam, lparam);
194 }
195
196 StorageMonitor* StorageMonitor::CreateInternal() {
197   return new StorageMonitorWin(std::make_unique<VolumeMountWatcherWin>(),
198                                std::make_unique<PortableDeviceWatcherWin>());
199 }
200
201 }  // namespace storage_monitor