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(BLOB) || ENABLE(FILE_SYSTEM)
     34 
     35 #include "FileStreamProxy.h"
     36 
     37 #include "Blob.h"
     38 #include "CrossThreadTask.h"
     39 #include "FileStream.h"
     40 #include "FileThread.h"
     41 #include "FileThreadTask.h"
     42 #include "PlatformString.h"
     43 #include "ScriptExecutionContext.h"
     44 
     45 namespace WebCore {
     46 
     47 inline FileStreamProxy::FileStreamProxy(ScriptExecutionContext* context, FileStreamClient* client)
     48     : AsyncFileStream(client)
     49     , m_context(context)
     50     , m_stream(FileStream::create())
     51 {
     52 }
     53 
     54 PassRefPtr<FileStreamProxy> FileStreamProxy::create(ScriptExecutionContext* context, FileStreamClient* client)
     55 {
     56     RefPtr<FileStreamProxy> proxy = adoptRef(new FileStreamProxy(context, client));
     57 
     58     // Hold an ref so that the instance will not get deleted while there are tasks on the file thread.
     59     // This is balanced by the deref in derefProxyOnContext below.
     60     proxy->ref();
     61 
     62     proxy->fileThread()->postTask(createFileThreadTask(proxy.get(), &FileStreamProxy::startOnFileThread));
     63 
     64     return proxy.release();
     65 }
     66 
     67 FileStreamProxy::~FileStreamProxy()
     68 {
     69 }
     70 
     71 FileThread* FileStreamProxy::fileThread()
     72 {
     73     ASSERT(m_context->isContextThread());
     74     ASSERT(m_context->fileThread());
     75     return m_context->fileThread();
     76 }
     77 
     78 static void didStart(ScriptExecutionContext*, FileStreamProxy* proxy)
     79 {
     80     if (proxy->client())
     81         proxy->client()->didStart();
     82 }
     83 
     84 void FileStreamProxy::startOnFileThread()
     85 {
     86     if (!client())
     87         return;
     88     m_stream->start();
     89     m_context->postTask(createCallbackTask(&didStart, this));
     90 }
     91 
     92 void FileStreamProxy::stop()
     93 {
     94     // Clear the client so that we won't be calling callbacks on the client.
     95     setClient(0);
     96 
     97     fileThread()->unscheduleTasks(m_stream.get());
     98     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::stopOnFileThread));
     99 }
    100 
    101 static void derefProxyOnContext(ScriptExecutionContext*, FileStreamProxy* proxy)
    102 {
    103     ASSERT(proxy->hasOneRef());
    104     proxy->deref();
    105 }
    106 
    107 void FileStreamProxy::stopOnFileThread()
    108 {
    109     m_stream->stop();
    110     m_context->postTask(createCallbackTask(&derefProxyOnContext, this));
    111 }
    112 
    113 static void didGetSize(ScriptExecutionContext*, FileStreamProxy* proxy, long long size)
    114 {
    115     if (proxy->client())
    116         proxy->client()->didGetSize(size);
    117 }
    118 
    119 void FileStreamProxy::getSize(const String& path, double expectedModificationTime)
    120 {
    121     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::getSizeOnFileThread, path, expectedModificationTime));
    122 }
    123 
    124 void FileStreamProxy::getSizeOnFileThread(const String& path, double expectedModificationTime)
    125 {
    126     long long size = m_stream->getSize(path, expectedModificationTime);
    127     m_context->postTask(createCallbackTask(&didGetSize, this, size));
    128 }
    129 
    130 static void didOpen(ScriptExecutionContext*, FileStreamProxy* proxy, bool success)
    131 {
    132     if (proxy->client())
    133         proxy->client()->didOpen(success);
    134 }
    135 
    136 void FileStreamProxy::openForRead(const String& path, long long offset, long long length)
    137 {
    138     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::openForReadOnFileThread, path, offset, length));
    139 }
    140 
    141 void FileStreamProxy::openForReadOnFileThread(const String& path, long long offset, long long length)
    142 {
    143     bool success = m_stream->openForRead(path, offset, length);
    144     m_context->postTask(createCallbackTask(&didOpen, this, success));
    145 }
    146 
    147 void FileStreamProxy::openForWrite(const String& path)
    148 {
    149     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::openForWriteOnFileThread, path));
    150 }
    151 
    152 void FileStreamProxy::openForWriteOnFileThread(const String& path)
    153 {
    154     bool success = m_stream->openForWrite(path);
    155     m_context->postTask(createCallbackTask(&didOpen, this, success));
    156 }
    157 
    158 void FileStreamProxy::close()
    159 {
    160     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::closeOnFileThread));
    161 }
    162 
    163 void FileStreamProxy::closeOnFileThread()
    164 {
    165     m_stream->close();
    166 }
    167 
    168 static void didRead(ScriptExecutionContext*, FileStreamProxy* proxy, int bytesRead)
    169 {
    170     if (proxy->client())
    171         proxy->client()->didRead(bytesRead);
    172 }
    173 
    174 void FileStreamProxy::read(char* buffer, int length)
    175 {
    176     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::readOnFileThread, buffer, length));
    177 }
    178 
    179 void FileStreamProxy::readOnFileThread(char* buffer, int length)
    180 {
    181     int bytesRead = m_stream->read(buffer, length);
    182     m_context->postTask(createCallbackTask(&didRead, this, bytesRead));
    183 }
    184 
    185 static void didWrite(ScriptExecutionContext*, FileStreamProxy* proxy, int bytesWritten)
    186 {
    187     if (proxy->client())
    188         proxy->client()->didWrite(bytesWritten);
    189 }
    190 
    191 void FileStreamProxy::write(const KURL& blobURL, long long position, int length)
    192 {
    193     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::writeOnFileThread, blobURL, position, length));
    194 }
    195 
    196 void FileStreamProxy::writeOnFileThread(const KURL& blobURL, long long position, int length)
    197 {
    198     int bytesWritten = m_stream->write(blobURL, position, length);
    199     m_context->postTask(createCallbackTask(&didWrite, this, bytesWritten));
    200 }
    201 
    202 static void didTruncate(ScriptExecutionContext*, FileStreamProxy* proxy, bool success)
    203 {
    204     if (proxy->client())
    205         proxy->client()->didTruncate(success);
    206 }
    207 
    208 void FileStreamProxy::truncate(long long position)
    209 {
    210     fileThread()->postTask(createFileThreadTask(this, &FileStreamProxy::truncateOnFileThread, position));
    211 }
    212 
    213 void FileStreamProxy::truncateOnFileThread(long long position)
    214 {
    215     bool success = m_stream->truncate(position);
    216     m_context->postTask(createCallbackTask(&didTruncate, this, success));
    217 }
    218 
    219 } // namespace WebCore
    220 
    221 #endif // ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
    222