diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-04 19:39:29 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-04 19:39:29 +0000 |
commit | 51df0c71a8a411016c23645be92e2066160a464a (patch) | |
tree | 238fde8421a1a818da2026ab7e9574969b33aba4 | |
parent | 1de08b360a306baa27e5f810fa5b5dd7a382ccde (diff) | |
download | chromium_src-51df0c71a8a411016c23645be92e2066160a464a.zip chromium_src-51df0c71a8a411016c23645be92e2066160a464a.tar.gz chromium_src-51df0c71a8a411016c23645be92e2066160a464a.tar.bz2 |
Add callback ability for URLLoader so an asynchronous proxy can send the
current progress to another process.
Adds a DOWNLOADPROGRESS flag to track download progress to be symetrical with
the upload progress. I implemented the backend of these two flags and made it
refuse to provide progress unless these flags were set.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/4423001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65098 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ppapi/c/dev/ppb_url_loader_dev.h | 25 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_url_loader_trusted_dev.h | 28 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_url_request_info_dev.h | 14 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_resource.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_resource.h | 14 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_loader.cc | 83 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_loader.h | 25 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_request_info.cc | 10 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_request_info.h | 6 |
9 files changed, 179 insertions, 30 deletions
diff --git a/ppapi/c/dev/ppb_url_loader_dev.h b/ppapi/c/dev/ppb_url_loader_dev.h index 44f4dc90..9d63b31 100644 --- a/ppapi/c/dev/ppb_url_loader_dev.h +++ b/ppapi/c/dev/ppb_url_loader_dev.h @@ -52,20 +52,27 @@ struct PPB_URLLoader_Dev { struct PP_CompletionCallback callback); // Returns the current upload progress, which is meaningful after Open has - // been called, and the request given to Open must have been configured with - // PP_URLREQUESTPROPERTY_REPORTUPLOADPROGRESS set to true. Progress only - // refers to the request body. This data is only available if the - // PP_URLREQUESTPROPERTY_REPORTUPLOADPROGRESS was set to true on the - // URLRequestInfo. This method returns false if upload progress is not - // available. + // been called. Progress only refers to the request body and does not include + // the headers. + // + // This data is only available if the URLRequestInfo passed to Open() had the + // PP_URLREQUESTPROPERTY_REPORTUPLOADPROGRESS flag set to true. + // + // This method returns false if upload progress is not available. bool (*GetUploadProgress)(PP_Resource loader, int64_t* bytes_sent, int64_t* total_bytes_to_be_sent); // Returns the current download progress, which is meaningful after Open has - // been called. Progress only refers to the response body. The total bytes - // to be received may be unknown, in which case -1 is returned. This method - // returns false if download progress is not available. + // been called. Progress only refers to the response body and does not + // include the headers. + // + // This data is only available if the URLRequestInfo passed to Open() had the + // PP_URLREQUESTPROPERTY_REPORTDOWNLOADPROGRESS flag set to true. + // + // The total bytes to be received may be unknown, in which case + // total_bytes_to_be_received will be set to -1. This method returns false if + // download progress is not available. bool (*GetDownloadProgress)(PP_Resource loader, int64_t* bytes_received, int64_t* total_bytes_to_be_received); diff --git a/ppapi/c/dev/ppb_url_loader_trusted_dev.h b/ppapi/c/dev/ppb_url_loader_trusted_dev.h index 4eabe14..84aff0e 100644 --- a/ppapi/c/dev/ppb_url_loader_trusted_dev.h +++ b/ppapi/c/dev/ppb_url_loader_trusted_dev.h @@ -5,15 +5,41 @@ #ifndef PPAPI_C_DEV_PPB_URL_LOADER_TRUSTED_DEV_H_ #define PPAPI_C_DEV_PPB_URL_LOADER_TRUSTED_DEV_H_ +#include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_stdint.h" -#define PPB_URLLOADERTRUSTED_DEV_INTERFACE "PPB_URLLoaderTrusted(Dev);0.1" +#define PPB_URLLOADERTRUSTED_DEV_INTERFACE "PPB_URLLoaderTrusted(Dev);0.2" + +// Callback that indicates the status of the download and upload for the +// given URLLoader resource. +typedef void (*PP_URLLoaderTrusted_StatusCallback)( + PP_Instance pp_instance, + PP_Resource pp_resource, + int64_t bytes_sent, + int64_t total_bytes_to_be_sent, + int64_t bytes_received, + int64_t total_bytes_to_be_received); // Available only to trusted implementations. struct PPB_URLLoaderTrusted_Dev { // Grant this URLLoader the capability to make unrestricted cross-origin // requests. void (*GrantUniversalAccess)(PP_Resource loader); + + // Registers that the given function will be called when the upload or + // downloaded byte count has changed. This is not exposed on the untrusted + // interface because it can be quite chatty and encourages people to write + // feedback UIs that update as frequently as the progress updates. + // + // The other serious gotcha with this callback is that the callback must not + // mutate the URL loader or cause it to be destroyed. + // + // However, the proxy layer needs this information to push to the other + // process, so we expose it here. Only one callback can be set per URL + // Loader. Setting to a NULL callback will disable it. + void (*RegisterStatusCallback)(PP_Resource loader, + PP_URLLoaderTrusted_StatusCallback cb); }; #endif // PPAPI_C_DEV_PPB_URL_LOADER_DEV_H_ diff --git a/ppapi/c/dev/ppb_url_request_info_dev.h b/ppapi/c/dev/ppb_url_request_info_dev.h index 2503a0c..9916804 100644 --- a/ppapi/c/dev/ppb_url_request_info_dev.h +++ b/ppapi/c/dev/ppb_url_request_info_dev.h @@ -18,7 +18,19 @@ typedef enum { PP_URLREQUESTPROPERTY_HEADERS, // string, \n-delim PP_URLREQUESTPROPERTY_STREAMTOFILE, // bool (default=false) PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS, // bool (default=true) - PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS // bool (default=false) + + // Set to true if you want to be able to poll the download progress via the + // URLLoader.GetDownloadProgress function. + // + // Boolean (default = false). + PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, + + // Set to true if you want to be able to pull the upload progress via the + // URLLoader.GetUploadProgress function. + // + // Boolean (default = false). + PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS + // TODO(darin): Add security/privacy options? } PP_URLRequestProperty_Dev; diff --git a/webkit/glue/plugins/pepper_resource.cc b/webkit/glue/plugins/pepper_resource.cc index cf7a7fe..851d6e7 100644 --- a/webkit/glue/plugins/pepper_resource.cc +++ b/webkit/glue/plugins/pepper_resource.cc @@ -25,6 +25,10 @@ PP_Resource Resource::GetReference() { return resource_id_; } +PP_Resource Resource::GetReferenceNoAddRef() const { + return resource_id_; +} + void Resource::StoppedTracking() { DCHECK(resource_id_ != 0); resource_id_ = 0; diff --git a/webkit/glue/plugins/pepper_resource.h b/webkit/glue/plugins/pepper_resource.h index 3ba2eb8..c21b4871 100644 --- a/webkit/glue/plugins/pepper_resource.h +++ b/webkit/glue/plugins/pepper_resource.h @@ -84,6 +84,19 @@ class Resource : public base::RefCountedThreadSafe<Resource> { const PP_Resource id; }; + protected: + // Returns the resource ID of this object OR NULL IF THERE IS NONE ASSIGNED. + // This will happen if the plugin doesn't have a reference to the given + // resource. The resource will not be addref'ed. + // + // This should only be used as an input parameter to the plugin for status + // updates in the proxy layer, where if the plugin has no reference, it will + // just give up since nothing needs to be updated. + // + // Generally you should use GetReference instead. This is why it has this + // obscure name rather than pp_resource(). + PP_Resource GetReferenceNoAddRef() const; + private: // Type-specific getters for individual resource types. These will return // NULL if the resource does not match the specified type. Used by the Cast() @@ -93,7 +106,6 @@ class Resource : public base::RefCountedThreadSafe<Resource> { FOR_ALL_RESOURCES(DEFINE_TYPE_GETTER) #undef DEFINE_TYPE_GETTER - private: // If referenced by a plugin, holds the id of this resource object. Do not // access this member directly, because it is possible that the plugin holds // no references to the object, and therefore the resource_id_ is zero. Use diff --git a/webkit/glue/plugins/pepper_url_loader.cc b/webkit/glue/plugins/pepper_url_loader.cc index 37059d0..2e68adb 100644 --- a/webkit/glue/plugins/pepper_url_loader.cc +++ b/webkit/glue/plugins/pepper_url_loader.cc @@ -84,9 +84,7 @@ bool GetUploadProgress(PP_Resource loader_id, scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); if (!loader) return false; - - *bytes_sent = loader->bytes_sent(); - *total_bytes_to_be_sent = loader->total_bytes_to_be_sent(); + return loader->GetUploadProgress(bytes_sent, total_bytes_to_be_sent); return true; } @@ -96,10 +94,8 @@ bool GetDownloadProgress(PP_Resource loader_id, scoped_refptr<URLLoader> loader(Resource::GetAs<URLLoader>(loader_id)); if (!loader) return false; - - *bytes_received = loader->bytes_received(); - *total_bytes_to_be_received = loader->total_bytes_to_be_received(); - return true; + return loader->GetDownloadProgress(bytes_received, + total_bytes_to_be_received); } PP_Resource GetResponseInfo(PP_Resource loader_id) { @@ -163,8 +159,17 @@ void GrantUniversalAccess(PP_Resource loader_id) { 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_Dev ppb_urlloadertrusted = { - &GrantUniversalAccess + &GrantUniversalAccess, + &SetStatusCallback }; } // namespace @@ -181,7 +186,10 @@ URLLoader::URLLoader(PluginInstance* instance, bool main_document_loader) user_buffer_(NULL), user_buffer_size_(0), done_status_(PP_ERROR_WOULDBLOCK), - has_universal_access_(false) { + record_download_progress_(false), + record_upload_progress_(false), + has_universal_access_(false), + status_callback_(NULL) { } URLLoader::~URLLoader() { @@ -230,6 +238,8 @@ int32_t URLLoader::Open(URLRequestInfo* request, loader_->loadAsynchronously(web_request, this); pending_callback_ = callback; + record_download_progress_ = request->record_download_progress(); + record_upload_progress_ = request->record_upload_progress(); // Notify completion when we receive a redirect or response headers. return PP_ERROR_WOULDBLOCK; @@ -240,6 +250,30 @@ int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { return PP_ERROR_FAILED; } +bool URLLoader::GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) { + if (!record_upload_progress_) { + *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 (!record_download_progress_) { + *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()) @@ -298,6 +332,10 @@ 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) { @@ -310,6 +348,7 @@ void URLLoader::didSendData(WebURLLoader* loader, // 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, @@ -320,6 +359,7 @@ void URLLoader::didReceiveResponse(WebURLLoader* loader, // Sets -1 if the content length is unknown. total_bytes_to_be_received_ = response.expectedContentLength(); + UpdateStatus(); RunCallback(PP_OK); } @@ -327,6 +367,7 @@ void URLLoader::didReceiveResponse(WebURLLoader* loader, void URLLoader::didDownloadData(WebURLLoader* loader, int data_length) { bytes_received_ += data_length; + UpdateStatus(); } void URLLoader::didReceiveData(WebURLLoader* loader, @@ -376,4 +417,28 @@ size_t URLLoader::FillUserBuffer() { return bytes_to_copy; } +void URLLoader::UpdateStatus() { + if (status_callback_ && + (record_download_progress_ || record_upload_progress_)) { + 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, + record_upload_progress_ ? bytes_sent_ : -1, + record_upload_progress_ ? total_bytes_to_be_sent_ : -1, + record_download_progress_ ? bytes_received_ : -1, + record_download_progress_ ? total_bytes_to_be_received_ : -1); + } + } +} + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_url_loader.h b/webkit/glue/plugins/pepper_url_loader.h index 2b4ebd4..e018555 100644 --- a/webkit/glue/plugins/pepper_url_loader.h +++ b/webkit/glue/plugins/pepper_url_loader.h @@ -9,6 +9,7 @@ #include "base/scoped_ptr.h" #include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/dev/ppb_url_loader_trusted_dev.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" #include "webkit/glue/plugins/pepper_resource.h" @@ -41,6 +42,10 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { // PPB_URLLoader implementation. int32_t Open(URLRequestInfo* request, PP_CompletionCallback callback); int32_t FollowRedirect(PP_CompletionCallback callback); + bool GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent); + bool GetDownloadProgress(int64_t* bytes_received, + int64_t* total_bytes_to_be_received); int32_t ReadResponseBody(char* buffer, int32_t bytes_to_read, PP_CompletionCallback callback); int32_t FinishStreamingToFile(PP_CompletionCallback callback); @@ -48,6 +53,7 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { // PPB_URLLoaderTrusted implementation. void GrantUniversalAccess(); + void SetStatusCallback(PP_URLLoaderTrusted_StatusCallback cb); // WebKit::WebURLLoaderClient implementation. virtual void willSendRequest(WebKit::WebURLLoader* loader, @@ -70,18 +76,15 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { URLResponseInfo* response_info() const { return response_info_; } - // Progress counters. - int64_t bytes_sent() const { return bytes_sent_; } - int64_t total_bytes_to_be_sent() const { return total_bytes_to_be_sent_; } - int64_t bytes_received() const { return bytes_received_; } - int64_t total_bytes_to_be_received() const { - return total_bytes_to_be_received_; - } - private: void RunCallback(int32_t result); size_t FillUserBuffer(); + // Calls the status_callback_ (if any) with the current upload and download + // progress. Call this function if you update any of these values to + // synchronize an out-of-process plugin's state. + void UpdateStatus(); + scoped_refptr<PluginInstance> instance_; // If true, then the plugin instance is a full-frame plugin and we're just // wrapping the main document's loader (i.e. loader_ is null). @@ -97,7 +100,13 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { char* user_buffer_; size_t user_buffer_size_; int32_t done_status_; + + bool record_download_progress_; + bool record_upload_progress_; + bool has_universal_access_; + + PP_URLLoaderTrusted_StatusCallback status_callback_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_url_request_info.cc b/webkit/glue/plugins/pepper_url_request_info.cc index 92cc5d0..723b327 100644 --- a/webkit/glue/plugins/pepper_url_request_info.cc +++ b/webkit/glue/plugins/pepper_url_request_info.cc @@ -146,7 +146,9 @@ struct URLRequestInfo::BodyItem { URLRequestInfo::URLRequestInfo(PluginModule* module) : Resource(module), - stream_to_file_(false) { + stream_to_file_(false), + record_download_progress_(false), + record_upload_progress_(false) { } URLRequestInfo::~URLRequestInfo() { @@ -163,6 +165,12 @@ bool URLRequestInfo::SetBooleanProperty(PP_URLRequestProperty_Dev property, case PP_URLREQUESTPROPERTY_STREAMTOFILE: stream_to_file_ = value; return true; + case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS: + record_download_progress_ = value; + return true; + case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS: + record_upload_progress_ = value; + return true; default: //NOTIMPLEMENTED(); // TODO(darin): Implement me! return false; diff --git a/webkit/glue/plugins/pepper_url_request_info.h b/webkit/glue/plugins/pepper_url_request_info.h index 1effa1f..067756f 100644 --- a/webkit/glue/plugins/pepper_url_request_info.h +++ b/webkit/glue/plugins/pepper_url_request_info.h @@ -44,6 +44,9 @@ class URLRequestInfo : public Resource { WebKit::WebURLRequest ToWebURLRequest(WebKit::WebFrame* frame) const; + bool record_download_progress() const { return record_download_progress_; } + bool record_upload_progress() const { return record_upload_progress_; } + private: struct BodyItem; typedef std::vector<BodyItem> Body; @@ -52,7 +55,10 @@ class URLRequestInfo : public Resource { std::string method_; std::string headers_; Body body_; + bool stream_to_file_; + bool record_download_progress_; + bool record_upload_progress_; }; } // namespace pepper |