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 |