Chromium Code Reviews| 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 |