| 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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 } | 355 } |
| 356 | 356 |
| 357 // Only UpdateGeometry if either the window or clip rects have changed. | 357 // Only UpdateGeometry if either the window or clip rects have changed. |
| 358 if (delegate_ && (first_geometry_update_ || | 358 if (delegate_ && (first_geometry_update_ || |
| 359 new_geometry.window_rect != geometry_.window_rect || | 359 new_geometry.window_rect != geometry_.window_rect || |
| 360 new_geometry.clip_rect != geometry_.clip_rect)) { | 360 new_geometry.clip_rect != geometry_.clip_rect)) { |
| 361 // Notify the plugin that its parameters have changed. | 361 // Notify the plugin that its parameters have changed. |
| 362 delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.clip_rect); | 362 delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.clip_rect); |
| 363 } | 363 } |
| 364 | 364 |
| 365 // Initiate a download on the plugin url. This should be done for the | |
| 366 // first update geometry sequence. We need to ensure that the plugin | |
| 367 // receives the geometry update before it starts receiving data. | |
| 368 if (first_geometry_update_) { | |
| 369 // An empty url corresponds to an EMBED tag with no src attribute. | |
| 370 if (!load_manually_ && plugin_url_.is_valid()) { | |
| 371 // The Flash plugin hangs for a while if it receives data before | |
| 372 // receiving valid plugin geometry. By valid geometry we mean the | |
| 373 // geometry received by a call to setFrameRect in the Webkit | |
| 374 // layout code path. To workaround this issue we download the | |
| 375 // plugin source url on a timer. | |
| 376 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 377 FROM_HERE, base::Bind(&WebPluginImpl::OnDownloadPluginSrcUrl, | |
| 378 weak_factory_.GetWeakPtr())); | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 #if defined(OS_WIN) | 365 #if defined(OS_WIN) |
| 383 // Don't cache the geometry during the first geometry update. The first | 366 // Don't cache the geometry during the first geometry update. The first |
| 384 // geometry update sequence is received when Widget::setParent is called. | 367 // geometry update sequence is received when Widget::setParent is called. |
| 385 // For plugins like media player which have a bug where they only honor | 368 // For plugins like media player which have a bug where they only honor |
| 386 // the first geometry update, we have a quirk which ignores the first | 369 // the first geometry update, we have a quirk which ignores the first |
| 387 // geometry update. To ensure that these plugins work correctly in cases | 370 // geometry update. To ensure that these plugins work correctly in cases |
| 388 // where we receive only one geometry update from webkit, we also force | 371 // where we receive only one geometry update from webkit, we also force |
| 389 // a geometry update during paint which should go out correctly as the | 372 // a geometry update during paint which should go out correctly as the |
| 390 // initial geometry update was not cached. | 373 // initial geometry update was not cached. |
| 391 if (!first_geometry_update_) | 374 if (!first_geometry_update_) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 cursor_info.hotSpot = web_cursor_info.hotspot; | 415 cursor_info.hotSpot = web_cursor_info.hotspot; |
| 433 cursor_info.customImage = web_cursor_info.custom_image; | 416 cursor_info.customImage = web_cursor_info.custom_image; |
| 434 cursor_info.imageScaleFactor = web_cursor_info.image_scale_factor; | 417 cursor_info.imageScaleFactor = web_cursor_info.image_scale_factor; |
| 435 #if defined(OS_WIN) | 418 #if defined(OS_WIN) |
| 436 cursor_info.externalHandle = web_cursor_info.external_handle; | 419 cursor_info.externalHandle = web_cursor_info.external_handle; |
| 437 #endif | 420 #endif |
| 438 return ret ? WebInputEventResult::HandledApplication | 421 return ret ? WebInputEventResult::HandledApplication |
| 439 : WebInputEventResult::NotHandled; | 422 : WebInputEventResult::NotHandled; |
| 440 } | 423 } |
| 441 | 424 |
| 442 void WebPluginImpl::didReceiveResponse(const WebURLResponse& response) { | |
| 443 ignore_response_error_ = false; | |
| 444 | |
| 445 ResponseInfo response_info; | |
| 446 GetResponseInfo(response, &response_info); | |
| 447 | |
| 448 delegate_->DidReceiveManualResponse( | |
| 449 response_info.url, | |
| 450 response_info.mime_type, | |
| 451 GetAllHeaders(response), | |
| 452 response_info.expected_length, | |
| 453 response_info.last_modified); | |
| 454 } | |
| 455 | |
| 456 void WebPluginImpl::didReceiveData(const char* data, int data_length) { | |
| 457 delegate_->DidReceiveManualData(data, data_length); | |
| 458 } | |
| 459 | |
| 460 void WebPluginImpl::didFinishLoading() { | |
| 461 delegate_->DidFinishManualLoading(); | |
| 462 } | |
| 463 | |
| 464 void WebPluginImpl::didFailLoading(const WebURLError& error) { | |
| 465 if (!ignore_response_error_) | |
| 466 delegate_->DidManualLoadFail(); | |
| 467 } | |
| 468 | |
| 469 void WebPluginImpl::didFinishLoadingFrameRequest( | |
| 470 const WebURL& url, void* notify_data) { | |
| 471 if (delegate_) { | |
| 472 // We're converting a void* into an arbitrary int id. Though | |
| 473 // these types are the same size on all the platforms we support, | |
| 474 // the compiler may complain as though they are different, so to | |
| 475 // make the casting gods happy go through an intptr_t (the union | |
| 476 // of void* and int) rather than converting straight across. | |
| 477 delegate_->DidFinishLoadWithReason( | |
| 478 url, NPRES_DONE, reinterpret_cast<intptr_t>(notify_data)); | |
| 479 } | |
| 480 } | |
| 481 | |
| 482 void WebPluginImpl::didFailLoadingFrameRequest( | |
| 483 const WebURL& url, void* notify_data, const WebURLError& error) { | |
| 484 if (!delegate_) | |
| 485 return; | |
| 486 | |
| 487 NPReason reason = | |
| 488 error.reason == net::ERR_ABORTED ? NPRES_USER_BREAK : NPRES_NETWORK_ERR; | |
| 489 // See comment in didFinishLoadingFrameRequest about the cast here. | |
| 490 delegate_->DidFinishLoadWithReason( | |
| 491 url, reason, reinterpret_cast<intptr_t>(notify_data)); | |
| 492 } | |
| 493 | |
| 494 bool WebPluginImpl::isPlaceholder() { | 425 bool WebPluginImpl::isPlaceholder() { |
| 495 return false; | 426 return false; |
| 496 } | 427 } |
| 497 | 428 |
| 498 WebPluginImpl::LoaderClient::LoaderClient(WebPluginImpl* parent) | 429 WebPluginImpl::LoaderClient::LoaderClient(WebPluginImpl* parent) |
| 499 : parent_(parent) {} | 430 : parent_(parent) {} |
| 500 | 431 |
| 501 void WebPluginImpl::LoaderClient::willFollowRedirect( | 432 void WebPluginImpl::LoaderClient::willFollowRedirect( |
| 502 blink::WebURLLoader* loader, blink::WebURLRequest& new_request, | 433 blink::WebURLLoader* loader, blink::WebURLRequest& new_request, |
| 503 const blink::WebURLResponse& redirect_response) { | 434 const blink::WebURLResponse& redirect_response) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 delegate_(NULL), | 488 delegate_(NULL), |
| 558 container_(NULL), | 489 container_(NULL), |
| 559 npp_(NULL), | 490 npp_(NULL), |
| 560 plugin_url_(params.url), | 491 plugin_url_(params.url), |
| 561 load_manually_(params.loadManually), | 492 load_manually_(params.loadManually), |
| 562 first_geometry_update_(true), | 493 first_geometry_update_(true), |
| 563 ignore_response_error_(false), | 494 ignore_response_error_(false), |
| 564 file_path_(file_path), | 495 file_path_(file_path), |
| 565 mime_type_(base::ToLowerASCII(base::UTF16ToASCII( | 496 mime_type_(base::ToLowerASCII(base::UTF16ToASCII( |
| 566 base::StringPiece16(params.mimeType)))), | 497 base::StringPiece16(params.mimeType)))), |
| 567 loader_client_(this), | 498 loader_client_(this) { |
| 568 weak_factory_(this) { | |
| 569 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); | 499 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); |
| 570 | 500 |
| 571 for (size_t i = 0; i < params.attributeNames.size(); ++i) { | 501 for (size_t i = 0; i < params.attributeNames.size(); ++i) { |
| 572 arg_names_.push_back(params.attributeNames[i].utf8()); | 502 arg_names_.push_back(params.attributeNames[i].utf8()); |
| 573 arg_values_.push_back(params.attributeValues[i].utf8()); | 503 arg_values_.push_back(params.attributeValues[i].utf8()); |
| 574 } | 504 } |
| 575 | 505 |
| 576 // Set subresource URL for crash reporting. | 506 // Set subresource URL for crash reporting. |
| 577 base::debug::SetCrashKeyValue("subresource_url", plugin_url_.spec()); | 507 base::debug::SetCrashKeyValue("subresource_url", plugin_url_.spec()); |
| 578 } | 508 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } | 623 } |
| 694 | 624 |
| 695 WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame( | 625 WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame( |
| 696 const char* url, | 626 const char* url, |
| 697 bool is_javascript_url, | 627 bool is_javascript_url, |
| 698 bool popups_allowed, | 628 bool popups_allowed, |
| 699 const char* method, | 629 const char* method, |
| 700 const char* target, | 630 const char* target, |
| 701 const char* buf, | 631 const char* buf, |
| 702 unsigned int len, | 632 unsigned int len, |
| 703 int notify_id, | |
| 704 ReferrerValue referrer_flag) { | 633 ReferrerValue referrer_flag) { |
| 705 // If there is no target, there is nothing to do | 634 // If there is no target, there is nothing to do |
| 706 if (!target) | 635 if (!target) |
| 707 return NOT_ROUTED; | 636 return NOT_ROUTED; |
| 708 | 637 |
| 709 // This could happen if the WebPluginContainer was already deleted. | 638 // This could happen if the WebPluginContainer was already deleted. |
| 710 if (!webframe_) | 639 if (!webframe_) |
| 711 return NOT_ROUTED; | 640 return NOT_ROUTED; |
| 712 | 641 |
| 713 WebString target_str = WebString::fromUTF8(target); | 642 WebString target_str = WebString::fromUTF8(target); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 request.setSkipServiceWorker(true); | 686 request.setSkipServiceWorker(true); |
| 758 if (len > 0) { | 687 if (len > 0) { |
| 759 if (!SetPostData(&request, buf, len)) { | 688 if (!SetPostData(&request, buf, len)) { |
| 760 // Uhoh - we're in trouble. There isn't a good way | 689 // Uhoh - we're in trouble. There isn't a good way |
| 761 // to recover at this point. Break out. | 690 // to recover at this point. Break out. |
| 762 NOTREACHED(); | 691 NOTREACHED(); |
| 763 return ROUTED; | 692 return ROUTED; |
| 764 } | 693 } |
| 765 } | 694 } |
| 766 | 695 |
| 767 container_->loadFrameRequest( | 696 container_->loadFrameRequest(request, target_str); |
| 768 request, target_str, notify_id != 0, reinterpret_cast<void*>(notify_id)); | |
| 769 return ROUTED; | 697 return ROUTED; |
| 770 } | 698 } |
| 771 | 699 |
| 772 NPObject* WebPluginImpl::GetWindowScriptNPObject() { | 700 NPObject* WebPluginImpl::GetWindowScriptNPObject() { |
| 773 if (!webframe_) { | 701 if (!webframe_) { |
| 774 NOTREACHED(); | 702 NOTREACHED(); |
| 775 return NULL; | 703 return NULL; |
| 776 } | 704 } |
| 777 return webframe_->windowObject(); | 705 return webframe_->windowObject(); |
| 778 } | 706 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 void WebPluginImpl::Invalidate() { | 824 void WebPluginImpl::Invalidate() { |
| 897 if (container_) | 825 if (container_) |
| 898 container_->invalidate(); | 826 container_->invalidate(); |
| 899 } | 827 } |
| 900 | 828 |
| 901 void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { | 829 void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) { |
| 902 if (container_) | 830 if (container_) |
| 903 container_->invalidateRect(rect); | 831 container_->invalidateRect(rect); |
| 904 } | 832 } |
| 905 | 833 |
| 906 void WebPluginImpl::OnDownloadPluginSrcUrl() { | |
| 907 HandleURLRequestInternal( | |
| 908 plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL, | |
| 909 false, true); | |
| 910 } | |
| 911 | |
| 912 WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( | 834 WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( |
| 913 WebURLLoader* loader) { | 835 WebURLLoader* loader) { |
| 914 ClientInfo* client_info = GetClientInfoFromLoader(loader); | 836 ClientInfo* client_info = GetClientInfoFromLoader(loader); |
| 915 if (client_info) | 837 if (client_info) |
| 916 return client_info->client; | 838 return client_info->client; |
| 917 return NULL; | 839 return NULL; |
| 918 } | 840 } |
| 919 | 841 |
| 920 WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader( | 842 WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader( |
| 921 WebURLLoader* loader) { | 843 WebURLLoader* loader) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 | 896 |
| 975 void WebPluginImpl::didSendData(WebURLLoader* loader, | 897 void WebPluginImpl::didSendData(WebURLLoader* loader, |
| 976 unsigned long long bytes_sent, | 898 unsigned long long bytes_sent, |
| 977 unsigned long long total_bytes_to_be_sent) { | 899 unsigned long long total_bytes_to_be_sent) { |
| 978 } | 900 } |
| 979 | 901 |
| 980 void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, | 902 void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, |
| 981 const WebURLResponse& response) { | 903 const WebURLResponse& response) { |
| 982 // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedResponse | 904 // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedResponse |
| 983 // until kDirectNPAPIRequests is the default and we can remove this old path. | 905 // until kDirectNPAPIRequests is the default and we can remove this old path. |
| 984 static const int kHttpPartialResponseStatusCode = 206; | |
| 985 static const int kHttpResponseSuccessStatusCode = 200; | |
| 986 | 906 |
| 987 WebPluginResourceClient* client = GetClientFromLoader(loader); | 907 WebPluginResourceClient* client = GetClientFromLoader(loader); |
| 988 if (!client) | 908 if (!client) |
| 989 return; | 909 return; |
| 990 | 910 |
| 991 ResponseInfo response_info; | 911 ResponseInfo response_info; |
| 992 GetResponseInfo(response, &response_info); | 912 GetResponseInfo(response, &response_info); |
| 993 ClientInfo* client_info = GetClientInfoFromLoader(loader); | 913 ClientInfo* client_info = GetClientInfoFromLoader(loader); |
| 994 if (!client_info) | 914 if (!client_info) |
| 995 return; | 915 return; |
| 996 | 916 |
| 997 bool request_is_seekable = true; | |
| 998 if (client->IsMultiByteResponseExpected()) { | |
| 999 if (response.httpStatusCode() == kHttpPartialResponseStatusCode) { | |
| 1000 ClientInfo* client_info = GetClientInfoFromLoader(loader); | |
| 1001 if (!client_info) | |
| 1002 return; | |
| 1003 if (HandleHttpMultipartResponse(response, client)) { | |
| 1004 // Multiple ranges requested, data will be delivered by | |
| 1005 // MultipartResponseDelegate. | |
| 1006 client_info->data_offset = 0; | |
| 1007 return; | |
| 1008 } | |
| 1009 int64 upper_bound = 0, instance_size = 0; | |
| 1010 // Single range requested - go through original processing for | |
| 1011 // non-multipart requests, but update data offset. | |
| 1012 MultipartResponseDelegate::ReadContentRanges(response, | |
| 1013 &client_info->data_offset, | |
| 1014 &upper_bound, | |
| 1015 &instance_size); | |
| 1016 } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) { | |
| 1017 RenderThreadImpl::current()->RecordAction( | |
| 1018 base::UserMetricsAction("Plugin_200ForByteRange")); | |
| 1019 // If the client issued a byte range request and the server responds with | |
| 1020 // HTTP 200 OK, it indicates that the server does not support byte range | |
| 1021 // requests. | |
| 1022 // We need to emulate Firefox behavior by doing the following:- | |
| 1023 // 1. Destroy the plugin instance in the plugin process. Ensure that | |
| 1024 // existing resource requests initiated for the plugin instance | |
| 1025 // continue to remain valid. | |
| 1026 // 2. Create a new plugin instance and notify it about the response | |
| 1027 // received here. | |
| 1028 if (!ReinitializePluginForResponse(loader)) { | |
| 1029 NOTREACHED(); | |
| 1030 return; | |
| 1031 } | |
| 1032 | |
| 1033 // The server does not support byte range requests. No point in creating | |
| 1034 // seekable streams. | |
| 1035 request_is_seekable = false; | |
| 1036 | |
| 1037 delete client; | |
| 1038 client = NULL; | |
| 1039 | |
| 1040 // Create a new resource client for this request. | |
| 1041 for (size_t i = 0; i < clients_.size(); ++i) { | |
| 1042 if (clients_[i].loader.get() == loader) { | |
| 1043 WebPluginResourceClient* resource_client = | |
| 1044 delegate_->CreateResourceClient(clients_[i].id, plugin_url_, 0); | |
| 1045 clients_[i].client = resource_client; | |
| 1046 client = resource_client; | |
| 1047 break; | |
| 1048 } | |
| 1049 } | |
| 1050 | |
| 1051 DCHECK(client != NULL); | |
| 1052 } | |
| 1053 } | |
| 1054 | |
| 1055 // Calling into a plugin could result in reentrancy if the plugin yields | 917 // Calling into a plugin could result in reentrancy if the plugin yields |
| 1056 // control to the OS like entering a modal loop etc. Prevent this by | 918 // control to the OS like entering a modal loop etc. Prevent this by |
| 1057 // stopping further loading until the plugin notifies us that it is ready to | 919 // stopping further loading until the plugin notifies us that it is ready to |
| 1058 // accept data | 920 // accept data |
| 1059 loader->setDefersLoading(true); | 921 loader->setDefersLoading(true); |
| 1060 | 922 |
| 1061 client->DidReceiveResponse( | 923 client->DidReceiveResponse( |
| 1062 response_info.mime_type, | 924 response_info.mime_type, |
| 1063 GetAllHeaders(response), | 925 GetAllHeaders(response), |
| 1064 response_info.expected_length, | 926 response_info.expected_length, |
| 1065 response_info.last_modified, | 927 response_info.last_modified, |
| 1066 request_is_seekable); | 928 true); |
| 1067 | 929 |
| 1068 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP | 930 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP |
| 1069 // error codes in the stream header and as a result, was unaware of the | 931 // error codes in the stream header and as a result, was unaware of the |
| 1070 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF | 932 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF |
| 1071 // destroy the stream and invoke the NPP_DestroyStream function on the | 933 // destroy the stream and invoke the NPP_DestroyStream function on the |
| 1072 // plugin if the HTTP request fails. | 934 // plugin if the HTTP request fails. |
| 1073 const GURL& url = response.url(); | 935 const GURL& url = response.url(); |
| 1074 if (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme)) { | 936 if (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme)) { |
| 1075 if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { | 937 if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { |
| 1076 // The plugin instance could be in the process of deletion here. | 938 // The plugin instance could be in the process of deletion here. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 } | 1016 } |
| 1155 | 1017 |
| 1156 void WebPluginImpl::SetContainer(WebPluginContainer* container) { | 1018 void WebPluginImpl::SetContainer(WebPluginContainer* container) { |
| 1157 if (!container) | 1019 if (!container) |
| 1158 TearDownPluginInstance(NULL); | 1020 TearDownPluginInstance(NULL); |
| 1159 container_ = container; | 1021 container_ = container; |
| 1160 if (container_) | 1022 if (container_) |
| 1161 container_->allowScriptObjects(); | 1023 container_->allowScriptObjects(); |
| 1162 } | 1024 } |
| 1163 | 1025 |
| 1164 void WebPluginImpl::HandleURLRequest(const char* url, | |
| 1165 const char* method, | |
| 1166 const char* target, | |
| 1167 const char* buf, | |
| 1168 unsigned int len, | |
| 1169 int notify_id, | |
| 1170 bool popups_allowed, | |
| 1171 bool notify_redirects) { | |
| 1172 // GetURL/PostURL requests initiated explicitly by plugins should specify the | |
| 1173 // plugin SRC url as the referrer if it is available. | |
| 1174 HandleURLRequestInternal( | |
| 1175 url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC, | |
| 1176 notify_redirects, false); | |
| 1177 } | |
| 1178 | |
| 1179 void WebPluginImpl::HandleURLRequestInternal(const char* url, | |
| 1180 const char* method, | |
| 1181 const char* target, | |
| 1182 const char* buf, | |
| 1183 unsigned int len, | |
| 1184 int notify_id, | |
| 1185 bool popups_allowed, | |
| 1186 ReferrerValue referrer_flag, | |
| 1187 bool notify_redirects, | |
| 1188 bool is_plugin_src_load) { | |
| 1189 // For this request, we either route the output to a frame | |
| 1190 // because a target has been specified, or we handle the request | |
| 1191 // here, i.e. by executing the script if it is a javascript url | |
| 1192 // or by initiating a download on the URL, etc. There is one special | |
| 1193 // case in that the request is a javascript url and the target is "_self", | |
| 1194 // in which case we route the output to the plugin rather than routing it | |
| 1195 // to the plugin's frame. | |
| 1196 bool is_javascript_url = | |
| 1197 url::FindAndCompareScheme(url, strlen(url), url::kJavaScriptScheme, NULL); | |
| 1198 RoutingStatus routing_status = RouteToFrame( | |
| 1199 url, is_javascript_url, popups_allowed, method, target, buf, len, | |
| 1200 notify_id, referrer_flag); | |
| 1201 if (routing_status == ROUTED) | |
| 1202 return; | |
| 1203 | |
| 1204 if (is_javascript_url) { | |
| 1205 GURL gurl(url); | |
| 1206 WebString result = container_->executeScriptURL(gurl, popups_allowed); | |
| 1207 | |
| 1208 // delegate_ could be NULL because executeScript caused the container to | |
| 1209 // be deleted. | |
| 1210 if (delegate_) { | |
| 1211 delegate_->SendJavaScriptStream( | |
| 1212 gurl, result.utf8(), !result.isNull(), notify_id); | |
| 1213 } | |
| 1214 | |
| 1215 return; | |
| 1216 } | |
| 1217 | |
| 1218 unsigned long resource_id = GetNextResourceId(); | |
| 1219 if (!resource_id) | |
| 1220 return; | |
| 1221 | |
| 1222 GURL complete_url = CompleteURL(url); | |
| 1223 // Remove when flash bug is fixed. http://crbug.com/40016. | |
| 1224 if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag)) | |
| 1225 return; | |
| 1226 | |
| 1227 // If the RouteToFrame call returned a failure then inform the result | |
| 1228 // back to the plugin asynchronously. | |
| 1229 if ((routing_status == INVALID_URL) || | |
| 1230 (routing_status == GENERAL_FAILURE)) { | |
| 1231 WebPluginResourceClient* resource_client = delegate_->CreateResourceClient( | |
| 1232 resource_id, complete_url, notify_id); | |
| 1233 if (resource_client) | |
| 1234 resource_client->DidFail(resource_id); | |
| 1235 return; | |
| 1236 } | |
| 1237 | |
| 1238 // CreateResourceClient() sends a synchronous IPC message so it's possible | |
| 1239 // that TearDownPluginInstance() may have been called in the nested | |
| 1240 // message loop. If so, don't start the request. | |
| 1241 if (!delegate_) | |
| 1242 return; | |
| 1243 | |
| 1244 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 1245 switches::kDisableDirectNPAPIRequests)) { | |
| 1246 // We got here either because the plugin called GetURL/PostURL, or because | |
| 1247 // we're fetching the data for an embed tag. If we're in multi-process mode, | |
| 1248 // we want to fetch the data in the plugin process as the renderer won't be | |
| 1249 // able to request any origin when site isolation is in place. So bounce | |
| 1250 // this request back to the plugin process which will use ResourceDispatcher | |
| 1251 // to fetch the url. | |
| 1252 | |
| 1253 // TODO(jam): any better way of getting this? Can't find a way to get | |
| 1254 // frame()->loader()->outgoingReferrer() which | |
| 1255 // WebFrameImpl::setReferrerForRequest does. | |
| 1256 WebURLRequest request(complete_url); | |
| 1257 SetReferrer(&request, referrer_flag); | |
| 1258 Referrer referrer( | |
| 1259 GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))), | |
| 1260 request.referrerPolicy()); | |
| 1261 | |
| 1262 GURL first_party_for_cookies = webframe_->document().firstPartyForCookies(); | |
| 1263 delegate_->FetchURL(resource_id, notify_id, complete_url, | |
| 1264 first_party_for_cookies, method, buf, len, referrer, | |
| 1265 notify_redirects, is_plugin_src_load, 0, | |
| 1266 render_frame_->GetRoutingID(), | |
| 1267 render_view_->GetRoutingID()); | |
| 1268 } else { | |
| 1269 WebPluginResourceClient* resource_client = delegate_->CreateResourceClient( | |
| 1270 resource_id, complete_url, notify_id); | |
| 1271 if (!resource_client) | |
| 1272 return; | |
| 1273 InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf, | |
| 1274 len, NULL, referrer_flag, notify_redirects, | |
| 1275 is_plugin_src_load); | |
| 1276 } | |
| 1277 } | |
| 1278 | |
| 1279 unsigned long WebPluginImpl::GetNextResourceId() { | 1026 unsigned long WebPluginImpl::GetNextResourceId() { |
| 1280 if (!webframe_) | 1027 if (!webframe_) |
| 1281 return 0; | 1028 return 0; |
| 1282 WebView* view = webframe_->view(); | 1029 WebView* view = webframe_->view(); |
| 1283 if (!view) | 1030 if (!view) |
| 1284 return 0; | 1031 return 0; |
| 1285 return view->createUniqueIdentifierForRequest(); | 1032 return view->createUniqueIdentifierForRequest(); |
| 1286 } | 1033 } |
| 1287 | 1034 |
| 1288 bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id, | |
| 1289 WebPluginResourceClient* client, | |
| 1290 const GURL& url, | |
| 1291 const char* method, | |
| 1292 const char* buf, | |
| 1293 int buf_len, | |
| 1294 const char* range_info, | |
| 1295 ReferrerValue referrer_flag, | |
| 1296 bool notify_redirects, | |
| 1297 bool is_plugin_src_load) { | |
| 1298 if (!client) { | |
| 1299 NOTREACHED(); | |
| 1300 return false; | |
| 1301 } | |
| 1302 | |
| 1303 ClientInfo info; | |
| 1304 info.id = resource_id; | |
| 1305 info.client = client; | |
| 1306 info.request.initialize(); | |
| 1307 info.request.setURL(url); | |
| 1308 info.request.setFirstPartyForCookies( | |
| 1309 webframe_->document().firstPartyForCookies()); | |
| 1310 info.request.setRequestorProcessID(delegate_->GetProcessId()); | |
| 1311 // TODO(mkwst): Is this a request for a plugin object itself | |
| 1312 // (RequestContextObject), or a request that the plugin makes | |
| 1313 // (RequestContextPlugin)? | |
| 1314 info.request.setRequestContext(WebURLRequest::RequestContextPlugin); | |
| 1315 info.request.setHTTPMethod(WebString::fromUTF8(method)); | |
| 1316 // ServiceWorker is disabled for NPAPI. | |
| 1317 info.request.setSkipServiceWorker(true); | |
| 1318 info.pending_failure_notification = false; | |
| 1319 info.notify_redirects = notify_redirects; | |
| 1320 info.is_plugin_src_load = is_plugin_src_load; | |
| 1321 info.data_offset = 0; | |
| 1322 | |
| 1323 if (range_info) { | |
| 1324 info.request.addHTTPHeaderField(WebString::fromUTF8("Range"), | |
| 1325 WebString::fromUTF8(range_info)); | |
| 1326 } | |
| 1327 | |
| 1328 if (strcmp(method, "POST") == 0) { | |
| 1329 // Adds headers or form data to a request. This must be called before | |
| 1330 // we initiate the actual request. | |
| 1331 SetPostData(&info.request, buf, buf_len); | |
| 1332 } | |
| 1333 | |
| 1334 SetReferrer(&info.request, referrer_flag); | |
| 1335 | |
| 1336 WebURLLoaderOptions options; | |
| 1337 options.allowCredentials = true; | |
| 1338 options.crossOriginRequestPolicy = | |
| 1339 WebURLLoaderOptions::CrossOriginRequestPolicyAllow; | |
| 1340 info.loader.reset(webframe_->createAssociatedURLLoader(options)); | |
| 1341 if (!info.loader.get()) | |
| 1342 return false; | |
| 1343 info.loader->loadAsynchronously(info.request, &loader_client_); | |
| 1344 | |
| 1345 clients_.push_back(info); | |
| 1346 return true; | |
| 1347 } | |
| 1348 | |
| 1349 void WebPluginImpl::CancelDocumentLoad() { | 1035 void WebPluginImpl::CancelDocumentLoad() { |
| 1350 if (webframe_) { | 1036 if (webframe_) { |
| 1351 ignore_response_error_ = true; | 1037 ignore_response_error_ = true; |
| 1352 webframe_->stopLoading(); | 1038 webframe_->stopLoading(); |
| 1353 } | 1039 } |
| 1354 } | 1040 } |
| 1355 | 1041 |
| 1356 void WebPluginImpl::InitiateHTTPRangeRequest( | |
| 1357 const char* url, const char* range_info, int range_request_id) { | |
| 1358 unsigned long resource_id = GetNextResourceId(); | |
| 1359 if (!resource_id) | |
| 1360 return; | |
| 1361 | |
| 1362 GURL complete_url = CompleteURL(url); | |
| 1363 // Remove when flash bug is fixed. http://crbug.com/40016. | |
| 1364 if (!WebPluginImpl::IsValidUrl(complete_url, | |
| 1365 load_manually_ ? NO_REFERRER : PLUGIN_SRC)) | |
| 1366 return; | |
| 1367 | |
| 1368 WebPluginResourceClient* resource_client = | |
| 1369 delegate_->CreateSeekableResourceClient(resource_id, range_request_id); | |
| 1370 InitiateHTTPRequest( | |
| 1371 resource_id, resource_client, complete_url, "GET", NULL, 0, range_info, | |
| 1372 load_manually_ ? NO_REFERRER : PLUGIN_SRC, false, false); | |
| 1373 } | |
| 1374 | |
| 1375 void WebPluginImpl::DidStartLoading() { | 1042 void WebPluginImpl::DidStartLoading() { |
| 1376 if (render_view_.get()) { | 1043 if (render_view_.get()) { |
| 1377 // TODO(darin): Make is_loading_ be a counter! | 1044 // TODO(darin): Make is_loading_ be a counter! |
| 1378 render_view_->DidStartLoading(); | 1045 render_view_->DidStartLoading(); |
| 1379 } | 1046 } |
| 1380 } | 1047 } |
| 1381 | 1048 |
| 1382 void WebPluginImpl::DidStopLoading() { | 1049 void WebPluginImpl::DidStopLoading() { |
| 1383 if (render_view_.get()) { | 1050 if (render_view_.get()) { |
| 1384 // TODO(darin): Make is_loading_ be a counter! | 1051 // TODO(darin): Make is_loading_ be a counter! |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 | 1199 |
| 1533 if (client_info.loader.get()) | 1200 if (client_info.loader.get()) |
| 1534 client_info.loader->cancel(); | 1201 client_info.loader->cancel(); |
| 1535 | 1202 |
| 1536 client_index = clients_.erase(client_index); | 1203 client_index = clients_.erase(client_index); |
| 1537 } | 1204 } |
| 1538 | 1205 |
| 1539 // This needs to be called now and not in the destructor since the | 1206 // This needs to be called now and not in the destructor since the |
| 1540 // webframe_ might not be valid anymore. | 1207 // webframe_ might not be valid anymore. |
| 1541 webframe_ = NULL; | 1208 webframe_ = NULL; |
| 1542 weak_factory_.InvalidateWeakPtrs(); | |
| 1543 } | 1209 } |
| 1544 | 1210 |
| 1545 void WebPluginImpl::SetReferrer(blink::WebURLRequest* request, | 1211 void WebPluginImpl::SetReferrer(blink::WebURLRequest* request, |
| 1546 ReferrerValue referrer_flag) { | 1212 ReferrerValue referrer_flag) { |
| 1547 switch (referrer_flag) { | 1213 switch (referrer_flag) { |
| 1548 case DOCUMENT_URL: | 1214 case DOCUMENT_URL: |
| 1549 webframe_->setReferrerForRequest(*request, GURL()); | 1215 webframe_->setReferrerForRequest(*request, GURL()); |
| 1550 break; | 1216 break; |
| 1551 | 1217 |
| 1552 case PLUGIN_SRC: | 1218 case PLUGIN_SRC: |
| 1553 webframe_->setReferrerForRequest(*request, plugin_url_); | 1219 webframe_->setReferrerForRequest(*request, plugin_url_); |
| 1554 break; | 1220 break; |
| 1555 | 1221 |
| 1556 default: | 1222 default: |
| 1557 break; | 1223 break; |
| 1558 } | 1224 } |
| 1559 } | 1225 } |
| 1560 | 1226 |
| 1561 } // namespace content | 1227 } // namespace content |
| OLD | NEW |