| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "config.h" | 5 #include "config.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
| 9 | 9 |
| 10 MSVC_PUSH_WARNING_LEVEL(0); | 10 MSVC_PUSH_WARNING_LEVEL(0); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 } | 276 } |
| 277 } | 277 } |
| 278 | 278 |
| 279 WebCore::Widget* WebPluginImpl::Create(const GURL& url, | 279 WebCore::Widget* WebPluginImpl::Create(const GURL& url, |
| 280 char** argn, | 280 char** argn, |
| 281 char** argv, | 281 char** argv, |
| 282 int argc, | 282 int argc, |
| 283 WebCore::Element *element, | 283 WebCore::Element *element, |
| 284 WebFrameImpl *frame, | 284 WebFrameImpl *frame, |
| 285 WebPluginDelegate* delegate, | 285 WebPluginDelegate* delegate, |
| 286 bool load_manually) { | 286 bool load_manually, |
| 287 const std::string& mime_type) { |
| 287 WebPluginImpl* webplugin = new WebPluginImpl(element, frame, delegate, url, | 288 WebPluginImpl* webplugin = new WebPluginImpl(element, frame, delegate, url, |
| 288 load_manually); | 289 load_manually, mime_type, argc, |
| 290 argn, argv); |
| 289 | 291 |
| 290 if (!delegate->Initialize(url, argn, argv, argc, webplugin, load_manually)) { | 292 if (!delegate->Initialize(url, argn, argv, argc, webplugin, load_manually)) { |
| 291 delegate->PluginDestroyed(); | 293 delegate->PluginDestroyed(); |
| 292 delegate = NULL; | 294 delegate = NULL; |
| 293 delete webplugin; | 295 delete webplugin; |
| 294 return NULL; | 296 return NULL; |
| 295 } | 297 } |
| 296 | 298 |
| 297 WebPluginContainer* container = new WebPluginContainer(webplugin); | 299 WebPluginContainer* container = new WebPluginContainer(webplugin); |
| 298 webplugin->SetContainer(container); | 300 webplugin->SetContainer(container); |
| 299 return container; | 301 return container; |
| 300 } | 302 } |
| 301 | 303 |
| 302 WebPluginImpl::WebPluginImpl(WebCore::Element* element, | 304 WebPluginImpl::WebPluginImpl(WebCore::Element* element, |
| 303 WebFrameImpl* webframe, | 305 WebFrameImpl* webframe, |
| 304 WebPluginDelegate* delegate, | 306 WebPluginDelegate* delegate, |
| 305 const GURL& plugin_url, | 307 const GURL& plugin_url, |
| 306 bool load_manually) | 308 bool load_manually, |
| 309 const std::string& mime_type, |
| 310 int arg_count, |
| 311 char** arg_names, |
| 312 char** arg_values) |
| 307 : windowless_(false), | 313 : windowless_(false), |
| 308 window_(NULL), | 314 window_(NULL), |
| 309 element_(element), | 315 element_(element), |
| 310 webframe_(webframe), | 316 webframe_(webframe), |
| 311 delegate_(delegate), | 317 delegate_(delegate), |
| 312 force_geometry_update_(false), | 318 force_geometry_update_(false), |
| 313 visible_(false), | 319 visible_(false), |
| 314 received_first_paint_notification_(false), | 320 received_first_paint_notification_(false), |
| 315 widget_(NULL), | 321 widget_(NULL), |
| 316 plugin_url_(plugin_url), | 322 plugin_url_(plugin_url), |
| 317 load_manually_(load_manually), | 323 load_manually_(load_manually), |
| 318 first_geometry_update_(true) { | 324 first_geometry_update_(true), |
| 325 mime_type_(mime_type) { |
| 326 |
| 327 ArrayToVector(arg_count, arg_names, &arg_names_); |
| 328 ArrayToVector(arg_count, arg_values, &arg_values_); |
| 319 } | 329 } |
| 320 | 330 |
| 321 WebPluginImpl::~WebPluginImpl() { | 331 WebPluginImpl::~WebPluginImpl() { |
| 322 } | 332 } |
| 323 | 333 |
| 324 void WebPluginImpl::SetWindow(HWND window, HANDLE pump_messages_event) { | 334 void WebPluginImpl::SetWindow(HWND window, HANDLE pump_messages_event) { |
| 325 if (window) { | 335 if (window) { |
| 326 DCHECK(!windowless_); // Make sure not called twice. | 336 DCHECK(!windowless_); // Make sure not called twice. |
| 327 window_ = window; | 337 window_ = window; |
| 328 } else { | 338 } else { |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 result.append(L"\n"); | 979 result.append(L"\n"); |
| 970 } | 980 } |
| 971 } | 981 } |
| 972 | 982 |
| 973 return result; | 983 return result; |
| 974 } | 984 } |
| 975 | 985 |
| 976 void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, | 986 void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, |
| 977 const WebCore::ResourceResponse& response) { | 987 const WebCore::ResourceResponse& response) { |
| 978 static const int kHttpPartialResponseStatusCode = 206; | 988 static const int kHttpPartialResponseStatusCode = 206; |
| 989 static const int kHttpResponseSuccessStatusCode = 200; |
| 979 | 990 |
| 980 WebPluginResourceClient* client = GetClientFromHandle(handle); | 991 WebPluginResourceClient* client = GetClientFromHandle(handle); |
| 981 if (!client) | 992 if (!client) |
| 982 return; | 993 return; |
| 983 | 994 |
| 984 WebPluginContainer::HttpResponseInfo http_response_info; | 995 WebPluginContainer::HttpResponseInfo http_response_info; |
| 985 WebPluginContainer::ReadHttpResponseInfo(response, &http_response_info); | 996 WebPluginContainer::ReadHttpResponseInfo(response, &http_response_info); |
| 986 | 997 |
| 987 bool cancel = false; | 998 bool cancel = false; |
| 999 bool request_is_seekable = true; |
| 1000 if (client->IsMultiByteResponseExpected()) { |
| 1001 if (response.httpStatusCode() == kHttpPartialResponseStatusCode) { |
| 1002 HandleHttpMultipartResponse(response, client); |
| 1003 return; |
| 1004 } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) { |
| 1005 // If the client issued a byte range request and the server responds with |
| 1006 // HTTP 200 OK, it indicates that the server does not support byte range |
| 1007 // requests. |
| 1008 // We need to emulate Firefox behavior by doing the following:- |
| 1009 // 1. Destroy the plugin instance in the plugin process. Ensure that |
| 1010 // existing resource requests initiated for the plugin instance |
| 1011 // continue to remain valid. |
| 1012 // 2. Create a new plugin instance and notify it about the response |
| 1013 // received here. |
| 1014 if (!ReinitializePluginForResponse(handle)) { |
| 1015 NOTREACHED(); |
| 1016 return; |
| 1017 } |
| 988 | 1018 |
| 989 if (response.httpStatusCode() == kHttpPartialResponseStatusCode) { | 1019 // The server does not support byte range requests. No point in creating |
| 990 HandleHttpMultipartResponse(response, client); | 1020 // seekable streams. |
| 991 return; | 1021 request_is_seekable = false; |
| 1022 |
| 1023 delete client; |
| 1024 client = NULL; |
| 1025 |
| 1026 // Create a new resource client for this request. |
| 1027 for (size_t i = 0; i < clients_.size(); ++i) { |
| 1028 if (clients_[i].handle.get() == handle) { |
| 1029 WebPluginResourceClient* resource_client = |
| 1030 delegate_->CreateResourceClient(clients_[i].id, |
| 1031 plugin_url_.spec().c_str(), |
| 1032 NULL, false, NULL); |
| 1033 clients_[i].client = resource_client; |
| 1034 client = resource_client; |
| 1035 break; |
| 1036 } |
| 1037 } |
| 1038 |
| 1039 DCHECK(client != NULL); |
| 1040 } |
| 992 } | 1041 } |
| 993 | 1042 |
| 994 client->DidReceiveResponse( | 1043 client->DidReceiveResponse( |
| 995 base::SysWideToNativeMB(http_response_info.mime_type), | 1044 base::SysWideToNativeMB(http_response_info.mime_type), |
| 996 base::SysWideToNativeMB(GetAllHeaders(response)), | 1045 base::SysWideToNativeMB(GetAllHeaders(response)), |
| 997 http_response_info.expected_length, | 1046 http_response_info.expected_length, |
| 998 http_response_info.last_modified, &cancel); | 1047 http_response_info.last_modified, request_is_seekable, &cancel); |
| 999 | 1048 |
| 1000 if (cancel) { | 1049 if (cancel) { |
| 1001 handle->cancel(); | 1050 handle->cancel(); |
| 1002 RemoveClient(handle); | 1051 RemoveClient(handle); |
| 1003 return; | 1052 return; |
| 1004 } | 1053 } |
| 1005 | 1054 |
| 1006 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP | 1055 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP |
| 1007 // error codes in the stream header and as a result, was unaware of the | 1056 // error codes in the stream header and as a result, was unaware of the |
| 1008 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF | 1057 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 for (size_t i = 0; i < clients_.size(); ++i) { | 1120 for (size_t i = 0; i < clients_.size(); ++i) { |
| 1072 if (clients_[i].handle.get() == handle) { | 1121 if (clients_[i].handle.get() == handle) { |
| 1073 RemoveClient(i); | 1122 RemoveClient(i); |
| 1074 return; | 1123 return; |
| 1075 } | 1124 } |
| 1076 } | 1125 } |
| 1077 } | 1126 } |
| 1078 | 1127 |
| 1079 void WebPluginImpl::SetContainer(WebPluginContainer* container) { | 1128 void WebPluginImpl::SetContainer(WebPluginContainer* container) { |
| 1080 if (container == NULL) { | 1129 if (container == NULL) { |
| 1081 // The frame maintains a list of JSObjects which are related to this | 1130 TearDownPluginInstance(NULL); |
| 1082 // plugin. Tell the frame we're gone so that it can invalidate all | |
| 1083 // of those sub JSObjects. | |
| 1084 if (frame()) { | |
| 1085 ASSERT(widget_ != NULL); | |
| 1086 frame()->script()->cleanupScriptObjectsForPlugin(widget_); | |
| 1087 } | |
| 1088 | |
| 1089 // Call PluginDestroyed() first to prevent the plugin from calling us back | |
| 1090 // in the middle of tearing down the render tree. | |
| 1091 delegate_->PluginDestroyed(); | |
| 1092 delegate_ = NULL; | |
| 1093 | |
| 1094 // Cancel any pending requests because otherwise this deleted object will be | |
| 1095 // called by the ResourceDispatcher. | |
| 1096 int int_offset = 0; | |
| 1097 while (!clients_.empty()) { | |
| 1098 if (clients_[int_offset].handle) | |
| 1099 clients_[int_offset].handle->cancel(); | |
| 1100 WebPluginResourceClient* resource_client = clients_[int_offset].client; | |
| 1101 RemoveClient(int_offset); | |
| 1102 if (resource_client) | |
| 1103 resource_client->DidFail(); | |
| 1104 } | |
| 1105 | |
| 1106 // This needs to be called now and not in the destructor since the | |
| 1107 // webframe_ might not be valid anymore. | |
| 1108 webframe_->set_plugin_delegate(NULL); | |
| 1109 webframe_ = NULL; | |
| 1110 } | 1131 } |
| 1111 widget_ = container; | 1132 widget_ = container; |
| 1112 } | 1133 } |
| 1113 | 1134 |
| 1114 WebCore::ScrollView* WebPluginImpl::parent() const { | 1135 WebCore::ScrollView* WebPluginImpl::parent() const { |
| 1115 if (widget_) | 1136 if (widget_) |
| 1116 return widget_->parent(); | 1137 return widget_->parent(); |
| 1117 | 1138 |
| 1118 return NULL; | 1139 return NULL; |
| 1119 } | 1140 } |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1308 | 1329 |
| 1309 MultiPartResponseClient* multi_part_response_client = | 1330 MultiPartResponseClient* multi_part_response_client = |
| 1310 new MultiPartResponseClient(client); | 1331 new MultiPartResponseClient(client); |
| 1311 | 1332 |
| 1312 MultipartResponseDelegate* multi_part_response_handler = | 1333 MultipartResponseDelegate* multi_part_response_handler = |
| 1313 new MultipartResponseDelegate(multi_part_response_client, NULL, | 1334 new MultipartResponseDelegate(multi_part_response_client, NULL, |
| 1314 response, | 1335 response, |
| 1315 multipart_boundary); | 1336 multipart_boundary); |
| 1316 multi_part_response_map_[client] = multi_part_response_handler; | 1337 multi_part_response_map_[client] = multi_part_response_handler; |
| 1317 } | 1338 } |
| 1339 |
| 1340 bool WebPluginImpl::ReinitializePluginForResponse( |
| 1341 WebCore::ResourceHandle* response_handle) { |
| 1342 WebFrameImpl* web_frame = WebFrameImpl::FromFrame(frame()); |
| 1343 if (!web_frame) |
| 1344 return false; |
| 1345 |
| 1346 WebViewImpl* web_view = web_frame->webview_impl(); |
| 1347 if (!web_view) |
| 1348 return false; |
| 1349 |
| 1350 WebPluginContainer* container_widget = widget_; |
| 1351 |
| 1352 // Destroy the current plugin instance. |
| 1353 TearDownPluginInstance(response_handle); |
| 1354 |
| 1355 widget_ = container_widget; |
| 1356 webframe_ = web_frame; |
| 1357 // Turn off the load_manually flag as we are going to hand data off to the |
| 1358 // plugin. |
| 1359 load_manually_ = false; |
| 1360 |
| 1361 WebViewDelegate* webview_delegate = web_view->GetDelegate(); |
| 1362 std::string actual_mime_type; |
| 1363 WebPluginDelegate* plugin_delegate = |
| 1364 webview_delegate->CreatePluginDelegate(web_view, plugin_url_, |
| 1365 mime_type_, std::string(), |
| 1366 &actual_mime_type); |
| 1367 |
| 1368 char** arg_names = new char*[arg_names_.size()]; |
| 1369 char** arg_values = new char*[arg_values_.size()]; |
| 1370 |
| 1371 for (unsigned int index = 0; index < arg_names_.size(); ++index) { |
| 1372 arg_names[index] = const_cast<char*>(arg_names_[index].c_str()); |
| 1373 arg_values[index] = const_cast<char*>(arg_values_[index].c_str()); |
| 1374 } |
| 1375 |
| 1376 bool init_ok = plugin_delegate->Initialize(plugin_url_, arg_names, |
| 1377 arg_values, arg_names_.size(), |
| 1378 this, load_manually_); |
| 1379 delete[] arg_names; |
| 1380 delete[] arg_values; |
| 1381 |
| 1382 if (!init_ok) { |
| 1383 SetContainer(NULL); |
| 1384 // TODO(iyengar) Should we delete the current plugin instance here? |
| 1385 return false; |
| 1386 } |
| 1387 |
| 1388 mime_type_ = actual_mime_type; |
| 1389 delegate_ = plugin_delegate; |
| 1390 // Force a geometry update to occur to ensure that the plugin becomes |
| 1391 // visible. |
| 1392 widget_->frameRectsChanged(); |
| 1393 delegate_->FlushGeometryUpdates(); |
| 1394 return true; |
| 1395 } |
| 1396 |
| 1397 void WebPluginImpl::ArrayToVector(int total_values, char** values, |
| 1398 std::vector<std::string>* value_vector) { |
| 1399 DCHECK(value_vector != NULL); |
| 1400 for (int index = 0; index < total_values; ++index) { |
| 1401 value_vector->push_back(values[index]); |
| 1402 } |
| 1403 } |
| 1404 |
| 1405 void WebPluginImpl::TearDownPluginInstance( |
| 1406 WebCore::ResourceHandle* response_handle_to_ignore) { |
| 1407 // The frame maintains a list of JSObjects which are related to this |
| 1408 // plugin. Tell the frame we're gone so that it can invalidate all |
| 1409 // of those sub JSObjects. |
| 1410 if (frame()) { |
| 1411 ASSERT(widget_ != NULL); |
| 1412 frame()->script()->cleanupScriptObjectsForPlugin(widget_); |
| 1413 } |
| 1414 |
| 1415 // Call PluginDestroyed() first to prevent the plugin from calling us back |
| 1416 // in the middle of tearing down the render tree. |
| 1417 delegate_->PluginDestroyed(); |
| 1418 delegate_ = NULL; |
| 1419 |
| 1420 // Cancel any pending requests because otherwise this deleted object will |
| 1421 // be called by the ResourceDispatcher. |
| 1422 std::vector<ClientInfo>::iterator client_index = clients_.begin(); |
| 1423 while (client_index != clients_.end()) { |
| 1424 ClientInfo& client_info = *client_index; |
| 1425 |
| 1426 if (response_handle_to_ignore == client_info.handle) { |
| 1427 client_index++; |
| 1428 continue; |
| 1429 } |
| 1430 |
| 1431 if (client_info.handle) |
| 1432 client_info.handle->cancel(); |
| 1433 |
| 1434 WebPluginResourceClient* resource_client = client_info.client; |
| 1435 client_index = clients_.erase(client_index); |
| 1436 if (resource_client) |
| 1437 resource_client->DidFail(); |
| 1438 } |
| 1439 |
| 1440 // This needs to be called now and not in the destructor since the |
| 1441 // webframe_ might not be valid anymore. |
| 1442 webframe_->set_plugin_delegate(NULL); |
| 1443 webframe_ = NULL; |
| 1444 } |
| OLD | NEW |