Use a Variant for FormDataElement
[WebKit-https.git] / Source / WebCore / platform / network / cf / FormDataStreamCFNet.cpp
index e5321c2..45e31e5 100644 (file)
@@ -136,30 +136,41 @@ static bool advanceCurrentStream(FormStreamFields* form)
     // Create the new stream.
     FormDataElement& nextInput = form->remainingElements.last();
 
-    if (nextInput.m_type == FormDataElement::Type::Data) {
-        size_t size = nextInput.m_data.size();
-        MallocPtr<char> data = nextInput.m_data.releaseBuffer();
-        form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data.get()), size, kCFAllocatorNull);
-        form->currentData = WTFMove(data);
-    } else {
-        // Check if the file has been changed or not if required.
-        if (FileSystem::isValidFileTime(nextInput.m_expectedFileModificationTime)) {
-            time_t fileModificationTime;
-            if (!FileSystem::getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
+    bool success = switchOn(nextInput.data,
+        [form] (Vector<char>& bytes) {
+            size_t size = bytes.size();
+            MallocPtr<char> data = bytes.releaseBuffer();
+            form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data.get()), size, kCFAllocatorNull);
+            form->currentData = WTFMove(data);
+            return true;
+        }, [form] (const FormDataElement::EncodedFileData& fileData) {
+            // Check if the file has been changed or not if required.
+            if (FileSystem::isValidFileTime(fileData.expectedFileModificationTime)) {
+                time_t fileModificationTime;
+                if (!FileSystem::getFileModificationTime(fileData.filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(fileData.expectedFileModificationTime))
+                    return false;
+            }
+            const String& path = fileData.shouldGenerateFile ? fileData.generatedFilename : fileData.filename;
+            form->currentStream = CFReadStreamCreateWithFile(0, FileSystem::pathAsURL(path).get());
+            if (!form->currentStream) {
+                // The file must have been removed or become unreadable.
                 return false;
-        }
-        const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
-        form->currentStream = CFReadStreamCreateWithFile(0, FileSystem::pathAsURL(path).get());
-        if (!form->currentStream) {
-            // The file must have been removed or become unreadable.
+            }
+            if (fileData.fileStart > 0) {
+                RetainPtr<CFNumberRef> position = adoptCF(CFNumberCreate(0, kCFNumberLongLongType, &fileData.fileStart));
+                CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
+            }
+            form->currentStreamRangeLength = fileData.fileLength;
+            return true;
+        }, [] (const FormDataElement::EncodedBlobData&) {
+            ASSERT_NOT_REACHED();
             return false;
         }
-        if (nextInput.m_fileStart > 0) {
-            RetainPtr<CFNumberRef> position = adoptCF(CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart));
-            CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
-        }
-        form->currentStreamRangeLength = nextInput.m_fileLength;
-    }
+    );
+
+    if (!success)
+        return false;
+
     form->remainingElements.removeLast();
 
     // Set up the callback.
@@ -363,22 +374,8 @@ RetainPtr<CFReadStreamRef> createHTTPBodyCFReadStream(FormData& formData)
 
     // Precompute the content length so CFNetwork doesn't use chunked mode.
     unsigned long long length = 0;
-
-    for (auto& element : resolvedFormData->elements()) {
-        if (element.m_type == FormDataElement::Type::Data)
-            length += element.m_data.size();
-        else {
-            // If we're sending the file range, use the existing range length for now.
-            // We will detect if the file has been changed right before we read the file and abort the operation if necessary.
-            if (element.m_fileLength != BlobDataItem::toEndOfFile) {
-                length += element.m_fileLength;
-                continue;
-            }
-            long long fileSize;
-            if (FileSystem::getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize))
-                length += fileSize;
-        }
-    }
+    for (auto& element : resolvedFormData->elements())
+        length += element.lengthInBytes();
 
     FormCreationContext formContext = { WTFMove(resolvedFormData), length };
     CFReadStreamCallBacksV1 callBacks = { 1, formCreate, formFinalize, nullptr, formOpen, nullptr, formRead, nullptr, formCanRead, formClose, formCopyProperty, nullptr, nullptr, formSchedule, formUnschedule };
@@ -393,10 +390,8 @@ void setHTTPBody(CFMutableURLRequestRef request, FormData* formData)
     // Handle the common special case of one piece of form data, with no files.
     auto& elements = formData->elements();
     if (elements.size() == 1 && !formData->alwaysStream()) {
-        auto& element = elements[0];
-        if (element.m_type == FormDataElement::Type::Data) {
-            auto& vector = element.m_data;
-            auto data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(vector.data()), vector.size()));
+        if (auto* vector = WTF::get_if<Vector<char>>(elements[0].data)) {
+            auto data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(vector->data()), vector->size()));
             CFURLRequestSetHTTPRequestBody(request, data.get());
             return;
         }
@@ -408,7 +403,7 @@ void setHTTPBody(CFMutableURLRequestRef request, FormData* formData)
 FormData* httpBodyFromStream(CFReadStreamRef stream)
 {
     if (!stream)
-        return 0;
+        return nullptr;
 
     // Passing the pointer as property appears to be the only way to associate a stream with FormData.
     // A new stream is always created in CFURLRequestCopyHTTPRequestBodyStream (or -[NSURLRequest HTTPBodyStream]),
@@ -417,11 +412,11 @@ FormData* httpBodyFromStream(CFReadStreamRef stream)
 
     RetainPtr<CFNumberRef> formDataPointerAsCFNumber = adoptCF(static_cast<CFNumberRef>(CFReadStreamCopyProperty(stream, formDataPointerPropertyName)));
     if (!formDataPointerAsCFNumber)
-        return 0;
+        return nullptr;
 
     long formDataPointerAsNumber;
     if (!CFNumberGetValue(formDataPointerAsCFNumber.get(), kCFNumberLongType, &formDataPointerAsNumber))
-        return 0;
+        return nullptr;
 
     return reinterpret_cast<FormData*>(static_cast<intptr_t>(formDataPointerAsNumber));
 }