diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-11 19:13:03 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-11 19:13:03 +0000 |
commit | 01cb1991150f05ffb77a43e98005661671a0aff0 (patch) | |
tree | c61b5e8446110c284eed4812ce511d5117853a9e /content/child/npapi/plugin_url_fetcher.cc | |
parent | 35179be6fcd7cf9cb4db346e266621aab6941c14 (diff) | |
download | chromium_src-01cb1991150f05ffb77a43e98005661671a0aff0.zip chromium_src-01cb1991150f05ffb77a43e98005661671a0aff0.tar.gz chromium_src-01cb1991150f05ffb77a43e98005661671a0aff0.tar.bz2 |
Load NPAPI plugin resources through the browser process directly instead of going through the renderer. This is needed because when we have site isolation enabled we won't trust the renderer to fetch urls from arbitrary origins, which is something that NPAPI plugins can do.
In a followup I'll implement range requests.
For now this is behind the --direct-npapi-requests flag.
BUG=286074
R=ananta@chromium.org, jschuh@chromium.org
Review URL: https://codereview.chromium.org/23503043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222602 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/child/npapi/plugin_url_fetcher.cc')
-rw-r--r-- | content/child/npapi/plugin_url_fetcher.cc | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/content/child/npapi/plugin_url_fetcher.cc b/content/child/npapi/plugin_url_fetcher.cc new file mode 100644 index 0000000..373f69d --- /dev/null +++ b/content/child/npapi/plugin_url_fetcher.cc @@ -0,0 +1,188 @@ +// Copyright (c) 2013 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 "content/child/npapi/plugin_url_fetcher.h" + +#include "content/child/child_thread.h" +#include "content/child/npapi/webplugin.h" +#include "content/child/npapi/plugin_host.h" +#include "content/child/npapi/plugin_instance.h" +#include "content/child/npapi/plugin_stream_url.h" +#include "content/child/npapi/webplugin_resource_client.h" +#include "content/child/plugin_messages.h" +#include "content/child/resource_dispatcher.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/http/http_response_headers.h" +#include "webkit/common/resource_request_body.h" + +namespace content { + +PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream, + const GURL& url, + const GURL& first_party_for_cookies, + const std::string& method, + const std::string& post_data, + const GURL& referrer, + bool notify_redirects, + bool is_plugin_src_load, + int origin_pid, + int render_view_id, + unsigned long resource_id) + : plugin_stream_(plugin_stream), + 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), + resource_id_(resource_id), + data_offset_(0) { + webkit_glue::ResourceLoaderBridge::RequestInfo request_info; + request_info.method = method; + request_info.url = url; + request_info.first_party_for_cookies = first_party_for_cookies; + request_info.referrer = referrer; + request_info.load_flags = net::LOAD_NORMAL; + request_info.requestor_pid = origin_pid; + request_info.request_type = ResourceType::OBJECT; + request_info.routing_id = render_view_id; + + std::vector<char> body; + if (method == "POST") { + std::vector<std::string> names; + std::vector<std::string> values; + PluginHost::SetPostData( + post_data.c_str(), post_data.size(), &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]; + } + } + + bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge( + request_info)); + if (!body.empty()) { + scoped_refptr<webkit_glue::ResourceRequestBody> request_body = + new webkit_glue::ResourceRequestBody; + request_body->AppendBytes(&body[0], body.size()); + bridge_->SetRequestBody(request_body.get()); + } + + bridge_->Start(this); + + // TODO(jam): range requests +} + +PluginURLFetcher::~PluginURLFetcher() { +} + +void PluginURLFetcher::Cancel() { + bridge_->Cancel(); +} + +void PluginURLFetcher::URLRedirectResponse(bool allow) { + if (allow) { + bridge_->SetDefersLoading(true); + } else { + bridge_->Cancel(); + plugin_stream_->DidFail(resource_id_); // That will delete |this|. + } +} + +void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) { +} + +bool PluginURLFetcher::OnReceivedRedirect( + const GURL& new_url, + const webkit_glue::ResourceResponseInfo& info, + bool* has_new_first_party_for_cookies, + GURL* new_first_party_for_cookies) { + // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::willSendRequest until + // kDirectNPAPIRequests is the default and we can remove the old path there. + + // Currently this check is just to catch an https -> http redirect when + // loading the main plugin src URL. Longer term, we could investigate + // firing mixed diplay or scripting issues for subresource loads + // initiated by plug-ins. + if (is_plugin_src_load_ && + !plugin_stream_->instance()->webplugin()->CheckIfRunInsecureContent( + new_url)) { + plugin_stream_->DidFail(resource_id_); // That will delete |this|. + return false; + } + + // 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) + method_ = "GET"; + GURL old_url = url_; + url_ = new_url; + *has_new_first_party_for_cookies = true; + *new_first_party_for_cookies = first_party_for_cookies_; + + // 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" && + old_url.GetOrigin() != new_url.GetOrigin()) { + plugin_stream_->DidFail(resource_id_); // That will delete |this|. + return false; + } + } 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()); + } + + return true; +} + +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; + + base::Time temp; + if (info.headers->GetLastModifiedValue(&temp)) + last_modified = static_cast<uint32>(temp.ToDoubleT()); + + std::string headers = info.headers->raw_headers(); + + plugin_stream_->DidReceiveResponse(info.mime_type, + headers, + info.content_length, + last_modified, + request_is_seekable); +} + +void PluginURLFetcher::OnDownloadedData(int len, + int encoded_data_length) { +} + +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; +} + +void PluginURLFetcher::OnCompletedRequest( + int error_code, + bool was_ignored_by_handler, + const std::string& security_info, + const base::TimeTicks& completion_time) { + if (error_code == net::OK) { + plugin_stream_->DidFinishLoading(resource_id_); + } else { + plugin_stream_->DidFail(resource_id_); + } +} + +} // namespace content |