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

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

Powered by Google App Engine
This is Rietveld 408576698