• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "config.h"
32 #include "DOMFileSystemBase.h"
33 
34 #if ENABLE(FILE_SYSTEM)
35 
36 #include "DOMFilePath.h"
37 #include "DirectoryEntry.h"
38 #include "DirectoryReaderBase.h"
39 #include "EntriesCallback.h"
40 #include "EntryArray.h"
41 #include "EntryBase.h"
42 #include "EntryCallback.h"
43 #include "ErrorCallback.h"
44 #include "FileError.h"
45 #include "FileSystemCallbacks.h"
46 #include "MetadataCallback.h"
47 #include "ScriptExecutionContext.h"
48 #include "VoidCallback.h"
49 #include <wtf/OwnPtr.h>
50 
51 namespace WebCore {
52 
53 const char DOMFileSystemBase::kPersistentPathPrefix[] = "persistent";
54 const size_t DOMFileSystemBase::kPersistentPathPrefixLength = sizeof(DOMFileSystemBase::kPersistentPathPrefix) - 1;
55 const char DOMFileSystemBase::kTemporaryPathPrefix[] = "temporary";
56 const size_t DOMFileSystemBase::kTemporaryPathPrefixLength = sizeof(DOMFileSystemBase::kTemporaryPathPrefix) - 1;
57 const char DOMFileSystemBase::kExternalPathPrefix[] = "external";
58 const size_t DOMFileSystemBase::kExternalPathPrefixLength = sizeof(DOMFileSystemBase::kExternalPathPrefix) - 1;
59 
crackFileSystemURL(const KURL & url,AsyncFileSystem::Type & type,String & filePath)60 bool DOMFileSystemBase::crackFileSystemURL(const KURL& url, AsyncFileSystem::Type& type, String& filePath)
61 {
62     if (!url.protocolIs("filesystem"))
63         return false;
64 
65     KURL originURL(ParsedURLString, url.path());
66     String path = originURL.path();
67     if (path.isEmpty() || path[0] != '/')
68         return false;
69     path = path.substring(1);
70 
71     if (path.startsWith(kTemporaryPathPrefix)) {
72         type = AsyncFileSystem::Temporary;
73         path = path.substring(kTemporaryPathPrefixLength);
74     } else if (path.startsWith(kPersistentPathPrefix)) {
75         type = AsyncFileSystem::Persistent;
76         path = path.substring(kPersistentPathPrefixLength);
77     } else if (path.startsWith(kExternalPathPrefix)) {
78         type = AsyncFileSystem::External;
79         path = path.substring(kExternalPathPrefixLength);
80     } else
81         return false;
82 
83     if (path.isEmpty() || path[0] != '/')
84         return false;
85 
86     filePath.swap(path);
87     return true;
88 }
89 
DOMFileSystemBase(ScriptExecutionContext * context,const String & name,PassOwnPtr<AsyncFileSystem> asyncFileSystem)90 DOMFileSystemBase::DOMFileSystemBase(ScriptExecutionContext* context, const String& name, PassOwnPtr<AsyncFileSystem> asyncFileSystem)
91     : m_context(context)
92     , m_name(name)
93     , m_asyncFileSystem(asyncFileSystem)
94 {
95 }
96 
~DOMFileSystemBase()97 DOMFileSystemBase::~DOMFileSystemBase()
98 {
99 }
100 
securityOrigin() const101 SecurityOrigin* DOMFileSystemBase::securityOrigin() const
102 {
103     return m_context->securityOrigin();
104 }
105 
getMetadata(const EntryBase * entry,PassRefPtr<MetadataCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)106 bool DOMFileSystemBase::getMetadata(const EntryBase* entry, PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
107 {
108     String platformPath = m_asyncFileSystem->virtualToPlatformPath(entry->fullPath());
109     m_asyncFileSystem->readMetadata(platformPath, MetadataCallbacks::create(successCallback, errorCallback));
110     return true;
111 }
112 
verifyAndGetDestinationPathForCopyOrMove(const EntryBase * source,EntryBase * parent,const String & newName,String & destinationPath)113 static bool verifyAndGetDestinationPathForCopyOrMove(const EntryBase* source, EntryBase* parent, const String& newName, String& destinationPath)
114 {
115     ASSERT(source);
116 
117     if (!parent || !parent->isDirectory())
118         return false;
119 
120     if (!newName.isEmpty() && !DOMFilePath::isValidName(newName))
121         return false;
122 
123     // It is an error to try to copy or move an entry inside itself at any depth if it is a directory.
124     if (source->isDirectory() && DOMFilePath::isParentOf(source->fullPath(), parent->fullPath()))
125         return false;
126 
127     // It is an error to copy or move an entry into its parent if a name different from its current one isn't provided.
128     if ((newName.isEmpty() || source->name() == newName) && DOMFilePath::getDirectory(source->fullPath()) == parent->fullPath())
129         return false;
130 
131     destinationPath = parent->fullPath();
132     if (!newName.isEmpty())
133         destinationPath = DOMFilePath::append(destinationPath, newName);
134     else
135         destinationPath = DOMFilePath::append(destinationPath, source->name());
136 
137     return true;
138 }
139 
pathToAbsolutePath(const EntryBase * base,String path,String & absolutePath)140 static bool pathToAbsolutePath(const EntryBase* base, String path, String& absolutePath)
141 {
142     ASSERT(base);
143 
144     if (!DOMFilePath::isAbsolute(path))
145         path = DOMFilePath::append(base->fullPath(), path);
146     absolutePath = DOMFilePath::removeExtraParentReferences(path);
147 
148     if (!DOMFilePath::isValidPath(absolutePath))
149         return false;
150     return true;
151 }
152 
move(const EntryBase * source,EntryBase * parent,const String & newName,PassRefPtr<EntryCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)153 bool DOMFileSystemBase::move(const EntryBase* source, EntryBase* parent, const String& newName, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
154 {
155     String destinationPath;
156     if (!verifyAndGetDestinationPathForCopyOrMove(source, parent, newName, destinationPath))
157         return false;
158 
159     String sourcePlatformPath = m_asyncFileSystem->virtualToPlatformPath(source->fullPath());
160     String destinationPlatformPath = parent->filesystem()->asyncFileSystem()->virtualToPlatformPath(destinationPath);
161     m_asyncFileSystem->move(sourcePlatformPath, destinationPlatformPath, EntryCallbacks::create(successCallback, errorCallback, this, destinationPath, source->isDirectory()));
162     return true;
163 }
164 
copy(const EntryBase * source,EntryBase * parent,const String & newName,PassRefPtr<EntryCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)165 bool DOMFileSystemBase::copy(const EntryBase* source, EntryBase* parent, const String& newName, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
166 {
167     String destinationPath;
168     if (!verifyAndGetDestinationPathForCopyOrMove(source, parent, newName, destinationPath))
169         return false;
170 
171     String sourcePlatformPath = m_asyncFileSystem->virtualToPlatformPath(source->fullPath());
172     String destinationPlatformPath = parent->filesystem()->asyncFileSystem()->virtualToPlatformPath(destinationPath);
173     m_asyncFileSystem->copy(sourcePlatformPath, destinationPlatformPath, EntryCallbacks::create(successCallback, errorCallback, this, destinationPath, source->isDirectory()));
174     return true;
175 }
176 
remove(const EntryBase * entry,PassRefPtr<VoidCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)177 bool DOMFileSystemBase::remove(const EntryBase* entry, PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
178 {
179     ASSERT(entry);
180     // We don't allow calling remove() on the root directory.
181     if (entry->fullPath() == String(DOMFilePath::root))
182         return false;
183     String platformPath = m_asyncFileSystem->virtualToPlatformPath(entry->fullPath());
184     m_asyncFileSystem->remove(platformPath, VoidCallbacks::create(successCallback, errorCallback));
185     return true;
186 }
187 
removeRecursively(const EntryBase * entry,PassRefPtr<VoidCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)188 bool DOMFileSystemBase::removeRecursively(const EntryBase* entry, PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
189 {
190     ASSERT(entry && entry->isDirectory());
191     // We don't allow calling remove() on the root directory.
192     if (entry->fullPath() == String(DOMFilePath::root))
193         return false;
194     String platformPath = m_asyncFileSystem->virtualToPlatformPath(entry->fullPath());
195     m_asyncFileSystem->removeRecursively(platformPath, VoidCallbacks::create(successCallback, errorCallback));
196     return true;
197 }
198 
getParent(const EntryBase * entry,PassRefPtr<EntryCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)199 bool DOMFileSystemBase::getParent(const EntryBase* entry, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
200 {
201     ASSERT(entry);
202     String path = DOMFilePath::getDirectory(entry->fullPath());
203     String platformPath = m_asyncFileSystem->virtualToPlatformPath(path);
204     m_asyncFileSystem->directoryExists(platformPath, EntryCallbacks::create(successCallback, errorCallback, this, path, true));
205     return true;
206 }
207 
getFile(const EntryBase * base,const String & path,PassRefPtr<WebKitFlags> flags,PassRefPtr<EntryCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)208 bool DOMFileSystemBase::getFile(const EntryBase* base, const String& path, PassRefPtr<WebKitFlags> flags, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
209 {
210     String absolutePath;
211     if (!pathToAbsolutePath(base, path, absolutePath))
212         return false;
213 
214     String platformPath = m_asyncFileSystem->virtualToPlatformPath(absolutePath);
215     OwnPtr<EntryCallbacks> callbacks = EntryCallbacks::create(successCallback, errorCallback, this, absolutePath, false);
216     if (flags && flags->isCreate())
217         m_asyncFileSystem->createFile(platformPath, flags->isExclusive(), callbacks.release());
218     else
219         m_asyncFileSystem->fileExists(platformPath, callbacks.release());
220     return true;
221 }
222 
getDirectory(const EntryBase * base,const String & path,PassRefPtr<WebKitFlags> flags,PassRefPtr<EntryCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)223 bool DOMFileSystemBase::getDirectory(const EntryBase* base, const String& path, PassRefPtr<WebKitFlags> flags, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
224 {
225     String absolutePath;
226     if (!pathToAbsolutePath(base, path, absolutePath))
227         return false;
228 
229     String platformPath = m_asyncFileSystem->virtualToPlatformPath(absolutePath);
230     OwnPtr<EntryCallbacks> callbacks = EntryCallbacks::create(successCallback, errorCallback, this, absolutePath, true);
231     if (flags && flags->isCreate())
232         m_asyncFileSystem->createDirectory(platformPath, flags->isExclusive(), callbacks.release());
233     else
234         m_asyncFileSystem->directoryExists(platformPath, callbacks.release());
235     return true;
236 }
237 
readDirectory(PassRefPtr<DirectoryReaderBase> reader,const String & path,PassRefPtr<EntriesCallback> successCallback,PassRefPtr<ErrorCallback> errorCallback)238 bool DOMFileSystemBase::readDirectory(PassRefPtr<DirectoryReaderBase> reader, const String& path, PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
239 {
240     ASSERT(DOMFilePath::isAbsolute(path));
241     String platformPath = m_asyncFileSystem->virtualToPlatformPath(path);
242     m_asyncFileSystem->readDirectory(platformPath, EntriesCallbacks::create(successCallback, errorCallback, reader, path));
243     return true;
244 }
245 
246 } // namespace WebCore
247 
248 #endif // ENABLE(FILE_SYSTEM)
249