| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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_stream_url.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/stl_util.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "content/child/npapi/plugin_host.h" | |
| 12 #include "content/child/npapi/plugin_instance.h" | |
| 13 #include "content/child/npapi/plugin_lib.h" | |
| 14 #include "content/child/npapi/plugin_url_fetcher.h" | |
| 15 #include "content/child/npapi/webplugin.h" | |
| 16 #include "net/http/http_response_headers.h" | |
| 17 | |
| 18 namespace content { | |
| 19 | |
| 20 PluginStreamUrl::PluginStreamUrl( | |
| 21 unsigned long resource_id, | |
| 22 const GURL &url, | |
| 23 PluginInstance *instance, | |
| 24 bool notify_needed, | |
| 25 void *notify_data) | |
| 26 : PluginStream(instance, url.spec().c_str(), notify_needed, notify_data), | |
| 27 url_(url), | |
| 28 id_(resource_id) { | |
| 29 } | |
| 30 | |
| 31 void PluginStreamUrl::SetPluginURLFetcher(PluginURLFetcher* fetcher) { | |
| 32 plugin_url_fetcher_.reset(fetcher); | |
| 33 } | |
| 34 | |
| 35 void PluginStreamUrl::URLRedirectResponse(bool allow) { | |
| 36 if (plugin_url_fetcher_.get()) { | |
| 37 plugin_url_fetcher_->URLRedirectResponse(allow); | |
| 38 } else { | |
| 39 instance()->webplugin()->URLRedirectResponse(allow, id_); | |
| 40 } | |
| 41 | |
| 42 if (allow) | |
| 43 UpdateUrl(pending_redirect_url_.c_str()); | |
| 44 } | |
| 45 | |
| 46 void PluginStreamUrl::FetchRange(const std::string& range) { | |
| 47 PluginURLFetcher* range_fetcher = new PluginURLFetcher( | |
| 48 this, url_, plugin_url_fetcher_->first_party_for_cookies(), "GET", NULL, | |
| 49 0, plugin_url_fetcher_->referrer(), range, false, false, | |
| 50 plugin_url_fetcher_->origin_pid(), | |
| 51 plugin_url_fetcher_->render_frame_id(), | |
| 52 plugin_url_fetcher_->render_view_id(), id_, | |
| 53 plugin_url_fetcher_->copy_stream_data()); | |
| 54 range_request_fetchers_.push_back(range_fetcher); | |
| 55 } | |
| 56 | |
| 57 bool PluginStreamUrl::Close(NPReason reason) { | |
| 58 // Protect the stream against it being destroyed or the whole plugin instance | |
| 59 // being destroyed within the destroy stream handler. | |
| 60 scoped_refptr<PluginStream> protect(this); | |
| 61 CancelRequest(); | |
| 62 bool result = PluginStream::Close(reason); | |
| 63 instance()->RemoveStream(this); | |
| 64 return result; | |
| 65 } | |
| 66 | |
| 67 WebPluginResourceClient* PluginStreamUrl::AsResourceClient() { | |
| 68 return static_cast<WebPluginResourceClient*>(this); | |
| 69 } | |
| 70 | |
| 71 void PluginStreamUrl::CancelRequest() { | |
| 72 if (id_ > 0) { | |
| 73 if (plugin_url_fetcher_.get()) { | |
| 74 plugin_url_fetcher_->Cancel(); | |
| 75 } else { | |
| 76 if (instance()->webplugin()) { | |
| 77 instance()->webplugin()->CancelResource(id_); | |
| 78 } | |
| 79 } | |
| 80 id_ = 0; | |
| 81 } | |
| 82 if (instance()->webplugin()) { | |
| 83 for (size_t i = 0; i < range_requests_.size(); ++i) | |
| 84 instance()->webplugin()->CancelResource(range_requests_[i]); | |
| 85 } | |
| 86 | |
| 87 range_requests_.clear(); | |
| 88 | |
| 89 STLDeleteElements(&range_request_fetchers_); | |
| 90 } | |
| 91 | |
| 92 void PluginStreamUrl::WillSendRequest(const GURL& url, int http_status_code) { | |
| 93 if (notify_needed()) { | |
| 94 // If the plugin participates in HTTP url redirect handling then notify it. | |
| 95 if (net::HttpResponseHeaders::IsRedirectResponseCode(http_status_code) && | |
| 96 instance()->handles_url_redirects()) { | |
| 97 pending_redirect_url_ = url.spec(); | |
| 98 instance()->NPP_URLRedirectNotify(url.spec().c_str(), http_status_code, | |
| 99 notify_data()); | |
| 100 return; | |
| 101 } | |
| 102 } | |
| 103 url_ = url; | |
| 104 UpdateUrl(url.spec().c_str()); | |
| 105 } | |
| 106 | |
| 107 void PluginStreamUrl::DidReceiveResponse(const std::string& mime_type, | |
| 108 const std::string& headers, | |
| 109 uint32 expected_length, | |
| 110 uint32 last_modified, | |
| 111 bool request_is_seekable) { | |
| 112 // Protect the stream against it being destroyed or the whole plugin instance | |
| 113 // being destroyed within the new stream handler. | |
| 114 scoped_refptr<PluginStream> protect(this); | |
| 115 | |
| 116 bool opened = Open(mime_type, | |
| 117 headers, | |
| 118 expected_length, | |
| 119 last_modified, | |
| 120 request_is_seekable); | |
| 121 if (!opened) { | |
| 122 CancelRequest(); | |
| 123 instance()->RemoveStream(this); | |
| 124 } else { | |
| 125 SetDeferLoading(false); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 void PluginStreamUrl::DidReceiveData(const char* buffer, int length, | |
| 130 int data_offset) { | |
| 131 if (!open()) | |
| 132 return; | |
| 133 | |
| 134 // Protect the stream against it being destroyed or the whole plugin instance | |
| 135 // being destroyed within the write handlers | |
| 136 scoped_refptr<PluginStream> protect(this); | |
| 137 | |
| 138 if (length > 0) { | |
| 139 // The PluginStreamUrl instance could get deleted if the plugin fails to | |
| 140 // accept data in NPP_Write. | |
| 141 if (Write(const_cast<char*>(buffer), length, data_offset) > 0) { | |
| 142 SetDeferLoading(false); | |
| 143 } | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void PluginStreamUrl::DidFinishLoading(unsigned long resource_id) { | |
| 148 if (!seekable()) { | |
| 149 Close(NPRES_DONE); | |
| 150 } else { | |
| 151 std::vector<unsigned long>::iterator it_resource = std::find( | |
| 152 range_requests_.begin(), | |
| 153 range_requests_.end(), | |
| 154 resource_id); | |
| 155 // Resource id must be known to us - either main resource id, or one | |
| 156 // of the resources, created for range requests. | |
| 157 DCHECK(resource_id == id_ || it_resource != range_requests_.end()); | |
| 158 // We should notify the plugin about failed/finished requests to ensure | |
| 159 // that the number of active resource clients does not continue to grow. | |
| 160 if (instance()->webplugin()) | |
| 161 instance()->webplugin()->CancelResource(resource_id); | |
| 162 if (it_resource != range_requests_.end()) | |
| 163 range_requests_.erase(it_resource); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 void PluginStreamUrl::DidFail(unsigned long resource_id) { | |
| 168 Close(NPRES_NETWORK_ERR); | |
| 169 } | |
| 170 | |
| 171 bool PluginStreamUrl::IsMultiByteResponseExpected() { | |
| 172 return seekable(); | |
| 173 } | |
| 174 | |
| 175 int PluginStreamUrl::ResourceId() { | |
| 176 return id_; | |
| 177 } | |
| 178 | |
| 179 PluginStreamUrl::~PluginStreamUrl() { | |
| 180 if (!plugin_url_fetcher_.get() && instance() && instance()->webplugin()) { | |
| 181 instance()->webplugin()->ResourceClientDeleted(AsResourceClient()); | |
| 182 } | |
| 183 | |
| 184 STLDeleteElements(&range_request_fetchers_); | |
| 185 } | |
| 186 | |
| 187 void PluginStreamUrl::AddRangeRequestResourceId(unsigned long resource_id) { | |
| 188 DCHECK_NE(resource_id, 0u); | |
| 189 range_requests_.push_back(resource_id); | |
| 190 } | |
| 191 | |
| 192 void PluginStreamUrl::SetDeferLoading(bool value) { | |
| 193 // If we determined that the request had failed via the HTTP headers in the | |
| 194 // response then we send out a failure notification to the plugin process, as | |
| 195 // certain plugins don't handle HTTP failure codes correctly. | |
| 196 if (plugin_url_fetcher_.get()) { | |
| 197 if (!value && plugin_url_fetcher_->pending_failure_notification()) { | |
| 198 // This object may be deleted now. | |
| 199 DidFail(id_); | |
| 200 } | |
| 201 return; | |
| 202 } | |
| 203 if (id_ > 0) | |
| 204 instance()->webplugin()->SetDeferResourceLoading(id_, value); | |
| 205 for (size_t i = 0; i < range_requests_.size(); ++i) | |
| 206 instance()->webplugin()->SetDeferResourceLoading(range_requests_[i], | |
| 207 value); | |
| 208 } | |
| 209 | |
| 210 void PluginStreamUrl::UpdateUrl(const char* url) { | |
| 211 DCHECK(!open()); | |
| 212 free(const_cast<char*>(stream()->url)); | |
| 213 stream()->url = base::strdup(url); | |
| 214 pending_redirect_url_.clear(); | |
| 215 } | |
| 216 | |
| 217 } // namespace content | |
| OLD | NEW |