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