summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-04 19:39:29 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-04 19:39:29 +0000
commit51df0c71a8a411016c23645be92e2066160a464a (patch)
tree238fde8421a1a818da2026ab7e9574969b33aba4
parent1de08b360a306baa27e5f810fa5b5dd7a382ccde (diff)
downloadchromium_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.h25
-rw-r--r--ppapi/c/dev/ppb_url_loader_trusted_dev.h28
-rw-r--r--ppapi/c/dev/ppb_url_request_info_dev.h14
-rw-r--r--webkit/glue/plugins/pepper_resource.cc4
-rw-r--r--webkit/glue/plugins/pepper_resource.h14
-rw-r--r--webkit/glue/plugins/pepper_url_loader.cc83
-rw-r--r--webkit/glue/plugins/pepper_url_loader.h25
-rw-r--r--webkit/glue/plugins/pepper_url_request_info.cc10
-rw-r--r--webkit/glue/plugins/pepper_url_request_info.h6
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