OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/browser/fileapi/cross_operation_delegate.h" | 5 #include "webkit/browser/fileapi/copy_or_move_operation_delegate.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" | 9 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" |
10 #include "webkit/browser/fileapi/file_system_context.h" | 10 #include "webkit/browser/fileapi/file_system_context.h" |
11 #include "webkit/browser/fileapi/file_system_operation_context.h" | 11 #include "webkit/browser/fileapi/file_system_operation_context.h" |
12 #include "webkit/browser/fileapi/file_system_url.h" | 12 #include "webkit/browser/fileapi/file_system_url.h" |
13 #include "webkit/browser/fileapi/local_file_system_operation.h" | 13 #include "webkit/browser/fileapi/local_file_system_operation.h" |
14 #include "webkit/common/blob/shareable_file_reference.h" | 14 #include "webkit/common/blob/shareable_file_reference.h" |
15 #include "webkit/common/fileapi/file_system_util.h" | 15 #include "webkit/common/fileapi/file_system_util.h" |
16 | 16 |
17 namespace fileapi { | 17 namespace fileapi { |
18 | 18 |
19 CrossOperationDelegate::CrossOperationDelegate( | 19 CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( |
20 FileSystemContext* file_system_context, | 20 FileSystemContext* file_system_context, |
21 scoped_ptr<LocalFileSystemOperation> src_root_operation, | 21 scoped_ptr<LocalFileSystemOperation> src_root_operation, |
22 LocalFileSystemOperation* dest_root_operation, | 22 LocalFileSystemOperation* dest_root_operation, |
23 const FileSystemURL& src_root, | 23 const FileSystemURL& src_root, |
24 const FileSystemURL& dest_root, | 24 const FileSystemURL& dest_root, |
25 OperationType operation_type, | 25 OperationType operation_type, |
26 const StatusCallback& callback) | 26 const StatusCallback& callback) |
27 : RecursiveOperationDelegate(file_system_context, dest_root_operation), | 27 : RecursiveOperationDelegate(file_system_context, dest_root_operation), |
28 src_root_(src_root), | 28 src_root_(src_root), |
29 dest_root_(dest_root), | 29 dest_root_(dest_root), |
30 operation_type_(operation_type), | 30 operation_type_(operation_type), |
31 callback_(callback), | 31 callback_(callback), |
32 src_root_operation_(src_root_operation.Pass()) { | 32 src_root_operation_(src_root_operation.Pass()) { |
33 same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); | 33 same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); |
34 } | 34 } |
35 | 35 |
36 CrossOperationDelegate::~CrossOperationDelegate() { | 36 CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() { |
37 } | 37 } |
38 | 38 |
39 void CrossOperationDelegate::Run() { | 39 void CopyOrMoveOperationDelegate::Run() { |
40 // Not supported; this should never be called. | 40 // Not supported; this should never be called. |
41 NOTREACHED(); | 41 NOTREACHED(); |
42 } | 42 } |
43 | 43 |
44 void CrossOperationDelegate::RunRecursively() { | 44 void CopyOrMoveOperationDelegate::RunRecursively() { |
45 // Perform light-weight checks first. | 45 // Perform light-weight checks first. |
46 | 46 |
47 // It is an error to try to copy/move an entry into its child. | 47 // It is an error to try to copy/move an entry into its child. |
48 if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) { | 48 if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) { |
49 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 49 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); |
50 return; | 50 return; |
51 } | 51 } |
52 | 52 |
53 // It is an error to copy/move an entry into the same path. | 53 // It is an error to copy/move an entry into the same path. |
54 if (same_file_system_ && src_root_.path() == dest_root_.path()) { | 54 if (same_file_system_ && src_root_.path() == dest_root_.path()) { |
55 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); | 55 callback_.Run(base::PLATFORM_FILE_ERROR_EXISTS); |
56 return; | 56 return; |
57 } | 57 } |
58 | 58 |
59 // First try to copy/move it as a file. | 59 // First try to copy/move it as a file. |
60 CopyOrMoveFile(URLPair(src_root_, dest_root_), | 60 CopyOrMoveFile(URLPair(src_root_, dest_root_), |
61 base::Bind(&CrossOperationDelegate::DidTryCopyOrMoveFile, | 61 base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile, |
62 AsWeakPtr())); | 62 AsWeakPtr())); |
63 } | 63 } |
64 | 64 |
65 void CrossOperationDelegate::ProcessFile(const FileSystemURL& src_url, | 65 void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url, |
66 const StatusCallback& callback) { | 66 const StatusCallback& callback) { |
67 CopyOrMoveFile(URLPair(src_url, CreateDestURL(src_url)), callback); | 67 CopyOrMoveFile(URLPair(src_url, CreateDestURL(src_url)), callback); |
68 } | 68 } |
69 | 69 |
70 void CrossOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, | 70 void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, |
71 const StatusCallback& callback) { | 71 const StatusCallback& callback) { |
72 FileSystemURL dest_url = CreateDestURL(src_url); | 72 FileSystemURL dest_url = CreateDestURL(src_url); |
73 | 73 |
74 // If operation_type == Move we may need to record directories and | 74 // If operation_type == Move we may need to record directories and |
75 // restore directory timestamps in the end, though it may have | 75 // restore directory timestamps in the end, though it may have |
76 // negative performance impact. | 76 // negative performance impact. |
77 // See http://crbug.com/171284 for more details. | 77 // See http://crbug.com/171284 for more details. |
78 NewDestOperation()->CreateDirectory( | 78 NewDestOperation()->CreateDirectory( |
79 dest_url, false /* exclusive */, false /* recursive */, callback); | 79 dest_url, false /* exclusive */, false /* recursive */, callback); |
80 } | 80 } |
81 | 81 |
82 void CrossOperationDelegate::DidTryCopyOrMoveFile( | 82 void CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile( |
83 base::PlatformFileError error) { | 83 base::PlatformFileError error) { |
84 if (error == base::PLATFORM_FILE_OK || | 84 if (error == base::PLATFORM_FILE_OK || |
85 error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { | 85 error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { |
86 callback_.Run(error); | 86 callback_.Run(error); |
87 return; | 87 return; |
88 } | 88 } |
89 | 89 |
90 // The src_root_ looks to be a directory. | 90 // The src_root_ looks to be a directory. |
91 // Try removing the dest_root_ to see if it exists and/or it is an | 91 // Try removing the dest_root_ to see if it exists and/or it is an |
92 // empty directory. | 92 // empty directory. |
93 NewDestOperation()->RemoveDirectory( | 93 NewDestOperation()->RemoveDirectory( |
94 dest_root_, base::Bind(&CrossOperationDelegate::DidTryRemoveDestRoot, | 94 dest_root_, base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot, |
95 AsWeakPtr())); | 95 AsWeakPtr())); |
96 } | 96 } |
97 | 97 |
98 void CrossOperationDelegate::DidTryRemoveDestRoot( | 98 void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot( |
99 base::PlatformFileError error) { | 99 base::PlatformFileError error) { |
100 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { | 100 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { |
101 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 101 callback_.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); |
102 return; | 102 return; |
103 } | 103 } |
104 if (error != base::PLATFORM_FILE_OK && | 104 if (error != base::PLATFORM_FILE_OK && |
105 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { | 105 error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
106 callback_.Run(error); | 106 callback_.Run(error); |
107 return; | 107 return; |
108 } | 108 } |
109 | 109 |
110 // Start to process the source directory recursively. | 110 // Start to process the source directory recursively. |
111 // TODO(kinuko): This could be too expensive for same_file_system_==true | 111 // TODO(kinuko): This could be too expensive for same_file_system_==true |
112 // and operation==MOVE case, probably we can just rename the root directory. | 112 // and operation==MOVE case, probably we can just rename the root directory. |
113 // http://crbug.com/172187 | 113 // http://crbug.com/172187 |
114 StartRecursiveOperation( | 114 StartRecursiveOperation( |
115 src_root_, base::Bind(&CrossOperationDelegate::DidFinishCopy, | 115 src_root_, base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, |
116 AsWeakPtr(), src_root_, callback_)); | 116 AsWeakPtr(), src_root_, callback_)); |
117 } | 117 } |
118 | 118 |
119 void CrossOperationDelegate::CopyOrMoveFile(const URLPair& url_pair, | 119 void CopyOrMoveOperationDelegate::CopyOrMoveFile(const URLPair& url_pair, |
120 const StatusCallback& callback) { | 120 const StatusCallback& callback) { |
121 // Same filesystem case. | 121 // Same filesystem case. |
122 if (same_file_system_) { | 122 if (same_file_system_) { |
123 if (operation_type_ == OPERATION_MOVE) { | 123 if (operation_type_ == OPERATION_MOVE) { |
124 NewSourceOperation()->MoveFileLocal(url_pair.src, url_pair.dest, | 124 NewSourceOperation()->MoveFileLocal(url_pair.src, url_pair.dest, |
125 callback); | 125 callback); |
126 } else { | 126 } else { |
127 NewSourceOperation()->CopyFileLocal(url_pair.src, url_pair.dest, | 127 NewSourceOperation()->CopyFileLocal(url_pair.src, url_pair.dest, |
128 callback); | 128 callback); |
129 } | 129 } |
130 return; | 130 return; |
131 } | 131 } |
132 | 132 |
133 // Cross filesystem case. | 133 // Cross filesystem case. |
134 // Perform CreateSnapshotFile, CopyInForeignFile and then calls | 134 // Perform CreateSnapshotFile, CopyInForeignFile and then calls |
135 // copy_callback which removes the source file if operation_type == MOVE. | 135 // copy_callback which removes the source file if operation_type == MOVE. |
136 StatusCallback copy_callback = | 136 StatusCallback copy_callback = |
137 base::Bind(&CrossOperationDelegate::DidFinishCopy, AsWeakPtr(), | 137 base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, AsWeakPtr(), |
138 url_pair.src, callback); | 138 url_pair.src, callback); |
139 NewSourceOperation()->CreateSnapshotFile( | 139 NewSourceOperation()->CreateSnapshotFile( |
140 url_pair.src, | 140 url_pair.src, |
141 base::Bind(&CrossOperationDelegate::DidCreateSnapshot, AsWeakPtr(), | 141 base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot, AsWeakPtr(), |
142 url_pair, copy_callback)); | 142 url_pair, copy_callback)); |
143 } | 143 } |
144 | 144 |
145 void CrossOperationDelegate::DidCreateSnapshot( | 145 void CopyOrMoveOperationDelegate::DidCreateSnapshot( |
146 const URLPair& url_pair, | 146 const URLPair& url_pair, |
147 const StatusCallback& callback, | 147 const StatusCallback& callback, |
148 base::PlatformFileError error, | 148 base::PlatformFileError error, |
149 const base::PlatformFileInfo& file_info, | 149 const base::PlatformFileInfo& file_info, |
150 const base::FilePath& platform_path, | 150 const base::FilePath& platform_path, |
151 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | 151 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
152 if (error != base::PLATFORM_FILE_OK) { | 152 if (error != base::PLATFORM_FILE_OK) { |
153 callback.Run(error); | 153 callback.Run(error); |
154 return; | 154 return; |
155 } | 155 } |
(...skipping 11 matching lines...) Expand all Loading... |
167 return; | 167 return; |
168 } | 168 } |
169 if (!factory) { | 169 if (!factory) { |
170 DidValidateFile(url_pair.dest, callback, file_info, platform_path, error); | 170 DidValidateFile(url_pair.dest, callback, file_info, platform_path, error); |
171 return; | 171 return; |
172 } | 172 } |
173 | 173 |
174 validator_.reset( | 174 validator_.reset( |
175 factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path)); | 175 factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path)); |
176 validator_->StartValidation( | 176 validator_->StartValidation( |
177 base::Bind(&CrossOperationDelegate::DidValidateFile, AsWeakPtr(), | 177 base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile, AsWeakPtr(), |
178 url_pair.dest, callback, file_info, platform_path)); | 178 url_pair.dest, callback, file_info, platform_path)); |
179 } | 179 } |
180 | 180 |
181 void CrossOperationDelegate::DidValidateFile( | 181 void CopyOrMoveOperationDelegate::DidValidateFile( |
182 const FileSystemURL& dest, | 182 const FileSystemURL& dest, |
183 const StatusCallback& callback, | 183 const StatusCallback& callback, |
184 const base::PlatformFileInfo& file_info, | 184 const base::PlatformFileInfo& file_info, |
185 const base::FilePath& platform_path, | 185 const base::FilePath& platform_path, |
186 base::PlatformFileError error) { | 186 base::PlatformFileError error) { |
187 if (error != base::PLATFORM_FILE_OK) { | 187 if (error != base::PLATFORM_FILE_OK) { |
188 callback.Run(error); | 188 callback.Run(error); |
189 return; | 189 return; |
190 } | 190 } |
191 | 191 |
192 NewDestOperation()->CopyInForeignFile(platform_path, dest, callback); | 192 NewDestOperation()->CopyInForeignFile(platform_path, dest, callback); |
193 } | 193 } |
194 | 194 |
195 void CrossOperationDelegate::DidFinishCopy( | 195 void CopyOrMoveOperationDelegate::DidFinishCopy( |
196 const FileSystemURL& src, | 196 const FileSystemURL& src, |
197 const StatusCallback& callback, | 197 const StatusCallback& callback, |
198 base::PlatformFileError error) { | 198 base::PlatformFileError error) { |
199 if (error != base::PLATFORM_FILE_OK || | 199 if (error != base::PLATFORM_FILE_OK || |
200 operation_type_ == OPERATION_COPY) { | 200 operation_type_ == OPERATION_COPY) { |
201 callback.Run(error); | 201 callback.Run(error); |
202 return; | 202 return; |
203 } | 203 } |
204 | 204 |
205 DCHECK_EQ(OPERATION_MOVE, operation_type_); | 205 DCHECK_EQ(OPERATION_MOVE, operation_type_); |
206 | 206 |
207 // Remove the source for finalizing move operation. | 207 // Remove the source for finalizing move operation. |
208 NewSourceOperation()->Remove( | 208 NewSourceOperation()->Remove( |
209 src, true /* recursive */, | 209 src, true /* recursive */, |
210 base::Bind(&CrossOperationDelegate::DidRemoveSourceForMove, | 210 base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove, |
211 AsWeakPtr(), callback)); | 211 AsWeakPtr(), callback)); |
212 } | 212 } |
213 | 213 |
214 void CrossOperationDelegate::DidRemoveSourceForMove( | 214 void CopyOrMoveOperationDelegate::DidRemoveSourceForMove( |
215 const StatusCallback& callback, | 215 const StatusCallback& callback, |
216 base::PlatformFileError error) { | 216 base::PlatformFileError error) { |
217 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 217 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
218 error = base::PLATFORM_FILE_OK; | 218 error = base::PLATFORM_FILE_OK; |
219 callback.Run(error); | 219 callback.Run(error); |
220 } | 220 } |
221 | 221 |
222 FileSystemURL CrossOperationDelegate::CreateDestURL( | 222 FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( |
223 const FileSystemURL& src_url) const { | 223 const FileSystemURL& src_url) const { |
224 DCHECK_EQ(src_root_.type(), src_url.type()); | 224 DCHECK_EQ(src_root_.type(), src_url.type()); |
225 DCHECK_EQ(src_root_.origin(), src_url.origin()); | 225 DCHECK_EQ(src_root_.origin(), src_url.origin()); |
226 | 226 |
227 base::FilePath relative = dest_root_.virtual_path(); | 227 base::FilePath relative = dest_root_.virtual_path(); |
228 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), | 228 src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(), |
229 &relative); | 229 &relative); |
230 return file_system_context()->CreateCrackedFileSystemURL( | 230 return file_system_context()->CreateCrackedFileSystemURL( |
231 dest_root_.origin(), | 231 dest_root_.origin(), |
232 dest_root_.mount_type(), | 232 dest_root_.mount_type(), |
233 relative); | 233 relative); |
234 } | 234 } |
235 | 235 |
236 LocalFileSystemOperation* CrossOperationDelegate::NewDestOperation() { | 236 LocalFileSystemOperation* CopyOrMoveOperationDelegate::NewDestOperation() { |
237 return NewNestedOperation(); | 237 return NewNestedOperation(); |
238 } | 238 } |
239 | 239 |
240 LocalFileSystemOperation* CrossOperationDelegate::NewSourceOperation() { | 240 LocalFileSystemOperation* CopyOrMoveOperationDelegate::NewSourceOperation() { |
241 if (same_file_system_) | 241 if (same_file_system_) |
242 return NewDestOperation(); | 242 return NewDestOperation(); |
243 return src_root_operation_->CreateNestedOperation(); | 243 return src_root_operation_->CreateNestedOperation(); |
244 } | 244 } |
245 | 245 |
246 } // namespace fileapi | 246 } // namespace fileapi |
OLD | NEW |