root/trunk/WebCore/platform/network/cf/FormDataStreamCFNet.cpp

Revision 56825, 13.4 KB (checked in by barraclough@apple.com, 4 months ago)

Rubber stamped by Sam Weinig.

 https://bugs.webkit.org/show_bug.cgi?id=36866
Move CString to WTF

JavaScriptCore:

* Android.mk:
* GNUmakefile.am:
* JavaScriptCore.exp:
* JavaScriptCore.gypi:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.vcproj/WTF/WTF.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* wtf/text: Added.
* wtf/text/CString.cpp: Copied from WebCore/platform/text/CString.cpp.
* wtf/text/CString.h: Copied from WebCore/platform/text/CString.h.
(WTF::CStringBuffer::data):
(WTF::CStringBuffer::length):
(WTF::CStringBuffer::create):
(WTF::CStringBuffer::CStringBuffer):
(WTF::CStringBuffer::mutableData):
(WTF::CString::CString):
(WTF::CString::isNull):
(WTF::CString::buffer):
(WTF::operator!=):

WebCore:

* Android.mk:
* ForwardingHeaders/wtf/text: Added.
* ForwardingHeaders/wtf/text/CString.h: Added.
* GNUmakefile.am:
* WebCore.base.exp:
* WebCore.gypi:
* WebCore.order:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* accessibility/gtk/AccessibilityObjectWrapperAtk.cpp:
* bindings/js/JSDOMWindowBase.cpp:
* bindings/js/ScheduledAction.cpp:
* bindings/js/ScriptController.cpp:
* bindings/v8/ScriptController.cpp:
* bindings/v8/V8Binding.cpp:
* bindings/v8/V8DOMWindowShell.cpp:
* bridge/jni/JNIBridge.cpp:
* bridge/jni/v8/JavaStringV8.h:
(JSC::Bindings::JavaStringImpl::init):
* css/CSSParser.cpp:
* dom/CharacterData.cpp:
* dom/Document.cpp:
* dom/Element.cpp:
* dom/Node.cpp:
* dom/Position.cpp:
* dom/Range.cpp:
* dom/Text.cpp:
* dom/XMLTokenizer.cpp:
* dom/XMLTokenizerLibxml2.cpp:
* dom/XMLTokenizerQt.cpp:
* editing/SelectionController.cpp:
* editing/VisiblePosition.cpp:
* editing/VisibleSelection.cpp:
* history/CachedFrame.cpp:
* history/HistoryItem.cpp:
* history/qt/HistoryItemQt.cpp:
* html/FormDataList.h:
(WebCore::FormDataList::appendData):
(WebCore::FormDataList::Item::Item):
(WebCore::FormDataList::Item::data):
* html/HTMLDocument.cpp:
* html/PreloadScanner.cpp:
* inspector/InspectorController.cpp:
* inspector/InspectorDOMAgent.cpp:
* loader/DocLoader.cpp:
* loader/FTPDirectoryDocument.cpp:
* loader/FrameLoader.cpp:
* loader/HistoryController.cpp:
* loader/ProgressTracker.cpp:
* loader/appcache/ApplicationCacheStorage.cpp:
* loader/archive/cf/LegacyWebArchive.cpp:
* loader/icon/wince/IconDatabaseWince.cpp:
* loader/loader.cpp:
* page/Console.cpp:
* page/DOMWindow.cpp:
* page/SecurityOrigin.cpp:
* page/XSSAuditor.cpp:
* page/animation/AnimationBase.cpp:
* platform/ContextMenu.cpp:
* platform/FileSystem.h:
* platform/KURL.cpp:
* platform/KURLGoogle.cpp:
* platform/KURLGooglePrivate.h:
* platform/Pasteboard.h:
* platform/android/FileSystemAndroid.cpp:
* platform/android/TemporaryLinkStubs.cpp:
* platform/brew/KURLBrew.cpp:
* platform/cf/FileSystemCF.cpp:
* platform/chromium/MIMETypeRegistryChromium.cpp:
* platform/efl/FileSystemEfl.cpp:
* platform/efl/PasteboardEfl.cpp:
* platform/efl/PlatformKeyboardEventEfl.cpp:
* platform/efl/PlatformScreenEfl.cpp:
* platform/efl/RenderThemeEfl.cpp:
* platform/efl/ScrollbarEfl.cpp:
* platform/efl/SharedBufferEfl.cpp:
* platform/efl/WidgetEfl.cpp:
* platform/graphics/GlyphPageTreeNode.cpp:
* platform/graphics/cairo/FontPlatformDataCairo.cpp:
* platform/graphics/cg/ImageBufferCG.cpp:
* platform/graphics/chromium/FontCacheLinux.cpp:
* platform/graphics/chromium/FontPlatformDataLinux.h:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
* platform/graphics/gtk/FontPlatformDataPango.cpp:
* platform/graphics/gtk/IconGtk.cpp:
* platform/graphics/gtk/ImageGtk.cpp:
* platform/graphics/haiku/GraphicsContextHaiku.cpp:
* platform/graphics/mac/GraphicsContext3DMac.cpp:
* platform/graphics/mac/GraphicsLayerCA.mm:
* platform/graphics/qt/GraphicsContext3DQt.cpp:
* platform/graphics/qt/ImageBufferQt.cpp:
* platform/graphics/qt/MediaPlayerPrivatePhonon.cpp:
* platform/graphics/qt/MediaPlayerPrivateQt.cpp:
* platform/graphics/skia/GraphicsLayerSkia.cpp:
* platform/graphics/win/GraphicsLayerCACF.cpp:
* platform/graphics/win/WKCACFLayer.cpp:
* platform/graphics/wx/FontPlatformData.h:
* platform/gtk/ClipboardGtk.cpp:
* platform/gtk/ContextMenuItemGtk.cpp:
* platform/gtk/DataObjectGtk.h:
* platform/gtk/FileChooserGtk.cpp:
* platform/gtk/FileSystemGtk.cpp:
* platform/gtk/GeolocationServiceGtk.cpp:
* platform/gtk/KURLGtk.cpp:
* platform/gtk/Language.cpp:
* platform/gtk/LocalizedStringsGtk.cpp:
* platform/gtk/PasteboardGtk.cpp:
* platform/gtk/PopupMenuGtk.cpp:
* platform/gtk/RenderThemeGtk.cpp:
* platform/gtk/SharedBufferGtk.cpp:
* platform/haiku/FileSystemHaiku.cpp:
* platform/haiku/PlatformKeyboardEventHaiku.cpp:
* platform/network/CredentialStorage.cpp:
* platform/network/FormData.cpp:
* platform/network/FormData.h:
* platform/network/FormDataBuilder.cpp:
* platform/network/FormDataBuilder.h:
* platform/network/HTTPParsers.cpp:
* platform/network/android/ResourceHandleAndroid.cpp:
* platform/network/cf/FormDataStreamCFNet.cpp:
* platform/network/cf/ResourceHandleCFNet.cpp:
* platform/network/chromium/ResourceResponse.h:
* platform/network/curl/FormDataStreamCurl.cpp:
* platform/network/curl/ResourceHandleManager.cpp:
* platform/network/curl/ResourceHandleManager.h:
* platform/network/mac/FormDataStreamMac.mm:
* platform/network/mac/ResourceHandleMac.mm:
* platform/network/qt/QNetworkReplyHandler.cpp:
* platform/network/soup/CookieJarSoup.cpp:
* platform/network/soup/ResourceHandleSoup.cpp:
* platform/network/soup/ResourceRequestSoup.cpp:
* platform/network/soup/ResourceResponseSoup.cpp:
* platform/network/win/ResourceHandleWin.cpp:
* platform/posix/FileSystemPOSIX.cpp:
* platform/qt/FileSystemQt.cpp:
* platform/qt/KURLQt.cpp:
* platform/qt/TemporaryLinkStubs.cpp:
* platform/sql/chromium/SQLiteFileSystemChromium.cpp:
* platform/text/CString.cpp: Removed.
* platform/text/CString.h: Removed.
* platform/text/PlatformString.h:
* platform/text/String.cpp:
* platform/text/StringImpl.cpp:
* platform/text/TextCodec.h:
* platform/text/TextCodecICU.cpp:
* platform/text/TextCodecLatin1.cpp:
* platform/text/TextCodecUTF16.cpp:
* platform/text/TextCodecUserDefined.cpp:
* platform/text/TextEncoding.cpp:
* platform/text/TextEncoding.h:
* platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp:
* platform/text/gtk/TextCodecGtk.cpp:
* platform/text/haiku/StringHaiku.cpp:
* platform/text/mac/TextCodecMac.cpp:
* platform/text/qt/TextCodecQt.cpp:
* platform/text/wx/StringWx.cpp:
* platform/win/ClipboardUtilitiesWin.cpp:
* platform/win/ClipboardWin.cpp:
* platform/win/ContextMenuItemWin.cpp:
* platform/win/ContextMenuWin.cpp:
* platform/win/FileSystemWin.cpp:
* platform/win/GDIObjectCounter.cpp:
* platform/win/Language.cpp:
* platform/win/PasteboardWin.cpp:
* platform/wince/FileSystemWince.cpp:
* platform/wince/KeygenWince.cpp:
* platform/wince/PasteboardWince.cpp:
* platform/wx/FileSystemWx.cpp:
* platform/wx/LoggingWx.cpp:
* plugins/PluginDebug.h:
* plugins/PluginPackage.cpp:
* plugins/PluginStream.cpp:
* plugins/PluginStream.h:
* plugins/PluginView.h:
* plugins/gtk/PluginPackageGtk.cpp:
* plugins/mac/PluginPackageMac.cpp:
* plugins/qt/PluginPackageQt.cpp:
* plugins/symbian/PluginPackageSymbian.cpp:
* plugins/win/PluginPackageWin.cpp:
* rendering/RenderLayer.cpp:
* rendering/RenderLayerCompositor.cpp:
* rendering/RenderTreeAsText.cpp:
* storage/Database.cpp:
* storage/SQLTransactionCoordinator.cpp:
* storage/SQLTransactionCoordinator.h:
* storage/StorageAreaSync.cpp:
* storage/StorageSyncManager.cpp:
* storage/chromium/DatabaseTrackerChromium.cpp:
* storage/chromium/QuotaTracker.cpp:
* storage/chromium/QuotaTracker.h:
* svg/SVGFontFaceElement.cpp:
* svg/SVGStyledElement.cpp:
* svg/SVGUseElement.cpp:
* websockets/WebSocket.cpp:
* websockets/WebSocketChannel.cpp:
* websockets/WebSocketHandshake.cpp:
* wml/WMLErrorHandling.cpp:
* wml/WMLGoElement.cpp:
* wml/WMLPageState.cpp:
* wml/WMLPostfieldElement.cpp:
* wml/WMLSelectElement.cpp:
* xml/XMLHttpRequest.cpp:
* xml/XSLStyleSheetLibxslt.cpp:
* xml/XSLTProcessorLibxslt.cpp:

WebKit:

* efl/WebCoreSupport/ChromeClientEfl.cpp:
* efl/ewk/ewk_frame.cpp:
(ewk_frame_name_get):
(ewk_frame_selection_get):
(ewk_frame_uri_changed):
* efl/ewk/ewk_history.cpp:
* efl/ewk/ewk_settings.cpp:

WebKit/chromium:

* public/WebCString.h:
* src/FrameLoaderClientImpl.cpp:
* src/GraphicsContext3D.cpp:
* src/WebCString.cpp:
(WebKit::WebCString::assign):
(WebKit::WebCString::WebCString):
(WebKit::WebCString::operator=):
(WebKit::WebCString::operator WTF::CString):
* src/WebMediaPlayerClientImpl.cpp:
* src/WebString.cpp:
* src/WebURLError.cpp:

WebKit/gtk:

* WebCoreSupport/ChromeClientGtk.cpp:
* WebCoreSupport/ContextMenuClientGtk.cpp:
* WebCoreSupport/EditorClientGtk.cpp:
* WebCoreSupport/FrameLoaderClientGtk.cpp:
* WebCoreSupport/InspectorClientGtk.cpp:
* gdom/ConvertToGCharPrivate.h:
* webkit/webkitdownload.cpp:
* webkit/webkithittestresult.cpp:
* webkit/webkitnetworkrequest.cpp:
* webkit/webkitprivate.h:
* webkit/webkitsecurityorigin.cpp:
* webkit/webkitwebdatabase.cpp:
* webkit/webkitwebframe.cpp:
* webkit/webkitwebhistoryitem.cpp:
(webkit_web_history_item_finalize):
(webkit_web_history_item_get_target):
* webkit/webkitwebresource.cpp:
* webkit/webkitwebsettings.cpp:
* webkit/webkitwebview.cpp:

WebKit/mac:

* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::getCookies):
(WebKit::NetscapePluginInstanceProxy::getProxy):
(WebKit::NetscapePluginInstanceProxy::getAuthenticationInfo):
(WebKit::NetscapePluginInstanceProxy::resolveURL):
* Plugins/WebBaseNetscapePluginView.h:
* Plugins/WebBaseNetscapePluginView.mm:
* Plugins/WebNetscapePluginView.mm:
(-[WebNetscapePluginView resolveURL:forTarget:]):

WebKit/qt:

* Api/qwebelement.cpp:

WebKit/win:

* WebDownload.cpp:
* WebDownloadCFNet.cpp:
* WebDownloadCurl.cpp:
* WebHistoryItem.cpp:
* WebLocalizableStrings.cpp:
* WebMutableURLRequest.cpp:
* WebPreferences.cpp:
(WebPreferences::migrateWebKitPreferencesToCFPreferences):
* WebView.cpp:

WebKit/wx:

* WebFrame.cpp:
* WebView.cpp:

  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (C) 2005, 2006, 2007 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 *
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 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* originally written by Becky Willrich, additional code by Darin Adler */
30
31#include "config.h"
32#include "FormDataStreamCFNet.h"
33
34#include "FileSystem.h"
35#include "FormData.h"
36#include <CFNetwork/CFURLRequestPriv.h>
37#include <CoreFoundation/CFStreamAbstract.h>
38#include <WebKitSystemInterface/WebKitSystemInterface.h>
39#include <sys/types.h>
40#include <wtf/Assertions.h>
41#include <wtf/HashMap.h>
42#include <wtf/RetainPtr.h>
43#include <wtf/text/CString.h>
44
45#define USE_V1_CFSTREAM_CALLBACKS
46#ifdef USE_V1_CFSTREAM_CALLBACKS
47typedef CFReadStreamCallBacksV1 WCReadStreamCallBacks;
48#else
49typedef CFReadStreamCallBacks WCReadStreamCallBacks;
50#endif
51
52namespace WebCore {
53
54static HashMap<CFReadStreamRef, RefPtr<FormData> >& getStreamFormDatas()
55{
56    static HashMap<CFReadStreamRef, RefPtr<FormData> > streamFormDatas;
57    return streamFormDatas;
58}
59
60static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context);
61
62struct FormStreamFields {
63    CFMutableSetRef scheduledRunLoopPairs;
64    Vector<FormDataElement> remainingElements; // in reverse order
65    CFReadStreamRef currentStream;
66    char* currentData;
67    CFReadStreamRef formStream;
68};
69
70struct SchedulePair {
71    CFRunLoopRef runLoop;
72    CFStringRef mode;
73};
74
75static const void* pairRetain(CFAllocatorRef alloc, const void* value)
76{
77    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
78
79    SchedulePair* result = new SchedulePair;
80    CFRetain(pair->runLoop);
81    result->runLoop = pair->runLoop;
82    result->mode = CFStringCreateCopy(alloc, pair->mode);
83    return result;
84}
85
86static void pairRelease(CFAllocatorRef alloc, const void* value)
87{
88    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
89
90    CFRelease(pair->runLoop);
91    CFRelease(pair->mode);
92    delete pair;
93}
94
95static Boolean pairEqual(const void* a, const void* b)
96{
97    const SchedulePair* pairA = static_cast<const SchedulePair*>(a);
98    const SchedulePair* pairB = static_cast<const SchedulePair*>(b);
99
100    return pairA->runLoop == pairB->runLoop && CFEqual(pairA->mode, pairB->mode);
101}
102
103static CFHashCode pairHash(const void* value)
104{
105    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
106
107    return (CFHashCode)pair->runLoop ^ CFHash(pair->mode);
108}
109
110static void closeCurrentStream(FormStreamFields *form)
111{
112    if (form->currentStream) {
113        CFReadStreamClose(form->currentStream);
114        CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL);
115        CFRelease(form->currentStream);
116        form->currentStream = NULL;
117    }
118    if (form->currentData) {
119        fastFree(form->currentData);
120        form->currentData = 0;
121    }
122}
123
124static void scheduleWithPair(const void* value, void* context)
125{
126    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
127    CFReadStreamRef stream = (CFReadStreamRef)context;
128
129    CFReadStreamScheduleWithRunLoop(stream, pair->runLoop, pair->mode);
130}
131
132static void advanceCurrentStream(FormStreamFields *form)
133{
134    closeCurrentStream(form);
135
136    if (form->remainingElements.isEmpty())
137        return;
138
139    // Create the new stream.
140    FormDataElement& nextInput = form->remainingElements.last();
141    if (nextInput.m_type == FormDataElement::data) {
142        size_t size = nextInput.m_data.size();
143        char* data = nextInput.m_data.releaseBuffer();
144        form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
145        form->currentData = data;
146    } else {
147        CFStringRef filename = nextInput.m_filename.createCFString();
148#if PLATFORM(WIN)
149        CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLWindowsPathStyle, FALSE);
150#else
151        CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE);
152#endif
153        CFRelease(filename);
154        form->currentStream = CFReadStreamCreateWithFile(0, fileURL);
155        CFRelease(fileURL);
156    }
157    form->remainingElements.removeLast();
158
159    // Set up the callback.
160    CFStreamClientContext context = { 0, form, NULL, NULL, NULL };
161    CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
162        formEventCallback, &context);
163
164    // Schedule with the current set of run loops.
165    CFSetApplyFunction(form->scheduledRunLoopPairs, scheduleWithPair, form->currentStream);
166}
167
168static void openNextStream(FormStreamFields* form)
169{
170    // Skip over any streams we can't open.
171    // For some purposes we might want to return an error, but the current CFURLConnection
172    // can't really do anything useful with an error at this point, so this is better.
173    advanceCurrentStream(form);
174    while (form->currentStream && !CFReadStreamOpen(form->currentStream))
175        advanceCurrentStream(form);
176}
177
178static void* formCreate(CFReadStreamRef stream, void* context)
179{
180    FormData* formData = static_cast<FormData*>(context);
181
182    CFSetCallBacks runLoopAndModeCallBacks = { 0, pairRetain, pairRelease, NULL, pairEqual, pairHash };
183
184    FormStreamFields* newInfo = new FormStreamFields;
185    newInfo->scheduledRunLoopPairs = CFSetCreateMutable(0, 0, &runLoopAndModeCallBacks);
186    newInfo->currentStream = NULL;
187    newInfo->currentData = 0;
188    newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
189
190    // Append in reverse order since we remove elements from the end.
191    size_t size = formData->elements().size();
192    newInfo->remainingElements.reserveCapacity(size);
193    for (size_t i = 0; i < size; ++i)
194        newInfo->remainingElements.append(formData->elements()[size - i - 1]);
195
196    getStreamFormDatas().set(stream, adoptRef(formData));
197
198    return newInfo;
199}
200
201static void formFinalize(CFReadStreamRef stream, void* context)
202{
203    FormStreamFields* form = static_cast<FormStreamFields*>(context);
204
205    getStreamFormDatas().remove(stream);
206
207    closeCurrentStream(form);
208    CFRelease(form->scheduledRunLoopPairs);
209    delete form;
210}
211
212static Boolean formOpen(CFReadStreamRef stream, CFStreamError* error, Boolean* openComplete, void* context)
213{
214    FormStreamFields* form = static_cast<FormStreamFields*>(context);
215
216    openNextStream(form);
217
218    *openComplete = TRUE;
219    error->error = 0;
220    return TRUE;
221}
222
223static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context)
224{
225    FormStreamFields* form = static_cast<FormStreamFields*>(context);
226
227    while (form->currentStream) {
228        CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bufferLength);
229        if (bytesRead < 0) {
230            *error = CFReadStreamGetError(form->currentStream);
231            return -1;
232        }
233        if (bytesRead > 0) {
234            error->error = 0;
235            *atEOF = FALSE;
236            return bytesRead;
237        }
238        openNextStream(form);
239    }
240
241    error->error = 0;
242    *atEOF = TRUE;
243    return 0;
244}
245
246static Boolean formCanRead(CFReadStreamRef stream, void* context)
247{
248    FormStreamFields* form = static_cast<FormStreamFields*>(context);
249
250    while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd) {
251        openNextStream(form);
252    }
253    if (!form->currentStream) {
254        CFReadStreamSignalEvent(stream, kCFStreamEventEndEncountered, 0);
255        return FALSE;
256    }
257    return CFReadStreamHasBytesAvailable(form->currentStream);
258}
259
260static void formClose(CFReadStreamRef stream, void* context)
261{
262    FormStreamFields* form = static_cast<FormStreamFields*>(context);
263
264    closeCurrentStream(form);
265}
266
267static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
268{
269    FormStreamFields* form = static_cast<FormStreamFields*>(context);
270
271    if (form->currentStream)
272        CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode);
273    SchedulePair pair = { runLoop, runLoopMode };
274    CFSetAddValue(form->scheduledRunLoopPairs, &pair);
275}
276
277static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
278{
279    FormStreamFields* form = static_cast<FormStreamFields*>(context);
280
281    if (form->currentStream)
282        CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode);
283    SchedulePair pair = { runLoop, runLoopMode };
284    CFSetRemoveValue(form->scheduledRunLoopPairs, &pair);
285}
286
287static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context)
288{
289    FormStreamFields* form = static_cast<FormStreamFields*>(context);
290
291    switch (type) {
292    case kCFStreamEventHasBytesAvailable:
293        CFReadStreamSignalEvent(form->formStream, kCFStreamEventHasBytesAvailable, 0);
294        break;
295    case kCFStreamEventErrorOccurred: {
296        CFStreamError readStreamError = CFReadStreamGetError(stream);
297        CFReadStreamSignalEvent(form->formStream, kCFStreamEventErrorOccurred, &readStreamError);
298        break;
299    }
300    case kCFStreamEventEndEncountered:
301        openNextStream(form);
302        if (!form->currentStream)
303            CFReadStreamSignalEvent(form->formStream, kCFStreamEventEndEncountered, 0);
304        break;
305    case kCFStreamEventNone:
306        LOG_ERROR("unexpected kCFStreamEventNone");
307        break;
308    case kCFStreamEventOpenCompleted:
309        LOG_ERROR("unexpected kCFStreamEventOpenCompleted");
310        break;
311    case kCFStreamEventCanAcceptBytes:
312        LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes");
313        break;
314    }
315}
316
317void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
318{
319    if (!formData) {
320        wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
321        return;
322    }
323
324    size_t count = formData->elements().size();
325
326    if (count == 0)
327        return;
328
329    // Handle the common special case of one piece of form data, with no files.
330    if (count == 1) {
331        const FormDataElement& element = formData->elements()[0];
332        if (element.m_type == FormDataElement::data) {
333            CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size());
334            CFURLRequestSetHTTPRequestBody(request, data);
335            CFRelease(data);
336            return;
337        }
338    }
339
340    RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
341
342    for (size_t i = 0; i < count; ++i) {
343        const FormDataElement& element = formData->elements()[i];
344        if (element.m_type == FormDataElement::data) {
345            RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
346            CFArrayAppendValue(array.get(), data.get());
347        } else {
348            RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
349            CFArrayAppendValue(array.get(), filename.get());
350        }
351    }
352
353    wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
354}
355
356PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
357{
358    if (RetainPtr<CFDataRef> bodyData = CFURLRequestCopyHTTPRequestBody(request))
359        return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
360
361    if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) {
362        RefPtr<FormData> formData = FormData::create();
363
364        CFIndex count = CFArrayGetCount(bodyParts.get());
365        for (CFIndex i = 0; i < count; i++) {
366            CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
367            CFTypeID typeID = CFGetTypeID(bodyPart);
368            if (typeID == CFStringGetTypeID()) {
369                String filename = (CFStringRef)bodyPart;
370                formData->appendFile(filename);
371            } else if (typeID == CFDataGetTypeID()) {
372                CFDataRef data = (CFDataRef)bodyPart;
373                formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
374            } else
375                ASSERT_NOT_REACHED();
376        }
377        return formData.release();
378    }
379
380    // FIXME: what to do about arbitrary body streams?
381    return 0;
382}
383
384}
Note: See TracBrowser for help on using the browser.