| 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/child/npapi/plugin_host.h" | 5 #include "content/child/npapi/plugin_host.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "content/child/npapi/plugin_instance.h" | 17 #include "content/child/npapi/plugin_instance.h" |
| 18 #include "content/child/npapi/plugin_lib.h" | 18 #include "content/child/npapi/plugin_lib.h" |
| 19 #include "content/child/npapi/plugin_stream_url.h" | |
| 20 #include "content/child/npapi/webplugin_delegate.h" | 19 #include "content/child/npapi/webplugin_delegate.h" |
| 21 #include "content/public/common/content_client.h" | 20 #include "content/public/common/content_client.h" |
| 22 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 23 #include "content/public/common/user_agent.h" | 22 #include "content/public/common/user_agent.h" |
| 24 #include "content/public/common/webplugininfo.h" | 23 #include "content/public/common/webplugininfo.h" |
| 25 #include "net/base/filename_util.h" | 24 #include "net/base/filename_util.h" |
| 26 #include "third_party/WebKit/public/web/WebBindings.h" | 25 #include "third_party/WebKit/public/web/WebBindings.h" |
| 27 #include "third_party/WebKit/public/web/WebKit.h" | 26 #include "third_party/WebKit/public/web/WebKit.h" |
| 28 #include "third_party/npapi/bindings/npruntime.h" | 27 #include "third_party/npapi/bindings/npruntime.h" |
| 29 #include "ui/gl/gl_implementation.h" | 28 #include "ui/gl/gl_implementation.h" |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 } | 331 } |
| 333 | 332 |
| 334 // This is for dynamic discovery of new plugins. | 333 // This is for dynamic discovery of new plugins. |
| 335 // Should force a re-scan of the plugins directory to load new ones. | 334 // Should force a re-scan of the plugins directory to load new ones. |
| 336 void NPN_ReloadPlugins(NPBool reload_pages) { | 335 void NPN_ReloadPlugins(NPBool reload_pages) { |
| 337 blink::resetPluginCache(reload_pages ? true : false); | 336 blink::resetPluginCache(reload_pages ? true : false); |
| 338 } | 337 } |
| 339 | 338 |
| 340 // Requests a range of bytes for a seekable stream. | 339 // Requests a range of bytes for a seekable stream. |
| 341 NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { | 340 NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { |
| 342 if (!stream || !range_list) | 341 return NPERR_GENERIC_ERROR; |
| 343 return NPERR_GENERIC_ERROR; | |
| 344 | |
| 345 scoped_refptr<PluginInstance> plugin( | |
| 346 reinterpret_cast<PluginInstance*>(stream->ndata)); | |
| 347 if (!plugin.get()) | |
| 348 return NPERR_GENERIC_ERROR; | |
| 349 | |
| 350 plugin->RequestRead(stream, range_list); | |
| 351 return NPERR_NO_ERROR; | |
| 352 } | 342 } |
| 353 | 343 |
| 354 // Generic form of GetURL for common code between GetURL and GetURLNotify. | |
| 355 static NPError GetURLNotify(NPP id, | |
| 356 const char* url, | |
| 357 const char* target, | |
| 358 bool notify, | |
| 359 void* notify_data) { | |
| 360 if (!url) | |
| 361 return NPERR_INVALID_URL; | |
| 362 | |
| 363 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 364 if (!plugin.get()) { | |
| 365 return NPERR_GENERIC_ERROR; | |
| 366 } | |
| 367 | |
| 368 plugin->RequestURL(url, "GET", target, NULL, 0, notify, notify_data); | |
| 369 return NPERR_NO_ERROR; | |
| 370 } | |
| 371 | |
| 372 // Requests creation of a new stream with the contents of the | |
| 373 // specified URL; gets notification of the result. | |
| 374 NPError NPN_GetURLNotify(NPP id, | 344 NPError NPN_GetURLNotify(NPP id, |
| 375 const char* url, | 345 const char* url, |
| 376 const char* target, | 346 const char* target, |
| 377 void* notify_data) { | 347 void* notify_data) { |
| 378 // This is identical to NPN_GetURL, but after finishing, the | 348 return NPERR_GENERIC_ERROR; |
| 379 // browser will call NPP_URLNotify to inform the plugin that | |
| 380 // it has completed. | |
| 381 | |
| 382 // According to the NPAPI documentation, if target == _self | |
| 383 // or a parent to _self, the browser should return NPERR_INVALID_PARAM, | |
| 384 // because it can't notify the plugin once deleted. This is | |
| 385 // absolutely false; firefox doesn't do this, and Flash relies on | |
| 386 // being able to use this. | |
| 387 | |
| 388 // Also according to the NPAPI documentation, we should return | |
| 389 // NPERR_INVALID_URL if the url requested is not valid. However, | |
| 390 // this would require that we synchronously start fetching the | |
| 391 // URL. That just isn't practical. As such, there really is | |
| 392 // no way to return this error. From looking at the Firefox | |
| 393 // implementation, it doesn't look like Firefox does this either. | |
| 394 | |
| 395 return GetURLNotify(id, url, target, true, notify_data); | |
| 396 } | 349 } |
| 397 | 350 |
| 398 NPError NPN_GetURL(NPP id, const char* url, const char* target) { | 351 NPError NPN_GetURL(NPP id, const char* url, const char* target) { |
| 399 // Notes: | 352 return NPERR_GENERIC_ERROR; |
| 400 // Request from the Plugin to fetch content either for the plugin | |
| 401 // or to be placed into a browser window. | |
| 402 // | |
| 403 // If target == null, the browser fetches content and streams to plugin. | |
| 404 // otherwise, the browser loads content into an existing browser frame. | |
| 405 // If the target is the window/frame containing the plugin, the plugin | |
| 406 // may be destroyed. | |
| 407 // If the target is _blank, a mailto: or news: url open content in a new | |
| 408 // browser window | |
| 409 // If the target is _self, no other instance of the plugin is created. The | |
| 410 // plugin continues to operate in its own window | |
| 411 | |
| 412 return GetURLNotify(id, url, target, false, 0); | |
| 413 } | |
| 414 | |
| 415 // Generic form of PostURL for common code between PostURL and PostURLNotify. | |
| 416 static NPError PostURLNotify(NPP id, | |
| 417 const char* url, | |
| 418 const char* target, | |
| 419 uint32_t len, | |
| 420 const char* buf, | |
| 421 NPBool file, | |
| 422 bool notify, | |
| 423 void* notify_data) { | |
| 424 if (!url) | |
| 425 return NPERR_INVALID_URL; | |
| 426 | |
| 427 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 428 if (!plugin.get()) { | |
| 429 NOTREACHED(); | |
| 430 return NPERR_GENERIC_ERROR; | |
| 431 } | |
| 432 | |
| 433 std::string post_file_contents; | |
| 434 | |
| 435 if (file) { | |
| 436 // Post data to be uploaded from a file. This can be handled in two | |
| 437 // ways. | |
| 438 // 1. Read entire file and send the contents as if it was a post data | |
| 439 // specified in the argument | |
| 440 // 2. Send just the file details and read them in the browser at the | |
| 441 // time of sending the request. | |
| 442 // Approach 2 is more efficient but complicated. Approach 1 has a major | |
| 443 // drawback of sending potentially large data over two IPC hops. In a way | |
| 444 // 'large data over IPC' problem exists as it is in case of plugin giving | |
| 445 // the data directly instead of in a file. | |
| 446 // Currently we are going with the approach 1 to get the feature working. | |
| 447 // We can optimize this later with approach 2. | |
| 448 | |
| 449 // TODO(joshia): Design a scheme to send a file descriptor instead of | |
| 450 // entire file contents across. | |
| 451 | |
| 452 // Security alert: | |
| 453 // --------------- | |
| 454 // Here we are blindly uploading whatever file requested by a plugin. | |
| 455 // This is risky as someone could exploit a plugin to send private | |
| 456 // data in arbitrary locations. | |
| 457 // A malicious (non-sandboxed) plugin has unfeterred access to OS | |
| 458 // resources and can do this anyway without using browser's HTTP stack. | |
| 459 // FWIW, Firefox and Safari don't perform any security checks. | |
| 460 | |
| 461 if (!buf) | |
| 462 return NPERR_FILE_NOT_FOUND; | |
| 463 | |
| 464 std::string file_path_ascii(buf); | |
| 465 base::FilePath file_path; | |
| 466 static const char kFileUrlPrefix[] = "file:"; | |
| 467 if (base::StartsWith(file_path_ascii, kFileUrlPrefix, | |
| 468 base::CompareCase::INSENSITIVE_ASCII)) { | |
| 469 GURL file_url(file_path_ascii); | |
| 470 DCHECK(file_url.SchemeIsFile()); | |
| 471 net::FileURLToFilePath(file_url, &file_path); | |
| 472 } else { | |
| 473 file_path = base::FilePath::FromUTF8Unsafe(file_path_ascii); | |
| 474 } | |
| 475 | |
| 476 base::File::Info post_file_info; | |
| 477 if (!base::GetFileInfo(file_path, &post_file_info) || | |
| 478 post_file_info.is_directory) | |
| 479 return NPERR_FILE_NOT_FOUND; | |
| 480 | |
| 481 if (!base::ReadFileToString(file_path, &post_file_contents)) | |
| 482 return NPERR_FILE_NOT_FOUND; | |
| 483 | |
| 484 buf = post_file_contents.c_str(); | |
| 485 len = post_file_contents.size(); | |
| 486 } | |
| 487 | |
| 488 // The post data sent by a plugin contains both headers | |
| 489 // and post data. Example: | |
| 490 // Content-type: text/html | |
| 491 // Content-length: 200 | |
| 492 // | |
| 493 // <200 bytes of content here> | |
| 494 // | |
| 495 // Unfortunately, our stream needs these broken apart, | |
| 496 // so we need to parse the data and set headers and data | |
| 497 // separately. | |
| 498 plugin->RequestURL(url, "POST", target, buf, len, notify, notify_data); | |
| 499 return NPERR_NO_ERROR; | |
| 500 } | 353 } |
| 501 | 354 |
| 502 NPError NPN_PostURLNotify(NPP id, | 355 NPError NPN_PostURLNotify(NPP id, |
| 503 const char* url, | 356 const char* url, |
| 504 const char* target, | 357 const char* target, |
| 505 uint32_t len, | 358 uint32_t len, |
| 506 const char* buf, | 359 const char* buf, |
| 507 NPBool file, | 360 NPBool file, |
| 508 void* notify_data) { | 361 void* notify_data) { |
| 509 return PostURLNotify(id, url, target, len, buf, file, true, notify_data); | 362 return NPERR_GENERIC_ERROR; |
| 510 } | 363 } |
| 511 | 364 |
| 512 NPError NPN_PostURL(NPP id, | 365 NPError NPN_PostURL(NPP id, |
| 513 const char* url, | 366 const char* url, |
| 514 const char* target, | 367 const char* target, |
| 515 uint32_t len, | 368 uint32_t len, |
| 516 const char* buf, | 369 const char* buf, |
| 517 NPBool file) { | 370 NPBool file) { |
| 518 // POSTs data to an URL, either from a temp file or a buffer. | 371 return NPERR_GENERIC_ERROR; |
| 519 // If file is true, buf contains a temp file (which host will delete after | |
| 520 // completing), and len contains the length of the filename. | |
| 521 // If file is false, buf contains the data to send, and len contains the | |
| 522 // length of the buffer | |
| 523 // | |
| 524 // If target is null, | |
| 525 // server response is returned to the plugin | |
| 526 // If target is _current, _self, or _top, | |
| 527 // server response is written to the plugin window and plugin is unloaded. | |
| 528 // If target is _new or _blank, | |
| 529 // server response is written to a new browser window | |
| 530 // If target is an existing frame, | |
| 531 // server response goes to that frame. | |
| 532 // | |
| 533 // For protocols other than FTP | |
| 534 // file uploads must be line-end converted from \r\n to \n | |
| 535 // | |
| 536 // Note: you cannot specify headers (even a blank line) in a memory buffer, | |
| 537 // use NPN_PostURLNotify | |
| 538 | |
| 539 return PostURLNotify(id, url, target, len, buf, file, false, 0); | |
| 540 } | 372 } |
| 541 | 373 |
| 542 NPError NPN_NewStream(NPP id, | 374 NPError NPN_NewStream(NPP id, |
| 543 NPMIMEType type, | 375 NPMIMEType type, |
| 544 const char* target, | 376 const char* target, |
| 545 NPStream** stream) { | 377 NPStream** stream) { |
| 546 // Requests creation of a new data stream produced by the plugin, | 378 // Requests creation of a new data stream produced by the plugin, |
| 547 // consumed by the browser. | 379 // consumed by the browser. |
| 548 // | 380 // |
| 549 // Browser should put this stream into a window target. | 381 // Browser should put this stream into a window target. |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 return false; | 923 return false; |
| 1092 } | 924 } |
| 1093 | 925 |
| 1094 NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { | 926 NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { |
| 1095 // TODO: Implement advanced key handling: http://crbug.com/46578 | 927 // TODO: Implement advanced key handling: http://crbug.com/46578 |
| 1096 NOTIMPLEMENTED(); | 928 NOTIMPLEMENTED(); |
| 1097 return false; | 929 return false; |
| 1098 } | 930 } |
| 1099 | 931 |
| 1100 void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { | 932 void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { |
| 1101 scoped_refptr<PluginInstance> plugin(FindInstance(instance)); | |
| 1102 if (plugin.get()) { | |
| 1103 plugin->URLRedirectResponse(!!allow, notify_data); | |
| 1104 } | |
| 1105 } | 933 } |
| 1106 | 934 |
| 1107 } // extern "C" | 935 } // extern "C" |
| OLD | NEW |