Index: webkit/glue/plugins/pepper_url_loader.cc |
=================================================================== |
--- webkit/glue/plugins/pepper_url_loader.cc (revision 51226) |
+++ webkit/glue/plugins/pepper_url_loader.cc (working copy) |
@@ -8,10 +8,28 @@ |
#include "third_party/ppapi/c/pp_completion_callback.h" |
#include "third_party/ppapi/c/pp_errors.h" |
#include "third_party/ppapi/c/ppb_url_loader.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebKit.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h" |
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" |
#include "webkit/glue/plugins/pepper_plugin_instance.h" |
#include "webkit/glue/plugins/pepper_url_request_info.h" |
#include "webkit/glue/plugins/pepper_url_response_info.h" |
+using WebKit::WebFrame; |
+using WebKit::WebURL; |
+using WebKit::WebURLError; |
+using WebKit::WebURLLoader; |
+using WebKit::WebURLRequest; |
+using WebKit::WebURLResponse; |
+ |
+#ifdef _MSC_VER |
+// Do not warn about use of std::copy with raw pointers. |
+#pragma warning(disable : 4996) |
+#endif |
+ |
namespace pepper { |
namespace { |
@@ -127,6 +145,8 @@ |
URLLoader::URLLoader(PluginInstance* instance) |
: Resource(instance->module()), |
+ instance_(instance), |
+ pending_callback_(), |
bytes_sent_(0), |
total_bytes_to_be_sent_(0), |
bytes_received_(0), |
@@ -136,10 +156,39 @@ |
URLLoader::~URLLoader() { |
} |
+// static |
+const PPB_URLLoader* URLLoader::GetInterface() { |
+ return &ppb_urlloader; |
+} |
+ |
int32_t URLLoader::Open(URLRequestInfo* request, |
PP_CompletionCallback callback) { |
- NOTIMPLEMENTED(); // TODO(darin): Implement me. |
- return PP_Error_Failed; |
+ if (loader_.get()) |
+ return PP_Error_InProgress; |
+ |
+ // We only support non-blocking calls. |
+ if (!callback.func) |
+ return PP_Error_BadArgument; |
+ |
+ WebURLRequest web_request(request->web_request()); |
+ |
+ WebFrame* frame = instance_->container()->element().document().frame(); |
+ if (!frame) |
+ return PP_Error_Failed; |
+ frame->setReferrerForRequest(web_request, WebURL()); // Use default. |
+ frame->dispatchWillSendRequest(web_request); |
+ |
+ loader_.reset(WebKit::webKitClient()->createURLLoader()); |
+ if (!loader_.get()) { |
+ loader_.reset(); |
+ return PP_Error_Failed; |
+ } |
+ loader_->loadAsynchronously(web_request, this); |
+ |
+ pending_callback_ = callback; |
+ |
+ // Notify completion when we receive a redirect or response headers. |
+ return PP_Error_WouldBlock; |
} |
int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { |
@@ -149,17 +198,90 @@ |
int32_t URLLoader::ReadResponseBody(char* buffer, int32_t bytes_to_read, |
PP_CompletionCallback callback) { |
- NOTIMPLEMENTED(); // TODO(darin): Implement me. |
- return PP_Error_Failed; |
+ if (bytes_to_read <= 0 || !buffer) |
+ return PP_Error_BadArgument; |
+ if (pending_callback_.func) |
+ return PP_Error_InProgress; |
+ |
+ // We only support non-blocking calls. |
+ if (!callback.func) |
+ return PP_Error_BadArgument; |
+ |
+ user_buffer_ = buffer; |
+ user_buffer_size_ = bytes_to_read; |
+ |
+ if (!buffer_.empty()) |
+ return FillUserBuffer(); |
+ |
+ pending_callback_ = callback; |
+ return PP_Error_WouldBlock; |
} |
void URLLoader::Close() { |
NOTIMPLEMENTED(); // TODO(darin): Implement me. |
} |
-// static |
-const PPB_URLLoader* URLLoader::GetInterface() { |
- return &ppb_urlloader; |
+void URLLoader::RunCallback(int32_t result) { |
+ if (!pending_callback_.func) |
+ return; |
+ |
+ PP_CompletionCallback callback = {0}; |
+ std::swap(callback, pending_callback_); |
+ PP_RunCompletionCallback(&callback, result); |
} |
+size_t URLLoader::FillUserBuffer() { |
+ DCHECK(user_buffer_); |
+ DCHECK(user_buffer_size_); |
+ |
+ size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_); |
+ std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_); |
+ buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy); |
+ |
+ // Reset for next time. |
+ user_buffer_ = NULL; |
+ user_buffer_size_ = 0; |
+ return bytes_to_copy; |
+} |
+ |
+void URLLoader::willSendRequest(WebURLLoader* loader, |
+ WebURLRequest& new_request, |
+ const WebURLResponse& redirect_response) { |
+ NOTIMPLEMENTED(); // TODO(darin): Allow the plugin to inspect redirects. |
+} |
+ |
+void URLLoader::didSendData(WebURLLoader* loader, |
+ unsigned long long bytes_sent, |
+ unsigned long long total_bytes_to_be_sent) { |
+ // TODO(darin): Bounds check input? |
+ bytes_sent_ = static_cast<int64_t>(bytes_sent); |
+ total_bytes_to_be_sent_ = static_cast<int64_t>(total_bytes_to_be_sent); |
+} |
+ |
+void URLLoader::didReceiveResponse(WebURLLoader* loader, |
+ const WebURLResponse& response) { |
+ // TODO(darin): Initialize response_info_. |
+ RunCallback(PP_OK); |
+} |
+ |
+void URLLoader::didReceiveData(WebURLLoader* loader, |
+ const char* data, |
+ int data_length) { |
+ buffer_.insert(buffer_.end(), data, data + data_length); |
+ if (user_buffer_) { |
+ RunCallback(FillUserBuffer()); |
+ } else { |
+ DCHECK(!pending_callback_.func); |
+ } |
+} |
+ |
+void URLLoader::didFinishLoading(WebURLLoader* loader) { |
+ RunCallback(PP_OK); |
+} |
+ |
+void URLLoader::didFail(WebURLLoader* loader, const WebURLError& error) { |
+ // TODO(darin): Provide more detailed error information. |
+ RunCallback(PP_Error_Failed); |
+} |
+ |
} // namespace pepper |