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