Skip to content
Permalink
Browse files
Upstream the Multipart feature in Blackberry port
https://bugs.webkit.org/show_bug.cgi?id=73533

Patch by Chris Guan <chris.guan@torchmobile.com.cn> on 2011-12-21
Reviewed by Rob Buis.

I refactored Multipart code of Blackberry port. Moved Multipart into
Blackerry network layer and removed the dependence of std::string.

Initial upstream, no new test cases.

* platform/network/blackberry/DeferredData.cpp:
(WebCore::DeferredData::deferMultipartHeaderReceived):
(WebCore::DeferredData::processHeaders):
(WebCore::DeferredData::processDeferredData):
* platform/network/blackberry/DeferredData.h:
(WebCore::DeferredData::hasDeferredData):
* platform/network/blackberry/NetworkJob.cpp:
(WebCore::NetworkJob::notifyMultipartHeaderReceived):
(WebCore::NetworkJob::handleNotifyMultipartHeaderReceived):
(WebCore::NetworkJob::handleNotifyDataReceived):
(WebCore::NetworkJob::handleNotifyClose):
(WebCore::NetworkJob::startNewJobWithRequest):
(WebCore::NetworkJob::sendResponseIfNeeded):
(WebCore::NetworkJob::sendMultipartResponseIfNeeded):
* platform/network/blackberry/NetworkJob.h:


Canonical link: https://commits.webkit.org/91799@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@103487 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Chris Guan authored and Leo Yang committed Dec 22, 2011
1 parent 63f5e84 commit 257a43d4cfe3eeb566cf69c59dfb355c8504d795
@@ -1,3 +1,31 @@
2011-12-21 Chris Guan <chris.guan@torchmobile.com.cn>

Upstream the Multipart feature in Blackberry port
https://bugs.webkit.org/show_bug.cgi?id=73533

Reviewed by Rob Buis.

I refactored Multipart code of Blackberry port. Moved Multipart into
Blackerry network layer and removed the dependence of std::string.

Initial upstream, no new test cases.

* platform/network/blackberry/DeferredData.cpp:
(WebCore::DeferredData::deferMultipartHeaderReceived):
(WebCore::DeferredData::processHeaders):
(WebCore::DeferredData::processDeferredData):
* platform/network/blackberry/DeferredData.h:
(WebCore::DeferredData::hasDeferredData):
* platform/network/blackberry/NetworkJob.cpp:
(WebCore::NetworkJob::notifyMultipartHeaderReceived):
(WebCore::NetworkJob::handleNotifyMultipartHeaderReceived):
(WebCore::NetworkJob::handleNotifyDataReceived):
(WebCore::NetworkJob::handleNotifyClose):
(WebCore::NetworkJob::startNewJobWithRequest):
(WebCore::NetworkJob::sendResponseIfNeeded):
(WebCore::NetworkJob::sendMultipartResponseIfNeeded):
* platform/network/blackberry/NetworkJob.h:

2011-12-21 Eric Carlson <eric.carlson@apple.com>

Fix text track cue font size and colors
@@ -55,6 +55,12 @@ void DeferredData::deferHeaderReceived(const String& key, const String& value)
m_headerValues.append(value);
}

void DeferredData::deferMultipartHeaderReceived(const String& key, const String& value)
{
m_multipartHeaderKeys.append(key);
m_multipartheaderValues.append(value);
}

void DeferredData::deferDataSent(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
{
m_bytesSent = bytesSent;
@@ -73,6 +79,30 @@ void DeferredData::deferClose(int status)
m_deferredClose = true;
}

bool DeferredData::processHeaders(Vector<String>& headerKeys, Vector<String>& headerValues, HandleHeadersFunction function)
{
size_t numHeaders = headerKeys.size();
ASSERT(headerValues.size() == numHeaders);
for (size_t i = 0; i < numHeaders; ++i) {
(m_job.*function)(headerKeys[i], headerValues[i]);

if (m_job.isDeferringLoading()) {
// Remove all the headers that have already been processed.
headerKeys.remove(0, i + 1);
headerValues.remove(0, i + 1);
return false;
}

if (m_job.isCancelled()) {
// Don't bother removing headers; job will be deleted.
return false;
}
}
headerKeys.clear();
headerValues.clear();
return true;
}

void DeferredData::processDeferredData()
{
if (m_inProcessDeferredData)
@@ -100,25 +130,9 @@ void DeferredData::processDeferredData()
return;
}

size_t numHeaders = m_headerKeys.size();
ASSERT(m_headerValues.size() == numHeaders);
for (unsigned i = 0; i < numHeaders; ++i) {
m_job.handleNotifyHeaderReceived(m_headerKeys[i], m_headerValues[i]);

if (m_job.isDeferringLoading()) {
// Remove all the headers that have already been processed.
m_headerKeys.remove(0, i + 1);
m_headerValues.remove(0, i + 1);
return;
}

if (m_job.isCancelled()) {
// Don't bother removing headers; job will be deleted.
return;
}
}
m_headerKeys.clear();
m_headerValues.clear();
if (!processHeaders(m_headerKeys, m_headerValues, &NetworkJob::handleNotifyHeaderReceived)
|| !processHeaders(m_multipartHeaderKeys, m_multipartheaderValues, &NetworkJob::handleNotifyMultipartHeaderReceived))
return;

// Only process 32k of data at a time to avoid blocking the event loop for too long.
static const unsigned maxData = 32 * 1024;
@@ -53,13 +53,14 @@ class DeferredData {
void deferOpen(int status, const String& message);
void deferWMLOverride();
void deferHeaderReceived(const String& key, const String& value);
void deferMultipartHeaderReceived(const String& key, const String& value);
void deferDataReceived(const char* buf, size_t len);
void deferDataSent(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
void deferClose(int status);

bool hasDeferredData() const
{
return m_deferredStatusReceived || m_deferredWMLOverride || !m_headerKeys.isEmpty() || !m_dataSegments.isEmpty() || m_deferredClose;
return m_deferredStatusReceived || m_deferredWMLOverride || !m_headerKeys.isEmpty() || !m_multipartHeaderKeys.isEmpty() || !m_dataSegments.isEmpty() || m_deferredClose;
}

void processDeferredData();
@@ -71,6 +72,11 @@ class DeferredData {
}

private:
typedef void (NetworkJob::*HandleHeadersFunction)(const String& key, const String& value);

// Returns false if the job is deferred or canceled, otherwise returns true.
bool processHeaders(Vector<String>& headerKeys, Vector<String>& headerValues, HandleHeadersFunction);

void fireProcessDataTimer(Timer<DeferredData>*);
NetworkJob& m_job;
Timer<DeferredData> m_processDataTimer;
@@ -80,6 +86,8 @@ class DeferredData {
bool m_deferredWMLOverride;
Vector<String> m_headerKeys;
Vector<String> m_headerValues;
Vector<String> m_multipartHeaderKeys;
Vector<String> m_multipartheaderValues;
Deque<Vector<char> > m_dataSegments;
unsigned long long m_bytesSent;
unsigned long long m_totalBytesToBeSent;
@@ -37,6 +37,7 @@
#include <BlackBerryPlatformLog.h>
#include <BlackBerryPlatformWebKitCredits.h>
#include <BuildInformation.h>
#include <network/MultipartStream.h>
#include <network/NetworkRequest.h>
#include <network/NetworkStreamFactory.h>
#include <wtf/ASCIICType.h>
@@ -279,6 +280,14 @@ void NetworkJob::notifyHeaderReceived(const char* key, const char* value)
}
}

void NetworkJob::notifyMultipartHeaderReceived(const char* key, const char* value)
{
if (shouldDeferLoading())
m_deferredData.deferMultipartHeaderReceived(key, value);
else
handleNotifyMultipartHeaderReceived(key, value);
}

void NetworkJob::notifyStringHeaderReceived(const String& key, const String& value)
{
if (shouldDeferLoading())
@@ -315,6 +324,44 @@ void NetworkJob::handleNotifyHeaderReceived(const String& key, const String& val
m_response.setHTTPHeaderField(key, value);
}

void NetworkJob::handleNotifyMultipartHeaderReceived(const String& key, const String& value)
{
if (!m_multipartResponse) {
// Create a new response based on the original set of headers + the
// replacement headers. We only replace the same few headers that gecko
// does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp.
m_multipartResponse = adoptPtr(new ResourceResponse);
m_multipartResponse->setURL(m_response.url());

// The list of BlackBerry::Platform::replaceHeaders that we do not copy from the original
// response when generating a response.
const WebCore::HTTPHeaderMap& map = m_response.httpHeaderFields();

for (WebCore::HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) {
bool needsCopyfromOriginalResponse = true;
int replaceHeadersIndex = 0;
while (BlackBerry::Platform::MultipartStream::replaceHeaders[replaceHeadersIndex]) {
if (it->first.lower() == BlackBerry::Platform::MultipartStream::replaceHeaders[replaceHeadersIndex]) {
needsCopyfromOriginalResponse = false;
break;
}
replaceHeadersIndex++;
}
if (needsCopyfromOriginalResponse)
m_multipartResponse->setHTTPHeaderField(it->first, it->second);
}

m_multipartResponse->setIsMultipartPayload(true);
} else {
if (key.lower() == "content-type") {
String contentType = value.lower();
m_multipartResponse->setMimeType(extractMIMETypeFromMediaType(contentType));
m_multipartResponse->setTextEncodingName(extractCharsetFromMediaType(contentType));
}
m_multipartResponse->setHTTPHeaderField(key, value);
}
}

void NetworkJob::handleSetCookieHeader(const String& value)
{
KURL url = m_response.url();
@@ -350,13 +397,10 @@ void NetworkJob::handleNotifyDataReceived(const char* buf, size_t len)

if (shouldSendClientData()) {
sendResponseIfNeeded();
sendMultipartResponseIfNeeded();
if (clientIsOk()) {
if (m_multipartDelegate)
m_multipartDelegate->onReceivedData(buf, len, len);
else {
RecursionGuard guard(m_callingClient);
m_handle->client()->didReceiveData(m_handle.get(), buf, len, len);
}
RecursionGuard guard(m_callingClient);
m_handle->client()->didReceiveData(m_handle.get(), buf, len, len);
}
}

@@ -419,8 +463,6 @@ void NetworkJob::handleNotifyClose(int status)

sendResponseIfNeeded();
if (clientIsOk()) {
if (m_multipartDelegate)
m_multipartDelegate->onCompletedRequest();

RecursionGuard guard(m_callingClient);
if (isError(m_extendedStatusCode) && !m_dataReceived) {
@@ -439,7 +481,7 @@ void NetworkJob::handleNotifyClose(int status)

// Detach from the ResourceHandle in any case.
m_handle = 0;
m_multipartDelegate = nullptr;
m_multipartResponse = nullptr;
}

bool NetworkJob::shouldNotifyClientFinished()
@@ -487,7 +529,7 @@ bool NetworkJob::startNewJobWithRequest(ResourceRequest& newRequest, bool increa
// Pass the ownership of the ResourceHandle to the new NetworkJob.
RefPtr<ResourceHandle> handle = m_handle;
m_handle = 0;
m_multipartDelegate = nullptr;
m_multipartResponse = nullptr;

NetworkManager::instance()->startJob(m_playerId,
m_pageGroupName,
@@ -582,13 +624,14 @@ void NetworkJob::sendResponseIfNeeded()
if (clientIsOk()) {
RecursionGuard guard(m_callingClient);
m_handle->client()->didReceiveResponse(m_handle.get(), m_response);
}
}

if (mimeType == "multipart/x-mixed-replace") {
std::string boundary;
bool isReadBoundary = MultipartResponseDelegate::readMultipartBoundary(m_contentType.lower().utf8().data(), boundary);
if (isReadBoundary && !boundary.empty())
m_multipartDelegate = adoptPtr(new MultipartResponseDelegate(m_handle, m_response, boundary));
}
void NetworkJob::sendMultipartResponseIfNeeded()
{
if (m_multipartResponse && clientIsOk()) {
m_handle->client()->didReceiveResponse(m_handle.get(), *m_multipartResponse);
m_multipartResponse = nullptr;
}
}

@@ -20,7 +20,6 @@
#define NetworkJob_h

#include "DeferredData.h"
#include "MultipartResponseDelegate.h"
#include "PlatformString.h"
#include "ProtectionSpace.h"
#include "ResourceHandle.h"
@@ -70,9 +69,11 @@ class NetworkJob : public BlackBerry::Platform::FilterStream {
virtual void notifyWMLOverride();
void handleNotifyWMLOverride() { m_response.setIsWML(true); }
virtual void notifyHeaderReceived(const char* key, const char* value);
virtual void notifyMultipartHeaderReceived(const char* key, const char* value);
// Exists only to resolve ambiguity between char* and String parameters
void notifyStringHeaderReceived(const String& key, const String& value);
void handleNotifyHeaderReceived(const String& key, const String& value);
void handleNotifyMultipartHeaderReceived(const String& key, const String& value);
void handleSetCookieHeader(const String& value);
void notifyDataReceivedPlain(const char* buf, size_t len);
void handleNotifyDataReceived(const char* buf, size_t len);
@@ -108,6 +109,7 @@ class NetworkJob : public BlackBerry::Platform::FilterStream {

// This can cause m_cancelled to be set to true, if it passes up an error to m_handle->client() which causes the job to be cancelled
void sendResponseIfNeeded();
void sendMultipartResponseIfNeeded();

void fireLoadDataTimer(Timer<NetworkJob>*)
{
@@ -149,7 +151,7 @@ class NetworkJob : public BlackBerry::Platform::FilterStream {
ResourceResponse m_response;
Timer<NetworkJob> m_loadDataTimer;
Timer<NetworkJob> m_loadAboutTimer;
OwnPtr<MultipartResponseDelegate> m_multipartDelegate;
OwnPtr<ResourceResponse> m_multipartResponse;
Timer<NetworkJob> m_deleteJobTimer;
String m_contentType;
String m_contentDisposition;

0 comments on commit 257a43d

Please sign in to comment.