OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "webkit/fileapi/media_file_system_proxy_win.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/location.h" | |
11 #include "base/logging.h" | |
12 #include "base/sequenced_task_runner.h" | |
13 #include "webkit/fileapi/file_system_operation_context.h" | |
14 | |
15 // const wchar_t ?? | |
16 #define CLIENT_NAME L"WPD Chromium" | |
17 #define CLIENT_MAJOR_VER 1 | |
18 #define CLIENT_MINOR_VER 0 | |
19 #define CLIENT_REVISION 2 | |
20 #define NUM_OBJECTS_TO_REQUEST 10 | |
21 | |
22 using fileapi::FileSystemURL; | |
23 | |
24 namespace fileapi { | |
25 | |
26 using base::Bind; | |
27 using base::Callback; | |
28 using base::Owned; | |
29 using base::PlatformFileError; | |
30 using base::Unretained; | |
31 | |
32 namespace { | |
33 | |
34 typedef fileapi::MediaFileSystemProxyWin Proxy; | |
35 | |
36 class ReadDirectoryHelper { | |
37 public: | |
38 ReadDirectoryHelper() : error_(base::PLATFORM_FILE_OK) {} | |
39 | |
40 void RunWork(IPortableDevice* pDevice, | |
41 const FilePath::StringType& device_id) { | |
42 base::win::ScopedComPtr<IPortableDeviceValues> client_info; | |
43 // Fill out information about your application, so the device knows | |
44 // who they are speaking to. Client information is optional. The client | |
45 // can choose to identify itself, or to remain unknown to the driver. It is | |
46 // beneficial to identify yourself because drivers may be able to optimize | |
47 // their behavior for known clients. | |
48 | |
49 // CoCreate an IPortableDeviceValues interface to hold the client | |
50 // information. | |
51 HRESULT hr = client_info.CreateInstance(__uuidof(PortableDeviceValues), | |
52 NULL, CLSCTX_INPROC_SERVER); | |
53 if (FAILED(hr)) { | |
54 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
55 return; | |
56 } | |
57 // Attempt to set all bits of client information | |
58 hr = client_info->SetStringValue(WPD_CLIENT_NAME, CLIENT_NAME); | |
59 if (FAILED(hr)) { | |
60 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
61 return; | |
62 } | |
63 hr = client_info->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, | |
64 CLIENT_MAJOR_VER); | |
65 if (FAILED(hr)) { | |
66 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
67 return; | |
68 } | |
69 hr = client_info->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, | |
70 CLIENT_REVISION); | |
71 if (FAILED(hr)) { | |
72 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
73 return; | |
74 } | |
75 // Some device drivers need to impersonate the caller in order to function | |
76 // correctly. Since our application does not need to restrict its identity, | |
77 // specify SECURITY_IMPERSONATION so that we work with all devices. | |
78 hr = client_info->SetUnsignedIntegerValue( | |
79 WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); | |
80 if (FAILED(hr)) { | |
81 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
82 return; | |
83 } | |
84 | |
85 hr = pDevice->Open(const_cast<wchar_t*>(device_id.c_str()), client_info); | |
86 if (FAILED(hr)) { | |
87 if (hr == E_ACCESSDENIED) { | |
88 // Failed to Open the device for Read Write access, will open it for | |
89 // Read-only access instead. | |
90 client_info->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, | |
91 GENERIC_READ); | |
92 hr = pDevice->Open(const_cast<wchar_t*>(device_id.c_str()), client_info) ; | |
kinuko
2012/07/18 10:33:24
nit: over 80 cols (here and more lines after 129-)
| |
93 if (FAILED(hr)) { | |
94 error_ = base::PLATFORM_FILE_ERROR_ACCESS_DENIED; | |
95 return; | |
96 } | |
97 } else { | |
98 error_ = base::PLATFORM_FILE_ERROR_ACCESS_DENIED; | |
99 return; | |
100 } | |
101 } | |
102 | |
103 base::win::ScopedComPtr<IPortableDeviceContent> pContent; | |
104 hr = pDevice->Content(pContent.Receive()); | |
105 if (FAILED(hr)) { | |
106 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
107 return; | |
108 } | |
109 | |
110 base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> pEnumObjectIDs; | |
111 | |
112 // Get an IEnumPortableDeviceObjectIDs interface by calling EnumObjects | |
113 // with the specified parent object identifier. | |
114 hr = pContent->EnumObjects(0, // Flags are unused | |
115 WPD_DEVICE_OBJECT_ID, | |
116 NULL, // Filter is unused | |
117 pEnumObjectIDs.Receive()); | |
118 if (FAILED(hr)) | |
119 { | |
120 error_ = base::PLATFORM_FILE_ERROR_FAILED; | |
121 return; | |
122 } | |
123 | |
124 // Loop calling Next() while S_OK is being returned. | |
125 while(hr == S_OK) | |
126 { | |
127 DWORD cFetched = 0; | |
128 PWSTR szObjectIDArray[NUM_OBJECTS_TO_REQUEST] = {0}; | |
129 hr = pEnumObjectIDs->Next(NUM_OBJECTS_TO_REQUEST, // Number of objects to request on each NEXT call | |
130 szObjectIDArray, // Array of PWSTR ar ray which will be populated on each NEXT call | |
131 &cFetched); // Number of objects written to the PWSTR array | |
132 if (SUCCEEDED(hr)) | |
133 { | |
134 // Traverse the results of the Next() operation and recursively enum erate | |
135 // Remember to free all returned object identifiers using CoTaskMemF ree() | |
136 for (DWORD dwIndex = 0; dwIndex < cFetched; dwIndex++) | |
137 { | |
138 // TODO(kmadhusu): Get the object properties. | |
139 base::FileUtilProxy::Entry entry; | |
140 entry.is_directory = (dwIndex%2) ? true: false; | |
141 entry.name = szObjectIDArray[dwIndex]; | |
142 entry.size = dwIndex * 100; | |
143 entries_.push_back(entry); | |
144 printf("%ws\n",szObjectIDArray[dwIndex]); | |
145 | |
146 // Free allocated PWSTRs after the recursive enumeration call ha s completed. | |
147 CoTaskMemFree(szObjectIDArray[dwIndex]); | |
148 szObjectIDArray[dwIndex] = NULL; | |
149 } | |
150 } | |
151 } | |
152 | |
153 // Enumerate the device content and populate entries. | |
154 } | |
155 | |
156 void Reply(const Proxy::ReadDirectoryCallback& callback) { | |
157 if (!callback.is_null()) | |
158 callback.Run(error_, entries_, false /* has_more */); | |
159 } | |
160 | |
161 private: | |
162 base::PlatformFileError error_; | |
163 std::vector<Proxy::Entry> entries_; | |
164 DISALLOW_COPY_AND_ASSIGN(ReadDirectoryHelper); | |
165 }; | |
166 | |
167 } // namespace | |
168 | |
169 MediaFileSystemProxyWin::MediaFileSystemProxyWin(const FilePath::StringType& dev ice_id) | |
170 : device_id_(device_id) { | |
171 // TODO(kmadhusu): Check if the portable device library is available in SDK. | |
172 CoInitialize(NULL); | |
173 HRESULT hr = portable_device_.CreateInstance(__uuidof(PortableDeviceFTM), | |
174 NULL, CLSCTX_INPROC_SERVER); | |
175 DCHECK(SUCCEEDED(hr)); | |
176 } | |
177 | |
178 MediaFileSystemProxyWin::~MediaFileSystemProxyWin() { | |
179 portable_device_.Release(); | |
180 CoUninitialize(); | |
181 } | |
182 | |
183 void MediaFileSystemProxyWin::GetFileInfo(const FileSystemURL& url, | |
184 const FileSystemOperationInterface::GetMetadataCallback& callback) { | |
185 NOTIMPLEMENTED(); | |
186 } | |
187 | |
188 void MediaFileSystemProxyWin::Copy( | |
189 const FileSystemURL& src_url, | |
190 const FileSystemURL& dest_url, | |
191 const FileSystemOperationInterface::StatusCallback& callback) { | |
192 NOTIMPLEMENTED(); | |
193 } | |
194 | |
195 void MediaFileSystemProxyWin::Move( | |
196 const FileSystemURL& src_url, | |
197 const FileSystemURL& dest_url, | |
198 const FileSystemOperationInterface::StatusCallback& callback){ | |
199 NOTIMPLEMENTED(); | |
200 } | |
201 | |
202 void MediaFileSystemProxyWin::ReadDirectory( | |
203 FileSystemOperationContext* context, | |
kinuko
2012/07/18 10:33:24
You don't probably need to pass this here, but ins
| |
204 const FileSystemURL& url, | |
kinuko
2012/07/18 10:33:24
How do you use the URL (from which you can access
| |
205 const FileSystemOperationInterface::ReadDirectoryCallback& callback){ | |
206 NOTIMPLEMENTED(); | |
207 ReadDirectoryHelper* helper = new ReadDirectoryHelper; | |
208 context->file_task_runner()->PostTaskAndReply( | |
kinuko
2012/07/18 10:33:24
As we talked offline I think we'd better separate
kinuko
2012/07/18 14:51:44
I was thinking about the architecture a bit furthe
kmadhusu
2012/07/19 00:57:50
Thanks for your comments. I discussed about this a
| |
209 FROM_HERE, | |
210 Bind(&ReadDirectoryHelper::RunWork, Unretained(helper), | |
211 portable_device_.get(), device_id_), | |
212 Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback)); | |
213 } | |
214 | |
215 void MediaFileSystemProxyWin::Remove(const FileSystemURL& url, bool recursive, | |
216 const FileSystemOperationInterface::StatusCallback& callback){ | |
217 NOTIMPLEMENTED(); | |
218 } | |
219 | |
220 void MediaFileSystemProxyWin::CreateDirectory( | |
221 const FileSystemURL& url, | |
222 bool exclusive, | |
223 bool recursive, | |
224 const FileSystemOperationInterface::StatusCallback& callback){ | |
225 NOTIMPLEMENTED(); | |
226 } | |
227 | |
228 void MediaFileSystemProxyWin::CreateFile( | |
229 const FileSystemURL& url, | |
230 bool exclusive, | |
231 const FileSystemOperationInterface::StatusCallback& callback){ | |
232 NOTIMPLEMENTED(); | |
233 } | |
234 | |
235 void MediaFileSystemProxyWin::OpenFile( | |
236 const FileSystemURL& url, | |
237 int flags, | |
238 base::ProcessHandle peer_handle, | |
239 const FileSystemOperationInterface::OpenFileCallback& callback){ | |
240 NOTIMPLEMENTED(); | |
241 } | |
242 | |
243 void MediaFileSystemProxyWin::NotifyCloseFile(const FileSystemURL& url){ | |
244 NOTIMPLEMENTED(); | |
245 } | |
246 | |
247 } | |
OLD | NEW |