Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: chrome/browser/media_gallery/win/mtp_device_delegate_impl_win.cc

Issue 11297002: [Media Gallery] Added code to support mtp device media file system on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase + IWYU Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 // MTPDeviceDelegateImplWin implementation.
6
7 #include "chrome/browser/media_gallery/win/mtp_device_delegate_impl_win.h"
8
9 #include <portabledevice.h>
10 #include <vector>
11
12 #include "base/file_path.h"
13 #include "base/file_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/sequenced_task_runner_helpers.h"
17 #include "base/string_split.h"
18 #include "base/string_util.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "base/utf_string_conversions.h"
21 #include "chrome/browser/media_gallery/win/mtp_device_object_entry.h"
22 #include "chrome/browser/media_gallery/win/mtp_device_object_enumerator.h"
23 #include "chrome/browser/media_gallery/win/mtp_device_operations_util.h"
24 #include "chrome/browser/media_gallery/win/recursive_mtp_device_object_enumerato r.h"
25 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi n.h"
26 #include "chrome/browser/system_monitor/removable_storage_notifications.h"
27 #include "content/public/browser/browser_thread.h"
28
29 namespace chrome {
30
31 namespace {
32
33 // Gets the details of the MTP partition storage specified by the
34 // |storage_path| on the UI thread. If the storage details are valid, creates a
35 // MTP device delegate on the media task runner.
36 void GetStorageInfoAndMaybeCreateDelegate(
37 const string16& storage_path,
38 const scoped_refptr<base::SequencedTaskRunner>& media_task_runner,
39 const CreateMTPDeviceDelegateCallback& callback) {
40 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
41 DCHECK(!storage_path.empty());
42 DCHECK(media_task_runner.get());
43 string16 storage_device_id;
44 RemoveChars(storage_path, L"\\\\", &storage_device_id);
45 DCHECK(!storage_device_id.empty());
46 RemovableStorageNotifications* notifications =
47 RemovableStorageNotifications::GetInstance();
48 DCHECK(notifications);
49 string16 pnp_device_id;
50 string16 storage_object_id;
51 if ((!notifications->GetMTPStorageInfoFromDeviceId(
52 UTF16ToUTF8(storage_device_id), &pnp_device_id,
53 &storage_object_id)) ||
54 pnp_device_id.empty() ||
55 storage_object_id.empty())
56 return;
57 media_task_runner->PostTask(FROM_HERE,
58 base::Bind(&OnGotStorageInfoCreateDelegate,
59 storage_path,
60 media_task_runner,
61 callback,
62 pnp_device_id,
63 storage_object_id));
64 }
65
66 } // namespace
67
68 // Used by GetStorageInfoAndMaybeCreateDelegate() to create the MTP device
69 // delegate on the media task runner.
70 void OnGotStorageInfoCreateDelegate(
71 const string16& device_location,
72 base::SequencedTaskRunner* media_task_runner,
73 const CreateMTPDeviceDelegateCallback& callback,
74 const string16& pnp_device_id,
75 const string16& storage_object_id) {
76 DCHECK(media_task_runner);
77 DCHECK(media_task_runner->RunsTasksOnCurrentThread());
78 callback.Run(new MTPDeviceDelegateImplWin(device_location,
79 pnp_device_id,
80 storage_object_id,
81 media_task_runner));
82 }
83
84 void CreateMTPDeviceDelegate(const string16& device_location,
85 base::SequencedTaskRunner* media_task_runner,
86 const CreateMTPDeviceDelegateCallback& callback) {
87 DCHECK(media_task_runner);
88 DCHECK(media_task_runner->RunsTasksOnCurrentThread());
89 content::BrowserThread::PostTask(
90 content::BrowserThread::UI, FROM_HERE,
91 base::Bind(&GetStorageInfoAndMaybeCreateDelegate,
92 device_location,
93 make_scoped_refptr(media_task_runner),
94 callback));
95 }
96
97 // MTPDeviceDelegateImplWin ---------------------------------------------------
98
99 MTPDeviceDelegateImplWin::MTPDeviceDelegateImplWin(
100 const string16& fs_root_path,
101 const string16& pnp_device_id,
102 const string16& storage_object_id,
103 base::SequencedTaskRunner* media_task_runner)
104 : registered_device_path_(fs_root_path),
105 pnp_device_id_(pnp_device_id),
106 storage_object_id_(storage_object_id),
107 media_task_runner_(media_task_runner),
108 cancel_pending_tasks_(false) {
109 DCHECK(!pnp_device_id_.empty());
110 DCHECK(!storage_object_id_.empty());
111 DCHECK(media_task_runner_.get());
112 }
113
114 MTPDeviceDelegateImplWin::~MTPDeviceDelegateImplWin() {
115 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
116 }
117
118 base::PlatformFileError MTPDeviceDelegateImplWin::GetFileInfo(
119 const FilePath& file_path,
120 base::PlatformFileInfo* file_info) {
121 if (!LazyInit())
122 return base::PLATFORM_FILE_ERROR_FAILED;
123 string16 object_id = GetFileObjectIdFromPath(file_path.value());
124 if (object_id.empty())
125 return base::PLATFORM_FILE_ERROR_FAILED;
126 return media_transfer_protocol::GetFileEntryInfo(device_.get(), object_id,
127 file_info);
128 }
129
130 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator>
131 MTPDeviceDelegateImplWin::CreateFileEnumerator(const FilePath& root,
132 bool recursive) {
133 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator>
134 file_enumerator(new fileapi::FileSystemFileUtil::EmptyFileEnumerator());
135 if (root.empty() || !LazyInit())
136 return file_enumerator.Pass();
137
138 string16 object_id = GetFileObjectIdFromPath(root.value());
139 if (object_id.empty())
140 return file_enumerator.Pass();
141
142 MTPDeviceObjectEntries entries;
143 if (!media_transfer_protocol::GetDirectoryEntries(device_.get(), object_id,
144 &entries) ||
145 entries.empty())
146 return file_enumerator.Pass();
147
148 if (recursive) {
149 file_enumerator.reset(
150 new RecursiveMTPDeviceObjectEnumerator(device_.get(), entries));
151 } else {
152 file_enumerator.reset(new MTPDeviceObjectEnumerator(entries));
153 }
154 return file_enumerator.Pass();
155 }
156
157 base::PlatformFileError MTPDeviceDelegateImplWin::CreateSnapshotFile(
158 const FilePath& device_file_path,
159 const FilePath& local_path,
160 base::PlatformFileInfo* file_info) {
161 if (!LazyInit())
162 return base::PLATFORM_FILE_ERROR_FAILED;
163 string16 file_object_id = GetFileObjectIdFromPath(device_file_path.value());
164 if (file_object_id.empty())
165 return base::PLATFORM_FILE_ERROR_FAILED;
166 base::PlatformFileError error = GetFileInfo(device_file_path, file_info);
167 if (error != base::PLATFORM_FILE_OK)
168 return error;
169 if (!media_transfer_protocol::WriteFileObjectContentToPath(device_.get(),
170 file_object_id,
171 local_path))
172 return base::PLATFORM_FILE_ERROR_FAILED;
173
174 // LocalFileStreamReader is used to read the contents of the snapshot file.
175 // Snapshot file modification time does not match the last modified time
176 // of the original media file. Therefore, set the last modified time to null
177 // in order to avoid the verification in LocalFileStreamReader.
178 //
179 // Users will use HTML5 FileSystem Entry getMetadata() interface to get the
180 // actual last modified time of the media file.
181 file_info->last_modified = base::Time();
182 return error;
183 }
184
185 void MTPDeviceDelegateImplWin::CancelPendingTasksAndDeleteDelegate() {
186 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
187 {
188 base::AutoLock locked(cancel_tasks_lock_);
189 cancel_pending_tasks_ = true;
190 }
191 media_task_runner_->DeleteSoon(FROM_HERE, this);
192 }
193
194 bool MTPDeviceDelegateImplWin::LazyInit() {
195 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
196 // Both OpenDevice() (which we call below) and any operations our callers do
197 // may take some time. Abort them immediately if we're in the process of
198 // shutting down.
199 {
200 base::AutoLock locked(cancel_tasks_lock_);
201 if (cancel_pending_tasks_)
202 return false;
203 }
204 if (device_.get())
205 return true; // Already successfully initialized.
206 device_ = media_transfer_protocol::OpenDevice(pnp_device_id_);
207 return (device_.get() != NULL);
208 }
209
210 string16 MTPDeviceDelegateImplWin::GetFileObjectIdFromPath(
211 const string16& file_path) {
212 DCHECK(media_task_runner_->RunsTasksOnCurrentThread());
213 DCHECK(!file_path.empty());
214 if (registered_device_path_ == file_path)
215 return storage_object_id_;
216
217 string16 actual_file_path(file_path);
218 ReplaceFirstSubstringAfterOffset(&actual_file_path, 0,
219 registered_device_path_, string16());
220 DCHECK(!actual_file_path.empty());
221 typedef std::vector<string16> PathComponents;
222 PathComponents path_components;
223 base::SplitString(actual_file_path, L'\\', &path_components);
224 DCHECK(!path_components.empty());
225 string16 parent_id(storage_object_id_);
226 string16 file_object_id;
227 for (PathComponents::const_iterator path_iter = path_components.begin() + 1;
228 path_iter != path_components.end(); ++path_iter) {
229 file_object_id = media_transfer_protocol::GetObjectIdFromName(device_,
230 parent_id,
231 *path_iter);
232 if (file_object_id.empty())
233 break;
234 parent_id = file_object_id;
235 }
236 return file_object_id;
237 }
238
239 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698