| 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 |