Chromium Code Reviews| Index: webkit/fileapi/media_file_system_proxy_win.cc |
| diff --git a/webkit/fileapi/media_file_system_proxy_win.cc b/webkit/fileapi/media_file_system_proxy_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..03f59ba7b79d1af60f8ccc2da4d6d1959cfb7559 |
| --- /dev/null |
| +++ b/webkit/fileapi/media_file_system_proxy_win.cc |
| @@ -0,0 +1,247 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "webkit/fileapi/media_file_system_proxy_win.h" |
| + |
| +#include <windows.h> |
| + |
| +#include "base/bind.h" |
| +#include "base/location.h" |
| +#include "base/logging.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "webkit/fileapi/file_system_operation_context.h" |
| + |
| +// const wchar_t ?? |
| +#define CLIENT_NAME L"WPD Chromium" |
| +#define CLIENT_MAJOR_VER 1 |
| +#define CLIENT_MINOR_VER 0 |
| +#define CLIENT_REVISION 2 |
| +#define NUM_OBJECTS_TO_REQUEST 10 |
| + |
| +using fileapi::FileSystemURL; |
| + |
| +namespace fileapi { |
| + |
| +using base::Bind; |
| +using base::Callback; |
| +using base::Owned; |
| +using base::PlatformFileError; |
| +using base::Unretained; |
| + |
| +namespace { |
| + |
| +typedef fileapi::MediaFileSystemProxyWin Proxy; |
| + |
| +class ReadDirectoryHelper { |
| + public: |
| + ReadDirectoryHelper() : error_(base::PLATFORM_FILE_OK) {} |
| + |
| + void RunWork(IPortableDevice* pDevice, |
| + const FilePath::StringType& device_id) { |
| + base::win::ScopedComPtr<IPortableDeviceValues> client_info; |
| + // Fill out information about your application, so the device knows |
| + // who they are speaking to. Client information is optional. The client |
| + // can choose to identify itself, or to remain unknown to the driver. It is |
| + // beneficial to identify yourself because drivers may be able to optimize |
| + // their behavior for known clients. |
| + |
| + // CoCreate an IPortableDeviceValues interface to hold the client |
| + // information. |
| + HRESULT hr = client_info.CreateInstance(__uuidof(PortableDeviceValues), |
| + NULL, CLSCTX_INPROC_SERVER); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + // Attempt to set all bits of client information |
| + hr = client_info->SetStringValue(WPD_CLIENT_NAME, CLIENT_NAME); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + hr = client_info->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, |
| + CLIENT_MAJOR_VER); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + hr = client_info->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, |
| + CLIENT_REVISION); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + // Some device drivers need to impersonate the caller in order to function |
| + // correctly. Since our application does not need to restrict its identity, |
| + // specify SECURITY_IMPERSONATION so that we work with all devices. |
| + hr = client_info->SetUnsignedIntegerValue( |
| + WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + |
| + hr = pDevice->Open(const_cast<wchar_t*>(device_id.c_str()), client_info); |
| + if (FAILED(hr)) { |
| + if (hr == E_ACCESSDENIED) { |
| + // Failed to Open the device for Read Write access, will open it for |
| + // Read-only access instead. |
| + client_info->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, |
| + GENERIC_READ); |
| + 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-)
|
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_ACCESS_DENIED; |
| + return; |
| + } |
| + } else { |
| + error_ = base::PLATFORM_FILE_ERROR_ACCESS_DENIED; |
| + return; |
| + } |
| + } |
| + |
| + base::win::ScopedComPtr<IPortableDeviceContent> pContent; |
| + hr = pDevice->Content(pContent.Receive()); |
| + if (FAILED(hr)) { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + |
| + base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> pEnumObjectIDs; |
| + |
| + // Get an IEnumPortableDeviceObjectIDs interface by calling EnumObjects |
| + // with the specified parent object identifier. |
| + hr = pContent->EnumObjects(0, // Flags are unused |
| + WPD_DEVICE_OBJECT_ID, |
| + NULL, // Filter is unused |
| + pEnumObjectIDs.Receive()); |
| + if (FAILED(hr)) |
| + { |
| + error_ = base::PLATFORM_FILE_ERROR_FAILED; |
| + return; |
| + } |
| + |
| + // Loop calling Next() while S_OK is being returned. |
| + while(hr == S_OK) |
| + { |
| + DWORD cFetched = 0; |
| + PWSTR szObjectIDArray[NUM_OBJECTS_TO_REQUEST] = {0}; |
| + hr = pEnumObjectIDs->Next(NUM_OBJECTS_TO_REQUEST, // Number of objects to request on each NEXT call |
| + szObjectIDArray, // Array of PWSTR array which will be populated on each NEXT call |
| + &cFetched); // Number of objects written to the PWSTR array |
| + if (SUCCEEDED(hr)) |
| + { |
| + // Traverse the results of the Next() operation and recursively enumerate |
| + // Remember to free all returned object identifiers using CoTaskMemFree() |
| + for (DWORD dwIndex = 0; dwIndex < cFetched; dwIndex++) |
| + { |
| + // TODO(kmadhusu): Get the object properties. |
| + base::FileUtilProxy::Entry entry; |
| + entry.is_directory = (dwIndex%2) ? true: false; |
| + entry.name = szObjectIDArray[dwIndex]; |
| + entry.size = dwIndex * 100; |
| + entries_.push_back(entry); |
| + printf("%ws\n",szObjectIDArray[dwIndex]); |
| + |
| + // Free allocated PWSTRs after the recursive enumeration call has completed. |
| + CoTaskMemFree(szObjectIDArray[dwIndex]); |
| + szObjectIDArray[dwIndex] = NULL; |
| + } |
| + } |
| + } |
| + |
| + // Enumerate the device content and populate entries. |
| + } |
| + |
| + void Reply(const Proxy::ReadDirectoryCallback& callback) { |
| + if (!callback.is_null()) |
| + callback.Run(error_, entries_, false /* has_more */); |
| + } |
| + |
| + private: |
| + base::PlatformFileError error_; |
| + std::vector<Proxy::Entry> entries_; |
| + DISALLOW_COPY_AND_ASSIGN(ReadDirectoryHelper); |
| +}; |
| + |
| +} // namespace |
| + |
| +MediaFileSystemProxyWin::MediaFileSystemProxyWin(const FilePath::StringType& device_id) |
| + : device_id_(device_id) { |
| + // TODO(kmadhusu): Check if the portable device library is available in SDK. |
| + CoInitialize(NULL); |
| + HRESULT hr = portable_device_.CreateInstance(__uuidof(PortableDeviceFTM), |
| + NULL, CLSCTX_INPROC_SERVER); |
| + DCHECK(SUCCEEDED(hr)); |
| +} |
| + |
| +MediaFileSystemProxyWin::~MediaFileSystemProxyWin() { |
| + portable_device_.Release(); |
| + CoUninitialize(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::GetFileInfo(const FileSystemURL& url, |
| + const FileSystemOperationInterface::GetMetadataCallback& callback) { |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::Copy( |
| + const FileSystemURL& src_url, |
| + const FileSystemURL& dest_url, |
| + const FileSystemOperationInterface::StatusCallback& callback) { |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::Move( |
| + const FileSystemURL& src_url, |
| + const FileSystemURL& dest_url, |
| + const FileSystemOperationInterface::StatusCallback& callback){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::ReadDirectory( |
| + FileSystemOperationContext* context, |
|
kinuko
2012/07/18 10:33:24
You don't probably need to pass this here, but ins
|
| + const FileSystemURL& url, |
|
kinuko
2012/07/18 10:33:24
How do you use the URL (from which you can access
|
| + const FileSystemOperationInterface::ReadDirectoryCallback& callback){ |
| + NOTIMPLEMENTED(); |
| + ReadDirectoryHelper* helper = new ReadDirectoryHelper; |
| + 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
|
| + FROM_HERE, |
| + Bind(&ReadDirectoryHelper::RunWork, Unretained(helper), |
| + portable_device_.get(), device_id_), |
| + Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback)); |
| +} |
| + |
| +void MediaFileSystemProxyWin::Remove(const FileSystemURL& url, bool recursive, |
| + const FileSystemOperationInterface::StatusCallback& callback){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::CreateDirectory( |
| + const FileSystemURL& url, |
| + bool exclusive, |
| + bool recursive, |
| + const FileSystemOperationInterface::StatusCallback& callback){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::CreateFile( |
| + const FileSystemURL& url, |
| + bool exclusive, |
| + const FileSystemOperationInterface::StatusCallback& callback){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::OpenFile( |
| + const FileSystemURL& url, |
| + int flags, |
| + base::ProcessHandle peer_handle, |
| + const FileSystemOperationInterface::OpenFileCallback& callback){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void MediaFileSystemProxyWin::NotifyCloseFile(const FileSystemURL& url){ |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +} |