#include "config.h"
#include "core/fileapi/File.h"
+#include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/ExceptionCode.h"
#include "platform/FileMetadata.h"
#include "platform/MIMETypeRegistry.h"
#include "public/platform/Platform.h"
#include "wtf/CurrentTime.h"
#include "wtf/DateMath.h"
-namespace WebCore {
+namespace blink {
static String getContentTypeFromFileName(const String& name, File::ContentTypeLookupPolicy policy)
{
return blobData.release();
}
-PassRefPtr<File> File::createWithRelativePath(const String& path, const String& relativePath)
+PassRefPtrWillBeRawPtr<File> File::createWithRelativePath(const String& path, const String& relativePath)
{
- RefPtr<File> file = adoptRef(new File(path, AllContentTypes));
+ RefPtrWillBeRawPtr<File> file = adoptRefWillBeNoop(new File(path, File::AllContentTypes, File::IsUserVisible));
file->m_relativePath = relativePath;
return file.release();
}
-File::File(const String& path, ContentTypeLookupPolicy policy)
+File::File(const String& path, ContentTypeLookupPolicy policy, UserVisibility userVisibility)
: Blob(BlobDataHandle::create(createBlobDataForFile(path, policy), -1))
, m_hasBackingFile(true)
+ , m_userVisibility(userVisibility)
, m_path(path)
- , m_name(blink::Platform::current()->fileUtilities()->baseName(path))
+ , m_name(Platform::current()->fileUtilities()->baseName(path))
, m_snapshotSize(-1)
, m_snapshotModificationTime(invalidFileTime())
{
ScriptWrappable::init(this);
}
-File::File(const String& path, const String& name, ContentTypeLookupPolicy policy)
+File::File(const String& path, const String& name, ContentTypeLookupPolicy policy, UserVisibility userVisibility)
: Blob(BlobDataHandle::create(createBlobDataForFileWithName(path, name, policy), -1))
, m_hasBackingFile(true)
+ , m_userVisibility(userVisibility)
, m_path(path)
, m_name(name)
, m_snapshotSize(-1)
ScriptWrappable::init(this);
}
-File::File(const String& path, const String& name, const String& relativePath, bool hasSnaphotData, uint64_t size, double lastModified, PassRefPtr<BlobDataHandle> blobDataHandle)
+File::File(const String& path, const String& name, const String& relativePath, UserVisibility userVisibility, bool hasSnaphotData, uint64_t size, double lastModified, PassRefPtr<BlobDataHandle> blobDataHandle)
: Blob(blobDataHandle)
, m_hasBackingFile(!path.isEmpty() || !relativePath.isEmpty())
+ , m_userVisibility(userVisibility)
, m_path(path)
, m_name(name)
, m_snapshotSize(hasSnaphotData ? static_cast<long long>(size) : -1)
File::File(const String& name, double modificationTime, PassRefPtr<BlobDataHandle> blobDataHandle)
: Blob(blobDataHandle)
, m_hasBackingFile(false)
+ , m_userVisibility(File::IsNotUserVisible)
, m_name(name)
, m_snapshotSize(Blob::size())
, m_snapshotModificationTime(modificationTime)
ScriptWrappable::init(this);
}
-File::File(const String& name, const FileMetadata& metadata)
- : Blob(BlobDataHandle::create(createBlobDataForFileWithMetadata(name, metadata), metadata.length))
+File::File(const String& name, const FileMetadata& metadata, UserVisibility userVisibility)
+ : Blob(BlobDataHandle::create(createBlobDataForFileWithMetadata(name, metadata), metadata.length))
, m_hasBackingFile(true)
+ , m_userVisibility(userVisibility)
, m_path(metadata.platformPath)
, m_name(name)
, m_snapshotSize(metadata.length)
File::File(const KURL& fileSystemURL, const FileMetadata& metadata)
: Blob(BlobDataHandle::create(createBlobDataForFileSystemURL(fileSystemURL, metadata), metadata.length))
, m_hasBackingFile(true)
+ , m_userVisibility(File::IsNotUserVisible)
+ , m_name(decodeURLEscapeSequences(fileSystemURL.lastPathComponent()))
, m_fileSystemURL(fileSystemURL)
, m_snapshotSize(metadata.length)
, m_snapshotModificationTime(metadata.modificationTime)
ScriptWrappable::init(this);
}
-double File::lastModifiedDate() const
+double File::lastModifiedMS() const
{
if (hasValidSnapshotMetadata() && isValidFileTime(m_snapshotModificationTime))
return m_snapshotModificationTime * msPerSecond;
time_t modificationTime;
- if (getFileModificationTime(m_path, modificationTime) && isValidFileTime(modificationTime))
+ if (hasBackingFile() && getFileModificationTime(m_path, modificationTime) && isValidFileTime(modificationTime))
return modificationTime * msPerSecond;
return currentTime() * msPerSecond;
}
+long long File::lastModified() const
+{
+ double modifiedDate = lastModifiedMS();
+
+ // The getter should return the current time when the last modification time isn't known.
+ if (!isValidFileTime(modifiedDate))
+ modifiedDate = currentTimeMS();
+
+ // lastModified returns a number, not a Date instance,
+ // http://dev.w3.org/2006/webapi/FileAPI/#file-attrs
+ return floor(modifiedDate);
+}
+
+double File::lastModifiedDate() const
+{
+ double modifiedDate = lastModifiedMS();
+
+ // The getter should return the current time when the last modification time isn't known.
+ if (!isValidFileTime(modifiedDate))
+ modifiedDate = currentTimeMS();
+
+ // lastModifiedDate returns a Date instance,
+ // http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
+ return modifiedDate;
+}
+
unsigned long long File::size() const
{
if (hasValidSnapshotMetadata())
// FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
// come up with an exception to throw if file size is not representable.
long long size;
- if (!getFileSize(m_path, size))
+ if (!hasBackingFile() || !getFileSize(m_path, size))
return 0;
return static_cast<unsigned long long>(size);
}
-PassRefPtr<Blob> File::slice(long long start, long long end, const String& contentType) const
+PassRefPtrWillBeRawPtr<Blob> File::slice(long long start, long long end, const String& contentType, ExceptionState& exceptionState) const
{
+ if (hasBeenClosed()) {
+ exceptionState.throwDOMException(InvalidStateError, "File has been closed.");
+ return nullptr;
+ }
+
if (!m_hasBackingFile)
- return Blob::slice(start, end, contentType);
+ return Blob::slice(start, end, contentType, exceptionState);
// FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
long long size;
// 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.
// If we fail to retrieve the size or modification time, probably due to that the file has been deleted, 0 size is returned.
FileMetadata metadata;
- if (!getFileMetadata(m_path, metadata)) {
+ if (!hasBackingFile() || !getFileMetadata(m_path, metadata)) {
snapshotSize = 0;
snapshotModificationTime = invalidFileTime();
return;
snapshotModificationTime = metadata.modificationTime;
}
+void File::close(ExecutionContext* executionContext, ExceptionState& exceptionState)
+{
+ if (hasBeenClosed()) {
+ exceptionState.throwDOMException(InvalidStateError, "Blob has been closed.");
+ return;
+ }
+
+ // Reset the File to its closed representation, an empty
+ // Blob. The name isn't cleared, as it should still be
+ // available.
+ m_hasBackingFile = false;
+ m_path = String();
+ m_fileSystemURL = KURL();
+ invalidateSnapshotMetadata();
+ m_relativePath = String();
+ Blob::close(executionContext, exceptionState);
+}
+
void File::appendTo(BlobData& blobData) const
{
if (!m_hasBackingFile) {
blobData.appendFile(m_path, 0, size, modificationTime);
}
-} // namespace WebCore
+} // namespace blink