Index: webkit/glue/plugins/pepper_url_loader.cc |
=================================================================== |
--- webkit/glue/plugins/pepper_url_loader.cc (revision 69381) |
+++ webkit/glue/plugins/pepper_url_loader.cc (working copy) |
@@ -1,536 +0,0 @@ |
-// Copyright (c) 2010 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. |
- |
-#include "webkit/glue/plugins/pepper_url_loader.h" |
- |
-#include "base/logging.h" |
-#include "ppapi/c/pp_completion_callback.h" |
-#include "ppapi/c/pp_errors.h" |
-#include "ppapi/c/ppb_url_loader.h" |
-#include "ppapi/c/trusted/ppb_url_loader_trusted.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 "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" |
-#include "webkit/appcache/web_application_cache_host_impl.h" |
-#include "webkit/glue/plugins/pepper_common.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 appcache::WebApplicationCacheHostImpl; |
-using WebKit::WebFrame; |
-using WebKit::WebString; |
-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 { |
- |
-PP_Resource Create(PP_Instance instance_id) { |
- PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); |
- if (!instance) |
- return 0; |
- |
- URLLoader* loader = new URLLoader(instance, false); |
- return loader->GetReference(); |
-} |
- |
-PP_Bool IsURLLoader(PP_Resource resource) { |
- return BoolToPPBool(!!Resource::GetAs<URLLoader>(resource)); |
-} |
- |
-int32_t Open(PP_Resource loader_id, |
- PP_Resource request_id, |
- PP_CompletionCallback callback) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_ERROR_BADRESOURCE; |
- |
- scoped_refptr<URLRequestInfo> request( |
- Resource::GetAs<URLRequestInfo>(request_id)); |
- if (!request) |
- return PP_ERROR_BADRESOURCE; |
- |
- return loader->Open(request, callback); |
-} |
- |
-int32_t FollowRedirect(PP_Resource loader_id, |
- PP_CompletionCallback callback) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_ERROR_BADRESOURCE; |
- |
- return loader->FollowRedirect(callback); |
-} |
- |
-PP_Bool GetUploadProgress(PP_Resource loader_id, |
- int64_t* bytes_sent, |
- int64_t* total_bytes_to_be_sent) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_FALSE; |
- |
- return BoolToPPBool(loader->GetUploadProgress(bytes_sent, |
- total_bytes_to_be_sent)); |
-} |
- |
-PP_Bool GetDownloadProgress(PP_Resource loader_id, |
- int64_t* bytes_received, |
- int64_t* total_bytes_to_be_received) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_FALSE; |
- |
- return BoolToPPBool(loader->GetDownloadProgress(bytes_received, |
- total_bytes_to_be_received)); |
-} |
- |
-PP_Resource GetResponseInfo(PP_Resource loader_id) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return 0; |
- |
- URLResponseInfo* response_info = loader->response_info(); |
- if (!response_info) |
- return 0; |
- |
- return response_info->GetReference(); |
-} |
- |
-int32_t ReadResponseBody(PP_Resource loader_id, |
- char* buffer, |
- int32_t bytes_to_read, |
- PP_CompletionCallback callback) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_ERROR_BADRESOURCE; |
- |
- return loader->ReadResponseBody(buffer, bytes_to_read, callback); |
-} |
- |
-int32_t FinishStreamingToFile(PP_Resource loader_id, |
- PP_CompletionCallback callback) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return PP_ERROR_BADRESOURCE; |
- |
- return loader->FinishStreamingToFile(callback); |
-} |
- |
-void Close(PP_Resource loader_id) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return; |
- |
- loader->Close(); |
-} |
- |
-const PPB_URLLoader ppb_urlloader = { |
- &Create, |
- &IsURLLoader, |
- &Open, |
- &FollowRedirect, |
- &GetUploadProgress, |
- &GetDownloadProgress, |
- &GetResponseInfo, |
- &ReadResponseBody, |
- &FinishStreamingToFile, |
- &Close |
-}; |
- |
-void GrantUniversalAccess(PP_Resource loader_id) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return; |
- |
- loader->GrantUniversalAccess(); |
-} |
- |
-void SetStatusCallback(PP_Resource loader_id, |
- PP_URLLoaderTrusted_StatusCallback cb) { |
- scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); |
- if (!loader) |
- return; |
- loader->SetStatusCallback(cb); |
-} |
- |
-const PPB_URLLoaderTrusted ppb_urlloadertrusted = { |
- &GrantUniversalAccess, |
- &SetStatusCallback |
-}; |
- |
-WebKit::WebFrame* GetFrame(PluginInstance* instance) { |
- return instance->container()->element().document().frame(); |
-} |
- |
-} // namespace |
- |
-URLLoader::URLLoader(PluginInstance* instance, bool main_document_loader) |
- : Resource(instance->module()), |
- instance_(instance), |
- main_document_loader_(main_document_loader), |
- pending_callback_(), |
- bytes_sent_(0), |
- total_bytes_to_be_sent_(-1), |
- bytes_received_(0), |
- total_bytes_to_be_received_(-1), |
- user_buffer_(NULL), |
- user_buffer_size_(0), |
- done_status_(PP_ERROR_WOULDBLOCK), |
- has_universal_access_(false), |
- status_callback_(NULL) { |
- instance->AddObserver(this); |
-} |
- |
-URLLoader::~URLLoader() { |
- if (instance_) |
- instance_->RemoveObserver(this); |
-} |
- |
-// static |
-const PPB_URLLoader* URLLoader::GetInterface() { |
- return &ppb_urlloader; |
-} |
- |
-// static |
-const PPB_URLLoaderTrusted* URLLoader::GetTrustedInterface() { |
- return &ppb_urlloadertrusted; |
-} |
- |
-URLLoader* URLLoader::AsURLLoader() { |
- return this; |
-} |
- |
-int32_t URLLoader::Open(URLRequestInfo* request, |
- PP_CompletionCallback callback) { |
- if (loader_.get()) |
- return PP_ERROR_INPROGRESS; |
- |
- // We only support non-blocking calls. |
- if (!callback.func) |
- return PP_ERROR_BADARGUMENT; |
- |
- WebFrame* frame = GetFrame(instance_); |
- if (!frame) |
- return PP_ERROR_FAILED; |
- WebURLRequest web_request(request->ToWebURLRequest(frame)); |
- |
- int32_t rv = CanRequest(frame, web_request.url()); |
- if (rv != PP_OK) |
- return rv; |
- |
- frame->dispatchWillSendRequest(web_request); |
- |
- // Sets the appcache host id to allow retrieval from the appcache. |
- if (WebApplicationCacheHostImpl* appcache_host = |
- WebApplicationCacheHostImpl::FromFrame(frame)) { |
- appcache_host->willStartSubResourceRequest(web_request); |
- } |
- |
- loader_.reset(WebKit::webKitClient()->createURLLoader()); |
- if (!loader_.get()) |
- return PP_ERROR_FAILED; |
- |
- loader_->loadAsynchronously(web_request, this); |
- |
- request_info_ = scoped_refptr<URLRequestInfo>(request); |
- pending_callback_ = callback; |
- |
- // Notify completion when we receive a redirect or response headers. |
- return PP_ERROR_WOULDBLOCK; |
-} |
- |
-int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { |
- if (pending_callback_.func) |
- return PP_ERROR_INPROGRESS; |
- |
- // We only support non-blocking calls. |
- if (!callback.func) |
- return PP_ERROR_BADARGUMENT; |
- |
- WebURL redirect_url = GURL(response_info_->redirect_url()); |
- |
- int32_t rv = CanRequest(GetFrame(instance_), redirect_url); |
- if (rv != PP_OK) |
- return rv; |
- |
- pending_callback_ = callback; |
- loader_->setDefersLoading(false); // Allow the redirect to continue. |
- return PP_ERROR_WOULDBLOCK; |
-} |
- |
-bool URLLoader::GetUploadProgress(int64_t* bytes_sent, |
- int64_t* total_bytes_to_be_sent) { |
- if (!RecordUploadProgress()) { |
- *bytes_sent = 0; |
- *total_bytes_to_be_sent = 0; |
- return false; |
- } |
- *bytes_sent = bytes_sent_; |
- *total_bytes_to_be_sent = total_bytes_to_be_sent_; |
- return true; |
-} |
- |
-bool URLLoader::GetDownloadProgress(int64_t* bytes_received, |
- int64_t* total_bytes_to_be_received) { |
- if (!RecordDownloadProgress()) { |
- *bytes_received = 0; |
- *total_bytes_to_be_received = 0; |
- return false; |
- } |
- *bytes_received = bytes_received_; |
- *total_bytes_to_be_received = total_bytes_to_be_received_; |
- return true; |
-} |
- |
-int32_t URLLoader::ReadResponseBody(char* buffer, int32_t bytes_to_read, |
- PP_CompletionCallback callback) { |
- if (!response_info_ || response_info_->body()) |
- 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(); |
- |
- // We may have already reached EOF. |
- if (done_status_ != PP_ERROR_WOULDBLOCK) { |
- user_buffer_ = NULL; |
- user_buffer_size_ = 0; |
- return done_status_; |
- } |
- |
- pending_callback_ = callback; |
- return PP_ERROR_WOULDBLOCK; |
-} |
- |
-int32_t URLLoader::FinishStreamingToFile(PP_CompletionCallback callback) { |
- if (!response_info_ || !response_info_->body()) |
- return PP_ERROR_FAILED; |
- if (pending_callback_.func) |
- return PP_ERROR_INPROGRESS; |
- |
- // We may have already reached EOF. |
- if (done_status_ != PP_ERROR_WOULDBLOCK) |
- return done_status_; |
- |
- // Wait for didFinishLoading / didFail. |
- pending_callback_ = callback; |
- return PP_ERROR_WOULDBLOCK; |
-} |
- |
-void URLLoader::Close() { |
- if (loader_.get()) { |
- loader_->cancel(); |
- } else if (main_document_loader_) { |
- WebFrame* frame = instance_->container()->element().document().frame(); |
- frame->stopLoading(); |
- } |
-} |
- |
-void URLLoader::GrantUniversalAccess() { |
- has_universal_access_ = true; |
-} |
- |
-void URLLoader::SetStatusCallback(PP_URLLoaderTrusted_StatusCallback cb) { |
- status_callback_ = cb; |
-} |
- |
-void URLLoader::willSendRequest(WebURLLoader* loader, |
- WebURLRequest& new_request, |
- const WebURLResponse& redirect_response) { |
- if (!request_info_->follow_redirects()) { |
- SaveResponse(redirect_response); |
- loader_->setDefersLoading(true); |
- RunCallback(PP_OK); |
- } else { |
- int32_t rv = CanRequest(GetFrame(instance_), new_request.url()); |
- if (rv != PP_OK) { |
- loader_->setDefersLoading(true); |
- RunCallback(rv); |
- } |
- } |
-} |
- |
-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); |
- UpdateStatus(); |
-} |
- |
-void URLLoader::didReceiveResponse(WebURLLoader* loader, |
- const WebURLResponse& response) { |
- SaveResponse(response); |
- |
- // Sets -1 if the content length is unknown. |
- total_bytes_to_be_received_ = response.expectedContentLength(); |
- UpdateStatus(); |
- |
- RunCallback(PP_OK); |
-} |
- |
-void URLLoader::didDownloadData(WebURLLoader* loader, |
- int data_length) { |
- bytes_received_ += data_length; |
- UpdateStatus(); |
-} |
- |
-void URLLoader::didReceiveData(WebURLLoader* loader, |
- const char* data, |
- int data_length) { |
- bytes_received_ += 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, double finish_time) { |
- done_status_ = PP_OK; |
- RunCallback(done_status_); |
-} |
- |
-void URLLoader::didFail(WebURLLoader* loader, const WebURLError& error) { |
- // TODO(darin): Provide more detailed error information. |
- done_status_ = PP_ERROR_FAILED; |
- RunCallback(done_status_); |
-} |
- |
-void URLLoader::InstanceDestroyed(PluginInstance* instance) { |
- // When the instance is destroyed, we force delete any associated loads. |
- DCHECK(instance == instance_); |
- instance_ = NULL; |
- |
- // Normally the only ref to this class will be from the plugin which |
- // ForceDeletePluginResourceRefs will free. We don't want our object to be |
- // deleted out from under us until the function completes. |
- scoped_refptr<URLLoader> death_grip(this); |
- |
- // Force delete any plugin refs to us. If the instance is being deleted, we |
- // don't want to allow the requests to continue to use bandwidth and send us |
- // callbacks (for which we might have no plugin). |
- ResourceTracker *tracker = ResourceTracker::Get(); |
- PP_Resource loader_resource = GetReferenceNoAddRef(); |
- if (loader_resource) |
- tracker->ForceDeletePluginResourceRefs(loader_resource); |
- |
- // Also force free the response from the plugin, both the plugin's ref(s) |
- // and ours. |
- if (response_info_.get()) { |
- PP_Resource response_info_resource = response_info_->GetReferenceNoAddRef(); |
- if (response_info_resource) |
- tracker->ForceDeletePluginResourceRefs(response_info_resource); |
- response_info_ = NULL; |
- } |
- |
- // Free the WebKit request. |
- loader_.reset(); |
- |
- // Often, |this| will be deleted at the end of this function when death_grip |
- // goes out of scope. |
-} |
- |
-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::SaveResponse(const WebKit::WebURLResponse& response) { |
- scoped_refptr<URLResponseInfo> response_info(new URLResponseInfo(module())); |
- if (response_info->Initialize(response)) |
- response_info_ = response_info; |
-} |
- |
-// Checks that the client can request the URL. Returns a PPAPI error code. |
-int32_t URLLoader::CanRequest(const WebKit::WebFrame* frame, |
- const WebKit::WebURL& url) { |
- if (!has_universal_access_ && |
- !frame->securityOrigin().canRequest(url)) |
- return PP_ERROR_NOACCESS; |
- |
- return PP_OK; |
-} |
- |
-void URLLoader::UpdateStatus() { |
- if (status_callback_ && |
- (RecordDownloadProgress() || RecordUploadProgress())) { |
- PP_Resource pp_resource = GetReferenceNoAddRef(); |
- if (pp_resource) { |
- // The PP_Resource on the plugin will be NULL if the plugin has no |
- // reference to this object. That's fine, because then we don't need to |
- // call UpdateStatus. |
- // |
- // Here we go through some effort to only send the exact information that |
- // the requestor wanted in the request flags. It would be just as |
- // efficient to send all of it, but we don't want people to rely on |
- // getting download progress when they happen to set the upload progress |
- // flag. |
- status_callback_( |
- instance_->pp_instance(), pp_resource, |
- RecordUploadProgress() ? bytes_sent_ : -1, |
- RecordUploadProgress() ? total_bytes_to_be_sent_ : -1, |
- RecordDownloadProgress() ? bytes_received_ : -1, |
- RecordDownloadProgress() ? total_bytes_to_be_received_ : -1); |
- } |
- } |
-} |
- |
-bool URLLoader::RecordDownloadProgress() const { |
- return request_info_ && request_info_->record_download_progress(); |
-} |
- |
-bool URLLoader::RecordUploadProgress() const { |
- return request_info_ && request_info_->record_upload_progress(); |
-} |
- |
-} // namespace pepper |