Home | History | Annotate | Download | only in fileapi
      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 
     33 #if ENABLE(FILE_SYSTEM)
     34 
     35 #include "FileWriter.h"
     36 
     37 #include "AsyncFileWriter.h"
     38 #include "Blob.h"
     39 #include "ExceptionCode.h"
     40 #include "FileError.h"
     41 #include "FileException.h"
     42 #include "ProgressEvent.h"
     43 
     44 namespace WebCore {
     45 
     46 FileWriter::FileWriter(ScriptExecutionContext* context)
     47     : ActiveDOMObject(context, this)
     48     , m_readyState(INIT)
     49     , m_startedWriting(false)
     50     , m_bytesWritten(0)
     51     , m_bytesToWrite(0)
     52     , m_truncateLength(-1)
     53 {
     54 }
     55 
     56 FileWriter::~FileWriter()
     57 {
     58     if (m_readyState == WRITING)
     59         stop();
     60 }
     61 
     62 bool FileWriter::hasPendingActivity() const
     63 {
     64     return m_readyState == WRITING || ActiveDOMObject::hasPendingActivity();
     65 }
     66 
     67 bool FileWriter::canSuspend() const
     68 {
     69     // FIXME: It is not currently possible to suspend a FileWriter, so pages with FileWriter can not go into page cache.
     70     return false;
     71 }
     72 
     73 void FileWriter::stop()
     74 {
     75     if (writer() && m_readyState == WRITING)
     76         writer()->abort();
     77     m_blobBeingWritten.clear();
     78     m_readyState = DONE;
     79 }
     80 
     81 void FileWriter::write(Blob* data, ExceptionCode& ec)
     82 {
     83     ASSERT(writer());
     84     if (m_readyState == WRITING) {
     85         setError(FileError::INVALID_STATE_ERR, ec);
     86         return;
     87     }
     88     if (!data) {
     89         setError(FileError::TYPE_MISMATCH_ERR, ec);
     90         return;
     91     }
     92 
     93     m_blobBeingWritten = data;
     94     m_readyState = WRITING;
     95     m_startedWriting = false;
     96     m_bytesWritten = 0;
     97     m_bytesToWrite = data->size();
     98     writer()->write(position(), data);
     99 }
    100 
    101 void FileWriter::seek(long long position, ExceptionCode& ec)
    102 {
    103     ASSERT(writer());
    104     if (m_readyState == WRITING) {
    105         setError(FileError::INVALID_STATE_ERR, ec);
    106         return;
    107     }
    108 
    109     m_bytesWritten = 0;
    110     m_bytesToWrite = 0;
    111     seekInternal(position);
    112 }
    113 
    114 void FileWriter::truncate(long long position, ExceptionCode& ec)
    115 {
    116     ASSERT(writer());
    117     if (m_readyState == WRITING || position < 0) {
    118         setError(FileError::INVALID_STATE_ERR, ec);
    119         return;
    120     }
    121     m_readyState = WRITING;
    122     m_bytesWritten = 0;
    123     m_bytesToWrite = 0;
    124     m_truncateLength = position;
    125     writer()->truncate(position);
    126 }
    127 
    128 void FileWriter::abort(ExceptionCode& ec)
    129 {
    130     ASSERT(writer());
    131     if (m_readyState != WRITING) {
    132         setError(FileError::INVALID_STATE_ERR, ec);
    133         return;
    134     }
    135 
    136     m_error = FileError::create(FileError::ABORT_ERR);
    137     writer()->abort();
    138 }
    139 
    140 void FileWriter::didWrite(long long bytes, bool complete)
    141 {
    142     ASSERT(bytes + m_bytesWritten > 0);
    143     ASSERT(bytes + m_bytesWritten <= m_bytesToWrite);
    144     if (!m_startedWriting) {
    145         fireEvent(eventNames().writestartEvent);
    146         m_startedWriting = true;
    147     }
    148     m_bytesWritten += bytes;
    149     ASSERT((m_bytesWritten == m_bytesToWrite) || !complete);
    150     setPosition(position() + bytes);
    151     if (position() > length())
    152         setLength(position());
    153     fireEvent(eventNames().progressEvent);
    154     if (complete) {
    155         m_blobBeingWritten.clear();
    156         fireEvent(eventNames().writeEvent);
    157         m_readyState = DONE;
    158         fireEvent(eventNames().writeendEvent);
    159     }
    160 }
    161 
    162 void FileWriter::didTruncate()
    163 {
    164     ASSERT(m_truncateLength >= 0);
    165     fireEvent(eventNames().writestartEvent);
    166     setLength(m_truncateLength);
    167     if (position() > length())
    168         setPosition(length());
    169     m_truncateLength = -1;
    170     fireEvent(eventNames().writeEvent);
    171     m_readyState = DONE;
    172     fireEvent(eventNames().writeendEvent);
    173 }
    174 
    175 void FileWriter::didFail(FileError::ErrorCode code)
    176 {
    177     m_error = FileError::create(code);
    178     fireEvent(eventNames().errorEvent);
    179     if (FileError::ABORT_ERR == code)
    180         fireEvent(eventNames().abortEvent);
    181     fireEvent(eventNames().errorEvent);
    182     m_blobBeingWritten.clear();
    183     m_readyState = DONE;
    184     fireEvent(eventNames().writeendEvent);
    185 }
    186 
    187 void FileWriter::fireEvent(const AtomicString& type)
    188 {
    189     dispatchEvent(ProgressEvent::create(type, true, m_bytesWritten, m_bytesToWrite));
    190 }
    191 
    192 void FileWriter::setError(FileError::ErrorCode errorCode, ExceptionCode& ec)
    193 {
    194     ec = FileException::ErrorCodeToExceptionCode(errorCode);
    195     m_error = FileError::create(errorCode);
    196 }
    197 
    198 } // namespace WebCore
    199 
    200 #endif // ENABLE(FILE_SYSTEM)
    201