| Index: content/child/npapi/plugin_url_fetcher.cc
|
| diff --git a/content/child/npapi/plugin_url_fetcher.cc b/content/child/npapi/plugin_url_fetcher.cc
|
| deleted file mode 100644
|
| index a307f6850a0d3c6f49a2818f6fc30be01075f6aa..0000000000000000000000000000000000000000
|
| --- a/content/child/npapi/plugin_url_fetcher.cc
|
| +++ /dev/null
|
| @@ -1,406 +0,0 @@
|
| -// 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 "base/memory/scoped_ptr.h"
|
| -#include "content/child/child_thread_impl.h"
|
| -#include "content/child/multipart_response_delegate.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.h"
|
| -#include "content/child/npapi/webplugin_resource_client.h"
|
| -#include "content/child/plugin_messages.h"
|
| -#include "content/child/request_extra_data.h"
|
| -#include "content/child/request_info.h"
|
| -#include "content/child/resource_dispatcher.h"
|
| -#include "content/child/web_url_loader_impl.h"
|
| -#include "content/common/resource_request_body.h"
|
| -#include "content/common/service_worker/service_worker_types.h"
|
| -#include "content/public/common/resource_response_info.h"
|
| -#include "net/base/load_flags.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "net/url_request/redirect_info.h"
|
| -#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
|
| -#include "third_party/WebKit/public/platform/WebURLResponse.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 blink::WebURLLoaderClient {
|
| - public:
|
| - explicit MultiPartResponseClient(PluginStreamUrl* plugin_stream)
|
| - : byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {}
|
| -
|
| - // blink::WebURLLoaderClient implementation:
|
| - void didReceiveResponse(blink::WebURLLoader* loader,
|
| - const blink::WebURLResponse& response) override {
|
| - int64 byte_range_upper_bound, instance_size;
|
| - if (!MultipartResponseDelegate::ReadContentRanges(response,
|
| - &byte_range_lower_bound_,
|
| - &byte_range_upper_bound,
|
| - &instance_size)) {
|
| - NOTREACHED();
|
| - }
|
| - }
|
| - void didReceiveData(blink::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.
|
| - int64 data_offset = byte_range_lower_bound_;
|
| - byte_range_lower_bound_ += data_length;
|
| - plugin_stream_->DidReceiveData(data, data_length, data_offset);
|
| - // DANGER: this instance may be deleted at this point.
|
| - }
|
| -
|
| - 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 char* buf,
|
| - unsigned int len,
|
| - const Referrer& referrer,
|
| - const std::string& range,
|
| - bool notify_redirects,
|
| - bool is_plugin_src_load,
|
| - int origin_pid,
|
| - int render_frame_id,
|
| - int render_view_id,
|
| - unsigned long resource_id,
|
| - bool copy_stream_data)
|
| - : plugin_stream_(plugin_stream),
|
| - url_(url),
|
| - first_party_for_cookies_(first_party_for_cookies),
|
| - referrer_(referrer),
|
| - notify_redirects_(notify_redirects),
|
| - is_plugin_src_load_(is_plugin_src_load),
|
| - origin_pid_(origin_pid),
|
| - render_frame_id_(render_frame_id),
|
| - render_view_id_(render_view_id),
|
| - resource_id_(resource_id),
|
| - copy_stream_data_(copy_stream_data),
|
| - data_offset_(0),
|
| - pending_failure_notification_(false),
|
| - request_id_(-1),
|
| - weak_factory_(this) {
|
| - 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 = RESOURCE_TYPE_OBJECT;
|
| - request_info.routing_id = render_view_id;
|
| - // ServiceWorker is disabled for NPAPI.
|
| - request_info.skip_service_worker = true;
|
| -
|
| - RequestExtraData extra_data;
|
| - extra_data.set_render_frame_id(render_frame_id);
|
| - extra_data.set_is_main_frame(false);
|
| - request_info.extra_data = &extra_data;
|
| -
|
| - std::vector<char> body;
|
| - if (method == "POST") {
|
| - bool content_type_found = false;
|
| - std::vector<std::string> names;
|
| - std::vector<std::string> values;
|
| - 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 (base::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";
|
| - }
|
| - } else {
|
| - if (!range.empty())
|
| - request_info.headers = std::string("Range: ") + range;
|
| - }
|
| -
|
| - scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
|
| - if (!body.empty())
|
| - request_body->AppendBytes(&body[0], body.size());
|
| -
|
| - request_id_ = ChildThreadImpl::current()->resource_dispatcher()->StartAsync(
|
| - request_info, request_body.get(), this);
|
| -
|
| - // TODO(jam): range requests
|
| -}
|
| -
|
| -PluginURLFetcher::~PluginURLFetcher() {
|
| - if (request_id_ >= 0) {
|
| - ChildThreadImpl::current()->resource_dispatcher()->RemovePendingRequest(
|
| - request_id_);
|
| - }
|
| -}
|
| -
|
| -void PluginURLFetcher::Cancel() {
|
| - ChildThreadImpl::current()->resource_dispatcher()->Cancel(request_id_);
|
| -
|
| - // Due to races and nested event loops, PluginURLFetcher may still receive
|
| - // events from the bridge before being destroyed. Do not forward additional
|
| - // events back to the plugin, via either |plugin_stream_| or
|
| - // |multipart_delegate_| which has its own pointer via
|
| - // MultiPartResponseClient.
|
| - if (multipart_delegate_)
|
| - multipart_delegate_->Cancel();
|
| - plugin_stream_ = NULL;
|
| -}
|
| -
|
| -void PluginURLFetcher::URLRedirectResponse(bool allow) {
|
| - if (!plugin_stream_)
|
| - return;
|
| -
|
| - if (allow) {
|
| - ChildThreadImpl::current()->resource_dispatcher()->SetDefersLoading(
|
| - request_id_, false);
|
| - } else {
|
| - ChildThreadImpl::current()->resource_dispatcher()->Cancel(request_id_);
|
| - plugin_stream_->DidFail(resource_id_); // That will delete |this|.
|
| - }
|
| -}
|
| -
|
| -void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) {
|
| -}
|
| -
|
| -bool PluginURLFetcher::OnReceivedRedirect(
|
| - const net::RedirectInfo& redirect_info,
|
| - const ResourceResponseInfo& info) {
|
| - if (!plugin_stream_)
|
| - return false;
|
| -
|
| - // 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 plugins.
|
| - if (is_plugin_src_load_ &&
|
| - !plugin_stream_->instance()->webplugin()->CheckIfRunInsecureContent(
|
| - redirect_info.new_url)) {
|
| - plugin_stream_->DidFail(resource_id_); // That will delete |this|.
|
| - return false;
|
| - }
|
| -
|
| - GURL old_url = url_;
|
| - url_ = redirect_info.new_url;
|
| - first_party_for_cookies_ = redirect_info.new_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 (redirect_info.status_code == 307 &&
|
| - redirect_info.new_method == "POST" &&
|
| - old_url.GetOrigin() != 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.
|
| - ChildThreadImpl::current()->resource_dispatcher()->SetDefersLoading(
|
| - request_id_, true);
|
| - plugin_stream_->WillSendRequest(url_, redirect_info.status_code);
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
|
| - if (!plugin_stream_)
|
| - return;
|
| -
|
| - // 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) {
|
| - blink::WebURLResponse response;
|
| - response.initialize();
|
| - WebURLLoaderImpl::PopulateURLResponse(url_, info, &response,
|
| - false /* report_security_info */);
|
| -
|
| - std::string multipart_boundary;
|
| - if (MultipartResponseDelegate::ReadMultipartBoundary(
|
| - response, &multipart_boundary)) {
|
| - plugin_stream_->instance()->webplugin()->DidStartLoading();
|
| -
|
| - MultiPartResponseClient* multi_part_response_client =
|
| - new MultiPartResponseClient(plugin_stream_);
|
| -
|
| - multipart_delegate_.reset(new 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.
|
| - 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;
|
| - uint32 last_modified = 0;
|
| - std::string headers;
|
| - if (info.headers.get()) { // NULL for data: urls.
|
| - if (info.headers->GetLastModifiedValue(&temp))
|
| - last_modified = static_cast<uint32>(temp.ToDoubleT());
|
| -
|
| - // TODO(darin): Shouldn't we also report HTTP version numbers?
|
| - int response_code = info.headers->response_code();
|
| - headers = base::StringPrintf("HTTP %d ", 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";
|
| - }
|
| -
|
| - // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
|
| - // error codes in the stream header and as a result, was unaware of the fate
|
| - // of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF destroy
|
| - // the stream and invoke the NPP_DestroyStream function on the plugin if the
|
| - // HTTPrequest fails.
|
| - if ((url_.SchemeIs(url::kHttpScheme) || url_.SchemeIs(url::kHttpsScheme)) &&
|
| - (response_code < 100 || response_code >= 400)) {
|
| - pending_failure_notification_ = true;
|
| - }
|
| - }
|
| -
|
| - plugin_stream_->DidReceiveResponse(info.mime_type,
|
| - headers,
|
| - expected_length,
|
| - last_modified,
|
| - request_is_seekable);
|
| -}
|
| -
|
| -void PluginURLFetcher::OnDownloadedData(int len,
|
| - int encoded_data_length) {
|
| -}
|
| -
|
| -void PluginURLFetcher::OnReceivedData(scoped_ptr<ReceivedData> data) {
|
| - const char* payload = data->payload();
|
| - int data_length = data->length();
|
| - int encoded_data_length = data->encoded_length();
|
| - if (!plugin_stream_)
|
| - return;
|
| -
|
| - if (multipart_delegate_) {
|
| - multipart_delegate_->OnReceivedData(payload, data_length,
|
| - encoded_data_length);
|
| - } else {
|
| - int64 offset = data_offset_;
|
| - data_offset_ += data_length;
|
| -
|
| - if (copy_stream_data_) {
|
| - // QuickTime writes to this memory, and since we got it from
|
| - // ResourceDispatcher it's not mapped for write access in this process.
|
| - // http://crbug.com/308466.
|
| - scoped_ptr<char[]> data_copy(new char[data_length]);
|
| - memcpy(data_copy.get(), payload, data_length);
|
| - plugin_stream_->DidReceiveData(data_copy.get(), data_length, offset);
|
| - } else {
|
| - plugin_stream_->DidReceiveData(payload, data_length, offset);
|
| - }
|
| - // DANGER: this instance may be deleted at this point.
|
| - }
|
| -}
|
| -
|
| -void PluginURLFetcher::OnCompletedRequest(
|
| - int error_code,
|
| - bool was_ignored_by_handler,
|
| - bool stale_copy_in_cache,
|
| - const std::string& security_info,
|
| - const base::TimeTicks& completion_time,
|
| - int64 total_transfer_size) {
|
| - if (!plugin_stream_)
|
| - return;
|
| -
|
| - if (multipart_delegate_) {
|
| - multipart_delegate_->OnCompletedRequest();
|
| - multipart_delegate_.reset();
|
| - }
|
| -
|
| - if (error_code == net::OK) {
|
| - plugin_stream_->DidFinishLoading(resource_id_);
|
| - } else {
|
| - plugin_stream_->DidFail(resource_id_);
|
| - }
|
| -}
|
| -
|
| -void PluginURLFetcher::OnReceivedCompletedResponse(
|
| - const content::ResourceResponseInfo& info,
|
| - scoped_ptr<ReceivedData> data,
|
| - int error_code,
|
| - bool was_ignored_by_handler,
|
| - bool stale_copy_in_cache,
|
| - const std::string& security_info,
|
| - const base::TimeTicks& completion_time,
|
| - int64 total_transfer_size) {
|
| - // |this| can be deleted on each callback. |weak_this| is placed here to
|
| - // detect the deletion.
|
| - base::WeakPtr<PluginURLFetcher> weak_this = weak_factory_.GetWeakPtr();
|
| - OnReceivedResponse(info);
|
| -
|
| - if (!weak_this)
|
| - return;
|
| - if (data)
|
| - OnReceivedData(data.Pass());
|
| -
|
| - if (!weak_this)
|
| - return;
|
| - OnCompletedRequest(error_code, was_ignored_by_handler, stale_copy_in_cache,
|
| - security_info, completion_time, total_transfer_size);
|
| -}
|
| -} // namespace content
|
|
|