1/* 2 * Copyright (C) 2008 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "File.h" 28 29#include "FileMetadata.h" 30#include "FileSystem.h" 31#include "MIMETypeRegistry.h" 32#include <wtf/CurrentTime.h> 33#include <wtf/DateMath.h> 34#include <wtf/text/WTFString.h> 35 36namespace WebCore { 37 38static String getContentTypeFromFileName(const String& name, File::ContentTypeLookupPolicy policy) 39{ 40 String type; 41 int index = name.reverseFind('.'); 42 if (index != -1) { 43 if (policy == File::WellKnownContentTypes) 44 type = MIMETypeRegistry::getWellKnownMIMETypeForExtension(name.substring(index + 1)); 45 else { 46 ASSERT(policy == File::AllContentTypes); 47 type = MIMETypeRegistry::getMIMETypeForExtension(name.substring(index + 1)); 48 } 49 } 50 return type; 51} 52 53static PassOwnPtr<BlobData> createBlobDataForFileWithType(const String& path, const String& contentType) 54{ 55 OwnPtr<BlobData> blobData = BlobData::create(); 56 ASSERT(Blob::isNormalizedContentType(contentType)); 57 blobData->setContentType(contentType); 58 blobData->appendFile(path); 59 return blobData.release(); 60} 61 62static PassOwnPtr<BlobData> createBlobDataForFile(const String& path, File::ContentTypeLookupPolicy policy) 63{ 64 return createBlobDataForFileWithType(path, getContentTypeFromFileName(path, policy)); 65} 66 67static PassOwnPtr<BlobData> createBlobDataForFileWithName(const String& path, const String& fileSystemName, File::ContentTypeLookupPolicy policy) 68{ 69 return createBlobDataForFileWithType(path, getContentTypeFromFileName(fileSystemName, policy)); 70} 71 72#if ENABLE(FILE_SYSTEM) 73static PassOwnPtr<BlobData> createBlobDataForFileWithMetadata(const String& fileSystemName, const FileMetadata& metadata) 74{ 75 OwnPtr<BlobData> blobData = BlobData::create(); 76 blobData->setContentType(getContentTypeFromFileName(fileSystemName, File::WellKnownContentTypes)); 77 blobData->appendFile(metadata.platformPath, 0, metadata.length, metadata.modificationTime); 78 return blobData.release(); 79} 80 81static PassOwnPtr<BlobData> createBlobDataForFileSystemURL(const KURL& fileSystemURL, const FileMetadata& metadata) 82{ 83 OwnPtr<BlobData> blobData = BlobData::create(); 84 blobData->setContentType(getContentTypeFromFileName(fileSystemURL.path(), File::WellKnownContentTypes)); 85 blobData->appendURL(fileSystemURL, 0, metadata.length, metadata.modificationTime); 86 return blobData.release(); 87} 88#endif 89 90#if ENABLE(DIRECTORY_UPLOAD) 91PassRefPtr<File> File::createWithRelativePath(const String& path, const String& relativePath) 92{ 93 RefPtr<File> file = adoptRef(new File(path, AllContentTypes)); 94 file->m_relativePath = relativePath; 95 return file.release(); 96} 97#endif 98 99File::File(const String& path, ContentTypeLookupPolicy policy) 100 : Blob(createBlobDataForFile(path, policy), -1) 101 , m_path(path) 102 , m_name(pathGetFileName(path)) 103#if ENABLE(FILE_SYSTEM) 104 , m_snapshotSize(-1) 105 , m_snapshotModificationTime(invalidFileTime()) 106#endif 107{ 108} 109 110File::File(const String& path, const KURL& url, const String& type) 111 : Blob(url, type, -1) 112 , m_path(path) 113#if ENABLE(FILE_SYSTEM) 114 , m_snapshotSize(-1) 115 , m_snapshotModificationTime(invalidFileTime()) 116#endif 117{ 118 m_name = pathGetFileName(path); 119 // FIXME: File object serialization/deserialization does not include 120 // newer file object data members: m_name and m_relativePath. 121 // See SerializedScriptValue.cpp 122} 123 124File::File(const String& path, const String& name, ContentTypeLookupPolicy policy) 125 : Blob(createBlobDataForFileWithName(path, name, policy), -1) 126 , m_path(path) 127 , m_name(name) 128#if ENABLE(FILE_SYSTEM) 129 , m_snapshotSize(-1) 130 , m_snapshotModificationTime(invalidFileTime()) 131#endif 132{ 133} 134 135#if ENABLE(FILE_SYSTEM) 136File::File(const String& name, const FileMetadata& metadata) 137 : Blob(createBlobDataForFileWithMetadata(name, metadata), metadata.length) 138 , m_path(metadata.platformPath) 139 , m_name(name) 140 , m_snapshotSize(metadata.length) 141 , m_snapshotModificationTime(metadata.modificationTime) 142{ 143} 144 145File::File(const KURL& fileSystemURL, const FileMetadata& metadata) 146 : Blob(createBlobDataForFileSystemURL(fileSystemURL, metadata), metadata.length) 147 , m_fileSystemURL(fileSystemURL) 148 , m_snapshotSize(metadata.length) 149 , m_snapshotModificationTime(metadata.modificationTime) 150{ 151} 152#endif 153 154double File::lastModifiedDate() const 155{ 156#if ENABLE(FILE_SYSTEM) 157 if (hasValidSnapshotMetadata() && isValidFileTime(m_snapshotModificationTime)) 158 return m_snapshotModificationTime * msPerSecond; 159#endif 160 161 time_t modificationTime; 162 if (getFileModificationTime(m_path, modificationTime) && isValidFileTime(modificationTime)) 163 return modificationTime * msPerSecond; 164 165 return currentTime() * msPerSecond; 166} 167 168unsigned long long File::size() const 169{ 170#if ENABLE(FILE_SYSTEM) 171 if (hasValidSnapshotMetadata()) 172 return m_snapshotSize; 173#endif 174 175 // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to 176 // come up with an exception to throw if file size is not representable. 177 long long size; 178 if (!getFileSize(m_path, size)) 179 return 0; 180 return static_cast<unsigned long long>(size); 181} 182 183void File::captureSnapshot(long long& snapshotSize, double& snapshotModificationTime) const 184{ 185#if ENABLE(FILE_SYSTEM) 186 if (hasValidSnapshotMetadata()) { 187 snapshotSize = m_snapshotSize; 188 snapshotModificationTime = m_snapshotModificationTime; 189 return; 190 } 191#endif 192 193 // Obtains a snapshot of the file by capturing its current size and modification time. This is used when we slice a file for the first time. 194 // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, 0 size is returned. 195 FileMetadata metadata; 196 if (!getFileMetadata(m_path, metadata)) { 197 snapshotSize = 0; 198 snapshotModificationTime = invalidFileTime(); 199 return; 200 } 201 202 snapshotSize = metadata.length; 203 snapshotModificationTime = metadata.modificationTime; 204} 205 206} // namespace WebCore 207