plugin_url_fetcher.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/child_thread.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/child/multipart_response_delegate.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"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/npapi/webplugin.h"
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/npapi/webplugin_resource_client.h"
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/plugin_messages.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/child/request_extra_data.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/child/request_info.h"
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/child/resource_dispatcher.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/child/web_url_loader_impl.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/common/resource_request_body.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/common/service_worker/service_worker_types.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/common/resource_response_info.h"
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/base/load_flags.h"
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/base/net_errors.h"
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/http/http_response_headers.h"
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/url_request/url_request.h"
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h"
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "webkit/child/resource_loader_bridge.h"
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace content {
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace {
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This class handles individual multipart responses. It is instantiated when
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// we receive HTTP status code 206 in the HTTP response. This indicates
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// that the response could have multiple parts each separated by a boundary
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// specified in the response header.
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(jam): this is similar to MultiPartResponseClient in webplugin_impl.cc,
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// we should remove that other class once we switch to loading from the plugin
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// process by default.
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class MultiPartResponseClient : public blink::WebURLLoaderClient {
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  explicit MultiPartResponseClient(PluginStreamUrl* plugin_stream)
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      : byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {}
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // blink::WebURLLoaderClient implementation:
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void didReceiveResponse(
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      blink::WebURLLoader* loader,
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const blink::WebURLResponse& response) OVERRIDE {
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int64 byte_range_upper_bound, instance_size;
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!MultipartResponseDelegate::ReadContentRanges(response,
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                      &byte_range_lower_bound_,
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                      &byte_range_upper_bound,
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                      &instance_size)) {
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      NOTREACHED();
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void didReceiveData(blink::WebURLLoader* loader,
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              const char* data,
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              int data_length,
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              int encoded_data_length) OVERRIDE {
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(ananta)
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // We should defer further loads on multipart resources on the same lines
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // as regular resources requested by plugins to prevent reentrancy.
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int64 data_offset = byte_range_lower_bound_;
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    byte_range_lower_bound_ += data_length;
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    plugin_stream_->DidReceiveData(data, data_length, data_offset);
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // DANGER: this instance may be deleted at this point.
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The lower bound of the byte range.
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int64 byte_range_lower_bound_;
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The handler for the data.
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PluginStreamUrl* plugin_stream_;
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   const GURL& url,
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   const GURL& first_party_for_cookies,
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   const std::string& method,
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                   const char* buf,
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                   unsigned int len,
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   const GURL& referrer,
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   const std::string& range,
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   bool notify_redirects,
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   bool is_plugin_src_load,
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   int origin_pid,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   int render_frame_id,
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   int render_view_id,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   unsigned long resource_id,
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   bool copy_stream_data)
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : plugin_stream_(plugin_stream),
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      url_(url),
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      first_party_for_cookies_(first_party_for_cookies),
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      method_(method),
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      referrer_(referrer),
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      notify_redirects_(notify_redirects),
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      is_plugin_src_load_(is_plugin_src_load),
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      origin_pid_(origin_pid),
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      render_frame_id_(render_frame_id),
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      render_view_id_(render_view_id),
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      resource_id_(resource_id),
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      copy_stream_data_(copy_stream_data),
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      data_offset_(0),
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pending_failure_notification_(false) {
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RequestInfo request_info;
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.method = method;
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.url = url;
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.first_party_for_cookies = first_party_for_cookies;
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.referrer = referrer;
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.load_flags = net::LOAD_NORMAL;
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.requestor_pid = origin_pid;
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  request_info.request_type = RESOURCE_TYPE_OBJECT;
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  request_info.routing_id = render_view_id;
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  RequestExtraData extra_data;
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  extra_data.set_render_frame_id(render_frame_id);
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  extra_data.set_is_main_frame(false);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request_info.extra_data = &extra_data;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<char> body;
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (method == "POST") {
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool content_type_found = false;
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> names;
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> values;
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    PluginHost::SetPostData(buf, len, &names, &values, &body);
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (size_t i = 0; i < names.size(); ++i) {
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (!request_info.headers.empty())
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        request_info.headers += "\r\n";
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      request_info.headers += names[i] + ": " + values[i];
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (LowerCaseEqualsASCII(names[i], "content-type"))
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        content_type_found = true;
136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!content_type_found) {
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!request_info.headers.empty())
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        request_info.headers += "\r\n";
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      request_info.headers += "Content-Type: application/x-www-form-urlencoded";
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  } else {
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (!range.empty())
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      request_info.headers = std::string("Range: ") + range;
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge(
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      request_info));
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!body.empty()) {
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<ResourceRequestBody> request_body =
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new ResourceRequestBody;
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    request_body->AppendBytes(&body[0], body.size());
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bridge_->SetRequestBody(request_body.get());
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bridge_->Start(this);
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(jam): range requests
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PluginURLFetcher::~PluginURLFetcher() {
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::Cancel() {
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bridge_->Cancel();
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Due to races and nested event loops, PluginURLFetcher may still receive
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // events from the bridge before being destroyed. Do not forward additional
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // events back to the plugin, via either |plugin_stream_| or
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // |multipart_delegate_| which has its own pointer via
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // MultiPartResponseClient.
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (multipart_delegate_)
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    multipart_delegate_->Cancel();
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  plugin_stream_ = NULL;
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::URLRedirectResponse(bool allow) {
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!plugin_stream_)
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (allow) {
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bridge_->SetDefersLoading(false);
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bridge_->Cancel();
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    plugin_stream_->DidFail(resource_id_);  // That will delete |this|.
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) {
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PluginURLFetcher::OnReceivedRedirect(
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const GURL& new_url,
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& new_first_party_for_cookies,
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceResponseInfo& info) {
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!plugin_stream_)
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::willSendRequest until
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // kDirectNPAPIRequests is the default and we can remove the old path there.
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Currently this check is just to catch an https -> http redirect when
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // loading the main plugin src URL. Longer term, we could investigate
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // firing mixed diplay or scripting issues for subresource loads
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // initiated by plug-ins.
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (is_plugin_src_load_ &&
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      !plugin_stream_->instance()->webplugin()->CheckIfRunInsecureContent(
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          new_url)) {
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    plugin_stream_->DidFail(resource_id_);  // That will delete |this|.
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // It's unfortunate that this logic of when a redirect's method changes is
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // in url_request.cc, but weburlloader_impl.cc and this file have to duplicate
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // it instead of passing that information.
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int response_code;
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (info.headers) {
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    response_code = info.headers->response_code();
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // A redirect may have NULL headers if it came from URLRequestRedirectJob.
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    //
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(davidben): Get the actual response code from the browser. Either
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // fake enough of headers to have a response code or pass it down as part of
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // https://crbug.com/384609.
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    response_code = 307;
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  method_ = net::URLRequest::ComputeMethodForRedirect(method_, response_code);
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  GURL old_url = url_;
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  url_ = new_url;
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  first_party_for_cookies_ = new_first_party_for_cookies;
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // If the plugin does not participate in url redirect notifications then just
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // block cross origin 307 POST redirects.
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!notify_redirects_) {
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (response_code == 307 && method_ == "POST" &&
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        old_url.GetOrigin() != new_url.GetOrigin()) {
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      plugin_stream_->DidFail(resource_id_);  // That will delete |this|.
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return false;
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Pause the request while we ask the plugin what to do about the redirect.
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bridge_->SetDefersLoading(true);
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    plugin_stream_->WillSendRequest(url_, response_code);
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!plugin_stream_)
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::didReceiveResponse
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // GetAllHeaders, and GetResponseInfo until kDirectNPAPIRequests is the
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // default and we can remove the old path there.
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool request_is_seekable = true;
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!multipart_delegate_.get());
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (plugin_stream_->seekable()) {
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int response_code = info.headers->response_code();
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (response_code == 206) {
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      blink::WebURLResponse response;
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      response.initialize();
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      WebURLLoaderImpl::PopulateURLResponse(url_, info, &response);
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      std::string multipart_boundary;
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (MultipartResponseDelegate::ReadMultipartBoundary(
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              response, &multipart_boundary)) {
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        plugin_stream_->instance()->webplugin()->DidStartLoading();
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        MultiPartResponseClient* multi_part_response_client =
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            new MultiPartResponseClient(plugin_stream_);
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        multipart_delegate_.reset(new MultipartResponseDelegate(
276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            multi_part_response_client, NULL, response, multipart_boundary));
277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Multiple ranges requested, data will be delivered by
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // MultipartResponseDelegate.
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        data_offset_ = 0;
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return;
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int64 upper_bound = 0, instance_size = 0;
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Single range requested - go through original processing for
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // non-multipart requests, but update data offset.
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      MultipartResponseDelegate::ReadContentRanges(
288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          response, &data_offset_, &upper_bound, &instance_size);
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    } else if (response_code == 200) {
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // TODO: should we handle this case? We used to but it's not clear that we
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // still need to. This was bug 5403, fixed in r7139.
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If the length comes in as -1, then it indicates that it was not
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // read off the HTTP headers. We replicate Safari webkit behavior here,
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // which is to set it to 0.
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int expected_length = std::max(static_cast<int>(info.content_length), 0);
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::Time temp;
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  uint32 last_modified = 0;
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string headers;
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (info.headers) {  // NULL for data: urls.
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (info.headers->GetLastModifiedValue(&temp))
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      last_modified = static_cast<uint32>(temp.ToDoubleT());
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     // TODO(darin): Shouldn't we also report HTTP version numbers?
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int response_code = info.headers->response_code();
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    headers = base::StringPrintf("HTTP %d ", response_code);
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    headers += info.headers->GetStatusText();
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    headers += "\n";
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    void* iter = NULL;
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::string name, value;
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    while (info.headers->EnumerateHeaderLines(&iter, &name, &value)) {
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // TODO(darin): Should we really exclude headers with an empty value?
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!name.empty() && !value.empty())
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        headers += name + ": " + value + "\n";
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // error codes in the stream header and as a result, was unaware of the fate
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF destroy
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // the stream and invoke the NPP_DestroyStream function on the plugin if the
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // HTTPrequest fails.
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if ((url_.SchemeIs("http") || url_.SchemeIs("https")) &&
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        (response_code < 100 || response_code >= 400)) {
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pending_failure_notification_ = true;
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  plugin_stream_->DidReceiveResponse(info.mime_type,
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     headers,
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     expected_length,
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     last_modified,
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     request_is_seekable);
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnDownloadedData(int len,
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                        int encoded_data_length) {
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnReceivedData(const char* data,
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      int data_length,
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      int encoded_data_length) {
346c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!plugin_stream_)
347c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (multipart_delegate_) {
350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int64 offset = data_offset_;
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    data_offset_ += data_length;
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (copy_stream_data_) {
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // QuickTime writes to this memory, and since we got it from
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // ResourceDispatcher it's not mapped for write access in this process.
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // http://crbug.com/308466.
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<char[]> data_copy(new char[data_length]);
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      memcpy(data_copy.get(), data, data_length);
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      plugin_stream_->DidReceiveData(data_copy.get(), data_length, offset);
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      plugin_stream_->DidReceiveData(data, data_length, offset);
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // DANGER: this instance may be deleted at this point.
366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PluginURLFetcher::OnCompletedRequest(
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int error_code,
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bool was_ignored_by_handler,
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool stale_copy_in_cache,
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& security_info,
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::TimeTicks& completion_time,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 total_transfer_size) {
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!plugin_stream_)
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (multipart_delegate_) {
380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    multipart_delegate_->OnCompletedRequest();
381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    multipart_delegate_.reset();
382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (error_code == net::OK) {
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    plugin_stream_->DidFinishLoading(resource_id_);
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    plugin_stream_->DidFail(resource_id_);
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace content
392