1/*
2 * Copyright (C) 2012 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 "ShareableResource.h"
28
29#include "ArgumentCoders.h"
30#include <WebCore/SharedBuffer.h>
31
32using namespace WebCore;
33
34namespace WebKit {
35
36ShareableResource::Handle::Handle()
37{
38}
39
40void ShareableResource::Handle::encode(CoreIPC::ArgumentEncoder& encoder) const
41{
42    encoder << m_handle;
43    encoder << m_offset;
44    encoder << m_size;
45}
46
47bool ShareableResource::Handle::decode(CoreIPC::ArgumentDecoder& decoder, Handle& handle)
48{
49    if (!decoder.decode(handle.m_handle))
50        return false;
51    if (!decoder.decode(handle.m_offset))
52        return false;
53    if (!decoder.decode(handle.m_size))
54        return false;
55    return true;
56}
57
58static void shareableResourceDeallocate(void *ptr, void *info)
59{
60    (static_cast<ShareableResource*>(info))->deref(); // Balanced by ref() in createShareableResourceDeallocator()
61}
62
63static CFAllocatorRef createShareableResourceDeallocator(ShareableResource* resource)
64{
65    resource->ref(); // Balanced by deref in shareableResourceDeallocate()
66
67    CFAllocatorContext context = { 0,
68        resource,
69        NULL, // retain
70        NULL, // release
71        NULL, // copyDescription
72        NULL, // allocate
73        NULL, // reallocate
74        shareableResourceDeallocate,
75        NULL, // preferredSize
76    };
77
78    return CFAllocatorCreate(kCFAllocatorDefault, &context);
79}
80
81PassRefPtr<SharedBuffer> ShareableResource::Handle::tryWrapInSharedBuffer() const
82{
83    RefPtr<ShareableResource> resource = ShareableResource::create(*this);
84    if (!resource) {
85        LOG_ERROR("Failed to recreate ShareableResource from handle.");
86        return 0;
87    }
88
89    RetainPtr<CFAllocatorRef> deallocator = adoptCF(createShareableResourceDeallocator(resource.get()));
90    RetainPtr<CFDataRef> data = adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(resource->data()), static_cast<CFIndex>(resource->size()), deallocator.get()));
91
92    return SharedBuffer::wrapCFData(data.get());
93}
94
95PassRefPtr<ShareableResource> ShareableResource::create(PassRefPtr<SharedMemory> sharedMemory, unsigned offset, unsigned size)
96{
97    return adoptRef(new ShareableResource(sharedMemory, offset, size));
98}
99
100PassRefPtr<ShareableResource> ShareableResource::create(const Handle& handle)
101{
102    RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle.m_handle, SharedMemory::ReadOnly);
103    if (!sharedMemory)
104        return 0;
105
106    return create(sharedMemory.release(), handle.m_offset, handle.m_size);
107}
108
109ShareableResource::ShareableResource(PassRefPtr<SharedMemory> sharedMemory, unsigned offset, unsigned size)
110    : m_sharedMemory(sharedMemory)
111    , m_offset(offset)
112    , m_size(size)
113{
114    ASSERT(m_sharedMemory);
115    ASSERT(m_offset + m_size <= m_sharedMemory->size());
116
117    // FIXME (NetworkProcess): This data was received from another process.  If it is bogus, should we assume that process is compromised and we should kill it?
118}
119
120ShareableResource::~ShareableResource()
121{
122}
123
124bool ShareableResource::createHandle(Handle& handle)
125{
126    if (!m_sharedMemory->createHandle(handle.m_handle, SharedMemory::ReadOnly))
127        return false;
128
129    handle.m_offset = m_offset;
130    handle.m_size = m_size;
131
132    return true;
133}
134
135const char* ShareableResource::data() const
136{
137    return static_cast<const char*>(m_sharedMemory->data()) + m_offset;
138}
139
140unsigned ShareableResource::size() const
141{
142    return m_size;
143}
144
145} // namespace WebKit
146