OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/npapi/webplugin_impl.h" | 5 #include "content/renderer/npapi/webplugin_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/crash_logging.h" | 9 #include "base/debug/crash_logging.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 #include "skia/ext/platform_canvas.h" | 40 #include "skia/ext/platform_canvas.h" |
41 #include "third_party/WebKit/public/platform/WebCString.h" | 41 #include "third_party/WebKit/public/platform/WebCString.h" |
42 #include "third_party/WebKit/public/platform/WebCookieJar.h" | 42 #include "third_party/WebKit/public/platform/WebCookieJar.h" |
43 #include "third_party/WebKit/public/platform/WebCursorInfo.h" | 43 #include "third_party/WebKit/public/platform/WebCursorInfo.h" |
44 #include "third_party/WebKit/public/platform/WebData.h" | 44 #include "third_party/WebKit/public/platform/WebData.h" |
45 #include "third_party/WebKit/public/platform/WebHTTPBody.h" | 45 #include "third_party/WebKit/public/platform/WebHTTPBody.h" |
46 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | 46 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" |
47 #include "third_party/WebKit/public/platform/WebURL.h" | 47 #include "third_party/WebKit/public/platform/WebURL.h" |
48 #include "third_party/WebKit/public/platform/WebURLError.h" | 48 #include "third_party/WebKit/public/platform/WebURLError.h" |
49 #include "third_party/WebKit/public/platform/WebURLLoader.h" | 49 #include "third_party/WebKit/public/platform/WebURLLoader.h" |
50 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | |
51 #include "third_party/WebKit/public/platform/WebURLResponse.h" | 50 #include "third_party/WebKit/public/platform/WebURLResponse.h" |
52 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | 51 #include "third_party/WebKit/public/web/WebConsoleMessage.h" |
53 #include "third_party/WebKit/public/web/WebDocument.h" | 52 #include "third_party/WebKit/public/web/WebDocument.h" |
54 #include "third_party/WebKit/public/web/WebFrame.h" | 53 #include "third_party/WebKit/public/web/WebFrame.h" |
55 #include "third_party/WebKit/public/web/WebInputEvent.h" | 54 #include "third_party/WebKit/public/web/WebInputEvent.h" |
56 #include "third_party/WebKit/public/web/WebKit.h" | 55 #include "third_party/WebKit/public/web/WebKit.h" |
57 #include "third_party/WebKit/public/web/WebPluginContainer.h" | 56 #include "third_party/WebKit/public/web/WebPluginContainer.h" |
58 #include "third_party/WebKit/public/web/WebPluginParams.h" | 57 #include "third_party/WebKit/public/web/WebPluginParams.h" |
59 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" | 58 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" |
60 #include "third_party/WebKit/public/web/WebView.h" | 59 #include "third_party/WebKit/public/web/WebView.h" |
(...skipping 15 matching lines...) Expand all Loading... |
76 using blink::WebInputEventResult; | 75 using blink::WebInputEventResult; |
77 using blink::WebKeyboardEvent; | 76 using blink::WebKeyboardEvent; |
78 using blink::WebMouseEvent; | 77 using blink::WebMouseEvent; |
79 using blink::WebPluginContainer; | 78 using blink::WebPluginContainer; |
80 using blink::WebPluginParams; | 79 using blink::WebPluginParams; |
81 using blink::WebRect; | 80 using blink::WebRect; |
82 using blink::WebString; | 81 using blink::WebString; |
83 using blink::WebURL; | 82 using blink::WebURL; |
84 using blink::WebURLError; | 83 using blink::WebURLError; |
85 using blink::WebURLLoader; | 84 using blink::WebURLLoader; |
86 using blink::WebURLLoaderClient; | |
87 using blink::WebURLLoaderOptions; | 85 using blink::WebURLLoaderOptions; |
88 using blink::WebURLRequest; | 86 using blink::WebURLRequest; |
89 using blink::WebURLResponse; | 87 using blink::WebURLResponse; |
90 using blink::WebVector; | 88 using blink::WebVector; |
91 using blink::WebView; | 89 using blink::WebView; |
92 | 90 |
93 namespace content { | 91 namespace content { |
94 | 92 |
95 namespace { | |
96 | |
97 // This class handles individual multipart responses. It is instantiated when | |
98 // we receive HTTP status code 206 in the HTTP response. This indicates | |
99 // that the response could have multiple parts each separated by a boundary | |
100 // specified in the response header. | |
101 class MultiPartResponseClient : public WebURLLoaderClient { | |
102 public: | |
103 explicit MultiPartResponseClient(WebPluginResourceClient* resource_client) | |
104 : byte_range_lower_bound_(0), resource_client_(resource_client) {} | |
105 | |
106 void willFollowRedirect(WebURLLoader*, | |
107 WebURLRequest&, | |
108 const WebURLResponse&) override {} | |
109 void didSendData(WebURLLoader*, | |
110 unsigned long long, | |
111 unsigned long long) override {} | |
112 | |
113 // Called when the multipart parser encounters an embedded multipart | |
114 // response. | |
115 void didReceiveResponse(WebURLLoader*, | |
116 const WebURLResponse& response) override { | |
117 int64_t byte_range_upper_bound, instance_size; | |
118 if (!MultipartResponseDelegate::ReadContentRanges( | |
119 response, | |
120 &byte_range_lower_bound_, | |
121 &byte_range_upper_bound, | |
122 &instance_size)) { | |
123 NOTREACHED(); | |
124 } | |
125 } | |
126 | |
127 // Receives individual part data from a multipart response. | |
128 void didReceiveData(WebURLLoader*, | |
129 const char* data, | |
130 int data_length, | |
131 int encoded_data_length) override { | |
132 // TODO(ananta) | |
133 // We should defer further loads on multipart resources on the same lines | |
134 // as regular resources requested by plugins to prevent reentrancy. | |
135 resource_client_->DidReceiveData( | |
136 data, data_length, byte_range_lower_bound_); | |
137 byte_range_lower_bound_ += data_length; | |
138 } | |
139 | |
140 void didFinishLoading(WebURLLoader*, | |
141 double finishTime, | |
142 int64_t total_encoded_data_length) override {} | |
143 void didFail(WebURLLoader*, const WebURLError&) override {} | |
144 | |
145 private: | |
146 // The lower bound of the byte range. | |
147 int64_t byte_range_lower_bound_; | |
148 // The handler for the data. | |
149 WebPluginResourceClient* resource_client_; | |
150 }; | |
151 | |
152 class HeaderFlattener : public WebHTTPHeaderVisitor { | |
153 public: | |
154 explicit HeaderFlattener(std::string* buf) : buf_(buf) { | |
155 } | |
156 | |
157 void visitHeader(const WebString& name, const WebString& value) override { | |
158 // TODO(darin): Should we really exclude headers with an empty value? | |
159 if (!name.isEmpty() && !value.isEmpty()) { | |
160 buf_->append(name.utf8()); | |
161 buf_->append(": "); | |
162 buf_->append(value.utf8()); | |
163 buf_->append("\n"); | |
164 } | |
165 } | |
166 | |
167 private: | |
168 std::string* buf_; | |
169 }; | |
170 | |
171 std::string GetAllHeaders(const WebURLResponse& response) { | |
172 // TODO(darin): It is possible for httpStatusText to be empty and still have | |
173 // an interesting response, so this check seems wrong. | |
174 std::string result; | |
175 const WebString& status = response.httpStatusText(); | |
176 if (status.isEmpty()) | |
177 return result; | |
178 | |
179 // TODO(darin): Shouldn't we also report HTTP version numbers? | |
180 result = base::StringPrintf("HTTP %d ", response.httpStatusCode()); | |
181 result.append(status.utf8()); | |
182 result.append("\n"); | |
183 | |
184 HeaderFlattener flattener(&result); | |
185 response.visitHTTPHeaderFields(&flattener); | |
186 | |
187 return result; | |
188 } | |
189 | |
190 struct ResponseInfo { | |
191 GURL url; | |
192 std::string mime_type; | |
193 uint32_t last_modified; | |
194 uint32_t expected_length; | |
195 }; | |
196 | |
197 void GetResponseInfo(const WebURLResponse& response, | |
198 ResponseInfo* response_info) { | |
199 response_info->url = response.url(); | |
200 response_info->mime_type = response.mimeType().utf8(); | |
201 | |
202 // Measured in seconds since 12:00 midnight GMT, January 1, 1970. | |
203 response_info->last_modified = | |
204 static_cast<uint32_t>(response.lastModifiedDate()); | |
205 | |
206 // If the length comes in as -1, then it indicates that it was not | |
207 // read off the HTTP headers. We replicate Safari webkit behavior here, | |
208 // which is to set it to 0. | |
209 response_info->expected_length = | |
210 static_cast<uint32_t>(std::max(response.expectedContentLength(), 0LL)); | |
211 | |
212 WebString content_encoding = | |
213 response.httpHeaderField(WebString::fromUTF8("Content-Encoding")); | |
214 if (!content_encoding.isNull() && | |
215 !base::EqualsASCII(base::StringPiece16(content_encoding), "identity")) { | |
216 // Don't send the compressed content length to the plugin, which only | |
217 // cares about the decoded length. | |
218 response_info->expected_length = 0; | |
219 } | |
220 } | |
221 | |
222 } // namespace | |
223 | |
224 // blink::WebPlugin ---------------------------------------------------------- | 93 // blink::WebPlugin ---------------------------------------------------------- |
225 | 94 |
226 struct WebPluginImpl::ClientInfo { | |
227 unsigned long id; | |
228 WebPluginResourceClient* client; | |
229 blink::WebURLRequest request; | |
230 bool pending_failure_notification; | |
231 linked_ptr<blink::WebURLLoader> loader; | |
232 bool notify_redirects; | |
233 bool is_plugin_src_load; | |
234 int64_t data_offset; | |
235 }; | |
236 | |
237 bool WebPluginImpl::initialize(WebPluginContainer* container) { | 95 bool WebPluginImpl::initialize(WebPluginContainer* container) { |
238 if (!render_view_.get()) { | 96 if (!render_view_.get()) { |
239 LOG(ERROR) << "No RenderView"; | 97 LOG(ERROR) << "No RenderView"; |
240 return false; | 98 return false; |
241 } | 99 } |
242 | 100 |
243 WebPluginDelegateProxy* plugin_delegate = new WebPluginDelegateProxy( | 101 WebPluginDelegateProxy* plugin_delegate = new WebPluginDelegateProxy( |
244 this, mime_type_, render_view_, render_frame_); | 102 this, mime_type_, render_view_, render_frame_); |
245 | 103 |
246 // Store the plugin's unique identifier, used by the container to track its | 104 // Store the plugin's unique identifier, used by the container to track its |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 cursor_info.externalHandle = web_cursor_info.external_handle; | 278 cursor_info.externalHandle = web_cursor_info.external_handle; |
421 #endif | 279 #endif |
422 return ret ? WebInputEventResult::HandledApplication | 280 return ret ? WebInputEventResult::HandledApplication |
423 : WebInputEventResult::NotHandled; | 281 : WebInputEventResult::NotHandled; |
424 } | 282 } |
425 | 283 |
426 bool WebPluginImpl::isPlaceholder() { | 284 bool WebPluginImpl::isPlaceholder() { |
427 return false; | 285 return false; |
428 } | 286 } |
429 | 287 |
430 WebPluginImpl::LoaderClient::LoaderClient(WebPluginImpl* parent) | |
431 : parent_(parent) {} | |
432 | |
433 void WebPluginImpl::LoaderClient::willFollowRedirect( | |
434 blink::WebURLLoader* loader, blink::WebURLRequest& new_request, | |
435 const blink::WebURLResponse& redirect_response) { | |
436 parent_->willFollowRedirect(loader, new_request, redirect_response); | |
437 } | |
438 | |
439 void WebPluginImpl::LoaderClient::didSendData( | |
440 blink::WebURLLoader* loader, unsigned long long bytesSent, | |
441 unsigned long long totalBytesToBeSent) { | |
442 parent_->didSendData(loader, bytesSent, totalBytesToBeSent); | |
443 } | |
444 | |
445 void WebPluginImpl::LoaderClient::didReceiveResponse( | |
446 blink::WebURLLoader* loader, const blink::WebURLResponse& response) { | |
447 parent_->didReceiveResponse(loader, response); | |
448 } | |
449 | |
450 void WebPluginImpl::LoaderClient::didDownloadData( | |
451 blink::WebURLLoader* loader, int dataLength, int encodedDataLength) { | |
452 } | |
453 | |
454 void WebPluginImpl::LoaderClient::didReceiveData( | |
455 blink::WebURLLoader* loader, const char* data, | |
456 int dataLength, int encodedDataLength) { | |
457 parent_->didReceiveData(loader, data, dataLength, encodedDataLength); | |
458 } | |
459 | |
460 void WebPluginImpl::LoaderClient::didReceiveCachedMetadata( | |
461 blink::WebURLLoader* loader, const char* data, int dataLength) { | |
462 } | |
463 | |
464 void WebPluginImpl::LoaderClient::didFinishLoading( | |
465 blink::WebURLLoader* loader, double finishTime, | |
466 int64_t total_encoded_data_length) { | |
467 parent_->didFinishLoading(loader, finishTime); | |
468 } | |
469 | |
470 void WebPluginImpl::LoaderClient::didFail( | |
471 blink::WebURLLoader* loader, const blink::WebURLError& error) { | |
472 parent_->didFail(loader, error); | |
473 } | |
474 | |
475 // ----------------------------------------------------------------------------- | 288 // ----------------------------------------------------------------------------- |
476 | 289 |
477 WebPluginImpl::WebPluginImpl( | 290 WebPluginImpl::WebPluginImpl( |
478 WebFrame* webframe, | 291 WebFrame* webframe, |
479 const WebPluginParams& params, | 292 const WebPluginParams& params, |
480 const base::FilePath& file_path, | 293 const base::FilePath& file_path, |
481 const base::WeakPtr<RenderViewImpl>& render_view, | 294 const base::WeakPtr<RenderViewImpl>& render_view, |
482 RenderFrameImpl* render_frame) | 295 RenderFrameImpl* render_frame) |
483 : windowless_(false), | 296 : windowless_(false), |
484 window_(gfx::kNullPluginWindow), | 297 window_(gfx::kNullPluginWindow), |
485 accepts_input_events_(false), | 298 accepts_input_events_(false), |
486 render_frame_(render_frame), | 299 render_frame_(render_frame), |
487 render_view_(render_view), | 300 render_view_(render_view), |
488 webframe_(webframe), | 301 webframe_(webframe), |
489 delegate_(NULL), | 302 delegate_(NULL), |
490 container_(NULL), | 303 container_(NULL), |
491 npp_(NULL), | 304 npp_(NULL), |
492 plugin_url_(params.url), | 305 plugin_url_(params.url), |
493 load_manually_(params.loadManually), | 306 load_manually_(params.loadManually), |
494 first_geometry_update_(true), | 307 first_geometry_update_(true), |
495 ignore_response_error_(false), | 308 ignore_response_error_(false), |
496 file_path_(file_path), | 309 file_path_(file_path), |
497 mime_type_(base::ToLowerASCII(base::UTF16ToASCII( | 310 mime_type_(base::ToLowerASCII(base::UTF16ToASCII( |
498 base::StringPiece16(params.mimeType)))), | 311 base::StringPiece16(params.mimeType)))) { |
499 loader_client_(this) { | |
500 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); | 312 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); |
501 | 313 |
502 for (size_t i = 0; i < params.attributeNames.size(); ++i) { | 314 for (size_t i = 0; i < params.attributeNames.size(); ++i) { |
503 arg_names_.push_back(params.attributeNames[i].utf8()); | 315 arg_names_.push_back(params.attributeNames[i].utf8()); |
504 arg_values_.push_back(params.attributeValues[i].utf8()); | 316 arg_values_.push_back(params.attributeValues[i].utf8()); |
505 } | 317 } |
506 | 318 |
507 // Set subresource URL for crash reporting. | 319 // Set subresource URL for crash reporting. |
508 base::debug::SetCrashKeyValue("subresource_url", plugin_url_.spec()); | 320 base::debug::SetCrashKeyValue("subresource_url", plugin_url_.spec()); |
509 } | 321 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 | 360 |
549 GURL WebPluginImpl::CompleteURL(const char* url) { | 361 GURL WebPluginImpl::CompleteURL(const char* url) { |
550 if (!webframe_) { | 362 if (!webframe_) { |
551 NOTREACHED(); | 363 NOTREACHED(); |
552 return GURL(); | 364 return GURL(); |
553 } | 365 } |
554 // TODO(darin): Is conversion from UTF8 correct here? | 366 // TODO(darin): Is conversion from UTF8 correct here? |
555 return webframe_->document().completeURL(WebString::fromUTF8(url)); | 367 return webframe_->document().completeURL(WebString::fromUTF8(url)); |
556 } | 368 } |
557 | 369 |
558 void WebPluginImpl::CancelResource(unsigned long id) { | |
559 for (size_t i = 0; i < clients_.size(); ++i) { | |
560 if (clients_[i].id == id) { | |
561 if (clients_[i].loader.get()) { | |
562 clients_[i].loader->setDefersLoading(false); | |
563 clients_[i].loader->cancel(); | |
564 RemoveClient(i); | |
565 } | |
566 return; | |
567 } | |
568 } | |
569 } | |
570 | |
571 bool WebPluginImpl::SetPostData(WebURLRequest* request, | 370 bool WebPluginImpl::SetPostData(WebURLRequest* request, |
572 const char* buf, | 371 const char* buf, |
573 uint32_t length) { | 372 uint32_t length) { |
574 std::vector<std::string> names; | 373 std::vector<std::string> names; |
575 std::vector<std::string> values; | 374 std::vector<std::string> values; |
576 std::vector<char> body; | 375 std::vector<char> body; |
577 bool rv = PluginHost::SetPostData(buf, length, &names, &values, &body); | 376 bool rv = PluginHost::SetPostData(buf, length, &names, &values, &body); |
578 | 377 |
579 for (size_t i = 0; i < names.size(); ++i) { | 378 for (size_t i = 0; i < names.size(); ++i) { |
580 request->addHTTPHeaderField(WebString::fromUTF8(names[i]), | 379 request->addHTTPHeaderField(WebString::fromUTF8(names[i]), |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 WebCookieJar* cookie_jar = render_frame_->cookie_jar(); | 538 WebCookieJar* cookie_jar = render_frame_->cookie_jar(); |
740 if (!cookie_jar) { | 539 if (!cookie_jar) { |
741 DLOG(WARNING) << "No cookie jar!"; | 540 DLOG(WARNING) << "No cookie jar!"; |
742 return std::string(); | 541 return std::string(); |
743 } | 542 } |
744 | 543 |
745 return base::UTF16ToUTF8(base::StringPiece16( | 544 return base::UTF16ToUTF8(base::StringPiece16( |
746 cookie_jar->cookies(url, first_party_for_cookies))); | 545 cookie_jar->cookies(url, first_party_for_cookies))); |
747 } | 546 } |
748 | 547 |
749 void WebPluginImpl::URLRedirectResponse(bool allow, int resource_id) { | |
750 for (size_t i = 0; i < clients_.size(); ++i) { | |
751 if (clients_[i].id == static_cast<unsigned long>(resource_id)) { | |
752 if (clients_[i].loader.get()) { | |
753 if (allow) { | |
754 clients_[i].loader->setDefersLoading(false); | |
755 } else { | |
756 clients_[i].loader->cancel(); | |
757 if (clients_[i].client) | |
758 clients_[i].client->DidFail(clients_[i].id); | |
759 } | |
760 } | |
761 break; | |
762 } | |
763 } | |
764 } | |
765 | |
766 #if defined(OS_MACOSX) | 548 #if defined(OS_MACOSX) |
767 WebPluginAcceleratedSurface* WebPluginImpl::GetAcceleratedSurface( | 549 WebPluginAcceleratedSurface* WebPluginImpl::GetAcceleratedSurface( |
768 gfx::GpuPreference gpu_preference) { | 550 gfx::GpuPreference gpu_preference) { |
769 return NULL; | 551 return NULL; |
770 } | 552 } |
771 | 553 |
772 void WebPluginImpl::AcceleratedPluginEnabledRendering() { | 554 void WebPluginImpl::AcceleratedPluginEnabledRendering() { |
773 } | 555 } |
774 | 556 |
775 void WebPluginImpl::AcceleratedPluginAllocatedIOSurface(int32_t width, | 557 void WebPluginImpl::AcceleratedPluginAllocatedIOSurface(int32_t width, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 void WebPluginImpl::Invalidate() { | 600 void WebPluginImpl::Invalidate() { |
819 if (container_) | 601 if (container_) |
820 container_->invalidate(); | 602 container_->invalidate(); |
821 } | 603 } |
822 | 604 |
823 void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { | 605 void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { |
824 if (container_) | 606 if (container_) |
825 container_->invalidateRect(rect); | 607 container_->invalidateRect(rect); |
826 } | 608 } |
827 | 609 |
828 WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( | |
829 WebURLLoader* loader) { | |
830 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
831 if (client_info) | |
832 return client_info->client; | |
833 return NULL; | |
834 } | |
835 | |
836 WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader( | |
837 WebURLLoader* loader) { | |
838 for (size_t i = 0; i < clients_.size(); ++i) { | |
839 if (clients_[i].loader.get() == loader) | |
840 return &clients_[i]; | |
841 } | |
842 | |
843 NOTREACHED(); | |
844 return 0; | |
845 } | |
846 | |
847 void WebPluginImpl::willFollowRedirect(WebURLLoader* loader, | |
848 WebURLRequest& new_request, | |
849 const WebURLResponse& response) { | |
850 // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedRedirect | |
851 // until kDirectNPAPIRequests is the default and we can remove this old path. | |
852 WebPluginImpl::ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
853 if (client_info) { | |
854 if (net::HttpResponseHeaders::IsRedirectResponseCode( | |
855 response.httpStatusCode())) { | |
856 // If the plugin does not participate in url redirect notifications then | |
857 // just block cross origin 307 POST redirects. | |
858 if (!client_info->notify_redirects) { | |
859 if (response.httpStatusCode() == 307 && | |
860 base::LowerCaseEqualsASCII( | |
861 new_request.httpMethod().utf8(), "post")) { | |
862 GURL original_request_url(response.url()); | |
863 GURL response_url(new_request.url()); | |
864 if (original_request_url.GetOrigin() != response_url.GetOrigin()) { | |
865 loader->setDefersLoading(true); | |
866 loader->cancel(); | |
867 client_info->client->DidFail(client_info->id); | |
868 return; | |
869 } | |
870 } | |
871 } else { | |
872 loader->setDefersLoading(true); | |
873 } | |
874 } | |
875 client_info->client->WillSendRequest(new_request.url(), | |
876 response.httpStatusCode()); | |
877 } | |
878 } | |
879 | |
880 void WebPluginImpl::didSendData(WebURLLoader* loader, | |
881 unsigned long long bytes_sent, | |
882 unsigned long long total_bytes_to_be_sent) { | |
883 } | |
884 | |
885 void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, | |
886 const WebURLResponse& response) { | |
887 // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedResponse | |
888 // until kDirectNPAPIRequests is the default and we can remove this old path. | |
889 | |
890 WebPluginResourceClient* client = GetClientFromLoader(loader); | |
891 if (!client) | |
892 return; | |
893 | |
894 ResponseInfo response_info; | |
895 GetResponseInfo(response, &response_info); | |
896 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
897 if (!client_info) | |
898 return; | |
899 | |
900 // Calling into a plugin could result in reentrancy if the plugin yields | |
901 // control to the OS like entering a modal loop etc. Prevent this by | |
902 // stopping further loading until the plugin notifies us that it is ready to | |
903 // accept data | |
904 loader->setDefersLoading(true); | |
905 | |
906 client->DidReceiveResponse( | |
907 response_info.mime_type, | |
908 GetAllHeaders(response), | |
909 response_info.expected_length, | |
910 response_info.last_modified, | |
911 true); | |
912 | |
913 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP | |
914 // error codes in the stream header and as a result, was unaware of the | |
915 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF | |
916 // destroy the stream and invoke the NPP_DestroyStream function on the | |
917 // plugin if the HTTP request fails. | |
918 const GURL& url = response.url(); | |
919 if (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme)) { | |
920 if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { | |
921 // The plugin instance could be in the process of deletion here. | |
922 // Verify if the WebPluginResourceClient instance still exists before | |
923 // use. | |
924 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
925 if (client_info) { | |
926 client_info->pending_failure_notification = true; | |
927 } | |
928 } | |
929 } | |
930 } | |
931 | |
932 void WebPluginImpl::didReceiveData(WebURLLoader* loader, | |
933 const char *buffer, | |
934 int data_length, | |
935 int encoded_data_length) { | |
936 WebPluginResourceClient* client = GetClientFromLoader(loader); | |
937 if (!client) | |
938 return; | |
939 | |
940 MultiPartResponseHandlerMap::iterator index = | |
941 multi_part_response_map_.find(client); | |
942 if (index != multi_part_response_map_.end()) { | |
943 MultipartResponseDelegate* multi_part_handler = (*index).second; | |
944 DCHECK(multi_part_handler != NULL); | |
945 multi_part_handler->OnReceivedData(buffer, | |
946 data_length, | |
947 encoded_data_length); | |
948 } else { | |
949 loader->setDefersLoading(true); | |
950 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
951 client->DidReceiveData(buffer, data_length, client_info->data_offset); | |
952 client_info->data_offset += data_length; | |
953 } | |
954 } | |
955 | |
956 void WebPluginImpl::didFinishLoading(WebURLLoader* loader, double finishTime) { | |
957 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
958 if (client_info && client_info->client) { | |
959 MultiPartResponseHandlerMap::iterator index = | |
960 multi_part_response_map_.find(client_info->client); | |
961 if (index != multi_part_response_map_.end()) { | |
962 delete (*index).second; | |
963 multi_part_response_map_.erase(index); | |
964 DidStopLoading(); | |
965 } | |
966 loader->setDefersLoading(true); | |
967 WebPluginResourceClient* resource_client = client_info->client; | |
968 // The ClientInfo can get deleted in the call to DidFinishLoading below. | |
969 // It is not safe to access this structure after that. | |
970 client_info->client = NULL; | |
971 resource_client->DidFinishLoading(client_info->id); | |
972 } | |
973 } | |
974 | |
975 void WebPluginImpl::didFail(WebURLLoader* loader, | |
976 const WebURLError& error) { | |
977 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
978 if (client_info && client_info->client) { | |
979 loader->setDefersLoading(true); | |
980 WebPluginResourceClient* resource_client = client_info->client; | |
981 // The ClientInfo can get deleted in the call to DidFail below. | |
982 // It is not safe to access this structure after that. | |
983 client_info->client = NULL; | |
984 resource_client->DidFail(client_info->id); | |
985 } | |
986 } | |
987 | |
988 void WebPluginImpl::RemoveClient(size_t i) { | |
989 clients_.erase(clients_.begin() + i); | |
990 } | |
991 | |
992 void WebPluginImpl::RemoveClient(WebURLLoader* loader) { | |
993 for (size_t i = 0; i < clients_.size(); ++i) { | |
994 if (clients_[i].loader.get() == loader) { | |
995 RemoveClient(i); | |
996 return; | |
997 } | |
998 } | |
999 } | |
1000 | |
1001 void WebPluginImpl::SetContainer(WebPluginContainer* container) { | 610 void WebPluginImpl::SetContainer(WebPluginContainer* container) { |
1002 if (!container) | 611 if (!container) |
1003 TearDownPluginInstance(NULL); | 612 TearDownPluginInstance(NULL); |
1004 container_ = container; | 613 container_ = container; |
1005 if (container_) | 614 if (container_) |
1006 container_->allowScriptObjects(); | 615 container_->allowScriptObjects(); |
1007 } | 616 } |
1008 | 617 |
1009 unsigned long WebPluginImpl::GetNextResourceId() { | 618 unsigned long WebPluginImpl::GetNextResourceId() { |
1010 if (!webframe_) | 619 if (!webframe_) |
(...skipping 18 matching lines...) Expand all Loading... |
1029 } | 638 } |
1030 } | 639 } |
1031 | 640 |
1032 void WebPluginImpl::DidStopLoading() { | 641 void WebPluginImpl::DidStopLoading() { |
1033 if (render_view_.get()) { | 642 if (render_view_.get()) { |
1034 // TODO(darin): Make is_loading_ be a counter! | 643 // TODO(darin): Make is_loading_ be a counter! |
1035 render_view_->DidStopLoading(); | 644 render_view_->DidStopLoading(); |
1036 } | 645 } |
1037 } | 646 } |
1038 | 647 |
1039 void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id, | |
1040 bool defer) { | |
1041 std::vector<ClientInfo>::iterator client_index = clients_.begin(); | |
1042 while (client_index != clients_.end()) { | |
1043 ClientInfo& client_info = *client_index; | |
1044 | |
1045 if (client_info.id == resource_id) { | |
1046 client_info.loader->setDefersLoading(defer); | |
1047 | |
1048 // If we determined that the request had failed via the HTTP headers | |
1049 // in the response then we send out a failure notification to the | |
1050 // plugin process, as certain plugins don't handle HTTP failure codes | |
1051 // correctly. | |
1052 if (!defer && client_info.client && | |
1053 client_info.pending_failure_notification) { | |
1054 // The ClientInfo and the iterator can become invalid due to the call | |
1055 // to DidFail below. | |
1056 WebPluginResourceClient* resource_client = client_info.client; | |
1057 client_info.loader->cancel(); | |
1058 clients_.erase(client_index++); | |
1059 resource_client->DidFail(resource_id); | |
1060 } | |
1061 break; | |
1062 } | |
1063 client_index++; | |
1064 } | |
1065 } | |
1066 | |
1067 bool WebPluginImpl::IsOffTheRecord() { | 648 bool WebPluginImpl::IsOffTheRecord() { |
1068 return false; | 649 return false; |
1069 } | 650 } |
1070 | 651 |
1071 bool WebPluginImpl::HandleHttpMultipartResponse( | |
1072 const WebURLResponse& response, WebPluginResourceClient* client) { | |
1073 std::string multipart_boundary; | |
1074 if (!MultipartResponseDelegate::ReadMultipartBoundary( | |
1075 response, &multipart_boundary)) { | |
1076 return false; | |
1077 } | |
1078 | |
1079 DidStartLoading(); | |
1080 | |
1081 MultiPartResponseClient* multi_part_response_client = | |
1082 new MultiPartResponseClient(client); | |
1083 | |
1084 MultipartResponseDelegate* multi_part_response_handler = | |
1085 new MultipartResponseDelegate(multi_part_response_client, NULL, | |
1086 response, | |
1087 multipart_boundary); | |
1088 multi_part_response_map_[client] = multi_part_response_handler; | |
1089 return true; | |
1090 } | |
1091 | |
1092 bool WebPluginImpl::ReinitializePluginForResponse( | 652 bool WebPluginImpl::ReinitializePluginForResponse( |
1093 WebURLLoader* loader) { | 653 WebURLLoader* loader) { |
1094 WebFrame* webframe = webframe_; | 654 WebFrame* webframe = webframe_; |
1095 if (!webframe) | 655 if (!webframe) |
1096 return false; | 656 return false; |
1097 | 657 |
1098 WebView* webview = webframe->view(); | 658 WebView* webview = webframe->view(); |
1099 if (!webview) | 659 if (!webview) |
1100 return false; | 660 return false; |
1101 | 661 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 container_->allowScriptObjects(); | 722 container_->allowScriptObjects(); |
1163 | 723 |
1164 delegate_->PluginDestroyed(); | 724 delegate_->PluginDestroyed(); |
1165 delegate_ = NULL; | 725 delegate_ = NULL; |
1166 | 726 |
1167 // Invalidate any script objects created during teardown here, before the | 727 // Invalidate any script objects created during teardown here, before the |
1168 // plugin might actually be unloaded. | 728 // plugin might actually be unloaded. |
1169 container_->clearScriptObjects(); | 729 container_->clearScriptObjects(); |
1170 } | 730 } |
1171 | 731 |
1172 // Cancel any pending requests because otherwise this deleted object will | |
1173 // be called by the ResourceDispatcher. | |
1174 std::vector<ClientInfo>::iterator client_index = clients_.begin(); | |
1175 while (client_index != clients_.end()) { | |
1176 ClientInfo& client_info = *client_index; | |
1177 | |
1178 if (loader_to_ignore == client_info.loader) { | |
1179 client_index++; | |
1180 continue; | |
1181 } | |
1182 | |
1183 if (client_info.loader.get()) | |
1184 client_info.loader->cancel(); | |
1185 | |
1186 client_index = clients_.erase(client_index); | |
1187 } | |
1188 | |
1189 // This needs to be called now and not in the destructor since the | 732 // This needs to be called now and not in the destructor since the |
1190 // webframe_ might not be valid anymore. | 733 // webframe_ might not be valid anymore. |
1191 webframe_ = NULL; | 734 webframe_ = NULL; |
1192 } | 735 } |
1193 | 736 |
1194 void WebPluginImpl::SetReferrer(blink::WebURLRequest* request, | 737 void WebPluginImpl::SetReferrer(blink::WebURLRequest* request, |
1195 ReferrerValue referrer_flag) { | 738 ReferrerValue referrer_flag) { |
1196 switch (referrer_flag) { | 739 switch (referrer_flag) { |
1197 case DOCUMENT_URL: | 740 case DOCUMENT_URL: |
1198 webframe_->setReferrerForRequest(*request, GURL()); | 741 webframe_->setReferrerForRequest(*request, GURL()); |
1199 break; | 742 break; |
1200 | 743 |
1201 case PLUGIN_SRC: | 744 case PLUGIN_SRC: |
1202 webframe_->setReferrerForRequest(*request, plugin_url_); | 745 webframe_->setReferrerForRequest(*request, plugin_url_); |
1203 break; | 746 break; |
1204 | 747 |
1205 default: | 748 default: |
1206 break; | 749 break; |
1207 } | 750 } |
1208 } | 751 } |
1209 | 752 |
1210 } // namespace content | 753 } // namespace content |
OLD | NEW |