Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1625)

Unified Diff: content/child/npapi/plugin_url_fetcher.cc

Issue 23830007: Support byte range requests when routing resource requests directly through the browser process. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: sync Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/child/npapi/plugin_url_fetcher.h ('k') | content/child/npapi/webplugin.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/child/npapi/plugin_url_fetcher.cc
===================================================================
--- content/child/npapi/plugin_url_fetcher.cc (revision 223418)
+++ content/child/npapi/plugin_url_fetcher.cc (working copy)
@@ -15,15 +15,64 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "webkit/child/multipart_response_delegate.h"
+#include "webkit/child/weburlloader_impl.h"
#include "webkit/common/resource_request_body.h"
namespace content {
+namespace {
+// 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.
+// TODO(jam): this is similar to MultiPartResponseClient in webplugin_impl.cc,
+// we should remove that other class once we switch to loading from the plugin
+// process by default.
+class MultiPartResponseClient : public WebKit::WebURLLoaderClient {
+ public:
+ explicit MultiPartResponseClient(PluginStreamUrl* plugin_stream)
+ : byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {}
+
+ // WebKit::WebURLLoaderClient implementation:
+ virtual void didReceiveResponse(
+ WebKit::WebURLLoader* loader,
+ const WebKit::WebURLResponse& response) OVERRIDE {
+ int64 byte_range_upper_bound, instance_size;
+ if (!webkit_glue::MultipartResponseDelegate::ReadContentRanges(
+ response, &byte_range_lower_bound_, &byte_range_upper_bound,
+ &instance_size)) {
+ NOTREACHED();
+ }
+ }
+ virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length) OVERRIDE {
+ // TODO(ananta)
+ // We should defer further loads on multipart resources on the same lines
+ // as regular resources requested by plugins to prevent reentrancy.
+ plugin_stream_->DidReceiveData(data, data_length, byte_range_lower_bound_);
+ byte_range_lower_bound_ += data_length;
+ }
+
+ private:
+ // The lower bound of the byte range.
+ int64 byte_range_lower_bound_;
+ // The handler for the data.
+ PluginStreamUrl* plugin_stream_;
+};
+
+} // namespace
+
PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
const GURL& url,
const GURL& first_party_for_cookies,
const std::string& method,
- const std::string& post_data,
+ const char* buf,
+ unsigned int len,
const GURL& referrer,
bool notify_redirects,
bool is_plugin_src_load,
@@ -34,7 +83,6 @@
url_(url),
first_party_for_cookies_(first_party_for_cookies),
method_(method),
- post_data_(post_data),
referrer_(referrer),
notify_redirects_(notify_redirects),
is_plugin_src_load_(is_plugin_src_load),
@@ -52,16 +100,23 @@
std::vector<char> body;
if (method == "POST") {
+ bool content_type_found = false;
std::vector<std::string> names;
std::vector<std::string> values;
- PluginHost::SetPostData(
- post_data.c_str(), post_data.size(), &names, &values, &body);
+ PluginHost::SetPostData(buf, len, &names, &values, &body);
for (size_t i = 0; i < names.size(); ++i) {
if (!request_info.headers.empty())
request_info.headers += "\r\n";
-
request_info.headers += names[i] + ": " + values[i];
+ if (LowerCaseEqualsASCII(names[i], "content-type"))
+ content_type_found = true;
}
+
+ if (!content_type_found) {
+ if (!request_info.headers.empty())
+ request_info.headers += "\r\n";
+ request_info.headers += "Content-Type: application/x-www-form-urlencoded";
+ }
}
bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge(
@@ -119,7 +174,8 @@
// It's unfortunate that this logic of when a redirect's method changes is
// in url_request.cc, but weburlloader_impl.cc and this file have to duplicate
// it instead of passing that information.
- if (info.headers->response_code() != 307)
+ int response_code = info.headers->response_code();
+ if (response_code != 307)
method_ = "GET";
GURL old_url = url_;
url_ = new_url;
@@ -129,7 +185,7 @@
// If the plugin does not participate in url redirect notifications then just
// block cross origin 307 POST redirects.
if (!notify_redirects_) {
- if (info.headers->response_code() == 307 && method_ == "POST" &&
+ if (response_code == 307 && method_ == "POST" &&
old_url.GetOrigin() != new_url.GetOrigin()) {
plugin_stream_->DidFail(resource_id_); // That will delete |this|.
return false;
@@ -137,7 +193,7 @@
} else {
// Pause the request while we ask the plugin what to do about the redirect.
bridge_->SetDefersLoading(true);
- plugin_stream_->WillSendRequest(url_, info.headers->response_code());
+ plugin_stream_->WillSendRequest(url_, response_code);
}
return true;
@@ -145,21 +201,78 @@
void PluginURLFetcher::OnReceivedResponse(
const webkit_glue::ResourceResponseInfo& info) {
- // TODO(jam): see WebPluginImpl::didReceiveResponse for request_is_seekable
- bool request_is_seekable = false;
- uint32 last_modified = 0;
+ // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::didReceiveResponse
+ // GetAllHeaders, and GetResponseInfo until kDirectNPAPIRequests is the
+ // default and we can remove the old path there.
+ bool request_is_seekable = true;
+ DCHECK(!multipart_delegate_.get());
+ if (plugin_stream_->seekable()) {
+ int response_code = info.headers->response_code();
+ if (response_code == 206) {
+ WebKit::WebURLResponse response;
+ response.initialize();
+ webkit_glue::WebURLLoaderImpl::PopulateURLResponse(url_, info, &response);
+
+ std::string multipart_boundary;
+ if (webkit_glue::MultipartResponseDelegate::ReadMultipartBoundary(
+ response, &multipart_boundary)) {
+ plugin_stream_->instance()->webplugin()->DidStartLoading();
+
+ MultiPartResponseClient* multi_part_response_client =
+ new MultiPartResponseClient(plugin_stream_);
+
+ multipart_delegate_.reset(new webkit_glue::MultipartResponseDelegate(
+ multi_part_response_client, NULL, response, multipart_boundary));
+
+ // Multiple ranges requested, data will be delivered by
+ // MultipartResponseDelegate.
+ data_offset_ = 0;
+ return;
+ }
+
+ int64 upper_bound = 0, instance_size = 0;
+ // Single range requested - go through original processing for
+ // non-multipart requests, but update data offset.
+ webkit_glue::MultipartResponseDelegate::ReadContentRanges(
+ response, &data_offset_, &upper_bound, &instance_size);
+ } else if (response_code == 200) {
+ // TODO: should we handle this case? We used to but it's not clear that we
+ // still need to. This was bug 5403, fixed in r7139.
+ }
+ }
+
+ // If the length comes in as -1, then it indicates that it was not
+ // read off the HTTP headers. We replicate Safari webkit behavior here,
+ // which is to set it to 0.
+ int expected_length = std::max(static_cast<int>(info.content_length), 0);
+
base::Time temp;
- if (info.headers->GetLastModifiedValue(&temp))
- last_modified = static_cast<uint32>(temp.ToDoubleT());
+ uint32 last_modified = 0;
+ std::string headers;
+ if (info.headers) { // NULL for data: urls.
+ if (info.headers->GetLastModifiedValue(&temp))
+ last_modified = static_cast<uint32>(temp.ToDoubleT());
- std::string headers = info.headers->raw_headers();
+ // TODO(darin): Shouldn't we also report HTTP version numbers?
+ headers = base::StringPrintf("HTTP %d ", info.headers->response_code());
+ headers += info.headers->GetStatusText();
+ headers += "\n";
+ void* iter = NULL;
+ std::string name, value;
+ while (info.headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ // TODO(darin): Should we really exclude headers with an empty value?
+ if (!name.empty() && !value.empty())
+ headers += name + ": " + value + "\n";
+ }
+ }
+
plugin_stream_->DidReceiveResponse(info.mime_type,
- headers,
- info.content_length,
- last_modified,
- request_is_seekable);
+ headers,
+ expected_length,
+ last_modified,
+ request_is_seekable);
}
void PluginURLFetcher::OnDownloadedData(int len,
@@ -169,8 +282,12 @@
void PluginURLFetcher::OnReceivedData(const char* data,
int data_length,
int encoded_data_length) {
- plugin_stream_->DidReceiveData(data, data_length, data_offset_);
- data_offset_ += data_length;
+ if (multipart_delegate_) {
+ multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
+ } else {
+ plugin_stream_->DidReceiveData(data, data_length, data_offset_);
+ data_offset_ += data_length;
+ }
}
void PluginURLFetcher::OnCompletedRequest(
@@ -178,6 +295,11 @@
bool was_ignored_by_handler,
const std::string& security_info,
const base::TimeTicks& completion_time) {
+ if (multipart_delegate_) {
+ multipart_delegate_->OnCompletedRequest();
+ multipart_delegate_.reset();
+ }
+
if (error_code == net::OK) {
plugin_stream_->DidFinishLoading(resource_id_);
} else {
« no previous file with comments | « content/child/npapi/plugin_url_fetcher.h ('k') | content/child/npapi/webplugin.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698