1/*
2 * Copyright (C) 2013 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "NetworkBlobRegistry.h"
28
29#if ENABLE(BLOB) && ENABLE(NETWORK_PROCESS)
30
31#include "SandboxExtension.h"
32#include <WebCore/BlobRegistryImpl.h>
33#include <wtf/MainThread.h>
34
35using namespace WebCore;
36
37namespace WebKit {
38
39NetworkBlobRegistry& NetworkBlobRegistry::shared()
40{
41    ASSERT(isMainThread());
42    DEFINE_STATIC_LOCAL(NetworkBlobRegistry, registry, ());
43    return registry;
44}
45
46NetworkBlobRegistry::NetworkBlobRegistry()
47{
48}
49
50void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const KURL& url, PassOwnPtr<BlobData> data, const Vector<RefPtr<SandboxExtension>>& newSandboxExtensions)
51{
52    ASSERT(!m_sandboxExtensions.contains(url.string()));
53
54    // Combine new extensions for File items and existing extensions for inner Blob items.
55    Vector<RefPtr<SandboxExtension>> sandboxExtensions = newSandboxExtensions;
56    const BlobDataItemList& items = data->items();
57    for (size_t i = 0, count = items.size(); i < count; ++i) {
58        if (items[i].type == BlobDataItem::Blob)
59            sandboxExtensions.appendVector(m_sandboxExtensions.get(items[i].url.string()));
60    }
61
62    blobRegistry().registerBlobURL(url, data);
63
64    if (!sandboxExtensions.isEmpty())
65        m_sandboxExtensions.add(url.string(), sandboxExtensions);
66
67    ASSERT(!m_blobsForConnection.get(connection).contains(url));
68    BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection);
69    if (mapIterator == m_blobsForConnection.end())
70        mapIterator = m_blobsForConnection.add(connection, HashSet<KURL>()).iterator;
71    mapIterator->value.add(url);
72}
73
74void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::KURL& url, const WebCore::KURL& srcURL)
75{
76    blobRegistry().registerBlobURL(url, srcURL);
77    SandboxExtensionMap::iterator iter = m_sandboxExtensions.find(srcURL.string());
78    if (iter != m_sandboxExtensions.end())
79        m_sandboxExtensions.add(url.string(), iter->value);
80
81    ASSERT(m_blobsForConnection.contains(connection));
82    ASSERT(m_blobsForConnection.find(connection)->value.contains(srcURL));
83    m_blobsForConnection.find(connection)->value.add(url);
84}
85
86void NetworkBlobRegistry::unregisterBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::KURL& url)
87{
88    blobRegistry().unregisterBlobURL(url);
89    m_sandboxExtensions.remove(url.string());
90
91    ASSERT(m_blobsForConnection.contains(connection));
92    ASSERT(m_blobsForConnection.find(connection)->value.contains(url));
93    m_blobsForConnection.find(connection)->value.remove(url);
94}
95
96void NetworkBlobRegistry::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection)
97{
98    if (!m_blobsForConnection.contains(connection))
99        return;
100
101    HashSet<KURL>& blobsForConnection = m_blobsForConnection.find(connection)->value;
102    for (HashSet<KURL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter) {
103        blobRegistry().unregisterBlobURL(*iter);
104        m_sandboxExtensions.remove(*iter);
105    }
106
107    m_blobsForConnection.remove(connection);
108}
109
110const Vector<RefPtr<SandboxExtension>> NetworkBlobRegistry::sandboxExtensions(const WebCore::KURL& url)
111{
112    return m_sandboxExtensions.get(url.string());
113}
114
115}
116
117#endif
118