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

Side by Side Diff: third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp

Issue 2297043002: Web expose FileSystemFileEntry, FileSystemDirectoryEntry and friends (Closed)
Patch Set: Rebased Created 4 years 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
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "modules/filesystem/DOMFileSystemBase.h"
32
33 #include "core/dom/ExecutionContext.h"
34 #include "core/fileapi/File.h"
35 #include "core/fileapi/FileError.h"
36 #include "core/html/VoidCallback.h"
37 #include "modules/filesystem/DOMFilePath.h"
38 #include "modules/filesystem/DirectoryEntry.h"
39 #include "modules/filesystem/DirectoryReaderBase.h"
40 #include "modules/filesystem/EntriesCallback.h"
41 #include "modules/filesystem/Entry.h"
42 #include "modules/filesystem/EntryBase.h"
43 #include "modules/filesystem/EntryCallback.h"
44 #include "modules/filesystem/FileSystemCallbacks.h"
45 #include "modules/filesystem/MetadataCallback.h"
46 #include "platform/weborigin/SecurityOrigin.h"
47 #include "public/platform/Platform.h"
48 #include "public/platform/WebFileSystem.h"
49 #include "public/platform/WebFileSystemCallbacks.h"
50 #include "wtf/text/StringBuilder.h"
51 #include "wtf/text/TextEncoding.h"
52 #include <memory>
53
54 namespace blink {
55
56 const char DOMFileSystemBase::persistentPathPrefix[] = "persistent";
57 const char DOMFileSystemBase::temporaryPathPrefix[] = "temporary";
58 const char DOMFileSystemBase::isolatedPathPrefix[] = "isolated";
59 const char DOMFileSystemBase::externalPathPrefix[] = "external";
60
61 DOMFileSystemBase::DOMFileSystemBase(ExecutionContext* context,
62 const String& name,
63 FileSystemType type,
64 const KURL& rootURL)
65 : m_context(context),
66 m_name(name),
67 m_type(type),
68 m_filesystemRootURL(rootURL),
69 m_clonable(false) {}
70
71 DOMFileSystemBase::~DOMFileSystemBase() {}
72
73 DEFINE_TRACE(DOMFileSystemBase) {
74 visitor->trace(m_context);
75 }
76
77 WebFileSystem* DOMFileSystemBase::fileSystem() const {
78 Platform* platform = Platform::current();
79 if (!platform)
80 return nullptr;
81 return platform->fileSystem();
82 }
83
84 SecurityOrigin* DOMFileSystemBase::getSecurityOrigin() const {
85 return m_context->getSecurityOrigin();
86 }
87
88 bool DOMFileSystemBase::isValidType(FileSystemType type) {
89 return type == FileSystemTypeTemporary || type == FileSystemTypePersistent ||
90 type == FileSystemTypeIsolated || type == FileSystemTypeExternal;
91 }
92
93 KURL DOMFileSystemBase::createFileSystemRootURL(const String& origin,
94 FileSystemType type) {
95 String typeString;
96 if (type == FileSystemTypeTemporary)
97 typeString = temporaryPathPrefix;
98 else if (type == FileSystemTypePersistent)
99 typeString = persistentPathPrefix;
100 else if (type == FileSystemTypeExternal)
101 typeString = externalPathPrefix;
102 else
103 return KURL();
104
105 String result = "filesystem:" + origin + "/" + typeString + "/";
106 return KURL(ParsedURLString, result);
107 }
108
109 bool DOMFileSystemBase::supportsToURL() const {
110 ASSERT(isValidType(m_type));
111 return m_type != FileSystemTypeIsolated;
112 }
113
114 KURL DOMFileSystemBase::createFileSystemURL(const EntryBase* entry) const {
115 return createFileSystemURL(entry->fullPath());
116 }
117
118 KURL DOMFileSystemBase::createFileSystemURL(const String& fullPath) const {
119 ASSERT(DOMFilePath::isAbsolute(fullPath));
120
121 if (type() == FileSystemTypeExternal) {
122 // For external filesystem originString could be different from what we have
123 // in m_filesystemRootURL.
124 StringBuilder result;
125 result.append("filesystem:");
126 result.append(getSecurityOrigin()->toString());
127 result.append('/');
128 result.append(externalPathPrefix);
129 result.append(m_filesystemRootURL.path());
130 // Remove the extra leading slash.
131 result.append(encodeWithURLEscapeSequences(fullPath.substring(1)));
132 return KURL(ParsedURLString, result.toString());
133 }
134
135 // For regular types we can just append the entry's fullPath to the
136 // m_filesystemRootURL that should look like
137 // 'filesystem:<origin>/<typePrefix>'.
138 ASSERT(!m_filesystemRootURL.isEmpty());
139 KURL url = m_filesystemRootURL;
140 // Remove the extra leading slash.
141 url.setPath(url.path() + encodeWithURLEscapeSequences(fullPath.substring(1)));
142 return url;
143 }
144
145 bool DOMFileSystemBase::pathToAbsolutePath(FileSystemType type,
146 const EntryBase* base,
147 String path,
148 String& absolutePath) {
149 ASSERT(base);
150
151 if (!DOMFilePath::isAbsolute(path))
152 path = DOMFilePath::append(base->fullPath(), path);
153 absolutePath = DOMFilePath::removeExtraParentReferences(path);
154
155 return (type != FileSystemTypeTemporary &&
156 type != FileSystemTypePersistent) ||
157 DOMFilePath::isValidPath(absolutePath);
158 }
159
160 bool DOMFileSystemBase::pathPrefixToFileSystemType(const String& pathPrefix,
161 FileSystemType& type) {
162 if (pathPrefix == temporaryPathPrefix) {
163 type = FileSystemTypeTemporary;
164 return true;
165 }
166
167 if (pathPrefix == persistentPathPrefix) {
168 type = FileSystemTypePersistent;
169 return true;
170 }
171
172 if (pathPrefix == externalPathPrefix) {
173 type = FileSystemTypeExternal;
174 return true;
175 }
176
177 return false;
178 }
179
180 File* DOMFileSystemBase::createFile(const FileMetadata& metadata,
181 const KURL& fileSystemURL,
182 FileSystemType type,
183 const String name) {
184 // For regular filesystem types (temporary or persistent), we should not cache
185 // file metadata as it could change File semantics. For other filesystem
186 // types (which could be platform-specific ones), there's a chance that the
187 // files are on remote filesystem. If the port has returned metadata just
188 // pass it to File constructor (so we may cache the metadata).
189 // FIXME: We should use the snapshot metadata for all files.
190 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17746
191 if (type == FileSystemTypeTemporary || type == FileSystemTypePersistent)
192 return File::createForFileSystemFile(metadata.platformPath, name);
193
194 const File::UserVisibility userVisibility = (type == FileSystemTypeExternal)
195 ? File::IsUserVisible
196 : File::IsNotUserVisible;
197
198 if (!metadata.platformPath.isEmpty()) {
199 // If the platformPath in the returned metadata is given, we create a File
200 // object for the snapshot path.
201 return File::createForFileSystemFile(name, metadata, userVisibility);
202 } else {
203 // Otherwise we create a File object for the fileSystemURL.
204 return File::createForFileSystemFile(fileSystemURL, metadata,
205 userVisibility);
206 }
207 }
208
209 void DOMFileSystemBase::getMetadata(const EntryBase* entry,
210 MetadataCallback* successCallback,
211 ErrorCallbackBase* errorCallback,
212 SynchronousType synchronousType) {
213 if (!fileSystem()) {
214 reportError(errorCallback, FileError::kAbortErr);
215 return;
216 }
217
218 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(MetadataCallbacks::create(
219 successCallback, errorCallback, m_context, this));
220 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
221 fileSystem()->readMetadata(createFileSystemURL(entry), std::move(callbacks));
222 }
223
224 static bool verifyAndGetDestinationPathForCopyOrMove(const EntryBase* source,
225 EntryBase* parent,
226 const String& newName,
227 String& destinationPath) {
228 ASSERT(source);
229
230 if (!parent || !parent->isDirectory())
231 return false;
232
233 if (!newName.isEmpty() && !DOMFilePath::isValidName(newName))
234 return false;
235
236 const bool isSameFileSystem =
237 (*source->filesystem() == *parent->filesystem());
238
239 // It is an error to try to copy or move an entry inside itself at any depth
240 // if it is a directory.
241 if (source->isDirectory() && isSameFileSystem &&
242 DOMFilePath::isParentOf(source->fullPath(), parent->fullPath()))
243 return false;
244
245 // It is an error to copy or move an entry into its parent if a name different
246 // from its current one isn't provided.
247 if (isSameFileSystem && (newName.isEmpty() || source->name() == newName) &&
248 DOMFilePath::getDirectory(source->fullPath()) == parent->fullPath())
249 return false;
250
251 destinationPath = parent->fullPath();
252 if (!newName.isEmpty())
253 destinationPath = DOMFilePath::append(destinationPath, newName);
254 else
255 destinationPath = DOMFilePath::append(destinationPath, source->name());
256
257 return true;
258 }
259
260 void DOMFileSystemBase::move(const EntryBase* source,
261 EntryBase* parent,
262 const String& newName,
263 EntryCallback* successCallback,
264 ErrorCallbackBase* errorCallback,
265 SynchronousType synchronousType) {
266 if (!fileSystem()) {
267 reportError(errorCallback, FileError::kAbortErr);
268 return;
269 }
270
271 String destinationPath;
272 if (!verifyAndGetDestinationPathForCopyOrMove(source, parent, newName,
273 destinationPath)) {
274 reportError(errorCallback, FileError::kInvalidModificationErr);
275 return;
276 }
277
278 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(
279 successCallback, errorCallback, m_context, parent->filesystem(),
280 destinationPath, source->isDirectory()));
281 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
282
283 fileSystem()->move(createFileSystemURL(source),
284 parent->filesystem()->createFileSystemURL(destinationPath),
285 std::move(callbacks));
286 }
287
288 void DOMFileSystemBase::copy(const EntryBase* source,
289 EntryBase* parent,
290 const String& newName,
291 EntryCallback* successCallback,
292 ErrorCallbackBase* errorCallback,
293 SynchronousType synchronousType) {
294 if (!fileSystem()) {
295 reportError(errorCallback, FileError::kAbortErr);
296 return;
297 }
298
299 String destinationPath;
300 if (!verifyAndGetDestinationPathForCopyOrMove(source, parent, newName,
301 destinationPath)) {
302 reportError(errorCallback, FileError::kInvalidModificationErr);
303 return;
304 }
305
306 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(
307 successCallback, errorCallback, m_context, parent->filesystem(),
308 destinationPath, source->isDirectory()));
309 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
310
311 fileSystem()->copy(createFileSystemURL(source),
312 parent->filesystem()->createFileSystemURL(destinationPath),
313 std::move(callbacks));
314 }
315
316 void DOMFileSystemBase::remove(const EntryBase* entry,
317 VoidCallback* successCallback,
318 ErrorCallbackBase* errorCallback,
319 SynchronousType synchronousType) {
320 if (!fileSystem()) {
321 reportError(errorCallback, FileError::kAbortErr);
322 return;
323 }
324
325 ASSERT(entry);
326 // We don't allow calling remove() on the root directory.
327 if (entry->fullPath() == String(DOMFilePath::root)) {
328 reportError(errorCallback, FileError::kInvalidModificationErr);
329 return;
330 }
331
332 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(
333 VoidCallbacks::create(successCallback, errorCallback, m_context, this));
334 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
335
336 fileSystem()->remove(createFileSystemURL(entry), std::move(callbacks));
337 }
338
339 void DOMFileSystemBase::removeRecursively(const EntryBase* entry,
340 VoidCallback* successCallback,
341 ErrorCallbackBase* errorCallback,
342 SynchronousType synchronousType) {
343 if (!fileSystem()) {
344 reportError(errorCallback, FileError::kAbortErr);
345 return;
346 }
347
348 ASSERT(entry && entry->isDirectory());
349 // We don't allow calling remove() on the root directory.
350 if (entry->fullPath() == String(DOMFilePath::root)) {
351 reportError(errorCallback, FileError::kInvalidModificationErr);
352 return;
353 }
354
355 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(
356 VoidCallbacks::create(successCallback, errorCallback, m_context, this));
357 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
358
359 fileSystem()->removeRecursively(createFileSystemURL(entry),
360 std::move(callbacks));
361 }
362
363 void DOMFileSystemBase::getParent(const EntryBase* entry,
364 EntryCallback* successCallback,
365 ErrorCallbackBase* errorCallback) {
366 if (!fileSystem()) {
367 reportError(errorCallback, FileError::kAbortErr);
368 return;
369 }
370
371 ASSERT(entry);
372 String path = DOMFilePath::getDirectory(entry->fullPath());
373
374 fileSystem()->directoryExists(
375 createFileSystemURL(path),
376 EntryCallbacks::create(successCallback, errorCallback, m_context, this,
377 path, true));
378 }
379
380 void DOMFileSystemBase::getFile(const EntryBase* entry,
381 const String& path,
382 const FileSystemFlags& flags,
383 EntryCallback* successCallback,
384 ErrorCallbackBase* errorCallback,
385 SynchronousType synchronousType) {
386 if (!fileSystem()) {
387 reportError(errorCallback, FileError::kAbortErr);
388 return;
389 }
390
391 String absolutePath;
392 if (!pathToAbsolutePath(m_type, entry, path, absolutePath)) {
393 reportError(errorCallback, FileError::kInvalidModificationErr);
394 return;
395 }
396
397 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(
398 successCallback, errorCallback, m_context, this, absolutePath, false));
399 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
400
401 if (flags.createFlag())
402 fileSystem()->createFile(createFileSystemURL(absolutePath),
403 flags.exclusive(), std::move(callbacks));
404 else
405 fileSystem()->fileExists(createFileSystemURL(absolutePath),
406 std::move(callbacks));
407 }
408
409 void DOMFileSystemBase::getDirectory(const EntryBase* entry,
410 const String& path,
411 const FileSystemFlags& flags,
412 EntryCallback* successCallback,
413 ErrorCallbackBase* errorCallback,
414 SynchronousType synchronousType) {
415 if (!fileSystem()) {
416 reportError(errorCallback, FileError::kAbortErr);
417 return;
418 }
419
420 String absolutePath;
421 if (!pathToAbsolutePath(m_type, entry, path, absolutePath)) {
422 reportError(errorCallback, FileError::kInvalidModificationErr);
423 return;
424 }
425
426 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(
427 successCallback, errorCallback, m_context, this, absolutePath, true));
428 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
429
430 if (flags.createFlag())
431 fileSystem()->createDirectory(createFileSystemURL(absolutePath),
432 flags.exclusive(), std::move(callbacks));
433 else
434 fileSystem()->directoryExists(createFileSystemURL(absolutePath),
435 std::move(callbacks));
436 }
437
438 int DOMFileSystemBase::readDirectory(DirectoryReaderBase* reader,
439 const String& path,
440 EntriesCallback* successCallback,
441 ErrorCallbackBase* errorCallback,
442 SynchronousType synchronousType) {
443 if (!fileSystem()) {
444 reportError(errorCallback, FileError::kAbortErr);
445 return 0;
446 }
447
448 ASSERT(DOMFilePath::isAbsolute(path));
449
450 std::unique_ptr<AsyncFileSystemCallbacks> callbacks(EntriesCallbacks::create(
451 successCallback, errorCallback, m_context, reader, path));
452 callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous);
453
454 return fileSystem()->readDirectory(createFileSystemURL(path),
455 std::move(callbacks));
456 }
457
458 bool DOMFileSystemBase::waitForAdditionalResult(int callbacksId) {
459 if (!fileSystem())
460 return false;
461 return fileSystem()->waitForAdditionalResult(callbacksId);
462 }
463
464 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698