OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/plugin/plugin_url_fetcher.h" |
| 6 |
| 7 #include "content/child/child_thread.h" |
| 8 #include "content/child/npapi/plugin_host.h" |
| 9 #include "content/child/npapi/webplugin_resource_client.h" |
| 10 #include "content/child/plugin_messages.h" |
| 11 #include "content/child/resource_dispatcher.h" |
| 12 #include "content/plugin/webplugin_proxy.h" |
| 13 #include "net/base/load_flags.h" |
| 14 #include "net/base/net_errors.h" |
| 15 #include "net/http/http_response_headers.h" |
| 16 #include "webkit/common/resource_request_body.h" |
| 17 |
| 18 namespace content { |
| 19 |
| 20 PluginURLFetcher::PluginURLFetcher(WebPluginResourceClient* client, |
| 21 WebPluginProxy* webplugin_proxy, |
| 22 const GURL& url, |
| 23 const GURL& first_party_for_cookies, |
| 24 const std::string& method, |
| 25 const std::string& post_data, |
| 26 const GURL& referrer, |
| 27 bool notify_redirects, |
| 28 bool is_plugin_src_load, |
| 29 int render_process_id, |
| 30 unsigned long resource_id) |
| 31 : client_(client), |
| 32 webplugin_proxy_(webplugin_proxy), |
| 33 url_(url), |
| 34 first_party_for_cookies_(first_party_for_cookies), |
| 35 method_(method), |
| 36 post_data_(post_data), |
| 37 referrer_(referrer), |
| 38 notify_redirects_(notify_redirects), |
| 39 is_plugin_src_load_(is_plugin_src_load), |
| 40 resource_id_(resource_id), |
| 41 data_offset_(0) { |
| 42 webkit_glue::ResourceLoaderBridge::RequestInfo request_info; |
| 43 request_info.method = method; |
| 44 request_info.url = url; |
| 45 request_info.first_party_for_cookies = first_party_for_cookies; |
| 46 request_info.referrer = referrer; |
| 47 request_info.load_flags = net::LOAD_NORMAL; |
| 48 request_info.requestor_pid = render_process_id; |
| 49 request_info.request_type = ResourceType::OBJECT; |
| 50 request_info.routing_id = webplugin_proxy_->host_render_view_routing_id(); |
| 51 |
| 52 std::vector<char> body; |
| 53 if (method == "POST") { |
| 54 std::vector<std::string> names; |
| 55 std::vector<std::string> values; |
| 56 PluginHost::SetPostData( |
| 57 post_data.c_str(), post_data.size(), &names, &values, &body); |
| 58 for (size_t i = 0; i < names.size(); ++i) { |
| 59 if (!request_info.headers.empty()) |
| 60 request_info.headers += "\r\n"; |
| 61 |
| 62 request_info.headers += names[i] + ": " + values[i]; |
| 63 } |
| 64 } |
| 65 |
| 66 bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge( |
| 67 request_info)); |
| 68 if (!body.empty()) { |
| 69 scoped_refptr<webkit_glue::ResourceRequestBody> request_body = |
| 70 new webkit_glue::ResourceRequestBody; |
| 71 request_body->AppendBytes(&body[0], body.size()); |
| 72 bridge_->SetRequestBody(request_body.get()); |
| 73 } |
| 74 |
| 75 bridge_->Start(this); |
| 76 |
| 77 // TODO(jam): range requests |
| 78 } |
| 79 |
| 80 PluginURLFetcher::~PluginURLFetcher() { |
| 81 } |
| 82 |
| 83 void PluginURLFetcher::Cancel() { |
| 84 bridge_->Cancel(); |
| 85 } |
| 86 |
| 87 void PluginURLFetcher::URLRedirectResponse(bool allow) { |
| 88 if (allow) { |
| 89 bridge_->SetDefersLoading(true); |
| 90 } else { |
| 91 bridge_->Cancel(); |
| 92 client_->DidFail(resource_id_); // That will delete |this|. |
| 93 } |
| 94 } |
| 95 |
| 96 void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) { |
| 97 } |
| 98 |
| 99 bool PluginURLFetcher::OnReceivedRedirect( |
| 100 const GURL& new_url, |
| 101 const webkit_glue::ResourceResponseInfo& info, |
| 102 bool* has_new_first_party_for_cookies, |
| 103 GURL* new_first_party_for_cookies) { |
| 104 // TODO(jam): THIS LOGIC IS COPIED FROM WebPluginImpl::willSendRequest until |
| 105 // kDirectNPAPIRequests is the default and we can remove the old path there. |
| 106 |
| 107 // Currently this check is just to catch an https -> http redirect when |
| 108 // loading the main plugin src URL. Longer term, we could investigate |
| 109 // firing mixed diplay or scripting issues for subresource loads |
| 110 // initiated by plug-ins. |
| 111 if (is_plugin_src_load_) { |
| 112 bool result = true; |
| 113 webplugin_proxy_->Send(new PluginHostMsg_CheckIfRunInsecureContent( |
| 114 webplugin_proxy_->host_render_view_routing_id(), new_url, &result)); |
| 115 if (!result) { |
| 116 client_->DidFail(resource_id_); // That will delete |this|. |
| 117 return false; |
| 118 } |
| 119 } |
| 120 |
| 121 // It's unfortunate that this logic of when a redirect's method changes is |
| 122 // in url_request.cc, but weburlloader_impl.cc and this file have to duplicate |
| 123 // it instead of passing that information. |
| 124 if (info.headers->response_code() != 307) |
| 125 method_ = "GET"; |
| 126 GURL old_url = url_; |
| 127 url_ = new_url; |
| 128 *has_new_first_party_for_cookies = true; |
| 129 *new_first_party_for_cookies = first_party_for_cookies_; |
| 130 |
| 131 // If the plugin does not participate in url redirect notifications then just |
| 132 // block cross origin 307 POST redirects. |
| 133 if (!notify_redirects_) { |
| 134 if (info.headers->response_code() == 307 && method_ == "POST" && |
| 135 old_url.GetOrigin() != new_url.GetOrigin()) { |
| 136 client_->DidFail(resource_id_); // That will delete |this|. |
| 137 return false; |
| 138 } |
| 139 } else { |
| 140 // Pause the request while we ask the plugin what to do about the redirect. |
| 141 bridge_->SetDefersLoading(true); |
| 142 client_->WillSendRequest(url_, info.headers->response_code()); |
| 143 } |
| 144 |
| 145 return true; |
| 146 } |
| 147 |
| 148 void PluginURLFetcher::OnReceivedResponse( |
| 149 const webkit_glue::ResourceResponseInfo& info) { |
| 150 // TODO(jam): see WebPluginImpl::didReceiveResponse for request_is_seekable |
| 151 bool request_is_seekable = false; |
| 152 uint32 last_modified = 0; |
| 153 |
| 154 base::Time temp; |
| 155 if (info.headers->GetLastModifiedValue(&temp)) |
| 156 last_modified = static_cast<uint32>(temp.ToDoubleT()); |
| 157 |
| 158 std::string headers = info.headers->raw_headers(); |
| 159 |
| 160 client_->DidReceiveResponse(info.mime_type, |
| 161 headers, |
| 162 info.content_length, |
| 163 last_modified, |
| 164 request_is_seekable); |
| 165 } |
| 166 |
| 167 void PluginURLFetcher::OnDownloadedData(int len, |
| 168 int encoded_data_length) { |
| 169 } |
| 170 |
| 171 void PluginURLFetcher::OnReceivedData(const char* data, |
| 172 int data_length, |
| 173 int encoded_data_length) { |
| 174 client_->DidReceiveData(data, data_length, data_offset_); |
| 175 data_offset_ += data_length; |
| 176 } |
| 177 |
| 178 void PluginURLFetcher::OnCompletedRequest( |
| 179 int error_code, |
| 180 bool was_ignored_by_handler, |
| 181 const std::string& security_info, |
| 182 const base::TimeTicks& completion_time) { |
| 183 if (error_code == net::OK) { |
| 184 client_->DidFinishLoading(resource_id_); |
| 185 } else { |
| 186 client_->DidFail(resource_id_); |
| 187 } |
| 188 } |
| 189 |
| 190 } // namespace content |
OLD | NEW |