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.
5 #include "content/child/npapi/plugin_stream_url.h"
9 #include "base/strings/string_util.h"
10 #include "content/child/npapi/plugin_host.h"
11 #include "content/child/npapi/plugin_instance.h"
12 #include "content/child/npapi/plugin_lib.h"
13 #include "content/child/npapi/plugin_url_fetcher.h"
14 #include "content/child/npapi/webplugin.h"
15 #include "net/http/http_response_headers.h"
19 PluginStreamUrl::PluginStreamUrl(
20 unsigned long resource_id
,
22 PluginInstance
*instance
,
25 : PluginStream(instance
, url
.spec().c_str(), notify_needed
, notify_data
),
30 void PluginStreamUrl::SetPluginURLFetcher(PluginURLFetcher
* fetcher
) {
31 plugin_url_fetcher_
.reset(fetcher
);
34 void PluginStreamUrl::URLRedirectResponse(bool allow
) {
35 if (plugin_url_fetcher_
.get()) {
36 plugin_url_fetcher_
->URLRedirectResponse(allow
);
38 instance()->webplugin()->URLRedirectResponse(allow
, id_
);
42 UpdateUrl(pending_redirect_url_
.c_str());
45 bool PluginStreamUrl::Close(NPReason reason
) {
46 // Protect the stream against it being destroyed or the whole plugin instance
47 // being destroyed within the destroy stream handler.
48 scoped_refptr
<PluginStream
> protect(this);
50 bool result
= PluginStream::Close(reason
);
51 instance()->RemoveStream(this);
55 WebPluginResourceClient
* PluginStreamUrl::AsResourceClient() {
56 return static_cast<WebPluginResourceClient
*>(this);
59 void PluginStreamUrl::CancelRequest() {
61 if (plugin_url_fetcher_
.get()) {
62 plugin_url_fetcher_
->Cancel();
64 if (instance()->webplugin()) {
65 instance()->webplugin()->CancelResource(id_
);
70 if (instance()->webplugin()) {
71 for (size_t i
= 0; i
< range_requests_
.size(); ++i
)
72 instance()->webplugin()->CancelResource(range_requests_
[i
]);
74 range_requests_
.clear();
77 void PluginStreamUrl::WillSendRequest(const GURL
& url
, int http_status_code
) {
78 if (notify_needed()) {
79 // If the plugin participates in HTTP url redirect handling then notify it.
80 if (net::HttpResponseHeaders::IsRedirectResponseCode(http_status_code
) &&
81 instance()->handles_url_redirects()) {
82 pending_redirect_url_
= url
.spec();
83 instance()->NPP_URLRedirectNotify(url
.spec().c_str(), http_status_code
,
89 UpdateUrl(url
.spec().c_str());
92 void PluginStreamUrl::DidReceiveResponse(const std::string
& mime_type
,
93 const std::string
& headers
,
94 uint32 expected_length
,
96 bool request_is_seekable
) {
97 // Protect the stream against it being destroyed or the whole plugin instance
98 // being destroyed within the new stream handler.
99 scoped_refptr
<PluginStream
> protect(this);
101 bool opened
= Open(mime_type
,
105 request_is_seekable
);
108 instance()->RemoveStream(this);
110 SetDeferLoading(false);
114 void PluginStreamUrl::DidReceiveData(const char* buffer
, int length
,
119 // Protect the stream against it being destroyed or the whole plugin instance
120 // being destroyed within the write handlers
121 scoped_refptr
<PluginStream
> protect(this);
124 // The PluginStreamUrl instance could get deleted if the plugin fails to
125 // accept data in NPP_Write.
126 if (Write(const_cast<char*>(buffer
), length
, data_offset
) > 0) {
127 SetDeferLoading(false);
132 void PluginStreamUrl::DidFinishLoading(unsigned long resource_id
) {
136 std::vector
<unsigned long>::iterator it_resource
= std::find(
137 range_requests_
.begin(),
138 range_requests_
.end(),
140 // Resource id must be known to us - either main resource id, or one
141 // of the resources, created for range requests.
142 DCHECK(resource_id
== id_
|| it_resource
!= range_requests_
.end());
143 // We should notify the plugin about failed/finished requests to ensure
144 // that the number of active resource clients does not continue to grow.
145 if (instance()->webplugin())
146 instance()->webplugin()->CancelResource(resource_id
);
147 if (it_resource
!= range_requests_
.end())
148 range_requests_
.erase(it_resource
);
152 void PluginStreamUrl::DidFail(unsigned long resource_id
) {
153 Close(NPRES_NETWORK_ERR
);
156 bool PluginStreamUrl::IsMultiByteResponseExpected() {
160 int PluginStreamUrl::ResourceId() {
164 PluginStreamUrl::~PluginStreamUrl() {
165 if (!plugin_url_fetcher_
.get() && instance() && instance()->webplugin()) {
166 instance()->webplugin()->ResourceClientDeleted(AsResourceClient());
170 void PluginStreamUrl::AddRangeRequestResourceId(unsigned long resource_id
) {
171 DCHECK_NE(resource_id
, 0u);
172 range_requests_
.push_back(resource_id
);
175 void PluginStreamUrl::SetDeferLoading(bool value
) {
176 // If we determined that the request had failed via the HTTP headers in the
177 // response then we send out a failure notification to the plugin process, as
178 // certain plugins don't handle HTTP failure codes correctly.
180 plugin_url_fetcher_
.get() &&
181 plugin_url_fetcher_
->pending_failure_notification()) {
182 // This object may be deleted now.
187 instance()->webplugin()->SetDeferResourceLoading(id_
, value
);
188 for (size_t i
= 0; i
< range_requests_
.size(); ++i
)
189 instance()->webplugin()->SetDeferResourceLoading(range_requests_
[i
],
193 void PluginStreamUrl::UpdateUrl(const char* url
) {
195 free(const_cast<char*>(stream()->url
));
196 stream()->url
= base::strdup(url
);
197 pending_redirect_url_
.clear();
200 } // namespace content