summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue')
-rw-r--r--webkit/glue/glue_util.cc42
-rw-r--r--webkit/glue/glue_util.h20
-rw-r--r--webkit/glue/multipart_response_delegate.cc162
-rw-r--r--webkit/glue/multipart_response_delegate.h57
-rw-r--r--webkit/glue/multipart_response_delegate_unittest.cc278
-rw-r--r--webkit/glue/resource_handle_impl.cc765
-rw-r--r--webkit/glue/webkitclient_impl.cc6
-rw-r--r--webkit/glue/webkitclient_impl.h1
-rw-r--r--webkit/glue/webplugin_impl.cc288
-rw-r--r--webkit/glue/webplugin_impl.h99
-rw-r--r--webkit/glue/webplugin_impl_unittest.cc171
-rw-r--r--webkit/glue/weburlloader_impl.cc502
-rw-r--r--webkit/glue/weburlloader_impl.h61
13 files changed, 1237 insertions, 1215 deletions
diff --git a/webkit/glue/glue_util.cc b/webkit/glue/glue_util.cc
index 5f7228f..b85ad71 100644
--- a/webkit/glue/glue_util.cc
+++ b/webkit/glue/glue_util.cc
@@ -35,6 +35,8 @@
#include "webkit/api/public/WebSize.h"
#include "webkit/api/public/WebString.h"
#include "webkit/api/public/WebURL.h"
+#include "webkit/api/public/WebURLRequest.h"
+#include "webkit/api/public/WebURLResponse.h"
namespace webkit_glue {
@@ -71,10 +73,9 @@ WebCore::String String16ToString(const string16& str) {
}
std::string StringToStdString(const WebCore::String& str) {
- if (str.length() == 0)
- return std::string();
std::string ret;
- UTF16ToUTF8(str.characters(), str.length(), &ret);
+ if (!str.isNull())
+ UTF16ToUTF8(str.characters(), str.length(), &ret);
return ret;
}
@@ -108,6 +109,17 @@ WebCore::CString WebCStringToCString(const WebKit::WebCString& str) {
return str;
}
+WebKit::WebString StdStringToWebString(const std::string& str) {
+ return WebKit::WebString::fromUTF8(str.data(), str.size());
+}
+
+std::string WebStringToStdString(const WebKit::WebString& str) {
+ std::string ret;
+ if (!str.isNull())
+ UTF16ToUTF8(str.data(), str.length(), &ret);
+ return ret;
+}
+
FilePath::StringType StringToFilePathString(const WebCore::String& str) {
#if defined(OS_WIN)
return StringToStdWString(str);
@@ -214,4 +226,28 @@ PassRefPtr<WebCore::ChromiumDataObject> WebDragDataToChromiumDataObject(
return data;
}
+// WebURLRequest conversions ---------------------------------------------------
+
+WebCore::ResourceRequest* WebURLRequestToMutableResourceRequest(
+ WebKit::WebURLRequest* request) {
+ return &request->toMutableResourceRequest();
+}
+
+const WebCore::ResourceRequest* WebURLRequestToResourceRequest(
+ const WebKit::WebURLRequest* request) {
+ return &request->toResourceRequest();
+}
+
+// WebURLResponse conversions --------------------------------------------------
+
+WebCore::ResourceResponse* WebURLResponseToMutableResourceResponse(
+ WebKit::WebURLResponse* response) {
+ return &response->toMutableResourceResponse();
+}
+
+const WebCore::ResourceResponse* WebURLResponseToResourceResponse(
+ const WebKit::WebURLResponse* response) {
+ return &response->toResourceResponse();
+}
+
} // namespace webkit_glue
diff --git a/webkit/glue/glue_util.h b/webkit/glue/glue_util.h
index 4bcebad..553802c 100644
--- a/webkit/glue/glue_util.h
+++ b/webkit/glue/glue_util.h
@@ -17,7 +17,9 @@ class IntPoint;
class IntRect;
class IntSize;
class KURL;
+class ResourceResponse;
class String;
+struct ResourceRequest;
}
namespace WebKit {
@@ -25,6 +27,8 @@ class WebCString;
class WebDragData;
class WebString;
class WebURL;
+class WebURLRequest;
+class WebURLResponse;
struct WebPoint;
struct WebRect;
struct WebSize;
@@ -68,6 +72,10 @@ WebCore::String WebStringToString(const WebKit::WebString& str);
WebKit::WebCString CStringToWebCString(const WebCore::CString& str);
WebCore::CString WebCStringToCString(const WebKit::WebCString& str);
+// std::string <-> WebString. Conversion to/from UTF-8.
+WebKit::WebString StdStringToWebString(const std::string& str);
+std::string WebStringToStdString(const WebKit::WebString& str);
+
FilePath::StringType StringToFilePathString(const WebCore::String& str);
WebCore::String FilePathStringToString(const FilePath::StringType& str);
@@ -99,6 +107,18 @@ WebKit::WebDragData ChromiumDataObjectToWebDragData(
WTF::PassRefPtr<WebCore::ChromiumDataObject> WebDragDataToChromiumDataObject(
const WebKit::WebDragData&);
+// Exposes the ResourceRequest contained by a WebURLRequest
+WebCore::ResourceRequest* WebURLRequestToMutableResourceRequest(
+ WebKit::WebURLRequest* req);
+const WebCore::ResourceRequest* WebURLRequestToResourceRequest(
+ const WebKit::WebURLRequest* req);
+
+// Exposes the ResourceResponse contained by a WebURLResponse
+WebCore::ResourceResponse* WebURLResponseToMutableResourceResponse(
+ WebKit::WebURLResponse* resp);
+const WebCore::ResourceResponse* WebURLResponseToResourceResponse(
+ const WebKit::WebURLResponse* resp);
+
} // namespace webkit_glue
#endif // #ifndef WEBKIT_GLUE_GLUE_UTIL_H_
diff --git a/webkit/glue/multipart_response_delegate.cc b/webkit/glue/multipart_response_delegate.cc
index 9e8e67d..2000b61 100644
--- a/webkit/glue/multipart_response_delegate.cc
+++ b/webkit/glue/multipart_response_delegate.cc
@@ -2,32 +2,64 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "config.h"
-#include <string>
-
-#include "base/compiler_specific.h"
-
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "HTTPHeaderMap.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "PlatformString.h"
-MSVC_POP_WARNING();
+#include "webkit/glue/multipart_response_delegate.h"
-#undef LOG
#include "base/logging.h"
#include "base/string_util.h"
-#include "webkit/glue/multipart_response_delegate.h"
-#include "webkit/glue/glue_util.h"
#include "net/base/net_util.h"
+#include "webkit/api/public/WebHTTPHeaderVisitor.h"
+#include "webkit/api/public/WebString.h"
+#include "webkit/api/public/WebURL.h"
+#include "webkit/api/public/WebURLLoaderClient.h"
+#include "webkit/glue/glue_util.h"
+
+using WebKit::WebHTTPHeaderVisitor;
+using WebKit::WebString;
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderClient;
+using WebKit::WebURLResponse;
+
+namespace webkit_glue {
+
+namespace {
+
+// The list of response headers that we do not copy from the original
+// response when generating a WebURLResponse for a MIME payload.
+const char* kReplaceHeaders[] = {
+ "content-type",
+ "content-length",
+ "content-disposition",
+ "content-range",
+ "range",
+ "set-cookie"
+};
+
+class HeaderCopier : public WebHTTPHeaderVisitor {
+ public:
+ HeaderCopier(WebURLResponse* response)
+ : response_(response) {
+ }
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ const std::string& name_utf8 = WebStringToStdString(name);
+ for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
+ if (LowerCaseEqualsASCII(name_utf8, kReplaceHeaders[i]))
+ return;
+ }
+ response_->setHTTPHeaderField(name, value);
+ }
+ private:
+ WebURLResponse* response_;
+};
+
+} // namespace
MultipartResponseDelegate::MultipartResponseDelegate(
- WebCore::ResourceHandleClient* client,
- WebCore::ResourceHandle* job,
- const WebCore::ResourceResponse& response,
+ WebURLLoaderClient* client,
+ WebURLLoader* loader,
+ const WebURLResponse& response,
const std::string& boundary)
: client_(client),
- job_(job),
+ loader_(loader),
original_response_(response),
boundary_("--"),
first_received_data_(true),
@@ -41,7 +73,8 @@ MultipartResponseDelegate::MultipartResponseDelegate(
}
}
-void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) {
+void MultipartResponseDelegate::OnReceivedData(const char* data,
+ int data_len) {
// stop_sending_ means that we've already received the final boundary token.
// The server should stop sending us data at this point, but if it does, we
// just throw it away.
@@ -49,8 +82,7 @@ void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) {
return;
// TODO(tc): Figure out what to use for length_received. Maybe we can just
- // pass the value on from our caller. See note in
- // resource_handle_win.cc:ResourceHandleInternal::OnReceivedData.
+ // pass the value on from our caller.
int length_received = -1;
data_.append(data, data_len);
@@ -98,8 +130,10 @@ void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) {
while ((boundary_pos = FindBoundary()) != std::string::npos) {
if (boundary_pos > 0) {
// Send the last data chunk.
- client_->didReceiveData(job_, data_.substr(0, boundary_pos).data(),
- static_cast<int>(boundary_pos), length_received);
+ client_->didReceiveData(loader_,
+ data_.substr(0, boundary_pos).data(),
+ static_cast<int>(boundary_pos),
+ length_received);
}
size_t boundary_end_pos = boundary_pos + boundary_.length();
if (boundary_end_pos < data_.length() && '-' == data_[boundary_end_pos]) {
@@ -128,12 +162,15 @@ void MultipartResponseDelegate::OnCompletedRequest() {
// TODO(tc): Figure out what to use for length_received. Maybe we can just
// pass the value on from our caller.
int length_received = -1;
- client_->didReceiveData(job_, data_.data(),
- static_cast<int>(data_.length()), length_received);
+ client_->didReceiveData(loader_,
+ data_.data(),
+ static_cast<int>(data_.length()),
+ length_received);
}
}
-int MultipartResponseDelegate::PushOverLine(const std::string& data, size_t pos) {
+int MultipartResponseDelegate::PushOverLine(const std::string& data,
+ size_t pos) {
int offset = 0;
if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) {
++offset;
@@ -175,47 +212,28 @@ bool MultipartResponseDelegate::ParseHeaders() {
headers.append(data_.substr(0, line_end_pos));
data_ = data_.substr(line_end_pos);
- // Create a ResourceResponse based on the original set of headers + the
+ // Create a WebURLResponse 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.
std::string mime_type = net::GetSpecificHeader(headers, "content-type");
std::string charset = net::GetHeaderParamValue(mime_type, "charset");
- WebCore::ResourceResponse response(original_response_.url(),
- webkit_glue::StdStringToString(mime_type.c_str()),
- -1,
- charset.c_str(),
- WebCore::String());
- const WebCore::HTTPHeaderMap& orig_headers =
- original_response_.httpHeaderFields();
- for (WebCore::HTTPHeaderMap::const_iterator it = orig_headers.begin();
- it != orig_headers.end(); ++it) {
- if (!(equalIgnoringCase("content-type", it->first) ||
- equalIgnoringCase("content-length", it->first) ||
- equalIgnoringCase("content-disposition", it->first) ||
- equalIgnoringCase("content-range", it->first) ||
- equalIgnoringCase("range", it->first) ||
- equalIgnoringCase("set-cookie", it->first))) {
- response.setHTTPHeaderField(it->first, it->second);
- }
- }
- static const char* replace_headers[] = {
- "Content-Type",
- "Content-Length",
- "Content-Disposition",
- "Content-Range",
- "Range",
- "Set-Cookie"
- };
- for (size_t i = 0; i < arraysize(replace_headers); ++i) {
- std::string name(replace_headers[i]);
+ WebURLResponse response(original_response_.url());
+ response.setMIMEType(StdStringToWebString(mime_type));
+ response.setTextEncodingName(StdStringToWebString(charset));
+
+ HeaderCopier copier(&response);
+ original_response_.visitHTTPHeaderFields(&copier);
+
+ for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
+ std::string name(kReplaceHeaders[i]);
std::string value = net::GetSpecificHeader(headers, name);
if (!value.empty()) {
- response.setHTTPHeaderField(webkit_glue::StdStringToString(name.c_str()),
- webkit_glue::StdStringToString(value.c_str()));
+ response.setHTTPHeaderField(StdStringToWebString(name),
+ StdStringToWebString(value));
}
}
// Send the response!
- client_->didReceiveResponse(job_, response);
+ client_->didReceiveResponse(loader_, response);
return true;
}
@@ -239,29 +257,27 @@ size_t MultipartResponseDelegate::FindBoundary() {
}
bool MultipartResponseDelegate::ReadMultipartBoundary(
- const WebCore::ResourceResponse& response,
+ const WebURLResponse& response,
std::string* multipart_boundary) {
- WebCore::String content_type = response.httpHeaderField("Content-Type");
- std::string content_type_as_string =
- webkit_glue::StringToStdString(content_type);
+ std::string content_type = WebStringToStdString(
+ response.httpHeaderField(WebString::fromUTF8("Content-Type")));
- size_t boundary_start_offset = content_type_as_string.find("boundary=");
+ size_t boundary_start_offset = content_type.find("boundary=");
if (boundary_start_offset == std::wstring::npos) {
return false;
}
boundary_start_offset += strlen("boundary=");
- size_t boundary_end_offset =
- content_type_as_string.find(';', boundary_start_offset);
+ size_t boundary_end_offset = content_type.find(';', boundary_start_offset);
if (boundary_end_offset == std::string::npos)
- boundary_end_offset = content_type_as_string.length();
+ boundary_end_offset = content_type.length();
size_t boundary_length = boundary_end_offset - boundary_start_offset;
*multipart_boundary =
- content_type_as_string.substr(boundary_start_offset, boundary_length);
+ content_type.substr(boundary_start_offset, boundary_length);
// The byte range response can have quoted boundary strings. This is legal
// as per MIME specifications. Individual data fragements however don't
// contain quoted boundary strings.
@@ -270,16 +286,14 @@ bool MultipartResponseDelegate::ReadMultipartBoundary(
}
bool MultipartResponseDelegate::ReadContentRanges(
- const WebCore::ResourceResponse& response,
+ const WebURLResponse& response,
int* content_range_lower_bound,
int* content_range_upper_bound) {
- std::string content_range =
- webkit_glue::StringToStdString(
- response.httpHeaderField("Content-Range"));
+ std::string content_range = WebStringToStdString(
+ response.httpHeaderField(WebString::fromUTF8("Content-Range")));
- size_t byte_range_lower_bound_start_offset =
- content_range.find(" ");
+ size_t byte_range_lower_bound_start_offset = content_range.find(" ");
if (byte_range_lower_bound_start_offset == std::string::npos) {
return false;
}
@@ -321,3 +335,5 @@ bool MultipartResponseDelegate::ReadContentRanges(
return false;
return true;
}
+
+} // namespace webkit_glue
diff --git a/webkit/glue/multipart_response_delegate.h b/webkit/glue/multipart_response_delegate.h
index 41d09c2..3676a78 100644
--- a/webkit/glue/multipart_response_delegate.h
+++ b/webkit/glue/multipart_response_delegate.h
@@ -1,11 +1,10 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// A delegate class of ResourceHandleInternal (resource_handle_win) that
-// handles multipart/x-mixed-replace data. We special case
-// multipart/x-mixed-replace because WebCore expects a separate
-// didReceiveResponse for each new message part.
+// A delegate class of WebURLLoaderImpl that handles multipart/x-mixed-replace
+// data. We special case multipart/x-mixed-replace because WebCore expects a
+// separate didReceiveResponse for each new message part.
//
// Most of the logic and edge case handling are based on the Mozilla's
// implementation in netwerk/streamconv/converters/nsMultiMixedConv.cpp.
@@ -47,28 +46,28 @@
*
* ***** END LICENSE BLOCK ***** */
+#ifndef WEBKIT_GLUE_MULTIPART_RESPONSE_DELEGATE_H_
+#define WEBKIT_GLUE_MULTIPART_RESPONSE_DELEGATE_H_
+
#include <string>
-#include "config.h"
+#include "webkit/api/public/WebURLResponse.h"
-#include "base/compiler_specific.h"
+namespace WebKit {
+class WebURLLoader;
+class WebURLLoaderClient;
+}
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "ResourceResponse.h"
-MSVC_POP_WARNING();
+namespace webkit_glue {
-namespace WebCore {
- class ResourceHandle;
- class ResourceHandleClient;
-}
+// Used by unit tests to access private members.
+class MultipartResponseDelegateTester;
class MultipartResponseDelegate {
- friend class MultipartResponseTest_Functions_Test; // For unittests.
-
public:
- MultipartResponseDelegate(WebCore::ResourceHandleClient* client,
- WebCore::ResourceHandle* job,
- const WebCore::ResourceResponse& response,
+ MultipartResponseDelegate(WebKit::WebURLLoaderClient* client,
+ WebKit::WebURLLoader* loader,
+ const WebKit::WebURLResponse& response,
const std::string& boundary);
// Passed through from ResourceHandleInternal
@@ -78,25 +77,27 @@ class MultipartResponseDelegate {
// Returns the multi part boundary string from the Content-type header
// in the response.
// Returns true on success.
- static bool ReadMultipartBoundary(const WebCore::ResourceResponse& response,
+ static bool ReadMultipartBoundary(const WebKit::WebURLResponse& response,
std::string* multipart_boundary);
// Returns the lower and higher content ranges from an individual multipart
// in a multipart response.
// Returns true on success.
- static bool ReadContentRanges(const WebCore::ResourceResponse& response,
+ static bool ReadContentRanges(const WebKit::WebURLResponse& response,
int* content_range_lower_bound,
int* content_range_upper_bound);
private:
- // Pointers back to our owning object so we can make callbacks as we parse
- // pieces of data.
- WebCore::ResourceHandleClient* client_;
- WebCore::ResourceHandle* job_;
+ friend class MultipartResponseDelegateTester; // For unittests.
+
+ // Pointers to the client and associated loader so we can make callbacks as
+ // we parse pieces of data.
+ WebKit::WebURLLoaderClient* client_;
+ WebKit::WebURLLoader* loader_;
// The original resource response for this request. We use this as a
// starting point for each parts response.
- WebCore::ResourceResponse original_response_;
+ WebKit::WebURLResponse original_response_;
// Checks to see if data[pos] character is a line break; handles crlf, lflf,
// lf, or cr. Returns the number of characters to skip over (0, 1 or 2).
@@ -128,3 +129,7 @@ class MultipartResponseDelegate {
// processing AddData requests.
bool stop_sending_;
};
+
+} // namespace webkit_glue
+
+#endif
diff --git a/webkit/glue/multipart_response_delegate_unittest.cc b/webkit/glue/multipart_response_delegate_unittest.cc
index e05879d..df47529 100644
--- a/webkit/glue/multipart_response_delegate_unittest.cc
+++ b/webkit/glue/multipart_response_delegate_unittest.cc
@@ -4,71 +4,105 @@
#include <vector>
-#include "config.h"
-
-#include "base/compiler_specific.h"
-
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "KURL.h"
-#include "ResourceResponse.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-MSVC_POP_WARNING();
-
#include "base/basictypes.h"
+#include "webkit/api/public/WebString.h"
+#include "webkit/api/public/WebURL.h"
+#include "webkit/api/public/WebURLLoaderClient.h"
+#include "webkit/api/public/WebURLResponse.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/multipart_response_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
-using namespace WebCore;
-using namespace std;
+using std::string;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebURLError;
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderClient;
+using WebKit::WebURLRequest;
+using WebKit::WebURLResponse;
+using webkit_glue::MultipartResponseDelegate;
+using webkit_glue::MultipartResponseDelegateTester;
+
+namespace webkit_glue {
+
+class MultipartResponseDelegateTester {
+ public:
+ MultipartResponseDelegateTester(MultipartResponseDelegate* delegate)
+ : delegate_(delegate) {
+ }
+
+ int PushOverLine(const std::string& data, size_t pos) {
+ return delegate_->PushOverLine(data, pos);
+ }
+
+ bool ParseHeaders() { return delegate_->ParseHeaders(); }
+ size_t FindBoundary() { return delegate_->FindBoundary(); }
+ std::string& boundary() { return delegate_->boundary_; }
+ std::string& data() { return delegate_->data_; }
+
+ private:
+ MultipartResponseDelegate* delegate_;
+};
+
+} // namespace webkit_glue
namespace {
class MultipartResponseTest : public testing::Test {
};
-class MockResourceHandleClient : public ResourceHandleClient {
+class MockWebURLLoaderClient : public WebURLLoaderClient {
public:
- MockResourceHandleClient() { Reset(); }
+ MockWebURLLoaderClient() { Reset(); }
- virtual void didReceiveResponse(ResourceHandle* handle,
- const ResourceResponse& response) {
+ virtual void willSendRequest(
+ WebURLLoader*, WebURLRequest&, const WebURLResponse&) {}
+ virtual void didSendData(
+ WebURLLoader*, unsigned long long, unsigned long long) {}
+
+ virtual void didReceiveResponse(WebURLLoader* loader,
+ const WebURLResponse& response) {
++received_response_;
- resource_response_ = response;
+ response_ = response;
data_.clear();
}
- virtual void didReceiveData(ResourceHandle* handle,
+ virtual void didReceiveData(WebURLLoader* loader,
const char* data, int data_length,
- int length_received) {
+ long long length_received) {
++received_data_;
data_.append(data, data_length);
}
+ virtual void didFinishLoading(WebURLLoader*) {}
+ virtual void didFail(WebURLLoader*, const WebURLError&) {}
+
void Reset() {
received_response_ = received_data_ = 0;
data_.clear();
- resource_response_ = ResourceResponse();
+ response_.reset();
}
int received_response_, received_data_;
string data_;
- ResourceResponse resource_response_;
+ WebURLResponse response_;
};
-} // namespace
-
// We can't put this in an anonymous function because it's a friend class for
// access to private members.
TEST(MultipartResponseTest, Functions) {
// PushOverLine tests
- ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US",
- String());
- response.setHTTPHeaderField(String("Foo"), String("Bar"));
- response.setHTTPHeaderField(String("Content-type"), String("text/plain"));
- MockResourceHandleClient client;
+ WebURLResponse response;
+ response.initialize();
+ response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Foo"),
+ WebString::fromUTF8("Bar"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8("text/plain"));
+ MockWebURLLoaderClient client;
MultipartResponseDelegate delegate(&client, NULL, response, "bound");
+ MultipartResponseDelegateTester delegate_tester(&delegate);
struct {
const char* input;
@@ -90,8 +124,8 @@ TEST(MultipartResponseTest, Functions) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(line_tests); ++i) {
EXPECT_EQ(line_tests[i].expected,
- delegate.PushOverLine(line_tests[i].input,
- line_tests[i].position));
+ delegate_tester.PushOverLine(line_tests[i].input,
+ line_tests[i].position));
}
// ParseHeaders tests
@@ -112,33 +146,33 @@ TEST(MultipartResponseTest, Functions) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(header_tests); ++i) {
client.Reset();
- delegate.data_.assign(header_tests[i].data);
+ delegate_tester.data().assign(header_tests[i].data);
EXPECT_EQ(header_tests[i].rv,
- delegate.ParseHeaders());
+ delegate_tester.ParseHeaders());
EXPECT_EQ(header_tests[i].received_response_calls,
client.received_response_);
EXPECT_EQ(string(header_tests[i].newdata),
- delegate.data_);
+ delegate_tester.data());
}
// Test that the resource response is filled in correctly when parsing
// headers.
client.Reset();
string test_header("content-type: image/png\ncontent-length: 10\n\n");
- delegate.data_.assign(test_header);
- EXPECT_TRUE(delegate.ParseHeaders());
- EXPECT_TRUE(delegate.data_.length() == 0);
- EXPECT_EQ(webkit_glue::StringToStdWString(
- client.resource_response_.httpHeaderField(
- String("Content-Type"))),
- wstring(L"image/png"));
- EXPECT_EQ(webkit_glue::StringToStdWString(
- client.resource_response_.httpHeaderField(
- String("content-length"))),
- wstring(L"10"));
+ delegate_tester.data().assign(test_header);
+ EXPECT_TRUE(delegate_tester.ParseHeaders());
+ EXPECT_TRUE(delegate_tester.data().length() == 0);
+ EXPECT_EQ(webkit_glue::WebStringToStdString(
+ client.response_.httpHeaderField(
+ WebString::fromUTF8("Content-Type"))),
+ string("image/png"));
+ EXPECT_EQ(webkit_glue::WebStringToStdString(
+ client.response_.httpHeaderField(
+ WebString::fromUTF8("content-length"))),
+ string("10"));
// This header is passed from the original request.
- EXPECT_EQ(webkit_glue::StringToStdWString(
- client.resource_response_.httpHeaderField(String("foo"))),
- wstring(L"Bar"));
+ EXPECT_EQ(webkit_glue::WebStringToStdString(
+ client.response_.httpHeaderField(WebString::fromUTF8("foo"))),
+ string("Bar"));
// FindBoundary tests
struct {
@@ -154,21 +188,22 @@ TEST(MultipartResponseTest, Functions) {
{ "bound", "--boundbound", 0 },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(boundary_tests); ++i) {
- delegate.boundary_.assign(boundary_tests[i].boundary);
- delegate.data_.assign(boundary_tests[i].data);
+ delegate_tester.boundary().assign(boundary_tests[i].boundary);
+ delegate_tester.data().assign(boundary_tests[i].data);
EXPECT_EQ(boundary_tests[i].position,
- delegate.FindBoundary());
+ delegate_tester.FindBoundary());
}
}
-namespace {
-
TEST(MultipartResponseTest, MissingBoundaries) {
- ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US",
- String());
- response.setHTTPHeaderField(String("Foo"), String("Bar"));
- response.setHTTPHeaderField(String("Content-type"), String("text/plain"));
- MockResourceHandleClient client;
+ WebURLResponse response;
+ response.initialize();
+ response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Foo"),
+ WebString::fromUTF8("Bar"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8("text/plain"));
+ MockWebURLLoaderClient client;
MultipartResponseDelegate delegate(&client, NULL, response, "bound");
// No start boundary
@@ -228,11 +263,14 @@ TEST(MultipartResponseTest, MissingBoundaries) {
TEST(MultipartResponseTest, MalformedBoundary) {
// Some servers send a boundary that is prefixed by "--". See bug 5786.
- ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US",
- String());
- response.setHTTPHeaderField(String("Foo"), String("Bar"));
- response.setHTTPHeaderField(String("Content-type"), String("text/plain"));
- MockResourceHandleClient client;
+ WebURLResponse response;
+ response.initialize();
+ response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Foo"),
+ WebString::fromUTF8("Bar"));
+ response.setHTTPHeaderField(WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8("text/plain"));
+ MockWebURLLoaderClient client;
MultipartResponseDelegate delegate(&client, NULL, response, "--bound");
string data(
@@ -272,13 +310,14 @@ void VariousChunkSizesTest(const TestChunk chunks[], int chunks_size, int respon
"foofoofoofoofoo" // 86-100
"--bound--"); // 101-109
- ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US",
- String());
- MockResourceHandleClient client;
+ WebURLResponse response;
+ response.initialize();
+ response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ MockWebURLLoaderClient client;
MultipartResponseDelegate delegate(&client, NULL, response, "bound");
for (int i = 0; i < chunks_size; ++i) {
- ASSERT(chunks[i].start_pos < chunks[i].end_pos);
+ ASSERT_TRUE(chunks[i].start_pos < chunks[i].end_pos);
string chunk = data.substr(chunks[i].start_pos,
chunks[i].end_pos - chunks[i].start_pos);
delegate.OnReceivedData(chunk.c_str(), static_cast<int>(chunk.length()));
@@ -385,9 +424,10 @@ TEST(MultipartResponseTest, BreakInData) {
TEST(MultipartResponseTest, MultipleBoundaries) {
// Test multiple boundaries back to back
- ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US",
- String());
- MockResourceHandleClient client;
+ WebURLResponse response;
+ response.initialize();
+ response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ MockWebURLLoaderClient client;
MultipartResponseDelegate delegate(&client, NULL, response, "bound");
string data("--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--");
@@ -402,12 +442,14 @@ TEST(MultipartResponseTest, MultipleBoundaries) {
TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
// Test multipart/byteranges based boundary parsing.
- ResourceResponse response1(KURL(), "multipart/byteranges", 0, "en-US",
- String());
- response1.setHTTPHeaderField(String("Content-Length"), String("200"));
+ WebURLResponse response1;
+ response1.initialize();
+ response1.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace"));
+ response1.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("200"));
response1.setHTTPHeaderField(
- String("Content-type"),
- String("multipart/byteranges; boundary=--bound--"));
+ WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8("multipart/byteranges; boundary=--bound--"));
std::string multipart_boundary;
bool result = MultipartResponseDelegate::ReadMultipartBoundary(
@@ -416,35 +458,39 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
EXPECT_EQ(string("--bound--"),
multipart_boundary);
- ResourceResponse response2(KURL(), "image/png", 0, "en-US",
- String());
+ WebURLResponse response2;
+ response2.initialize();
+ response2.setMIMEType(WebString::fromUTF8("image/png"));
- response2.setHTTPHeaderField(String("Content-Length"), String("300"));
+ response2.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("300"));
response2.setHTTPHeaderField(
- String("Last-Modified"),
- String("Mon, 04 Apr 2005 20:36:01 GMT"));
+ WebString::fromUTF8("Last-Modified"),
+ WebString::fromUTF8("Mon, 04 Apr 2005 20:36:01 GMT"));
response2.setHTTPHeaderField(
- String("Date"),
- String("Thu, 11 Sep 2008 18:21:42 GMT"));
+ WebString::fromUTF8("Date"),
+ WebString::fromUTF8("Thu, 11 Sep 2008 18:21:42 GMT"));
multipart_boundary.clear();
result = MultipartResponseDelegate::ReadMultipartBoundary(
response2, &multipart_boundary);
EXPECT_EQ(result, false);
- ResourceResponse response3(KURL(), "multipart/byteranges", 0, "en-US",
- String());
+ WebURLResponse response3;
+ response3.initialize();
+ response3.setMIMEType(WebString::fromUTF8("multipart/byteranges"));
- response3.setHTTPHeaderField(String("Content-Length"), String("300"));
+ response3.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("300"));
response3.setHTTPHeaderField(
- String("Last-Modified"),
- String("Mon, 04 Apr 2005 20:36:01 GMT"));
+ WebString::fromUTF8("Last-Modified"),
+ WebString::fromUTF8("Mon, 04 Apr 2005 20:36:01 GMT"));
response3.setHTTPHeaderField(
- String("Date"),
- String("Thu, 11 Sep 2008 18:21:42 GMT"));
+ WebString::fromUTF8("Date"),
+ WebString::fromUTF8("Thu, 11 Sep 2008 18:21:42 GMT"));
response3.setHTTPHeaderField(
- String("Content-type"),
- String("multipart/byteranges"));
+ WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8("multipart/byteranges"));
multipart_boundary.clear();
result = MultipartResponseDelegate::ReadMultipartBoundary(
@@ -452,12 +498,15 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
EXPECT_EQ(result, false);
EXPECT_EQ(multipart_boundary.length(), 0U);
- ResourceResponse response4(KURL(), "multipart/byteranges", 0, "en-US",
- String());
- response4.setHTTPHeaderField(String("Content-Length"), String("200"));
+ WebURLResponse response4;
+ response4.initialize();
+ response4.setMIMEType(WebString::fromUTF8("multipart/byteranges"));
+ response4.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("200"));
response4.setHTTPHeaderField(
- String("Content-type"),
- String("multipart/byteranges; boundary=--bound--; charSet=utf8"));
+ WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8(
+ "multipart/byteranges; boundary=--bound--; charSet=utf8"));
multipart_boundary.clear();
@@ -466,12 +515,15 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
EXPECT_EQ(result, true);
EXPECT_EQ(string("--bound--"), multipart_boundary);
- ResourceResponse response5(KURL(), "multipart/byteranges", 0, "en-US",
- String());
- response5.setHTTPHeaderField(String("Content-Length"), String("200"));
+ WebURLResponse response5;
+ response5.initialize();
+ response5.setMIMEType(WebString::fromUTF8("multipart/byteranges"));
+ response5.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("200"));
response5.setHTTPHeaderField(
- String("Content-type"),
- String("multipart/byteranges; boundary=\"--bound--\"; charSet=utf8"));
+ WebString::fromUTF8("Content-type"),
+ WebString::fromUTF8(
+ "multipart/byteranges; boundary=\"--bound--\"; charSet=utf8"));
multipart_boundary.clear();
@@ -482,12 +534,14 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
}
TEST(MultipartResponseTest, MultipartContentRangesTest) {
- ResourceResponse response1(KURL(), "application/pdf", 0, "en-US",
- String());
- response1.setHTTPHeaderField(String("Content-Length"), String("200"));
+ WebURLResponse response1;
+ response1.initialize();
+ response1.setMIMEType(WebString::fromUTF8("application/pdf"));
+ response1.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("200"));
response1.setHTTPHeaderField(
- String("Content-Range"),
- String("bytes 1000-1050/5000"));
+ WebString::fromUTF8("Content-Range"),
+ WebString::fromUTF8("bytes 1000-1050/5000"));
int content_range_lower_bound = 0;
int content_range_upper_bound = 0;
@@ -500,12 +554,14 @@ TEST(MultipartResponseTest, MultipartContentRangesTest) {
EXPECT_EQ(content_range_lower_bound, 1000);
EXPECT_EQ(content_range_upper_bound, 1050);
- ResourceResponse response2(KURL(), "application/pdf", 0, "en-US",
- String());
- response2.setHTTPHeaderField(String("Content-Length"), String("200"));
+ WebURLResponse response2;
+ response2.initialize();
+ response2.setMIMEType(WebString::fromUTF8("application/pdf"));
+ response2.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8("200"));
response2.setHTTPHeaderField(
- String("Content-Range"),
- String("bytes 1000/1050"));
+ WebString::fromUTF8("Content-Range"),
+ WebString::fromUTF8("bytes 1000/1050"));
content_range_lower_bound = 0;
content_range_upper_bound = 0;
diff --git a/webkit/glue/resource_handle_impl.cc b/webkit/glue/resource_handle_impl.cc
deleted file mode 100644
index 1912094..0000000
--- a/webkit/glue/resource_handle_impl.cc
+++ /dev/null
@@ -1,765 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file replaces WebCore/platform/network/win/ResourceHandleWin.cpp with a
-// platform-neutral implementation that simply defers almost entirely to
-// ResouceLoaderBridge.
-//
-// This uses the same ResourceHandle.h header file that the rest of WebKit
-// uses, allowing us to avoid complicated changes. Our specific things are
-// added on ResourceHandleInternal. The ResourceHandle owns the
-// ResourceHandleInternal and passes off almost all processing to it.
-//
-// The WebKit version of this code keeps the ResourceHandle AddRef'd when
-// there are any callbacks. This prevents the callbacks from occuring into
-// destroyed objects. However, our destructors should always stop callbacks
-// from happening, making this (hopefully) unnecessary.
-//
-// We preserve this behavior for safety. A client could count on this behavior
-// and fire off a request, release it, and wait for callbacks to get the data
-// as long as it doesn't care about canceling the request. Although this is
-// dumb, we support it. We use pending_ to indicate this extra AddRef, which
-// is done in start() and released in OnCompletedRequest.
-
-#include "config.h"
-
-#include "base/compiler_specific.h"
-
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "CString.h"
-#include "DocLoader.h"
-#include "FormData.h"
-#include "FrameLoader.h"
-#include "Page.h"
-#include "ResourceError.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
-MSVC_POP_WARNING();
-
-#undef LOG
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/process_util.h"
-#include "base/time.h"
-#include "base/string_util.h"
-#include "base/string_tokenizer.h"
-#include "webkit/glue/feed_preview.h"
-#include "webkit/glue/glue_util.h"
-#include "webkit/glue/multipart_response_delegate.h"
-#include "webkit/glue/resource_loader_bridge.h"
-#include "net/base/data_url.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_response_headers.h"
-
-using webkit_glue::ResourceLoaderBridge;
-using base::Time;
-using base::TimeDelta;
-using net::HttpResponseHeaders;
-
-namespace WebCore {
-
-static ResourceType::Type FromTargetType(ResourceRequest::TargetType type) {
- switch (type) {
- case ResourceRequest::TargetIsMainFrame:
- return ResourceType::MAIN_FRAME;
- case ResourceRequest::TargetIsSubFrame:
- return ResourceType::SUB_FRAME;
- case ResourceRequest::TargetIsSubResource:
- return ResourceType::SUB_RESOURCE;
- case ResourceRequest::TargetIsObject:
- return ResourceType::OBJECT;
- case ResourceRequest::TargetIsMedia:
- return ResourceType::MEDIA;
- default:
- NOTREACHED();
- return ResourceType::SUB_RESOURCE;
- }
-}
-
-// Extracts the information from a data: url.
-static bool GetInfoFromDataUrl(const GURL& url,
- ResourceLoaderBridge::ResponseInfo* info,
- std::string* data, URLRequestStatus* status) {
- std::string mime_type;
- std::string charset;
- if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
- *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0);
- info->request_time = Time::Now();
- info->response_time = Time::Now();
- info->headers = NULL;
- info->mime_type.swap(mime_type);
- info->charset.swap(charset);
- info->security_info.clear();
- info->content_length = -1;
-
- return true;
- }
-
- *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL);
- return false;
-}
-
-static void ExtractInfoFromHeaders(const HttpResponseHeaders* headers,
- HTTPHeaderMap* header_map,
- int* status_code,
- String* status_text,
- long long* expected_content_length) {
- *status_code = headers->response_code();
-
- // Set the status text
- *status_text = webkit_glue::StdStringToString(headers->GetStatusText());
-
- // Set the content length.
- std::string length_val;
- if (headers->EnumerateHeader(NULL, "content-length", &length_val))
- *expected_content_length = StringToInt64(length_val);
-
- // Build up the header map. Take care with duplicate headers.
- void* iter = NULL;
- std::string name, value;
- while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
- String name_str = webkit_glue::StdStringToString(name);
- String value_str = webkit_glue::StdStringToString(value);
-
- pair<HTTPHeaderMap::iterator, bool> result =
- header_map->add(name_str, value_str);
- if (!result.second)
- result.first->second += ", " + value_str;
- }
-}
-
-static ResourceResponse MakeResourceResponse(
- const KURL& kurl,
- const ResourceLoaderBridge::ResponseInfo& info) {
- int status_code = 0;
- long long expected_content_length = info.content_length;
- String status_text;
- HTTPHeaderMap header_map;
-
- // It's okay if there are no headers
- if (info.headers)
- ExtractInfoFromHeaders(info.headers,
- &header_map,
- &status_code,
- &status_text,
- &expected_content_length);
-
- // TODO(darin): We should leverage HttpResponseHeaders for this, and this
- // should be using the same code as ResourceDispatcherHost.
- // TODO(jungshik): Figure out the actual value of the referrer charset and
- // pass it to GetSuggestedFilename.
- std::wstring suggested_filename;
- if (info.headers) {
- std::string disp_val;
- if (info.headers->EnumerateHeader(NULL, "content-disposition", &disp_val)) {
- suggested_filename = net::GetSuggestedFilename(
- webkit_glue::KURLToGURL(kurl), disp_val, "", std::wstring());
- }
- }
-
- ResourceResponse response(kurl,
- webkit_glue::StdStringToString(info.mime_type),
- expected_content_length,
- webkit_glue::StdStringToString(info.charset),
- webkit_glue::StdWStringToString(suggested_filename));
-
- if (info.headers) {
- Time time_val;
- if (info.headers->GetLastModifiedValue(&time_val))
- response.setLastModifiedDate(time_val.ToTimeT());
-
- // Compute expiration date
- TimeDelta freshness_lifetime =
- info.headers->GetFreshnessLifetime(info.response_time);
- if (freshness_lifetime != TimeDelta()) {
- Time now = Time::Now();
- TimeDelta current_age =
- info.headers->GetCurrentAge(info.request_time, info.response_time,
- now);
- time_val = now + freshness_lifetime - current_age;
-
- response.setExpirationDate(time_val.ToTimeT());
- } else {
- // WebKit uses 0 as a special expiration date that means never expire.
- // 1 is a small enough value to let it always expire.
- response.setExpirationDate(1);
- }
- }
-
- response.setHTTPStatusCode(status_code);
- response.setHTTPStatusText(status_text);
- response.setSecurityInfo(webkit_glue::StdStringToCString(info.security_info));
- response.setAppCacheID(info.app_cache_id);
-
- // WebKit doesn't provide a way for us to set expected content length after
- // calling the constructor, so we parse the headers first and then swap in
- // our HTTP header map. Ideally we would like a setter for expected content
- // length (perhaps by abstracting ResourceResponse interface into
- // ResourceResponseBase) but that would require forking.
- const_cast<HTTPHeaderMap*>(&response.httpHeaderFields())->swap(header_map);
-
- return response;
-}
-
-class ResourceHandleInternal : public ResourceLoaderBridge::Peer {
- public:
- ResourceHandleInternal(ResourceHandle* job, const ResourceRequest& r,
- ResourceHandleClient* c);
- ~ResourceHandleInternal();
-
- // If the response parameter is null, then an asynchronous load is started.
- bool Start(ResourceLoaderBridge::SyncLoadResponse* response);
-
- // Used to cancel an asynchronous load.
- void Cancel();
-
- // Used to suspend/resume an asynchronous load.
- void SetDefersLoading(bool value);
-
- // ResourceLoaderBridge::Peer implementation
- virtual void OnUploadProgress(uint64 position, uint64 size);
- virtual void OnReceivedRedirect(const GURL& new_url);
- virtual void OnReceivedResponse(
- const ResourceLoaderBridge::ResponseInfo& info,
- bool content_filtered);
- virtual void OnReceivedData(const char* data, int len);
- virtual void OnCompletedRequest(const URLRequestStatus& status,
- const std::string& security_info);
- virtual std::string GetURLForDebugging();
-
- // Handles a data: url internally instead of calling the bridge.
- void HandleDataUrl();
-
- // This is the bridge implemented by the embedder.
- // The bridge is kept alive as long as the request is valid and we
- // are ready for callbacks.
- scoped_ptr<ResourceLoaderBridge> bridge_;
-
- // The resource loader that owns us
- ResourceHandle* job_;
-
- // This is the object that receives various status messages (such as when the
- // loader has received data). See definition for the exact messages that are
- // sent to it.
- ResourceHandleClient* client_;
-
- ResourceRequest request_;
-
- // Runnable Method Factory used to invoke later HandleDataUrl().
- ScopedRunnableMethodFactory<ResourceHandleInternal> data_url_factory_;
-
- int load_flags_;
-
- private:
- // Set to true when we're waiting for data from the bridge, also indicating
- // we have addrefed our job.
- bool pending_;
-
- // Expected content length of the response
- long long expected_content_length_;
-
- // NULL unless we are handling a multipart/x-mixed-replace request
- scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
-
- // NULL unless we are handling a feed:// request.
- scoped_ptr<FeedClientProxy> feed_client_proxy_;
-};
-
-ResourceHandleInternal::ResourceHandleInternal(ResourceHandle* job,
- const ResourceRequest& r,
- ResourceHandleClient* c)
- : job_(job),
- client_(c),
- request_(r),
-MSVC_SUPPRESS_WARNING(4355) // can use this
- data_url_factory_(this),
- load_flags_(net::LOAD_NORMAL),
- pending_(false),
- expected_content_length_(-1),
- multipart_delegate_(NULL) {
-}
-
-ResourceHandleInternal::~ResourceHandleInternal() {
- DCHECK(!pending_);
-}
-
-void ResourceHandleInternal::HandleDataUrl() {
- ResourceLoaderBridge::ResponseInfo info;
- URLRequestStatus status;
- std::string data;
-
- if (GetInfoFromDataUrl(webkit_glue::KURLToGURL(request_.url()), &info, &data,
- &status)) {
- OnReceivedResponse(info, false);
-
- if (data.size())
- OnReceivedData(data.c_str(), data.size());
- }
-
- OnCompletedRequest(status, info.security_info);
-
- // We are done using the object. ResourceHandle and ResourceHandleInternal
- // might be destroyed now.
- job_->deref();
-}
-
-bool ResourceHandleInternal::Start(
- ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
- DCHECK(!bridge_.get());
-
- CString method = request_.httpMethod().latin1();
- GURL referrer(webkit_glue::StringToStdString(request_.httpReferrer()));
-
- // Compute the URL of the load.
- GURL url = webkit_glue::KURLToGURL(request_.url());
- if (url.SchemeIs("feed:")) {
- // Feed URLs are special, they actually mean "http".
- url_canon::Replacements<char> replacements;
- replacements.SetScheme("http", url_parse::Component(0, 4));
- url = url.ReplaceComponents(replacements);
-
- // Replace our client with a client that understands previewing feeds
- // and forwards the feeds along to the original client.
- feed_client_proxy_.reset(new FeedClientProxy(client_));
- client_ = feed_client_proxy_.get();
- }
-
- switch (request_.cachePolicy()) {
- case ReloadIgnoringCacheData:
- // Required by LayoutTests/http/tests/misc/refresh-headers.php
- load_flags_ |= net::LOAD_VALIDATE_CACHE;
- break;
- case ReturnCacheDataElseLoad:
- load_flags_ |= net::LOAD_PREFERRING_CACHE;
- break;
- case ReturnCacheDataDontLoad:
- load_flags_ |= net::LOAD_ONLY_FROM_CACHE;
- break;
- case UseProtocolCachePolicy:
- break;
- }
-
- if (request_.reportUploadProgress())
- load_flags_ |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
-
- // Translate the table of request headers to a formatted string blob
- String headerBuf;
- const HTTPHeaderMap& headerMap = request_.httpHeaderFields();
-
- // In some cases, WebCore doesn't add an Accept header, but not having the
- // header confuses some web servers. See bug 808613.
- // Note: headerMap uses case-insenstive keys, so this will find Accept as
- // as well.
- if (!headerMap.contains("accept"))
- request_.addHTTPHeaderField("Accept", "*/*");
-
- const String crlf("\r\n");
- const String sep(": ");
- for (HTTPHeaderMap::const_iterator it = headerMap.begin();
- it != headerMap.end(); ++it) {
- // Skip over referrer headers found in the header map because we already
- // pulled it out as a separate parameter. We likewise prune the UA since
- // that will be added back by the network layer.
- if (equalIgnoringCase((*it).first, "referer") ||
- equalIgnoringCase((*it).first, "user-agent"))
- continue;
-
- // Skip over "Cache-Control: max-age=0" header if the corresponding
- // load flag is already specified. FrameLoader sets both the flag and
- // the extra header -- the extra header is redundant since our network
- // implementation will add the necessary headers based on load flags.
- // See http://code.google.com/p/chromium/issues/detail?id=3434.
- if ((load_flags_ & net::LOAD_VALIDATE_CACHE) &&
- equalIgnoringCase((*it).first, "cache-control") &&
- (*it).second == "max-age=0")
- continue;
-
- if (!headerBuf.isEmpty())
- headerBuf.append(crlf);
- headerBuf.append((*it).first + sep + (*it).second);
- }
-
- // TODO(jcampan): in the non out-of-process plugin case the request does not
- // have a requestor_pid. Find a better place to set this.
- int requestor_pid = request_.requestorProcessID();
- if (requestor_pid == 0)
- requestor_pid = base::GetCurrentProcId();
-
- if (url.SchemeIs("data")) {
- if (sync_load_response) {
- // This is a sync load. Do the work now.
- sync_load_response->url = url;
- std::string data;
- GetInfoFromDataUrl(sync_load_response->url, sync_load_response,
- &sync_load_response->data,
- &sync_load_response->status);
- } else {
- pending_ = true;
- job_->ref(); // to be released when we get a OnCompletedRequest.
- job_->ref(); // to be released when HandleDataUrl is completed.
- MessageLoop::current()->PostTask(FROM_HERE,
- data_url_factory_.NewRunnableMethod(
- &ResourceHandleInternal::HandleDataUrl));
- }
- return true;
- }
-
- // TODO(abarth): These are wrong! I need to figure out how to get the right
- // strings here. See: http://crbug.com/8706
- std::string frame_origin =
- webkit_glue::StringToStdString(request_.firstPartyForCookies().string());
- std::string main_frame_origin =
- webkit_glue::StringToStdString(request_.firstPartyForCookies().string());
-
- // TODO(darin): is latin1 really correct here? It is if the strings are
- // already ASCII (i.e., if they are already escaped properly).
- // TODO(brettw) this should take parameter encoding into account when
- // creating the GURLs.
- bridge_.reset(ResourceLoaderBridge::Create(
- webkit_glue::CStringToStdString(method),
- url,
- webkit_glue::KURLToGURL(request_.firstPartyForCookies()),
- referrer,
- frame_origin,
- main_frame_origin,
- webkit_glue::CStringToStdString(headerBuf.latin1()),
- load_flags_,
- requestor_pid,
- FromTargetType(request_.targetType()),
- request_.appCacheContextID(),
- request_.requestorID()));
- if (!bridge_.get())
- return false;
-
- if (request_.httpBody()) {
- // GET and HEAD requests shouldn't have http bodies.
- DCHECK(method != "GET" && method != "HEAD");
- const Vector<FormDataElement>& elements = request_.httpBody()->elements();
- size_t n = elements.size();
- for (size_t i = 0; i < n; ++i) {
- const FormDataElement& e = elements[static_cast<unsigned>(i)];
- if (e.m_type == FormDataElement::data) {
- if (e.m_data.size() > 0) {
- // WebKit sometimes gives up empty data to append. These aren't
- // necessary so we just optimize those out here.
- bridge_->AppendDataToUpload(e.m_data.data(),
- static_cast<int>(e.m_data.size()));
- }
- } else {
- bridge_->AppendFileToUpload(
- FilePath(webkit_glue::StringToFilePathString(e.m_filename)));
- }
- }
- bridge_->SetUploadIdentifier(request_.httpBody()->identifier());
- }
-
- if (sync_load_response) {
- bridge_->SyncLoad(sync_load_response);
- return true;
- }
-
- bool rv = bridge_->Start(this);
- if (rv) {
- pending_ = true;
- job_->ref(); // to be released when we get a OnCompletedRequest.
- } else {
- bridge_.reset();
- }
-
- return rv;
-}
-
-void ResourceHandleInternal::Cancel() {
- // The bridge will still send OnCompletedRequest, which will deref() us,
- // so we don't do that here.
- if (bridge_.get())
- bridge_->Cancel();
-
- // Ensure that we do not notify the multipart delegate anymore as it has
- // its own pointer to the client.
- multipart_delegate_.reset();
-
- // Do not make any further calls to the client.
- client_ = NULL;
-}
-
-void ResourceHandleInternal::SetDefersLoading(bool value) {
- if (bridge_.get())
- bridge_->SetDefersLoading(value);
-}
-
-// ResourceLoaderBridge::Peer impl --------------------------------------------
-
-void ResourceHandleInternal::OnUploadProgress(uint64 position, uint64 size) {
- if (client_)
- client_->didSendData(job_, position, size);
-}
-
-void ResourceHandleInternal::OnReceivedRedirect(const GURL& new_url) {
- DCHECK(pending_);
-
- KURL url = webkit_glue::GURLToKURL(new_url);
-
- // TODO(darin): need a way to properly initialize a ResourceResponse
- ResourceResponse response(request_.url(), String(), -1, String(), String());
-
- ResourceRequest new_request(url);
-
- // TODO(darin): we need to setup new_request to reflect the fact that we
- // for example drop the httpBody when following a POST request that is
- // redirected to a GET request.
-
- if (client_)
- client_->willSendRequest(job_, new_request, response);
-
- //
- // TODO(darin): since new_request is sent as a mutable reference, it is
- // possible that willSendRequest may expect to be able to modify it.
- //
- // andresca on #webkit confirms that that is intentional, so we'll need
- // to rework the ResourceLoaderBridge to give us control over what URL
- // is really loaded (and with what headers) when a redirect is encountered.
- //
-
- request_ = new_request;
-}
-
-void ResourceHandleInternal::OnReceivedResponse(
- const ResourceLoaderBridge::ResponseInfo& info,
- bool content_filtered) {
- DCHECK(pending_);
-
- // TODO(darin): need a way to properly initialize a ResourceResponse
- ResourceResponse response = MakeResourceResponse(request_.url(), info);
- response.setIsContentFiltered(content_filtered);
-
- expected_content_length_ = response.expectedContentLength();
-
- if (client_)
- client_->didReceiveResponse(job_, response);
-
- // we may have been cancelled after didReceiveResponse, which would leave us
- // without a client and therefore without much need to do multipart handling.
-
- DCHECK(!multipart_delegate_.get());
- if (client_ && info.headers && response.isMultipart()) {
- std::string content_type;
- info.headers->EnumerateHeader(NULL, "content-type", &content_type);
-
- std::string boundary = net::GetHeaderParamValue(content_type, "boundary");
- TrimString(boundary, " \"", &boundary);
- // If there's no boundary, just handle the request normally. In the gecko
- // code, nsMultiMixedConv::OnStartRequest throws an exception.
- if (!boundary.empty()) {
- multipart_delegate_.reset(new MultipartResponseDelegate(client_, job_,
- response, boundary));
- }
- }
-
- // TODO(darin): generate willCacheResponse callback. debug mac webkit to
- // determine when it should be called.
-}
-
-void ResourceHandleInternal::OnReceivedData(const char* data, int data_len) {
- DCHECK(pending_);
-
- if (client_) {
- // TODO(darin): figure out what to pass for lengthReceived. from reading
- // the loader code, it looks like this is supposed to be the content-length
- // value, but it seems really wacky to include that here! we have to debug
- // webkit on mac to figure out what this should be.
-
- // TODO(jackson): didReceiveData expects an int, but an expected content
- // length is an int64, so we do our best to fit it inside an int. The only
- // code that cares currently about this value is the Inspector, so beware
- // that the Inspector's network panel might under-represent the size of
- // some resources if they're larger than a gigabyte.
- int lengthReceived = static_cast<int>(expected_content_length_);
- if (lengthReceived != expected_content_length_) // overflow occurred
- lengthReceived = -1;
-
- if (!multipart_delegate_.get()) {
- client_->didReceiveData(job_, data, data_len, lengthReceived);
- } else {
- // AddData will make the appropriate calls to client_->didReceiveData
- // and client_->didReceiveResponse
- multipart_delegate_->OnReceivedData(data, data_len);
- }
- }
-}
-
-void ResourceHandleInternal::OnCompletedRequest(
- const URLRequestStatus& status,
- const std::string& security_info) {
- if (multipart_delegate_.get()) {
- multipart_delegate_->OnCompletedRequest();
- multipart_delegate_.reset(NULL);
- }
-
- pending_ = false;
-
- if (client_) {
- if (status.status() != URLRequestStatus::SUCCESS) {
- int error_code;
- if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) {
- // By marking this request as aborted we insure that we don't navigate
- // to an error page.
- error_code = net::ERR_ABORTED;
- } else {
- error_code = status.os_error();
- }
- // TODO(tc): fill in these fields properly
- ResourceError error(net::kErrorDomain,
- error_code,
- request_.url().string(),
- String() /*localized description*/);
- client_->didFail(job_, error);
- } else {
- client_->didFinishLoading(job_);
- }
- }
-
- job_->deref(); // may destroy our owner and hence |this|
-}
-
-std::string ResourceHandleInternal::GetURLForDebugging() {
- return webkit_glue::CStringToStdString(request_.url().string().latin1());
-}
-
-// ResourceHandle -------------------------------------------------------------
-
-ResourceHandle::ResourceHandle(const ResourceRequest& request,
- ResourceHandleClient* client,
- bool defersLoading,
- bool shouldContentSniff,
- bool mightDownloadFromHandle)
-MSVC_SUPPRESS_WARNING(4355) // it's okay to pass |this| here!
- : d(new ResourceHandleInternal(this, request, client)) {
- // TODO(darin): figure out what to do with the two bool params
-}
-
-PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request,
- ResourceHandleClient* client,
- Frame* deprecated,
- bool defersLoading,
- bool shouldContentSniff,
- bool mightDownloadFromHandle) {
- RefPtr<ResourceHandle> newHandle =
- adoptRef(new ResourceHandle(request, client, defersLoading,
- shouldContentSniff, mightDownloadFromHandle));
-
- if (newHandle->start(NULL))
- return newHandle.release();
-
- return NULL;
-}
-
-const ResourceRequest& ResourceHandle::request() const {
- return d->request_;
-}
-
-ResourceHandleClient* ResourceHandle::client() const {
- return d->client_;
-}
-
-void ResourceHandle::setClient(ResourceHandleClient* client) {
- d->client_ = client;
-}
-
-void ResourceHandle::setDefersLoading(bool value) {
- d->SetDefersLoading(value);
-}
-
-bool ResourceHandle::start(Frame* deprecated) {
- return d->Start(NULL);
-}
-
-void ResourceHandle::clearAuthentication() {
- // TODO(darin): do something here. it looks like the ResourceLoader calls
- // this method when it is canceled. i have no idea why it does this.
-}
-
-void ResourceHandle::cancel() {
- d->Cancel();
-}
-
-ResourceHandle::~ResourceHandle() {
-}
-
-PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() {
- return NULL;
-}
-
-/*static*/ bool ResourceHandle::loadsBlocked() {
- return false; // this seems to be related to sync XMLHttpRequest...
-}
-
-/*static*/ bool ResourceHandle::supportsBufferedData() {
- return false; // the loader will buffer manually if it needs to
-}
-
-/*static*/ void ResourceHandle::loadResourceSynchronously(
- const ResourceRequest& request, StoredCredentials, ResourceError& error,
- ResourceResponse& response, Vector<char>& data, Frame*) {
-
- RefPtr<ResourceHandle> handle =
- adoptRef(new ResourceHandle(request, NULL, false, false, false));
-
- ResourceLoaderBridge::SyncLoadResponse sync_load_response;
- if (!handle->d->Start(&sync_load_response)) {
- response =
- ResourceResponse(request.url(), String(), 0, String(), String());
- // TODO(darin): what should the error code really be?
- error = ResourceError(net::kErrorDomain,
- net::ERR_FAILED,
- request.url().string(),
- String() /* localized description */);
- return;
- }
-
- KURL kurl = webkit_glue::GURLToKURL(sync_load_response.url);
-
- // TODO(tc): For file loads, we may want to include a more descriptive
- // status code or status text.
- const URLRequestStatus::Status& status = sync_load_response.status.status();
- if (status != URLRequestStatus::SUCCESS &&
- status != URLRequestStatus::HANDLED_EXTERNALLY) {
- response = ResourceResponse(kurl, String(), 0, String(), String());
- error = ResourceError(net::kErrorDomain,
- sync_load_response.status.os_error(),
- kurl.string(),
- String() /* localized description */);
- return;
- }
-
- response = MakeResourceResponse(kurl, sync_load_response);
-
- data.clear();
- data.append(sync_load_response.data.data(),
- sync_load_response.data.size());
-}
-
-// static
-bool ResourceHandle::willLoadFromCache(ResourceRequest& request) {
- //
- // This method is used to determine if a POST request can be repeated from
- // cache, but you cannot really know until you actually try to read from the
- // cache. Even if we checked now, something else could come along and wipe
- // out the cache entry by the time we fetch it.
- //
- // So, we always say yes here, which allows us to generate an ERR_CACHE_MISS
- // if the request cannot be serviced from cache. We force the 'DontLoad'
- // cache policy at this point to ensure that we never hit the network for
- // this request.
- //
- DCHECK(request.httpMethod() == "POST");
- request.setCachePolicy(ReturnCacheDataDontLoad);
- return true;
-}
-
-} // namespace WebCore
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index e075686..91152f4 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -14,10 +14,12 @@
#include "webkit/api/public/WebString.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugininfo.h"
+#include "webkit/glue/weburlloader_impl.h"
using WebKit::WebData;
using WebKit::WebPluginListBuilder;
using WebKit::WebThemeEngine;
+using WebKit::WebURLLoader;
namespace webkit_glue {
@@ -34,6 +36,10 @@ WebThemeEngine* WebKitClientImpl::themeEngine() {
#endif
}
+WebURLLoader* WebKitClientImpl::createURLLoader() {
+ return new WebURLLoaderImpl();
+}
+
void WebKitClientImpl::getPluginList(bool refresh,
WebPluginListBuilder* builder) {
std::vector<WebPluginInfo> plugins;
diff --git a/webkit/glue/webkitclient_impl.h b/webkit/glue/webkitclient_impl.h
index 679cb61..54f691c 100644
--- a/webkit/glue/webkitclient_impl.h
+++ b/webkit/glue/webkitclient_impl.h
@@ -21,6 +21,7 @@ class WebKitClientImpl : public WebKit::WebKitClient {
// WebKitClient methods (partial implementation):
virtual WebKit::WebThemeEngine* themeEngine();
+ virtual WebKit::WebURLLoader* createURLLoader();
virtual void getPluginList(bool refresh, WebKit::WebPluginListBuilder*);
virtual void decrementStatsCounter(const char* name);
virtual void incrementStatsCounter(const char* name);
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index 18cf347..0134c9a 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "config.h"
-#include "webkit/glue/webplugin_impl.h"
#include "Cursor.h"
#include "Document.h"
@@ -49,17 +48,23 @@
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "net/base/escape.h"
+#include "webkit/api/public/WebData.h"
+#include "webkit/api/public/WebHTTPBody.h"
#include "webkit/api/public/WebInputEvent.h"
#include "webkit/api/public/WebKit.h"
#include "webkit/api/public/WebKitClient.h"
#include "webkit/api/public/WebString.h"
#include "webkit/api/public/WebURL.h"
+#include "webkit/api/public/WebURLLoader.h"
+#include "webkit/api/public/WebURLLoaderClient.h"
+#include "webkit/api/public/WebURLResponse.h"
#include "webkit/glue/chrome_client_impl.h"
#include "webkit/glue/event_conversion.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/multipart_response_delegate.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webkit_glue.h"
+#include "webkit/glue/webplugin_impl.h"
#include "webkit/glue/plugins/plugin_host.h"
#include "webkit/glue/plugins/plugin_instance.h"
#include "webkit/glue/stacking_order_iterator.h"
@@ -67,27 +72,43 @@
#include "webkit/glue/webview_impl.h"
#include "googleurl/src/gurl.h"
-using WebKit::WebKeyboardEvent;
+using WebKit::WebData;
+using WebKit::WebHTTPBody;
using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
using WebKit::WebMouseEvent;
+using WebKit::WebString;
+using WebKit::WebURLError;
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderClient;
+using WebKit::WebURLRequest;
+using WebKit::WebURLResponse;
+using webkit_glue::MultipartResponseDelegate;
// This class handles individual multipart responses. It is instantiated when
// we receive HTTP status code 206 in the HTTP response. This indicates
// that the response could have multiple parts each separated by a boundary
// specified in the response header.
-class MultiPartResponseClient : public WebCore::ResourceHandleClient {
+class MultiPartResponseClient : public WebURLLoaderClient {
public:
MultiPartResponseClient(WebPluginResourceClient* resource_client)
: resource_client_(resource_client) {
Clear();
}
+ virtual void willSendRequest(
+ WebURLLoader*, WebURLRequest&, const WebURLResponse&) {}
+ virtual void didSendData(
+ WebURLLoader*, unsigned long long, unsigned long long) {}
+
// Called when the multipart parser encounters an embedded multipart
// response.
- virtual void didReceiveResponse(WebCore::ResourceHandle* handle,
- const WebCore::ResourceResponse& response) {
+ virtual void didReceiveResponse(
+ WebURLLoader*, const WebURLResponse& response) {
if (!MultipartResponseDelegate::ReadContentRanges(
- response, &byte_range_lower_bound_, &byte_range_upper_bound_)) {
+ response,
+ &byte_range_lower_bound_,
+ &byte_range_upper_bound_)) {
NOTREACHED();
return;
}
@@ -96,21 +117,23 @@ class MultiPartResponseClient : public WebCore::ResourceHandleClient {
}
// Receives individual part data from a multipart response.
- virtual void didReceiveData(WebCore::ResourceHandle* handle,
- const char* data, int data_size,
- int reserved) {
+ virtual void didReceiveData(
+ WebURLLoader*, const char* data, int data_size, long long) {
resource_client_->DidReceiveData(
data, data_size, byte_range_lower_bound_);
}
+ virtual void didFinishLoading(WebURLLoader*) {}
+ virtual void didFail(WebURLLoader*, const WebURLError&) {}
+
void Clear() {
- resource_response_ = WebCore::ResourceResponse();
+ resource_response_.reset();
byte_range_lower_bound_ = 0;
byte_range_upper_bound_ = 0;
}
private:
- WebCore::ResourceResponse resource_response_;
+ WebURLResponse resource_response_;
// The lower bound of the byte range.
int byte_range_lower_bound_;
// The upper bound of the byte range.
@@ -119,6 +142,32 @@ class MultiPartResponseClient : public WebCore::ResourceHandleClient {
WebPluginResourceClient* resource_client_;
};
+static std::wstring GetAllHeaders(const WebCore::ResourceResponse& response) {
+ std::wstring result;
+ const WebCore::String& status = response.httpStatusText();
+ if (status.isEmpty())
+ return result;
+
+ result.append(L"HTTP ");
+ result.append(FormatNumber(response.httpStatusCode()));
+ result.append(L" ");
+ result.append(webkit_glue::StringToStdWString(status));
+ result.append(L"\n");
+
+ WebCore::HTTPHeaderMap::const_iterator it =
+ response.httpHeaderFields().begin();
+ for (; it != response.httpHeaderFields().end(); ++it) {
+ if (!it->first.isEmpty() && !it->second.isEmpty()) {
+ result.append(webkit_glue::StringToStdWString(it->first));
+ result.append(L": ");
+ result.append(webkit_glue::StringToStdWString(it->second));
+ result.append(L"\n");
+ }
+ }
+
+ return result;
+}
+
WebPluginContainer::WebPluginContainer(WebPluginImpl* impl)
: impl_(impl),
ignore_response_error_(false) {
@@ -243,7 +292,7 @@ void WebPluginContainer::didReceiveResponse(
impl_->delegate_->DidReceiveManualResponse(
http_response_info.url,
base::SysWideToNativeMB(http_response_info.mime_type),
- base::SysWideToNativeMB(impl_->GetAllHeaders(response)),
+ base::SysWideToNativeMB(GetAllHeaders(response)),
http_response_info.expected_length,
http_response_info.last_modified);
}
@@ -404,17 +453,16 @@ bool WebPluginImpl::ExecuteScript(const std::string& url,
void WebPluginImpl::CancelResource(int id) {
for (size_t i = 0; i < clients_.size(); ++i) {
if (clients_[i].id == id) {
- if (clients_[i].handle) {
- clients_[i].handle->cancel();
+ if (clients_[i].loader.get()) {
+ clients_[i].loader->cancel();
RemoveClient(i);
}
-
return;
}
}
}
-bool WebPluginImpl::SetPostData(WebCore::ResourceRequest* request,
+bool WebPluginImpl::SetPostData(WebURLRequest* request,
const char *buf,
uint32 length) {
std::vector<std::string> names;
@@ -422,19 +470,26 @@ bool WebPluginImpl::SetPostData(WebCore::ResourceRequest* request,
std::vector<char> body;
bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body);
- for (size_t i = 0; i < names.size(); ++i)
- request->addHTTPHeaderField(webkit_glue::StdStringToString(names[i]),
- webkit_glue::StdStringToString(values[i]));
-
- WebCore::String content_type = request->httpContentType();
- if (content_type.isEmpty())
- request->setHTTPContentType("application/x-www-form-urlencoded");
+ for (size_t i = 0; i < names.size(); ++i) {
+ request->addHTTPHeaderField(webkit_glue::StdStringToWebString(names[i]),
+ webkit_glue::StdStringToWebString(values[i]));
+ }
- RefPtr<WebCore::FormData> data = WebCore::FormData::create();
- if (body.size())
- data->appendData(&body.front(), body.size());
+ WebString content_type_header = WebString::fromUTF8("Content-Type");
+ const WebString& content_type =
+ request->httpHeaderField(content_type_header);
+ if (content_type.isEmpty()) {
+ request->setHTTPHeaderField(
+ content_type_header,
+ WebString::fromUTF8("application/x-www-form-urlencoded"));
+ }
- request->setHTTPBody(data.release());
+ WebHTTPBody http_body;
+ if (body.size()) {
+ http_body.initialize();
+ http_body.appendData(WebData(&body[0], body.size()));
+ }
+ request->setHTTPBody(http_body);
return rv;
}
@@ -486,8 +541,8 @@ RoutingStatus WebPluginImpl::RouteToFrame(const char *method,
}
*completeURL = webkit_glue::KURLToGURL(complete_url_kurl);
- WebCore::ResourceRequest request(complete_url_kurl);
- request.setHTTPMethod(method);
+ WebURLRequest request(webkit_glue::KURLToWebURL(complete_url_kurl));
+ request.setHTTPMethod(WebString::fromUTF8(method));
if (len > 0) {
if (!is_file_data) {
if (!SetPostData(&request, buf, len)) {
@@ -503,7 +558,8 @@ RoutingStatus WebPluginImpl::RouteToFrame(const char *method,
return ROUTED;
}
}
- WebCore::FrameLoadRequest load_request(request);
+ WebCore::FrameLoadRequest load_request(
+ *webkit_glue::WebURLRequestToResourceRequest(&request));
load_request.setFrameName(str_target);
WebCore::FrameLoader *loader = frame()->loader();
// we actually don't know whether usergesture is true or false,
@@ -820,10 +876,10 @@ NPObject* WebPluginImpl::GetPluginScriptableObject() {
return delegate_->GetPluginScriptableObject();
}
-WebPluginResourceClient* WebPluginImpl::GetClientFromHandle(
- WebCore::ResourceHandle* handle) {
+WebPluginResourceClient* WebPluginImpl::GetClientFromLoader(
+ WebURLLoader* loader) {
for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].handle.get() == handle)
+ if (clients_[i].loader.get() == loader)
return clients_[i].client;
}
@@ -832,54 +888,34 @@ WebPluginResourceClient* WebPluginImpl::GetClientFromHandle(
}
-void WebPluginImpl::willSendRequest(WebCore::ResourceHandle* handle,
- WebCore::ResourceRequest& request,
- const WebCore::ResourceResponse&) {
- WebPluginResourceClient* client = GetClientFromHandle(handle);
- if (client) {
- GURL gurl(webkit_glue::KURLToGURL(request.url()));
- client->WillSendRequest(gurl);
- }
+void WebPluginImpl::willSendRequest(WebURLLoader* loader,
+ WebURLRequest& request,
+ const WebURLResponse&) {
+ WebPluginResourceClient* client = GetClientFromLoader(loader);
+ if (client)
+ client->WillSendRequest(request.url());
}
-std::wstring WebPluginImpl::GetAllHeaders(
- const WebCore::ResourceResponse& response) {
- std::wstring result;
- const WebCore::String& status = response.httpStatusText();
- if (status.isEmpty())
- return result;
-
- result.append(L"HTTP ");
- result.append(FormatNumber(response.httpStatusCode()));
- result.append(L" ");
- result.append(webkit_glue::StringToStdWString(status));
- result.append(L"\n");
-
- WebCore::HTTPHeaderMap::const_iterator it =
- response.httpHeaderFields().begin();
- for (; it != response.httpHeaderFields().end(); ++it) {
- if (!it->first.isEmpty() && !it->second.isEmpty()) {
- result.append(webkit_glue::StringToStdWString(it->first));
- result.append(L": ");
- result.append(webkit_glue::StringToStdWString(it->second));
- result.append(L"\n");
- }
- }
-
- return result;
+void WebPluginImpl::didSendData(WebURLLoader* loader,
+ unsigned long long bytes_sent,
+ unsigned long long total_bytes_to_be_sent) {
}
-void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle,
- const WebCore::ResourceResponse& response) {
+void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
+ const WebURLResponse& response) {
static const int kHttpPartialResponseStatusCode = 206;
static const int kHttpResponseSuccessStatusCode = 200;
- WebPluginResourceClient* client = GetClientFromHandle(handle);
+ WebPluginResourceClient* client = GetClientFromLoader(loader);
if (!client)
return;
+ const WebCore::ResourceResponse& resource_response =
+ *webkit_glue::WebURLResponseToResourceResponse(&response);
+
WebPluginContainer::HttpResponseInfo http_response_info;
- WebPluginContainer::ReadHttpResponseInfo(response, &http_response_info);
+ WebPluginContainer::ReadHttpResponseInfo(resource_response,
+ &http_response_info);
bool cancel = false;
bool request_is_seekable = true;
@@ -897,7 +933,7 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle,
// continue to remain valid.
// 2. Create a new plugin instance and notify it about the response
// received here.
- if (!ReinitializePluginForResponse(handle)) {
+ if (!ReinitializePluginForResponse(loader)) {
NOTREACHED();
return;
}
@@ -911,7 +947,7 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle,
// Create a new resource client for this request.
for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].handle.get() == handle) {
+ if (clients_[i].loader.get() == loader) {
WebPluginResourceClient* resource_client =
delegate_->CreateResourceClient(clients_[i].id,
plugin_url_.spec().c_str(),
@@ -928,13 +964,13 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle,
client->DidReceiveResponse(
base::SysWideToNativeMB(http_response_info.mime_type),
- base::SysWideToNativeMB(GetAllHeaders(response)),
+ base::SysWideToNativeMB(GetAllHeaders(resource_response)),
http_response_info.expected_length,
http_response_info.last_modified, request_is_seekable, &cancel);
if (cancel) {
- handle->cancel();
- RemoveClient(handle);
+ loader->cancel();
+ RemoveClient(loader);
return;
}
@@ -943,41 +979,41 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle,
// fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF
// destroy the stream and invoke the NPP_DestroyStream function on the
// plugin if the HTTP request fails.
- const WebCore::String& protocol_scheme = response.url().protocol();
- if ((protocol_scheme == "http") || (protocol_scheme == "https")) {
+ const GURL& url = response.url();
+ if (url.SchemeIs("http") || url.SchemeIs("https")) {
if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) {
// The plugin instance could be in the process of deletion here.
// Verify if the WebPluginResourceClient instance still exists before
// use.
- WebPluginResourceClient* resource_client = GetClientFromHandle(handle);
+ WebPluginResourceClient* resource_client = GetClientFromLoader(loader);
if (resource_client) {
- handle->cancel();
+ loader->cancel();
resource_client->DidFail();
- RemoveClient(handle);
+ RemoveClient(loader);
}
}
}
}
-void WebPluginImpl::didReceiveData(WebCore::ResourceHandle* handle,
+void WebPluginImpl::didReceiveData(WebURLLoader* loader,
const char *buffer,
- int length, int) {
- WebPluginResourceClient* client = GetClientFromHandle(handle);
- if (client) {
- MultiPartResponseHandlerMap::iterator index =
- multi_part_response_map_.find(client);
- if (index != multi_part_response_map_.end()) {
- MultipartResponseDelegate* multi_part_handler = (*index).second;
- DCHECK(multi_part_handler != NULL);
- multi_part_handler->OnReceivedData(buffer, length);
- } else {
- client->DidReceiveData(buffer, length, 0);
- }
+ int length, long long) {
+ WebPluginResourceClient* client = GetClientFromLoader(loader);
+ if (!client)
+ return;
+ MultiPartResponseHandlerMap::iterator index =
+ multi_part_response_map_.find(client);
+ if (index != multi_part_response_map_.end()) {
+ MultipartResponseDelegate* multi_part_handler = (*index).second;
+ DCHECK(multi_part_handler != NULL);
+ multi_part_handler->OnReceivedData(buffer, length);
+ } else {
+ client->DidReceiveData(buffer, length, 0);
}
}
-void WebPluginImpl::didFinishLoading(WebCore::ResourceHandle* handle) {
- WebPluginResourceClient* client = GetClientFromHandle(handle);
+void WebPluginImpl::didFinishLoading(WebURLLoader* loader) {
+ WebPluginResourceClient* client = GetClientFromLoader(loader);
if (client) {
MultiPartResponseHandlerMap::iterator index =
multi_part_response_map_.find(client);
@@ -991,25 +1027,25 @@ void WebPluginImpl::didFinishLoading(WebCore::ResourceHandle* handle) {
client->DidFinishLoading();
}
- RemoveClient(handle);
+ RemoveClient(loader);
}
-void WebPluginImpl::didFail(WebCore::ResourceHandle* handle,
- const WebCore::ResourceError&) {
- WebPluginResourceClient* client = GetClientFromHandle(handle);
+void WebPluginImpl::didFail(WebURLLoader* loader,
+ const WebURLError&) {
+ WebPluginResourceClient* client = GetClientFromLoader(loader);
if (client)
client->DidFail();
- RemoveClient(handle);
+ RemoveClient(loader);
}
void WebPluginImpl::RemoveClient(size_t i) {
clients_.erase(clients_.begin() + i);
}
-void WebPluginImpl::RemoveClient(WebCore::ResourceHandle* handle) {
+void WebPluginImpl::RemoveClient(WebURLLoader* loader) {
for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].handle.get() == handle) {
+ if (clients_[i].loader.get() == loader) {
RemoveClient(i);
return;
}
@@ -1141,18 +1177,19 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id,
return false;
}
- WebCore::KURL kurl = webkit_glue::GURLToKURL(url);
-
ClientInfo info;
info.id = resource_id;
info.client = client;
- info.request.setURL(kurl);
+ info.request.initialize();
+ info.request.setURL(url);
info.request.setRequestorProcessID(delegate_->GetProcessId());
- info.request.setTargetType(WebCore::ResourceRequest::TargetIsObject);
- info.request.setHTTPMethod(method);
+ info.request.setTargetType(WebURLRequest::TargetIsObject);
+ info.request.setHTTPMethod(WebString::fromUTF8(method));
- if (range_info)
- info.request.addHTTPHeaderField("Range", range_info);
+ if (range_info) {
+ info.request.addHTTPHeaderField(WebString::fromUTF8("Range"),
+ WebString::fromUTF8(range_info));
+ }
WebCore::String referrer;
// GetURL/PostURL requests initiated explicitly by plugins should specify the
@@ -1163,8 +1200,11 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id,
referrer = frame()->loader()->outgoingReferrer();
}
- if (!WebCore::FrameLoader::shouldHideReferrer(kurl, referrer))
- info.request.setHTTPReferrer(referrer);
+ if (!WebCore::FrameLoader::shouldHideReferrer(webkit_glue::GURLToKURL(url),
+ referrer)) {
+ info.request.setHTTPHeaderField(WebString::fromUTF8("Referer"),
+ webkit_glue::StringToWebString(referrer));
+ }
if (strcmp(method, "POST") == 0) {
// Adds headers or form data to a request. This must be called before
@@ -1175,13 +1215,15 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id,
// Sets the routing id to associate the ResourceRequest with the RenderView.
WebCore::ResourceResponse response;
frame()->loader()->client()->dispatchWillSendRequest(
- NULL, 0, info.request, response);
+ NULL,
+ 0,
+ *webkit_glue::WebURLRequestToMutableResourceRequest(&info.request),
+ response);
- info.handle = WebCore::ResourceHandle::create(
- info.request, this, NULL, false, false);
- if (!info.handle) {
+ info.loader.reset(WebKit::webKitClient()->createURLLoader());
+ if (!info.loader.get())
return false;
- }
+ info.loader->loadAsynchronously(info.request, this);
clients_.push_back(info);
return true;
@@ -1212,7 +1254,7 @@ void WebPluginImpl::InitiateHTTPRangeRequest(const char* url,
}
void WebPluginImpl::HandleHttpMultipartResponse(
- const WebCore::ResourceResponse& response,
+ const WebURLResponse& response,
WebPluginResourceClient* client) {
std::string multipart_boundary;
if (!MultipartResponseDelegate::ReadMultipartBoundary(
@@ -1235,7 +1277,7 @@ void WebPluginImpl::HandleHttpMultipartResponse(
}
bool WebPluginImpl::ReinitializePluginForResponse(
- WebCore::ResourceHandle* response_handle) {
+ WebURLLoader* loader) {
WebFrameImpl* web_frame = WebFrameImpl::FromFrame(frame());
if (!web_frame)
return false;
@@ -1247,7 +1289,7 @@ bool WebPluginImpl::ReinitializePluginForResponse(
WebPluginContainer* container_widget = widget_;
// Destroy the current plugin instance.
- TearDownPluginInstance(response_handle);
+ TearDownPluginInstance(loader);
widget_ = container_widget;
webframe_ = web_frame;
@@ -1300,7 +1342,7 @@ void WebPluginImpl::ArrayToVector(int total_values, char** values,
}
void WebPluginImpl::TearDownPluginInstance(
- WebCore::ResourceHandle* response_handle_to_ignore) {
+ WebURLLoader* loader_to_ignore) {
// The frame maintains a list of JSObjects which are related to this
// plugin. Tell the frame we're gone so that it can invalidate all
// of those sub JSObjects.
@@ -1322,13 +1364,13 @@ void WebPluginImpl::TearDownPluginInstance(
while (client_index != clients_.end()) {
ClientInfo& client_info = *client_index;
- if (response_handle_to_ignore == client_info.handle) {
+ if (loader_to_ignore == client_info.loader) {
client_index++;
continue;
}
- if (client_info.handle)
- client_info.handle->cancel();
+ if (client_info.loader.get())
+ client_info.loader->cancel();
WebPluginResourceClient* resource_client = client_info.client;
client_index = clients_.erase(client_index);
diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h
index 223e96d..1127a73 100644
--- a/webkit/glue/webplugin_impl.h
+++ b/webkit/glue/webplugin_impl.h
@@ -9,40 +9,42 @@
#include <map>
#include <vector>
-#include "config.h"
-#include "base/compiler_specific.h"
-#include "base/gfx/native_widget_types.h"
-
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "ResourceRequest.h"
#include "Widget.h"
-MSVC_POP_WARNING();
#include "base/basictypes.h"
+#include "base/gfx/native_widget_types.h"
+#include "base/linked_ptr.h"
+#include "webkit/api/public/WebURLLoaderClient.h"
+#include "webkit/api/public/WebURLRequest.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/webplugin.h"
+
class WebFrameImpl;
class WebPluginDelegate;
class WebPluginImpl;
-class MultipartResponseDelegate;
namespace WebCore {
- class Event;
- class Frame;
- class HTMLPlugInElement;
- class IntRect;
- class KeyboardEvent;
- class KURL;
- class MouseEvent;
- class ResourceHandle;
- class ResourceError;
- class ResourceResponse;
- class ScrollView;
- class String;
- class Widget;
+class Event;
+class Frame;
+class HTMLPlugInElement;
+class IntRect;
+class KeyboardEvent;
+class KURL;
+class MouseEvent;
+class ResourceError;
+class ResourceResponse;
+class ScrollView;
+class String;
+class Widget;
+}
+
+namespace WebKit {
+class WebURLResponse;
+}
+
+namespace webkit_glue {
+class MultipartResponseDelegate;
}
// Implements WebCore::Widget functions that WebPluginImpl needs. This class
@@ -114,7 +116,7 @@ class WebPluginContainer : public WebCore::Widget {
// after changing out of WebCore types, to a delegate. The delegate will
// be in a different process.
class WebPluginImpl : public WebPlugin,
- public WebCore::ResourceHandleClient {
+ public WebKit::WebURLLoaderClient {
public:
// Creates a WebPlugin instance, as long as the delegate's initialization
// succeeds. If it fails, the delegate is deleted and NULL is returned.
@@ -133,7 +135,7 @@ class WebPluginImpl : public WebPlugin,
virtual NPObject* GetPluginScriptableObject();
// Helper function for sorting post data.
- static bool SetPostData(WebCore::ResourceRequest* request,
+ static bool SetPostData(WebKit::WebURLRequest* request,
const char* buf,
uint32 length);
@@ -239,27 +241,28 @@ class WebPluginImpl : public WebPlugin,
// Destroys the plugin instance.
// The response_handle_to_ignore parameter if not NULL indicates the
// resource handle to be left valid during plugin shutdown.
- void TearDownPluginInstance(
- WebCore::ResourceHandle* response_handle_to_ignore);
+ void TearDownPluginInstance(WebKit::WebURLLoader* loader_to_ignore);
WebCore::ScrollView* parent() const;
- // ResourceHandleClient implementation. We implement this interface in the
+ // WebURLLoaderClient implementation. We implement this interface in the
// renderer process, and then use the simple WebPluginResourceClient interface
// to relay the callbacks to the plugin.
- void willSendRequest(WebCore::ResourceHandle* handle,
- WebCore::ResourceRequest& request,
- const WebCore::ResourceResponse&);
-
- void didReceiveResponse(WebCore::ResourceHandle* handle,
- const WebCore::ResourceResponse& response);
- void didReceiveData(WebCore::ResourceHandle* handle, const char *buffer,
- int length, int);
- void didFinishLoading(WebCore::ResourceHandle* handle);
- void didFail(WebCore::ResourceHandle* handle, const WebCore::ResourceError&);
+ virtual void willSendRequest(WebKit::WebURLLoader* loader,
+ WebKit::WebURLRequest& request,
+ const WebKit::WebURLResponse&);
+ virtual void didSendData(WebKit::WebURLLoader* loader,
+ unsigned long long bytes_sent,
+ unsigned long long total_bytes_to_be_sent);
+ virtual void didReceiveResponse(WebKit::WebURLLoader* loader,
+ const WebKit::WebURLResponse& response);
+ virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer,
+ int length, long long total_length);
+ virtual void didFinishLoading(WebKit::WebURLLoader* loader);
+ virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError&);
// Helper function
- WebPluginResourceClient* GetClientFromHandle(WebCore::ResourceHandle* handle);
+ WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader);
// Helper function to remove the stored information about a resource
// request given its index in m_clients.
@@ -267,10 +270,7 @@ class WebPluginImpl : public WebPlugin,
// Helper function to remove the stored information about a resource
// request given a handle.
- void RemoveClient(WebCore::ResourceHandle* handle);
-
- // Returns all the response headers in one string, including the status code.
- std::wstring GetAllHeaders(const WebCore::ResourceResponse& response);
+ void RemoveClient(WebKit::WebURLLoader* loader);
WebCore::Frame* frame() { return webframe_ ? webframe_->frame() : NULL; }
@@ -299,7 +299,7 @@ class WebPluginImpl : public WebPlugin,
// Handles HTTP multipart responses, i.e. responses received with a HTTP
// status code of 206.
- void HandleHttpMultipartResponse(const WebCore::ResourceResponse& response,
+ void HandleHttpMultipartResponse(const WebKit::WebURLResponse& response,
WebPluginResourceClient* client);
void HandleURLRequestInternal(const char *method, bool is_javascript_url,
@@ -310,8 +310,8 @@ class WebPluginImpl : public WebPlugin,
bool use_plugin_src_as_referrer);
// Tears down the existing plugin instance and creates a new plugin instance
- // to handle the response identified by the response_handle parameter.
- bool ReinitializePluginForResponse(WebCore::ResourceHandle* response_handle);
+ // to handle the response identified by the loader parameter.
+ bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader);
// Notifies us that the visibility of the plugin has changed.
void UpdateVisibility();
@@ -323,8 +323,8 @@ class WebPluginImpl : public WebPlugin,
struct ClientInfo {
int id;
WebPluginResourceClient* client;
- WebCore::ResourceRequest request;
- RefPtr<WebCore::ResourceHandle> handle;
+ WebKit::WebURLRequest request;
+ linked_ptr<WebKit::WebURLLoader> loader;
};
std::vector<ClientInfo> clients_;
@@ -338,7 +338,8 @@ class WebPluginImpl : public WebPlugin,
WebPluginContainer* widget_;
- typedef std::map<WebPluginResourceClient*, MultipartResponseDelegate*>
+ typedef std::map<WebPluginResourceClient*,
+ webkit_glue::MultipartResponseDelegate*>
MultiPartResponseHandlerMap;
// Tracks HTTP multipart response handlers instantiated for
// a WebPluginResourceClient instance.
diff --git a/webkit/glue/webplugin_impl_unittest.cc b/webkit/glue/webplugin_impl_unittest.cc
index b518361..b6c62f6 100644
--- a/webkit/glue/webplugin_impl_unittest.cc
+++ b/webkit/glue/webplugin_impl_unittest.cc
@@ -4,18 +4,21 @@
#include "config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "base/compiler_specific.h"
-
-MSVC_PUSH_WARNING_LEVEL(0);
-#include "ResourceRequest.h"
-#include "CString.h"
-MSVC_POP_WARNING();
+// Avoid collisions with the LOG macro
+#include <wtf/Assertions.h>
#undef LOG
+#include "base/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/api/public/WebString.h"
+#include "webkit/api/public/WebURLRequest.h"
+#include "webkit/glue/glue_util.h"
#include "webkit/glue/webplugin_impl.h"
+using WebKit::WebHTTPBody;
+using WebKit::WebString;
+using WebKit::WebURLRequest;
+
namespace {
class WebPluginImplTest : public testing::Test {
@@ -30,6 +33,34 @@ std::ostream& operator<<(std::ostream& out, const WebCore::String& str)
return out << str.latin1().data();
}
+static std::string GetHeader(const WebURLRequest& request, const char* name) {
+ std::string result;
+ TrimWhitespace(
+ webkit_glue::WebStringToStdString(
+ request.httpHeaderField(WebString::fromUTF8(name))),
+ TRIM_ALL,
+ &result);
+ return result;
+}
+
+static std::string GetBodyText(const WebURLRequest& request) {
+ const WebHTTPBody& body = request.httpBody();
+ if (body.isNull())
+ return std::string();
+
+ std::string result;
+ size_t i = 0;
+ WebHTTPBody::Element element;
+ while (body.elementAt(i++, element)) {
+ if (element.type == WebHTTPBody::Element::TypeData) {
+ result.append(element.data.data(), element.data.size());
+ } else {
+ NOTREACHED() << "unexpected element type encountered!";
+ }
+ }
+ return result;
+}
+
// The Host functions for NPN_PostURL and NPN_PostURLNotify
// need to parse out some HTTP headers. Make sure it works
// with the following tests
@@ -37,46 +68,47 @@ std::ostream& operator<<(std::ostream& out, const WebCore::String& str)
TEST(WebPluginImplTest, PostParserSimple) {
// Test a simple case with headers & data
const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ(0U, request.httpHeaderField("Content-length").length());
- EXPECT_EQ("abcdefghij", request.httpBody()->flattenToString());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
+ EXPECT_EQ("abcdefghij", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserLongHeader) {
// Test a simple case with long headers
const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ(100U, request.httpHeaderField("foo").stripWhiteSpace().length());
+ EXPECT_EQ(100U, GetHeader(request, "foo").length());
}
TEST(WebPluginImplTest, PostParserManyHeaders) {
// Test a simple case with long headers
const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("h1", request.httpHeaderField("h1").stripWhiteSpace());
- EXPECT_EQ("h2", request.httpHeaderField("h2").stripWhiteSpace());
- EXPECT_EQ("h3", request.httpHeaderField("h3").stripWhiteSpace());
- EXPECT_EQ("h4", request.httpHeaderField("h4").stripWhiteSpace());
- EXPECT_EQ("h5", request.httpHeaderField("h5").stripWhiteSpace());
- EXPECT_EQ("h6", request.httpHeaderField("h6").stripWhiteSpace());
- EXPECT_EQ("h7", request.httpHeaderField("h7").stripWhiteSpace());
- EXPECT_EQ("h8", request.httpHeaderField("h8").stripWhiteSpace());
- EXPECT_EQ("h9", request.httpHeaderField("h9").stripWhiteSpace());
- EXPECT_EQ("h10", request.httpHeaderField("h10").stripWhiteSpace());
- WebCore::FormData *form_data = request.httpBody();
- WebCore::String string_data = form_data->flattenToString();
- EXPECT_EQ(string_data, "body");
+ EXPECT_EQ("h1", GetHeader(request, "h1"));
+ EXPECT_EQ("h2", GetHeader(request, "h2"));
+ EXPECT_EQ("h3", GetHeader(request, "h3"));
+ EXPECT_EQ("h4", GetHeader(request, "h4"));
+ EXPECT_EQ("h5", GetHeader(request, "h5"));
+ EXPECT_EQ("h6", GetHeader(request, "h6"));
+ EXPECT_EQ("h7", GetHeader(request, "h7"));
+ EXPECT_EQ("h8", GetHeader(request, "h8"));
+ EXPECT_EQ("h9", GetHeader(request, "h9"));
+ EXPECT_EQ("h10", GetHeader(request, "h10"));
+ EXPECT_EQ("body", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserDuplicateHeaders) {
@@ -84,7 +116,8 @@ TEST(WebPluginImplTest, PostParserDuplicateHeaders) {
// What value gets returned doesn't really matter. It shouldn't error
// out.
const char *ex1 = "h1:h1\nh1:h2\n\nbody";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
@@ -93,43 +126,47 @@ TEST(WebPluginImplTest, PostParserDuplicateHeaders) {
TEST(WebPluginImplTest, PostParserNoHeaders) {
// Test a simple case with no headers but with data
const char *ex1 = "\nabcdefghij";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ(0U, request.httpHeaderField("foo").length());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ(0U, request.httpHeaderField("Content-length").length());
- EXPECT_EQ("abcdefghij", request.httpBody()->flattenToString());
+ EXPECT_EQ(0U, GetHeader(request, "foo").length());
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
+ EXPECT_EQ("abcdefghij", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserNoBody) {
// Test a simple case with headers and no body
const char *ex1 = "Foo:bar\n\n";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ(0U, request.httpHeaderField("Content-length").length());
- EXPECT_EQ(0U, request.httpBody()->flattenToString().length());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
+ EXPECT_EQ(0U, GetBodyText(request).length());
}
TEST(WebPluginImplTest, PostParserBodyWithNewLines) {
// Test a simple case with headers and no body
const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ(request.httpBody()->flattenToString(), "\n\nabcdefg\n\nabcdefg");
+ EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg");
}
TEST(WebPluginImplTest, PostParserErrorNoBody) {
// Test with headers and no body
const char *ex1 = "Foo:bar\n";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
@@ -138,7 +175,8 @@ TEST(WebPluginImplTest, PostParserErrorNoBody) {
TEST(WebPluginImplTest, PostParserErrorEmpty) {
// Test with an empty string
const char *ex1 = "";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
@@ -147,36 +185,39 @@ TEST(WebPluginImplTest, PostParserErrorEmpty) {
TEST(WebPluginImplTest, PostParserEmptyName) {
// Test an error case with an empty header name field
const char *ex1 = "foo:bar\n:blat\n\nbody";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ("body", request.httpBody()->flattenToString());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ("body", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserEmptyValue) {
// Test an error case with an empty value field
const char *ex1 = "foo:bar\nbar:\n\nbody";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ("body", request.httpBody()->flattenToString());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ("body", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserCRLF) {
// Test an error case with an empty value field
const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2";
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
static_cast<uint32>(strlen(ex1)));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ("body\r\n\r\nbody2", request.httpBody()->flattenToString());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request));
}
TEST(WebPluginImplTest, PostParserBodyWithBinaryData) {
@@ -186,19 +227,19 @@ TEST(WebPluginImplTest, PostParserBodyWithBinaryData) {
memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data,
sizeof(binary_data));
- WebCore::ResourceRequest request;
+ WebURLRequest request;
+ request.initialize();
bool rv = WebPluginImpl::SetPostData(&request, ex1,
sizeof(ex1)/sizeof(ex1[0]));
EXPECT_EQ(true, rv);
- EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace());
- EXPECT_EQ(0U, request.httpHeaderField("bar").length());
- EXPECT_EQ(0U, request.httpHeaderField("Content-length").length());
+ EXPECT_EQ("bar", GetHeader(request, "foo"));
+ EXPECT_EQ(0U, GetHeader(request, "bar").length());
+ EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
- Vector<char> expected_data;
- request.httpBody()->flatten(expected_data);
+ std::string body = GetBodyText(request);
- EXPECT_EQ(0xF0, (unsigned char)expected_data[0]);
- EXPECT_EQ(0xFF, (unsigned char)expected_data[1]);
- EXPECT_EQ(0xFF, (unsigned char)expected_data[2]);
- EXPECT_EQ(0xFF, (unsigned char)expected_data[3]);
+ EXPECT_EQ(0xF0, (unsigned char)body[0]);
+ EXPECT_EQ(0xFF, (unsigned char)body[1]);
+ EXPECT_EQ(0xFF, (unsigned char)body[2]);
+ EXPECT_EQ(0xFF, (unsigned char)body[3]);
}
diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc
new file mode 100644
index 0000000..1780014
--- /dev/null
+++ b/webkit/glue/weburlloader_impl.cc
@@ -0,0 +1,502 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// An implementation of WebURLLoader in terms of ResourceLoaderBridge.
+
+#include "webkit/glue/weburlloader_impl.h"
+
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "net/base/data_url.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/http/http_response_headers.h"
+#include "webkit/api/public/WebHTTPHeaderVisitor.h"
+#include "webkit/api/public/WebURL.h"
+#include "webkit/api/public/WebURLError.h"
+#include "webkit/api/public/WebURLLoaderClient.h"
+#include "webkit/api/public/WebURLRequest.h"
+#include "webkit/api/public/WebURLResponse.h"
+#include "webkit/glue/glue_util.h"
+#include "webkit/glue/webkit_glue.h"
+
+using base::Time;
+using base::TimeDelta;
+using WebKit::WebData;
+using WebKit::WebHTTPBody;
+using WebKit::WebHTTPHeaderVisitor;
+using WebKit::WebString;
+using WebKit::WebURLError;
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderClient;
+using WebKit::WebURLRequest;
+using WebKit::WebURLResponse;
+
+namespace webkit_glue {
+
+namespace {
+
+class HeaderFlattener : public WebHTTPHeaderVisitor {
+ public:
+ explicit HeaderFlattener(int load_flags)
+ : load_flags_(load_flags),
+ has_accept_header_(false) {
+ }
+
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ // TODO(darin): is UTF-8 really correct here? It is if the strings are
+ // already ASCII (i.e., if they are already escaped properly).
+ const std::string& name_utf8 = WebStringToStdString(name);
+ const std::string& value_utf8 = WebStringToStdString(value);
+
+ // Skip over referrer headers found in the header map because we already
+ // pulled it out as a separate parameter. We likewise prune the UA since
+ // that will be added back by the network layer.
+ if (LowerCaseEqualsASCII(name_utf8, "referer") ||
+ LowerCaseEqualsASCII(name_utf8, "user-agent"))
+ return;
+
+ // Skip over "Cache-Control: max-age=0" header if the corresponding
+ // load flag is already specified. FrameLoader sets both the flag and
+ // the extra header -- the extra header is redundant since our network
+ // implementation will add the necessary headers based on load flags.
+ // See http://code.google.com/p/chromium/issues/detail?id=3434.
+ if ((load_flags_ & net::LOAD_VALIDATE_CACHE) &&
+ LowerCaseEqualsASCII(name_utf8, "cache-control") &&
+ LowerCaseEqualsASCII(value_utf8, "max-age=0"))
+ return;
+
+ if (LowerCaseEqualsASCII(name_utf8, "accept"))
+ has_accept_header_ = true;
+
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append(name_utf8 + ": " + value_utf8);
+ }
+
+ const std::string& GetBuffer() {
+ // In some cases, WebKit doesn't add an Accept header, but not having the
+ // header confuses some web servers. See bug 808613.
+ if (!has_accept_header_) {
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append("Accept: */*");
+ has_accept_header_ = true;
+ }
+ return buffer_;
+ }
+
+ private:
+ int load_flags_;
+ std::string buffer_;
+ bool has_accept_header_;
+};
+
+ResourceType::Type FromTargetType(WebURLRequest::TargetType type) {
+ switch (type) {
+ case WebURLRequest::TargetIsMainFrame:
+ return ResourceType::MAIN_FRAME;
+ case WebURLRequest::TargetIsSubFrame:
+ return ResourceType::SUB_FRAME;
+ case WebURLRequest::TargetIsSubResource:
+ return ResourceType::SUB_RESOURCE;
+ case WebURLRequest::TargetIsObject:
+ return ResourceType::OBJECT;
+ case WebURLRequest::TargetIsMedia:
+ return ResourceType::MEDIA;
+ default:
+ NOTREACHED();
+ return ResourceType::SUB_RESOURCE;
+ }
+}
+
+// Extracts the information from a data: url.
+bool GetInfoFromDataURL(const GURL& url,
+ ResourceLoaderBridge::ResponseInfo* info,
+ std::string* data, URLRequestStatus* status) {
+ std::string mime_type;
+ std::string charset;
+ if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
+ *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0);
+ info->request_time = Time::Now();
+ info->response_time = Time::Now();
+ info->headers = NULL;
+ info->mime_type.swap(mime_type);
+ info->charset.swap(charset);
+ info->security_info.clear();
+ info->content_length = -1;
+
+ return true;
+ }
+
+ *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL);
+ return false;
+}
+
+void PopulateURLResponse(
+ const GURL& url,
+ const ResourceLoaderBridge::ResponseInfo& info,
+ WebURLResponse* response) {
+ response->setURL(url);
+ response->setMIMEType(StdStringToWebString(info.mime_type));
+ response->setTextEncodingName(StdStringToWebString(info.charset));
+ response->setExpectedContentLength(info.content_length);
+ response->setSecurityInfo(info.security_info);
+ response->setAppCacheID(info.app_cache_id);
+
+ const net::HttpResponseHeaders* headers = info.headers;
+ if (!headers)
+ return;
+
+ response->setHTTPStatusCode(headers->response_code());
+ response->setHTTPStatusText(StdStringToWebString(headers->GetStatusText()));
+
+ // TODO(darin): We should leverage HttpResponseHeaders for this, and this
+ // should be using the same code as ResourceDispatcherHost.
+ // TODO(jungshik): Figure out the actual value of the referrer charset and
+ // pass it to GetSuggestedFilename.
+ std::string value;
+ if (headers->EnumerateHeader(NULL, "content-disposition", &value)) {
+ response->setSuggestedFileName(WideToUTF16Hack(
+ net::GetSuggestedFilename(url, value, "", std::wstring())));
+ }
+
+ Time time_val;
+ if (headers->GetLastModifiedValue(&time_val))
+ response->setLastModifiedDate(time_val.ToDoubleT());
+
+ // Compute expiration date
+ TimeDelta freshness_lifetime =
+ headers->GetFreshnessLifetime(info.response_time);
+ if (freshness_lifetime != TimeDelta()) {
+ Time now = Time::Now();
+ TimeDelta current_age =
+ headers->GetCurrentAge(info.request_time, info.response_time, now);
+ time_val = now + freshness_lifetime - current_age;
+
+ response->setExpirationDate(time_val.ToDoubleT());
+ } else {
+ // WebKit uses 0 as a special expiration date that means never expire.
+ // 1 is a small enough value to let it always expire.
+ response->setExpirationDate(1);
+ }
+
+ // Build up the header map.
+ void* iter = NULL;
+ std::string name;
+ while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ response->addHTTPHeaderField(StdStringToWebString(name),
+ StdStringToWebString(value));
+ }
+}
+
+} // namespace
+
+WebURLLoaderImpl::WebURLLoaderImpl()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
+ client_(NULL) {
+}
+
+WebURLLoaderImpl::~WebURLLoaderImpl() {
+}
+
+void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request,
+ WebURLResponse& response,
+ WebURLError& error,
+ WebData& data) {
+ ResourceLoaderBridge::SyncLoadResponse sync_load_response;
+ Start(request, &sync_load_response);
+
+ const GURL& final_url = sync_load_response.url;
+
+ // TODO(tc): For file loads, we may want to include a more descriptive
+ // status code or status text.
+ const URLRequestStatus::Status& status = sync_load_response.status.status();
+ if (status != URLRequestStatus::SUCCESS &&
+ status != URLRequestStatus::HANDLED_EXTERNALLY) {
+ response.setURL(final_url);
+ error.domain = WebString::fromUTF8(net::kErrorDomain);
+ error.reason = sync_load_response.status.os_error();
+ error.unreachableURL = final_url;
+ return;
+ }
+
+ PopulateURLResponse(final_url, sync_load_response, &response);
+
+ data.assign(sync_load_response.data.data(),
+ sync_load_response.data.size());
+}
+
+void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request,
+ WebURLLoaderClient* client) {
+ DCHECK(!client_);
+
+ client_ = client;
+ Start(request, NULL);
+}
+
+void WebURLLoaderImpl::cancel() {
+ // The bridge will still send OnCompletedRequest, which will deref() us,
+ // so we don't do that here.
+ if (bridge_.get())
+ bridge_->Cancel();
+
+ // Ensure that we do not notify the multipart delegate anymore as it has
+ // its own pointer to the client.
+ multipart_delegate_.reset();
+
+ // Do not make any further calls to the client.
+ client_ = NULL;
+}
+
+void WebURLLoaderImpl::setDefersLoading(bool value) {
+ if (bridge_.get())
+ bridge_->SetDefersLoading(value);
+}
+
+void WebURLLoaderImpl::OnUploadProgress(uint64 position, uint64 size) {
+ if (client_)
+ client_->didSendData(this, position, size);
+}
+
+void WebURLLoaderImpl::OnReceivedRedirect(const GURL& new_url) {
+ if (!client_)
+ return;
+
+ // TODO(darin): We lack sufficient information to construct the
+ // actual redirect response, so we just simulate it here.
+ WebURLResponse response(url_);
+
+ // TODO(darin): We lack sufficient information to construct the
+ // actual request that resulted from the redirect, so we just
+ // report a GET navigation to the new location.
+ WebURLRequest new_request(new_url);
+
+ url_ = new_url;
+ client_->willSendRequest(this, new_request, response);
+
+ // TODO(darin): since new_request is sent as a mutable reference, it is
+ // possible that willSendRequest may have modified it.
+ //
+ // andresca on #webkit confirms that that is intentional, so we'll need
+ // to rework the ResourceLoaderBridge to give us control over what URL
+ // is really loaded (and with what headers) when a redirect is encountered.
+ // TODO(darin): we fail this assertion in some layout tests!
+ //DCHECK(GURL(new_request.url()) == new_url);
+}
+
+void WebURLLoaderImpl::OnReceivedResponse(
+ const ResourceLoaderBridge::ResponseInfo& info,
+ bool content_filtered) {
+ if (!client_)
+ return;
+
+ WebURLResponse response;
+ response.initialize();
+ PopulateURLResponse(url_, info, &response);
+ response.setIsContentFiltered(content_filtered);
+
+ expected_content_length_ = response.expectedContentLength();
+
+ client_->didReceiveResponse(this, response);
+
+ // we may have been cancelled after didReceiveResponse, which would leave us
+ // without a client and therefore without much need to do multipart handling.
+ if (!client_)
+ return;
+
+ DCHECK(!multipart_delegate_.get());
+ if (info.headers && info.mime_type == "multipart/x-mixed-replace") {
+ std::string content_type;
+ info.headers->EnumerateHeader(NULL, "content-type", &content_type);
+
+ std::string boundary = net::GetHeaderParamValue(content_type, "boundary");
+ TrimString(boundary, " \"", &boundary);
+
+ // If there's no boundary, just handle the request normally. In the gecko
+ // code, nsMultiMixedConv::OnStartRequest throws an exception.
+ if (!boundary.empty()) {
+ multipart_delegate_.reset(
+ new MultipartResponseDelegate(client_, this, response, boundary));
+ }
+ }
+}
+
+void WebURLLoaderImpl::OnReceivedData(const char* data, int len) {
+ if (!client_)
+ return;
+
+ if (multipart_delegate_.get()) {
+ // The multipart delegate will make the appropriate calls to
+ // client_->didReceiveData and client_->didReceiveResponse.
+ multipart_delegate_->OnReceivedData(data, len);
+ } else {
+ client_->didReceiveData(this, data, len, expected_content_length_);
+ }
+}
+
+void WebURLLoaderImpl::OnCompletedRequest(const URLRequestStatus& status,
+ const std::string& security_info) {
+ if (multipart_delegate_.get()) {
+ multipart_delegate_->OnCompletedRequest();
+ multipart_delegate_.reset(NULL);
+ }
+
+ if (!client_)
+ return;
+
+ if (status.status() != URLRequestStatus::SUCCESS) {
+ int error_code;
+ if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) {
+ // By marking this request as aborted we insure that we don't navigate
+ // to an error page.
+ error_code = net::ERR_ABORTED;
+ } else {
+ error_code = status.os_error();
+ }
+ WebURLError error;
+ error.domain = WebString::fromUTF8(net::kErrorDomain);
+ error.reason = error_code;
+ error.unreachableURL = url_;
+ client_->didFail(this, error);
+ } else {
+ client_->didFinishLoading(this);
+ }
+}
+
+std::string WebURLLoaderImpl::GetURLForDebugging() {
+ return url_.spec();
+}
+
+void WebURLLoaderImpl::Start(
+ const WebURLRequest& request,
+ ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
+ DCHECK(!bridge_.get());
+
+ url_ = request.url();
+ if (url_.SchemeIs("data")) {
+ if (sync_load_response) {
+ // This is a sync load. Do the work now.
+ sync_load_response->url = url_;
+ std::string data;
+ GetInfoFromDataURL(sync_load_response->url, sync_load_response,
+ &sync_load_response->data,
+ &sync_load_response->status);
+ } else {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ task_factory_.NewRunnableMethod(&WebURLLoaderImpl::HandleDataURL));
+ }
+ return;
+ }
+
+ GURL referrer_url(WebStringToStdString(
+ request.httpHeaderField(WebString::fromUTF8("Referer"))));
+ const std::string& method = WebStringToStdString(request.httpMethod());
+
+ int load_flags = net::LOAD_NORMAL;
+ switch (request.cachePolicy()) {
+ case WebURLRequest::ReloadIgnoringCacheData:
+ // Required by LayoutTests/http/tests/misc/refresh-headers.php
+ load_flags |= net::LOAD_VALIDATE_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataElseLoad:
+ load_flags |= net::LOAD_PREFERRING_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataDontLoad:
+ load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ break;
+ case WebURLRequest::UseProtocolCachePolicy:
+ break;
+ }
+
+ if (request.reportUploadProgress())
+ load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
+
+ // TODO(jcampan): in the non out-of-process plugin case the request does not
+ // have a requestor_pid. Find a better place to set this.
+ int requestor_pid = request.requestorProcessID();
+ if (requestor_pid == 0)
+ requestor_pid = base::GetCurrentProcId();
+
+ HeaderFlattener flattener(load_flags);
+ request.visitHTTPHeaderFields(&flattener);
+
+ // TODO(abarth): These are wrong! I need to figure out how to get the right
+ // strings here. See: http://crbug.com/8706
+ std::string frame_origin = request.firstPartyForCookies().spec();
+ std::string main_frame_origin = request.firstPartyForCookies().spec();
+
+ // TODO(brettw) this should take parameter encoding into account when
+ // creating the GURLs.
+ bridge_.reset(ResourceLoaderBridge::Create(
+ method,
+ url_,
+ request.firstPartyForCookies(),
+ referrer_url,
+ frame_origin,
+ main_frame_origin,
+ flattener.GetBuffer(),
+ load_flags,
+ requestor_pid,
+ FromTargetType(request.targetType()),
+ request.appCacheContextID(),
+ request.requestorID()));
+
+ if (!request.httpBody().isNull()) {
+ // GET and HEAD requests shouldn't have http bodies.
+ DCHECK(method != "GET" && method != "HEAD");
+ const WebHTTPBody& httpBody = request.httpBody();
+ size_t i = 0;
+ WebHTTPBody::Element element;
+ while (httpBody.elementAt(i++, element)) {
+ switch (element.type) {
+ case WebHTTPBody::Element::TypeData:
+ if (!element.data.isEmpty()) {
+ // WebKit sometimes gives up empty data to append. These aren't
+ // necessary so we just optimize those out here.
+ bridge_->AppendDataToUpload(
+ element.data.data(), static_cast<int>(element.data.size()));
+ }
+ break;
+ case WebHTTPBody::Element::TypeFile:
+ bridge_->AppendFileToUpload(
+ FilePath(WebStringToFilePathString(element.filePath)));
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ bridge_->SetUploadIdentifier(request.httpBody().identifier());
+ }
+
+ if (sync_load_response) {
+ bridge_->SyncLoad(sync_load_response);
+ return;
+ }
+
+ if (!bridge_->Start(this))
+ bridge_.reset();
+}
+
+void WebURLLoaderImpl::HandleDataURL() {
+ if (!client_)
+ return;
+
+ ResourceLoaderBridge::ResponseInfo info;
+ URLRequestStatus status;
+ std::string data;
+
+ if (GetInfoFromDataURL(url_, &info, &data, &status)) {
+ OnReceivedResponse(info, false);
+ if (!data.empty())
+ OnReceivedData(data.data(), data.size());
+ }
+
+ OnCompletedRequest(status, info.security_info);
+}
+
+} // namespace webkit_glue
diff --git a/webkit/glue/weburlloader_impl.h b/webkit/glue/weburlloader_impl.h
new file mode 100644
index 0000000..2ad50c3
--- /dev/null
+++ b/webkit/glue/weburlloader_impl.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef WEBKIT_GLUE_WEBURLLOADER_IMPL_H_
+#define WEBKIT_GLUE_WEBURLLOADER_IMPL_H_
+
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "webkit/api/public/WebURLLoader.h"
+#include "webkit/glue/multipart_response_delegate.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+namespace webkit_glue {
+
+class WebURLLoaderImpl : public WebKit::WebURLLoader,
+ public ResourceLoaderBridge::Peer {
+ public:
+ WebURLLoaderImpl();
+ ~WebURLLoaderImpl();
+
+ // WebURLLoader methods:
+ virtual void loadSynchronously(
+ const WebKit::WebURLRequest& request,
+ WebKit::WebURLResponse& response,
+ WebKit::WebURLError& error,
+ WebKit::WebData& data);
+ virtual void loadAsynchronously(
+ const WebKit::WebURLRequest& request,
+ WebKit::WebURLLoaderClient* client);
+ virtual void cancel();
+ virtual void setDefersLoading(bool value);
+
+ // ResourceLoaderBridge::Peer methods:
+ virtual void OnUploadProgress(uint64 position, uint64 size);
+ virtual void OnReceivedRedirect(const GURL& new_url);
+ virtual void OnReceivedResponse(
+ const ResourceLoaderBridge::ResponseInfo& info, bool content_filtered);
+ virtual void OnReceivedData(const char* data, int len);
+ virtual void OnCompletedRequest(
+ const URLRequestStatus& status, const std::string& security_info);
+ virtual std::string GetURLForDebugging();
+
+ private:
+ void Start(
+ const WebKit::WebURLRequest& request,
+ ResourceLoaderBridge::SyncLoadResponse* sync_load_response);
+ void HandleDataURL();
+
+ ScopedRunnableMethodFactory<WebURLLoaderImpl> task_factory_;
+
+ GURL url_;
+ WebKit::WebURLLoaderClient* client_;
+ scoped_ptr<ResourceLoaderBridge> bridge_;
+ scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
+ int64 expected_content_length_;
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_WEBURLLOADER_IMPL_H_