Home | History | Annotate | Download | only in blob
      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 "platform/blob/BlobRegistry.h"
     33 
     34 #include "platform/blob/BlobData.h"
     35 #include "platform/blob/BlobURL.h"
     36 #include "platform/weborigin/SecurityOrigin.h"
     37 #include "platform/weborigin/SecurityOriginCache.h"
     38 #include "public/platform/Platform.h"
     39 #include "public/platform/WebBlobData.h"
     40 #include "public/platform/WebBlobRegistry.h"
     41 #include "public/platform/WebString.h"
     42 #include "public/platform/WebThreadSafeData.h"
     43 #include "wtf/Assertions.h"
     44 #include "wtf/HashMap.h"
     45 #include "wtf/MainThread.h"
     46 #include "wtf/RefPtr.h"
     47 #include "wtf/ThreadSpecific.h"
     48 #include "wtf/Threading.h"
     49 #include "wtf/text/StringHash.h"
     50 #include "wtf/text/WTFString.h"
     51 
     52 using blink::WebBlobData;
     53 using blink::WebBlobRegistry;
     54 using blink::WebThreadSafeData;
     55 using WTF::ThreadSpecific;
     56 
     57 namespace WebCore {
     58 
     59 class BlobOriginCache : public SecurityOriginCache {
     60 public:
     61     BlobOriginCache();
     62     virtual SecurityOrigin* cachedOrigin(const KURL&) OVERRIDE;
     63 };
     64 
     65 struct BlobRegistryContext {
     66     WTF_MAKE_FAST_ALLOCATED;
     67 public:
     68     BlobRegistryContext(const KURL& url, PassOwnPtr<BlobData> blobData)
     69         : url(url.copy())
     70         , blobData(blobData)
     71     {
     72         this->blobData->detachFromCurrentThread();
     73     }
     74 
     75     BlobRegistryContext(const KURL& url, const String& type)
     76         : url(url.copy())
     77         , type(type.isolatedCopy())
     78     {
     79     }
     80 
     81     BlobRegistryContext(const KURL& url, const KURL& srcURL)
     82         : url(url.copy())
     83         , srcURL(srcURL.copy())
     84     {
     85     }
     86 
     87     BlobRegistryContext(const KURL& url, PassRefPtr<RawData> streamData)
     88         : url(url.copy())
     89         , streamData(streamData)
     90     {
     91     }
     92 
     93     BlobRegistryContext(const KURL& url)
     94         : url(url.copy())
     95     {
     96     }
     97 
     98     KURL url;
     99     KURL srcURL;
    100     OwnPtr<BlobData> blobData;
    101     PassRefPtr<RawData> streamData;
    102     String type;
    103 };
    104 
    105 static WebBlobRegistry* blobRegistry()
    106 {
    107     return blink::Platform::current()->blobRegistry();
    108 }
    109 
    110 typedef HashMap<String, RefPtr<SecurityOrigin> > BlobURLOriginMap;
    111 static ThreadSpecific<BlobURLOriginMap>& originMap()
    112 {
    113     // We want to create the BlobOriginCache exactly once because it is shared by all the threads.
    114     AtomicallyInitializedStatic(BlobOriginCache*, cache = new BlobOriginCache);
    115     (void)cache; // BlobOriginCache's constructor does the interesting work.
    116 
    117     AtomicallyInitializedStatic(ThreadSpecific<BlobURLOriginMap>*, map = new ThreadSpecific<BlobURLOriginMap>);
    118     return *map;
    119 }
    120 
    121 static void saveToOriginMap(SecurityOrigin* origin, const KURL& url)
    122 {
    123     // If the blob URL contains null origin, as in the context with unique
    124     // security origin or file URL, save the mapping between url and origin so
    125     // that the origin can be retrived when doing security origin check.
    126     if (origin && BlobURL::getOrigin(url) == "null")
    127         originMap()->add(url.string(), origin);
    128 }
    129 
    130 static void removeFromOriginMap(const KURL& url)
    131 {
    132     if (BlobURL::getOrigin(url) == "null")
    133         originMap()->remove(url.string());
    134 }
    135 
    136 void BlobRegistry::registerBlobData(const String& uuid, PassOwnPtr<BlobData> data)
    137 {
    138     blobRegistry()->registerBlobData(uuid, blink::WebBlobData(data));
    139 }
    140 
    141 void BlobRegistry::addBlobDataRef(const String& uuid)
    142 {
    143     blobRegistry()->addBlobDataRef(uuid);
    144 }
    145 
    146 void BlobRegistry::removeBlobDataRef(const String& uuid)
    147 {
    148     blobRegistry()->removeBlobDataRef(uuid);
    149 }
    150 
    151 void BlobRegistry::registerPublicBlobURL(SecurityOrigin* origin, const KURL& url, PassRefPtr<BlobDataHandle> handle)
    152 {
    153     saveToOriginMap(origin, url);
    154     blobRegistry()->registerPublicBlobURL(url, handle->uuid());
    155 }
    156 
    157 void BlobRegistry::revokePublicBlobURL(const KURL& url)
    158 {
    159     removeFromOriginMap(url);
    160     blobRegistry()->revokePublicBlobURL(url);
    161 }
    162 
    163 static void registerStreamURLTask(void* context)
    164 {
    165     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    166     if (WebBlobRegistry* registry = blobRegistry())
    167         registry->registerStreamURL(blobRegistryContext->url, blobRegistryContext->type);
    168 }
    169 
    170 void BlobRegistry::registerStreamURL(const KURL& url, const String& type)
    171 {
    172     if (isMainThread()) {
    173         if (WebBlobRegistry* registry = blobRegistry())
    174             registry->registerStreamURL(url, type);
    175     } else {
    176         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url, type));
    177         callOnMainThread(&registerStreamURLTask, context.leakPtr());
    178     }
    179 }
    180 
    181 static void registerStreamURLFromTask(void* context)
    182 {
    183     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    184     if (WebBlobRegistry* registry = blobRegistry())
    185         registry->registerStreamURL(blobRegistryContext->url, blobRegistryContext->srcURL);
    186 }
    187 
    188 void BlobRegistry::registerStreamURL(SecurityOrigin* origin, const KURL& url, const KURL& srcURL)
    189 {
    190     saveToOriginMap(origin, url);
    191 
    192     if (isMainThread()) {
    193         if (WebBlobRegistry* registry = blobRegistry())
    194             registry->registerStreamURL(url, srcURL);
    195     } else {
    196         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url, srcURL));
    197         callOnMainThread(&registerStreamURLFromTask, context.leakPtr());
    198     }
    199 }
    200 
    201 static void addDataToStreamTask(void* context)
    202 {
    203     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    204     if (WebBlobRegistry* registry = blobRegistry()) {
    205         WebThreadSafeData webThreadSafeData(blobRegistryContext->streamData);
    206         registry->addDataToStream(blobRegistryContext->url, webThreadSafeData);
    207     }
    208 }
    209 
    210 void BlobRegistry::addDataToStream(const KURL& url, PassRefPtr<RawData> streamData)
    211 {
    212     if (isMainThread()) {
    213         if (WebBlobRegistry* registry = blobRegistry()) {
    214             WebThreadSafeData webThreadSafeData(streamData);
    215             registry->addDataToStream(url, webThreadSafeData);
    216         }
    217     } else {
    218         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url, streamData));
    219         callOnMainThread(&addDataToStreamTask, context.leakPtr());
    220     }
    221 }
    222 
    223 static void finalizeStreamTask(void* context)
    224 {
    225     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    226     if (WebBlobRegistry* registry = blobRegistry())
    227         registry->finalizeStream(blobRegistryContext->url);
    228 }
    229 
    230 void BlobRegistry::finalizeStream(const KURL& url)
    231 {
    232     if (isMainThread()) {
    233         if (WebBlobRegistry* registry = blobRegistry())
    234             registry->finalizeStream(url);
    235     } else {
    236         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url));
    237         callOnMainThread(&finalizeStreamTask, context.leakPtr());
    238     }
    239 }
    240 
    241 static void abortStreamTask(void* context)
    242 {
    243     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    244     if (WebBlobRegistry* registry = blobRegistry())
    245         registry->abortStream(blobRegistryContext->url);
    246 }
    247 
    248 void BlobRegistry::abortStream(const KURL& url)
    249 {
    250     if (isMainThread()) {
    251         if (WebBlobRegistry* registry = blobRegistry())
    252             registry->abortStream(url);
    253     } else {
    254         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url));
    255         callOnMainThread(&abortStreamTask, context.leakPtr());
    256     }
    257 }
    258 
    259 static void unregisterStreamURLTask(void* context)
    260 {
    261     OwnPtr<BlobRegistryContext> blobRegistryContext = adoptPtr(static_cast<BlobRegistryContext*>(context));
    262     if (WebBlobRegistry* registry = blobRegistry())
    263         registry->unregisterStreamURL(blobRegistryContext->url);
    264 }
    265 
    266 void BlobRegistry::unregisterStreamURL(const KURL& url)
    267 {
    268     removeFromOriginMap(url);
    269 
    270     if (isMainThread()) {
    271         if (WebBlobRegistry* registry = blobRegistry())
    272             registry->unregisterStreamURL(url);
    273     } else {
    274         OwnPtr<BlobRegistryContext> context = adoptPtr(new BlobRegistryContext(url));
    275         callOnMainThread(&unregisterStreamURLTask, context.leakPtr());
    276     }
    277 }
    278 
    279 BlobOriginCache::BlobOriginCache()
    280 {
    281     SecurityOrigin::setCache(this);
    282 }
    283 
    284 SecurityOrigin* BlobOriginCache::cachedOrigin(const KURL& url)
    285 {
    286     if (url.protocolIs("blob"))
    287         return originMap()->get(url.string());
    288     return 0;
    289 }
    290 
    291 } // namespace WebCore
    292