158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/plugin_url_fetcher.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 781843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/child_thread.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/webplugin.h" 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/plugin_host.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/plugin_instance.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/plugin_stream_url.h" 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/webplugin_resource_client.h" 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/plugin_messages.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/resource_dispatcher.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/base/load_flags.h" 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/base/net_errors.h" 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/http/http_response_headers.h" 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h" 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "webkit/child/multipart_response_delegate.h" 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "webkit/child/weburlloader_impl.h" 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "webkit/common/resource_request_body.h" 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace content { 26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This class handles individual multipart responses. It is instantiated when 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// we receive HTTP status code 206 in the HTTP response. This indicates 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// that the response could have multiple parts each separated by a boundary 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// specified in the response header. 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(jam): this is similar to MultiPartResponseClient in webplugin_impl.cc, 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// we should remove that other class once we switch to loading from the plugin 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// process by default. 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class MultiPartResponseClient : public blink::WebURLLoaderClient { 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit MultiPartResponseClient(PluginStreamUrl* plugin_stream) 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {} 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // blink::WebURLLoaderClient implementation: 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void didReceiveResponse( 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebURLLoader* loader, 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebURLResponse& response) OVERRIDE { 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 byte_range_upper_bound, instance_size; 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!webkit_glue::MultipartResponseDelegate::ReadContentRanges( 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) response, &byte_range_lower_bound_, &byte_range_upper_bound, 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &instance_size)) { 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void didReceiveData(blink::WebURLLoader* loader, 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const char* data, 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int data_length, 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int encoded_data_length) OVERRIDE { 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(ananta) 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We should defer further loads on multipart resources on the same lines 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // as regular resources requested by plugins to prevent reentrancy. 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int64 data_offset = byte_range_lower_bound_; 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) byte_range_lower_bound_ += data_length; 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) plugin_stream_->DidReceiveData(data, data_length, data_offset); 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // DANGER: this instance may be deleted at this point. 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The lower bound of the byte range. 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 byte_range_lower_bound_; 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The handler for the data. 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PluginStreamUrl* plugin_stream_; 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream, 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& url, 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& first_party_for_cookies, 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& method, 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const char* buf, 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) unsigned int len, 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& referrer, 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool notify_redirects, 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool is_plugin_src_load, 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int origin_pid, 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int render_view_id, 8481843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) unsigned long resource_id, 8581843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) bool copy_stream_data) 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : plugin_stream_(plugin_stream), 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url_(url), 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) first_party_for_cookies_(first_party_for_cookies), 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) method_(method), 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) referrer_(referrer), 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) notify_redirects_(notify_redirects), 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) is_plugin_src_load_(is_plugin_src_load), 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) resource_id_(resource_id), 9481843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) copy_stream_data_(copy_stream_data), 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data_offset_(0), 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_failure_notification_(false) { 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) webkit_glue::ResourceLoaderBridge::RequestInfo request_info; 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.method = method; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.url = url; 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.first_party_for_cookies = first_party_for_cookies; 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.referrer = referrer; 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.load_flags = net::LOAD_NORMAL; 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.requestor_pid = origin_pid; 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.request_type = ResourceType::OBJECT; 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.routing_id = render_view_id; 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<char> body; 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (method == "POST") { 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool content_type_found = false; 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<std::string> names; 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<std::string> values; 112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PluginHost::SetPostData(buf, len, &names, &values, &body); 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (size_t i = 0; i < names.size(); ++i) { 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!request_info.headers.empty()) 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.headers += "\r\n"; 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info.headers += names[i] + ": " + values[i]; 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (LowerCaseEqualsASCII(names[i], "content-type")) 118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) content_type_found = true; 119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!content_type_found) { 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!request_info.headers.empty()) 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) request_info.headers += "\r\n"; 124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) request_info.headers += "Content-Type: application/x-www-form-urlencoded"; 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge( 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_info)); 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!body.empty()) { 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_refptr<webkit_glue::ResourceRequestBody> request_body = 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new webkit_glue::ResourceRequestBody; 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_body->AppendBytes(&body[0], body.size()); 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_->SetRequestBody(request_body.get()); 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_->Start(this); 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(jam): range requests 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PluginURLFetcher::~PluginURLFetcher() { 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::Cancel() { 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_->Cancel(); 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::URLRedirectResponse(bool allow) { 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (allow) { 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bridge_->SetDefersLoading(false); 15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_->Cancel(); 15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidFail(resource_id_); // That will delete |this|. 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) { 15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PluginURLFetcher::OnReceivedRedirect( 16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& new_url, 16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const webkit_glue::ResourceResponseInfo& info, 16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool* has_new_first_party_for_cookies, 16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GURL* new_first_party_for_cookies) { 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::willSendRequest until 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // kDirectNPAPIRequests is the default and we can remove the old path there. 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Currently this check is just to catch an https -> http redirect when 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // loading the main plugin src URL. Longer term, we could investigate 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // firing mixed diplay or scripting issues for subresource loads 17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // initiated by plug-ins. 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (is_plugin_src_load_ && 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !plugin_stream_->instance()->webplugin()->CheckIfRunInsecureContent( 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new_url)) { 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidFail(resource_id_); // That will delete |this|. 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // It's unfortunate that this logic of when a redirect's method changes is 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // in url_request.cc, but weburlloader_impl.cc and this file have to duplicate 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // it instead of passing that information. 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int response_code = info.headers->response_code(); 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (response_code != 307) 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) method_ = "GET"; 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GURL old_url = url_; 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url_ = new_url; 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *has_new_first_party_for_cookies = true; 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *new_first_party_for_cookies = first_party_for_cookies_; 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If the plugin does not participate in url redirect notifications then just 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // block cross origin 307 POST redirects. 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!notify_redirects_) { 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (response_code == 307 && method_ == "POST" && 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) old_url.GetOrigin() != new_url.GetOrigin()) { 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidFail(resource_id_); // That will delete |this|. 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Pause the request while we ask the plugin what to do about the redirect. 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bridge_->SetDefersLoading(true); 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) plugin_stream_->WillSendRequest(url_, response_code); 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnReceivedResponse( 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const webkit_glue::ResourceResponseInfo& info) { 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::didReceiveResponse 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // GetAllHeaders, and GetResponseInfo until kDirectNPAPIRequests is the 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // default and we can remove the old path there. 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool request_is_seekable = true; 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!multipart_delegate_.get()); 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (plugin_stream_->seekable()) { 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int response_code = info.headers->response_code(); 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (response_code == 206) { 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebURLResponse response; 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) response.initialize(); 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webkit_glue::WebURLLoaderImpl::PopulateURLResponse(url_, info, &response); 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string multipart_boundary; 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (webkit_glue::MultipartResponseDelegate::ReadMultipartBoundary( 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) response, &multipart_boundary)) { 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) plugin_stream_->instance()->webplugin()->DidStartLoading(); 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) MultiPartResponseClient* multi_part_response_client = 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) new MultiPartResponseClient(plugin_stream_); 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) multipart_delegate_.reset(new webkit_glue::MultipartResponseDelegate( 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) multi_part_response_client, NULL, response, multipart_boundary)); 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Multiple ranges requested, data will be delivered by 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // MultipartResponseDelegate. 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) data_offset_ = 0; 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 upper_bound = 0, instance_size = 0; 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Single range requested - go through original processing for 242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // non-multipart requests, but update data offset. 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webkit_glue::MultipartResponseDelegate::ReadContentRanges( 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) response, &data_offset_, &upper_bound, &instance_size); 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (response_code == 200) { 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO: should we handle this case? We used to but it's not clear that we 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // still need to. This was bug 5403, fixed in r7139. 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the length comes in as -1, then it indicates that it was not 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // read off the HTTP headers. We replicate Safari webkit behavior here, 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // which is to set it to 0. 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int expected_length = std::max(static_cast<int>(info.content_length), 0); 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Time temp; 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 last_modified = 0; 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string headers; 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (info.headers) { // NULL for data: urls. 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (info.headers->GetLastModifiedValue(&temp)) 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) last_modified = static_cast<uint32>(temp.ToDoubleT()); 26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(darin): Shouldn't we also report HTTP version numbers? 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int response_code = info.headers->response_code(); 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) headers = base::StringPrintf("HTTP %d ", response_code); 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) headers += info.headers->GetStatusText(); 267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) headers += "\n"; 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void* iter = NULL; 270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string name, value; 271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) while (info.headers->EnumerateHeaderLines(&iter, &name, &value)) { 272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(darin): Should we really exclude headers with an empty value? 273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!name.empty() && !value.empty()) 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) headers += name + ": " + value + "\n"; 275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // error codes in the stream header and as a result, was unaware of the fate 2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF destroy 2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the stream and invoke the NPP_DestroyStream function on the plugin if the 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // HTTPrequest fails. 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if ((url_.SchemeIs("http") || url_.SchemeIs("https")) && 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (response_code < 100 || response_code >= 400)) { 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_failure_notification_ = true; 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidReceiveResponse(info.mime_type, 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) headers, 290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) expected_length, 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) last_modified, 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) request_is_seekable); 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnDownloadedData(int len, 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int encoded_data_length) { 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnReceivedData(const char* data, 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int data_length, 30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int encoded_data_length) { 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (multipart_delegate_) { 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length); 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int64 offset = data_offset_; 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) data_offset_ += data_length; 30781843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) 30881843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) if (copy_stream_data_) { 30981843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) // QuickTime writes to this memory, and since we got it from 31081843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) // ResourceDispatcher it's not mapped for write access in this process. 31181843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) // http://crbug.com/308466. 31281843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) scoped_ptr<char[]> data_copy(new char[data_length]); 31381843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) memcpy(data_copy.get(), data, data_length); 31481843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) plugin_stream_->DidReceiveData(data_copy.get(), data_length, offset); 31581843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) } else { 31681843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) plugin_stream_->DidReceiveData(data, data_length, offset); 31781843c7b1423e241009db79d34acf2450330fcc5Torne (Richard Coles) } 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // DANGER: this instance may be deleted at this point. 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnCompletedRequest( 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int error_code, 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool was_ignored_by_handler, 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& security_info, 32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::TimeTicks& completion_time) { 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (multipart_delegate_) { 328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) multipart_delegate_->OnCompletedRequest(); 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) multipart_delegate_.reset(); 330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (error_code == net::OK) { 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidFinishLoading(resource_id_); 33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) plugin_stream_->DidFail(resource_id_); 33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace content 340