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/core/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 blink {
     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 }
     79 
     80 Blob::~Blob()
     81 {
     82 }
     83 
     84 void Blob::clampSliceOffsets(long long size, long long& start, long long& end)
     85 {
     86     ASSERT(size != -1);
     87 
     88     // Convert the negative value that is used to select from the end.
     89     if (start < 0)
     90         start = start + size;
     91     if (end < 0)
     92         end = end + size;
     93 
     94     // Clamp the range if it exceeds the size limit.
     95     if (start < 0)
     96         start = 0;
     97     if (end < 0)
     98         end = 0;
     99     if (start >= size) {
    100         start = 0;
    101         end = 0;
    102     } else if (end < start)
    103         end = start;
    104     else if (end > size)
    105         end = size;
    106 }
    107 
    108 PassRefPtrWillBeRawPtr<Blob> Blob::slice(long long start, long long end, const String& contentType, ExceptionState& exceptionState) const
    109 {
    110     if (hasBeenClosed()) {
    111         exceptionState.throwDOMException(InvalidStateError, "Blob has been closed.");
    112         return nullptr;
    113     }
    114 
    115     long long size = this->size();
    116     clampSliceOffsets(size, start, end);
    117 
    118     long long length = end - start;
    119     OwnPtr<BlobData> blobData = BlobData::create();
    120     blobData->setContentType(contentType);
    121     blobData->appendBlob(m_blobDataHandle, start, length);
    122     return Blob::create(BlobDataHandle::create(blobData.release(), length));
    123 }
    124 
    125 void Blob::close(ExecutionContext* executionContext, ExceptionState& exceptionState)
    126 {
    127     if (hasBeenClosed()) {
    128         exceptionState.throwDOMException(InvalidStateError, "Blob has been closed.");
    129         return;
    130     }
    131 
    132     // Dereferencing a Blob that has been closed should result in
    133     // a network error. Revoke URLs registered against it through
    134     // its UUID.
    135     DOMURL::revokeObjectUUID(executionContext, uuid());
    136 
    137     // A Blob enters a 'readability state' of closed, where it will report its
    138     // size as zero. Blob and FileReader operations now throws on
    139     // being passed a Blob in that state. Downstream uses of closed Blobs
    140     // (e.g., XHR.send()) consider them as empty.
    141     OwnPtr<BlobData> blobData = BlobData::create();
    142     blobData->setContentType(type());
    143     m_blobDataHandle = BlobDataHandle::create(blobData.release(), 0);
    144     m_hasBeenClosed = true;
    145 }
    146 
    147 void Blob::appendTo(BlobData& blobData) const
    148 {
    149     blobData.appendBlob(m_blobDataHandle, 0, m_blobDataHandle->size());
    150 }
    151 
    152 URLRegistry& Blob::registry() const
    153 {
    154     return BlobURLRegistry::registry();
    155 }
    156 
    157 } // namespace blink
    158