Sharing SharedBuffer between WebCore and ImageIO is racy and crash prone
[WebKit-https.git] / Source / WebCore / platform / SharedBuffer.h
1 /*
2  * Copyright (C) 2006 Apple Inc.  All rights reserved.
3  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #ifndef SharedBuffer_h
28 #define SharedBuffer_h
29
30 #include <runtime/ArrayBuffer.h>
31 #include <wtf/Forward.h>
32 #include <wtf/OwnPtr.h>
33 #include <wtf/RefCounted.h>
34 #include <wtf/ThreadSafeRefCounted.h>
35 #include <wtf/Vector.h>
36 #include <wtf/text/WTFString.h>
37
38 #if USE(CF)
39 #include <wtf/RetainPtr.h>
40 #endif
41
42 #if USE(SOUP)
43 #include "GUniquePtrSoup.h"
44 #endif
45
46 #if USE(FOUNDATION)
47 OBJC_CLASS NSData;
48 #endif
49
50 namespace WebCore {
51     
52 class PurgeableBuffer;
53
54 class SharedBuffer : public RefCounted<SharedBuffer> {
55 public:
56     static PassRefPtr<SharedBuffer> create() { return adoptRef(new SharedBuffer); }
57     static PassRefPtr<SharedBuffer> create(unsigned size) { return adoptRef(new SharedBuffer(size)); }
58     static PassRefPtr<SharedBuffer> create(const char* c, unsigned i) { return adoptRef(new SharedBuffer(c, i)); }
59     static PassRefPtr<SharedBuffer> create(const unsigned char* c, unsigned i) { return adoptRef(new SharedBuffer(c, i)); }
60
61     static PassRefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
62
63     static PassRefPtr<SharedBuffer> adoptVector(Vector<char>& vector);
64     
65     // The buffer must be in non-purgeable state before adopted to a SharedBuffer. 
66     // It will stay that way until released.
67     static PassRefPtr<SharedBuffer> adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer>);
68     
69     ~SharedBuffer();
70     
71 #if USE(FOUNDATION)
72     RetainPtr<NSData> createNSData();
73     static PassRefPtr<SharedBuffer> wrapNSData(NSData *data);
74 #endif
75 #if USE(CF)
76     RetainPtr<CFDataRef> createCFData();
77     static PassRefPtr<SharedBuffer> wrapCFData(CFDataRef);
78 #endif
79
80 #if USE(SOUP)
81     static PassRefPtr<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
82 #endif
83
84     // Calling this function will force internal segmented buffers
85     // to be merged into a flat buffer. Use getSomeData() whenever possible
86     // for better performance.
87     const char* data() const;
88     // Creates an ArrayBuffer and copies this SharedBuffer's contents to that
89     // ArrayBuffer without merging segmented buffers into a flat buffer.
90     PassRefPtr<ArrayBuffer> createArrayBuffer() const;
91
92     unsigned size() const;
93
94
95     bool isEmpty() const { return !size(); }
96
97     void append(SharedBuffer*);
98     void append(const char*, unsigned);
99     void append(const Vector<char>&);
100
101     void clear();
102     const char* platformData() const;
103     unsigned platformDataSize() const;
104
105 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
106     static PassRefPtr<SharedBuffer> wrapCFDataArray(CFArrayRef);
107     void append(CFDataRef);
108 #endif
109
110     PassRefPtr<SharedBuffer> copy() const;
111     
112     bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
113
114     // Ensure this buffer has no other clients before calling this.
115     PassOwnPtr<PurgeableBuffer> releasePurgeableBuffer();
116
117     // Return the number of consecutive bytes after "position". "data"
118     // points to the first byte.
119     // Return 0 when no more data left.
120     // When extracting all data with getSomeData(), the caller should
121     // repeat calling it until it returns 0.
122     // Usage:
123     //      const char* segment;
124     //      unsigned pos = 0;
125     //      while (unsigned length = sharedBuffer->getSomeData(segment, pos)) {
126     //          // Use the data. for example: decoder->decode(segment, length);
127     //          pos += length;
128     //      }
129     unsigned getSomeData(const char*& data, unsigned position = 0) const;
130
131     void shouldUsePurgeableMemory(bool use) { m_shouldUsePurgeableMemory = use; }
132
133 #if ENABLE(DISK_IMAGE_CACHE)
134     enum MemoryMappingState { QueuedForMapping, PreviouslyQueuedForMapping, SuccessAlreadyMapped, FailureCacheFull };
135
136     // Calling this will cause this buffer to be memory mapped.
137     MemoryMappingState allowToBeMemoryMapped();
138     bool isAllowedToBeMemoryMapped() const;
139
140     // This is called to indicate that the memory mapping failed.
141     void failedMemoryMap();
142
143     // This is called only once the buffer has been completely memory mapped.
144     void markAsMemoryMapped();
145     bool isMemoryMapped() const { return m_isMemoryMapped; }
146
147     // This callback function will be called when either the buffer has been memory mapped or failed to be memory mapped.
148     enum CompletionStatus { Failed, Succeeded };
149     typedef void* MemoryMappedNotifyCallbackData;
150     typedef void (*MemoryMappedNotifyCallback)(PassRefPtr<SharedBuffer>, CompletionStatus, MemoryMappedNotifyCallbackData);
151
152     MemoryMappedNotifyCallbackData memoryMappedNotificationCallbackData() const;
153     MemoryMappedNotifyCallback memoryMappedNotificationCallback() const;
154     void setMemoryMappedNotificationCallback(MemoryMappedNotifyCallback, MemoryMappedNotifyCallbackData);
155 #endif
156
157     void createPurgeableBuffer() const;
158
159     void tryReplaceContentsWithPlatformBuffer(SharedBuffer*);
160     bool hasPlatformData() const;
161
162     struct DataBuffer : public ThreadSafeRefCounted<DataBuffer> {
163         Vector<char> data;
164     };
165
166 private:
167     SharedBuffer();
168     explicit SharedBuffer(unsigned);
169     SharedBuffer(const char*, unsigned);
170     SharedBuffer(const unsigned char*, unsigned);
171     
172     // Calling this function will force internal segmented buffers
173     // to be merged into a flat buffer. Use getSomeData() whenever possible
174     // for better performance.
175     // As well, be aware that this method does *not* return any purgeable
176     // memory, which can be a source of bugs.
177     const Vector<char>& buffer() const;
178
179     void clearPlatformData();
180     void maybeTransferPlatformData();
181     bool maybeAppendPlatformData(SharedBuffer*);
182
183     void copyBufferAndClear(char* destination, unsigned bytesToCopy) const;
184
185     void appendToDataBuffer(const char *, unsigned) const;
186     void duplicateDataBufferIfNecessary() const;
187     void clearDataBuffer();
188
189     unsigned m_size;
190     mutable RefPtr<DataBuffer> m_buffer;
191
192     bool m_shouldUsePurgeableMemory;
193     mutable OwnPtr<PurgeableBuffer> m_purgeableBuffer;
194 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
195     explicit SharedBuffer(CFArrayRef);
196     mutable Vector<RetainPtr<CFDataRef>> m_dataArray;
197     unsigned copySomeDataFromDataArray(const char*& someData, unsigned position) const;
198     const char *singleDataArrayBuffer() const;
199     bool maybeAppendDataArray(SharedBuffer*);
200 #else
201     mutable Vector<char*> m_segments;
202 #endif
203 #if ENABLE(DISK_IMAGE_CACHE)
204     bool m_isMemoryMapped;
205     unsigned m_diskImageCacheId; // DiskImageCacheId is unsigned.
206     MemoryMappedNotifyCallback m_notifyMemoryMappedCallback;
207     MemoryMappedNotifyCallbackData m_notifyMemoryMappedCallbackData;
208 #endif
209 #if USE(CF)
210     explicit SharedBuffer(CFDataRef);
211     RetainPtr<CFDataRef> m_cfData;
212 #endif
213
214 #if USE(SOUP)
215     explicit SharedBuffer(SoupBuffer*);
216     GUniquePtr<SoupBuffer> m_soupBuffer;
217 #endif
218 };
219
220 PassRefPtr<SharedBuffer> utf8Buffer(const String&);
221
222 } // namespace WebCore
223
224 #endif // SharedBuffer_h