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 #include "core/fileapi/Blob.h"
     33 
     34 #include "bindings/v8/ExceptionState.h"
     35 #include "core/dom/DOMURL.h"
     36 #include "core/dom/ExceptionCode.h"
     37 #include "core/dom/ExecutionContext.h"
     38 #include "core/fileapi/File.h"
     39 #include "platform/blob/BlobRegistry.h"
     40 #include "platform/blob/BlobURL.h"
     41 
     42 namespace WebCore {
     43 
     44 namespace {
     45 
     46 class BlobURLRegistry FINAL : public URLRegistry {
     47 public:
     48     virtual void registerURL(SecurityOrigin*, const KURL&, URLRegistrable*) OVERRIDE;
     49     virtual void unregisterURL(const KURL&) OVERRIDE;
     50 
     51     static URLRegistry& registry();
     52 };
     53 
     54 void BlobURLRegistry::registerURL(SecurityOrigin* origin, const KURL& publicURL, URLRegistrable* registrableObject)
     55 {
     56     ASSERT(&registrableObject->registry() == this);
     57     Blob* blob = static_cast<Blob*>(registrableObject);
     58     BlobRegistry::registerPublicBlobURL(origin, publicURL, blob->blobDataHandle());
     59 }
     60 
     61 void BlobURLRegistry::unregisterURL(const KURL& publicURL)
     62 {
     63     BlobRegistry::revokePublicBlobURL(publicURL);
     64 }
     65 
     66 URLRegistry& BlobURLRegistry::registry()
     67 {
     68     DEFINE_STATIC_LOCAL(BlobURLRegistry, instance, ());
     69     return instance;
     70 }
     71 
     72 } // namespace
     73 
     74 Blob::Blob(PassRefPtr<BlobDataHandle> dataHandle)
     75     : m_blobDataHandle(dataHandle)
     76     , m_hasBeenClosed(false)
     77 {
     78     ScriptWrappable::init(this);
     79 }
     80 
     81 Blob::~Blob()
     82 {
     83 }
     84 
     85 void Blob::clampSliceOffsets(long long size, long long& start, long long& end)
     86 {
     87     ASSERT(size != -1);
     88 
     89     // Convert the negative value that is used to select from the end.
     90     if (start < 0)
     91         start = start + size;
     92     if (end < 0)
     93         end = end + size;
     94 
     95     // Clamp the range if it exceeds the size limit.
     96     if (start < 0)
     97         start = 0;
     98     if (end < 0)
     99         end = 0;
    100     if (start >= size) {
    101         start = 0;
    102         end = 0;
    103     } else if (end < start)
    104         end = start;
    105     else if (end > size)
    106         end = size;
    107 }
    108 
    109 PassRefPtrWillBeRawPtr<Blob> Blob::slice(long long start, long long end, const String& contentType, ExceptionState& exceptionState) const
    110 {
    111     if (hasBeenClosed()) {
    112         exceptionState.throwDOMException(InvalidStateError, "Blob has been closed.");
    113         return nullptr;
    114     }
    115 
    116     long long size = this->size();
    117     clampSliceOffsets(size, start, end);
    118 
    119     long long length = end - start;
    120     OwnPtr<BlobData> blobData = BlobData::create();
    121     blobData->setContentType(contentType);
    122     blobData->appendBlob(m_blobDataHandle, start, length);
    123     return Blob::create(BlobDataHandle::create(blobData.release(), length));
    124 }
    125 
    126 void Blob::close(ExecutionContext* executionContext, ExceptionState& exceptionState)
    127 {
    128     if (hasBeenClosed()) {
    129         exceptionState.throwDOMException(InvalidStateError, "Blob has been closed.");
    130         return;
    131     }
    132 
    133     // Dereferencing a Blob that has been closed should result in
    134     // a network error. Revoke URLs registered against it through
    135     // its UUID.
    136     DOMURL::revokeObjectUUID(executionContext, uuid());
    137 
    138     // A Blob enters a 'readability state' of closed, where it will report its
    139     // size as zero. Blob and FileReader operations now throws on
    140     // being passed a Blob in that state. Downstream uses of closed Blobs
    141     // (e.g., XHR.send()) consider them as empty.
    142     OwnPtr<BlobData> blobData = BlobData::create();
    143     blobData->setContentType(type());
    144     m_blobDataHandle = BlobDataHandle::create(blobData.release(), 0);
    145     m_hasBeenClosed = true;
    146 }
    147 
    148 void Blob::appendTo(BlobData& blobData) const
    149 {
    150     blobData.appendBlob(m_blobDataHandle, 0, m_blobDataHandle->size());
    151 }
    152 
    153 URLRegistry& Blob::registry() const
    154 {
    155     return BlobURLRegistry::registry();
    156 }
    157 
    158 } // namespace WebCore
    159