| 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 #ifdef _MSC_VER | 5 #ifdef _MSC_VER |
| 6 // Do not warn about use of std::copy with raw pointers. | 6 // Do not warn about use of std::copy with raw pointers. |
| 7 #pragma warning(disable : 4996) | 7 #pragma warning(disable : 4996) |
| 8 #endif | 8 #endif |
| 9 | 9 |
| 10 #include "native_client/src/trusted/plugin/plugin.h" | 10 #include "native_client/src/trusted/plugin/plugin.h" |
| 11 | 11 |
| 12 #include <assert.h> | |
| 13 #include <fcntl.h> | 12 #include <fcntl.h> |
| 14 #include <stdarg.h> | |
| 15 #include <stdio.h> | 13 #include <stdio.h> |
| 16 #include <stdlib.h> | 14 #include <stdlib.h> |
| 17 #include <string.h> | 15 #include <string.h> |
| 18 | 16 |
| 19 #include <sys/stat.h> | 17 #include <sys/stat.h> |
| 20 #include <sys/types.h> | 18 #include <sys/types.h> |
| 21 | 19 |
| 22 #include <algorithm> | 20 #include <algorithm> |
| 23 #include <deque> | 21 #include <deque> |
| 24 #include <string> | 22 #include <string> |
| 25 #include <vector> | 23 #include <vector> |
| 26 | 24 |
| 27 #include "base/memory/scoped_ptr.h" | |
| 28 #include "native_client/src/include/nacl_base.h" | 25 #include "native_client/src/include/nacl_base.h" |
| 29 #include "native_client/src/include/nacl_macros.h" | 26 #include "native_client/src/include/nacl_macros.h" |
| 30 #include "native_client/src/include/nacl_scoped_ptr.h" | 27 #include "native_client/src/include/nacl_scoped_ptr.h" |
| 31 #include "native_client/src/include/nacl_string.h" | 28 #include "native_client/src/include/nacl_string.h" |
| 32 #include "native_client/src/include/portability.h" | 29 #include "native_client/src/include/portability.h" |
| 33 #include "native_client/src/include/portability_io.h" | 30 #include "native_client/src/include/portability_io.h" |
| 34 #include "native_client/src/include/portability_string.h" | 31 #include "native_client/src/include/portability_string.h" |
| 35 #include "native_client/src/shared/platform/nacl_check.h" | 32 #include "native_client/src/shared/platform/nacl_check.h" |
| 36 #include "native_client/src/shared/platform/nacl_time.h" | |
| 37 #include "native_client/src/shared/ppapi_proxy/browser_ppp.h" | 33 #include "native_client/src/shared/ppapi_proxy/browser_ppp.h" |
| 38 #include "native_client/src/trusted/desc/nacl_desc_base.h" | |
| 39 #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h" | |
| 40 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" | 34 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
| 41 #include "native_client/src/trusted/handle_pass/browser_handle.h" | 35 #include "native_client/src/trusted/handle_pass/browser_handle.h" |
| 42 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" | 36 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" |
| 43 #include "native_client/src/trusted/plugin/browser_interface.h" | |
| 44 #include "native_client/src/trusted/plugin/desc_based_handle.h" | |
| 45 #include "native_client/src/trusted/plugin/json_manifest.h" | 37 #include "native_client/src/trusted/plugin/json_manifest.h" |
| 46 #include "native_client/src/trusted/plugin/nacl_subprocess.h" | 38 #include "native_client/src/trusted/plugin/nacl_subprocess.h" |
| 47 #include "native_client/src/trusted/plugin/nexe_arch.h" | 39 #include "native_client/src/trusted/plugin/nexe_arch.h" |
| 48 #include "native_client/src/trusted/plugin/plugin_error.h" | 40 #include "native_client/src/trusted/plugin/plugin_error.h" |
| 49 #include "native_client/src/trusted/plugin/scriptable_handle.h" | 41 #include "native_client/src/trusted/plugin/scriptable_plugin.h" |
| 50 #include "native_client/src/trusted/plugin/service_runtime.h" | 42 #include "native_client/src/trusted/plugin/service_runtime.h" |
| 51 #include "native_client/src/trusted/plugin/string_encoding.h" | 43 #include "native_client/src/trusted/plugin/string_encoding.h" |
| 52 #include "native_client/src/trusted/plugin/utility.h" | 44 #include "native_client/src/trusted/plugin/utility.h" |
| 53 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" | |
| 54 #include "native_client/src/trusted/service_runtime/nacl_error_code.h" | 45 #include "native_client/src/trusted/service_runtime/nacl_error_code.h" |
| 55 | 46 |
| 47 #include "ppapi/c/dev/ppb_console_dev.h" |
| 56 #include "ppapi/c/dev/ppp_find_dev.h" | 48 #include "ppapi/c/dev/ppp_find_dev.h" |
| 57 #include "ppapi/c/dev/ppp_printing_dev.h" | 49 #include "ppapi/c/dev/ppp_printing_dev.h" |
| 58 #include "ppapi/c/dev/ppp_scrollbar_dev.h" | 50 #include "ppapi/c/dev/ppp_scrollbar_dev.h" |
| 59 #include "ppapi/c/dev/ppp_selection_dev.h" | 51 #include "ppapi/c/dev/ppp_selection_dev.h" |
| 60 #include "ppapi/c/dev/ppp_widget_dev.h" | 52 #include "ppapi/c/dev/ppp_widget_dev.h" |
| 61 #include "ppapi/c/dev/ppp_zoom_dev.h" | 53 #include "ppapi/c/dev/ppp_zoom_dev.h" |
| 62 #include "ppapi/c/pp_errors.h" | 54 #include "ppapi/c/pp_errors.h" |
| 55 #include "ppapi/c/ppb_var.h" |
| 63 #include "ppapi/c/ppp_input_event.h" | 56 #include "ppapi/c/ppp_input_event.h" |
| 64 #include "ppapi/c/ppp_instance.h" | 57 #include "ppapi/c/ppp_instance.h" |
| 65 #include "ppapi/c/ppp_mouse_lock.h" | 58 #include "ppapi/c/ppp_mouse_lock.h" |
| 66 #include "ppapi/c/private/ppb_uma_private.h" | 59 #include "ppapi/c/private/ppb_uma_private.h" |
| 67 #include "ppapi/cpp/dev/find_dev.h" | 60 #include "ppapi/cpp/dev/find_dev.h" |
| 68 #include "ppapi/cpp/dev/printing_dev.h" | 61 #include "ppapi/cpp/dev/printing_dev.h" |
| 69 #include "ppapi/cpp/dev/scrollbar_dev.h" | 62 #include "ppapi/cpp/dev/scrollbar_dev.h" |
| 70 #include "ppapi/cpp/dev/selection_dev.h" | 63 #include "ppapi/cpp/dev/selection_dev.h" |
| 71 #include "ppapi/cpp/dev/text_input_dev.h" | 64 #include "ppapi/cpp/dev/text_input_dev.h" |
| 72 #include "ppapi/cpp/dev/url_util_dev.h" | 65 #include "ppapi/cpp/dev/url_util_dev.h" |
| 73 #include "ppapi/cpp/dev/widget_client_dev.h" | 66 #include "ppapi/cpp/dev/widget_client_dev.h" |
| 74 #include "ppapi/cpp/dev/zoom_dev.h" | 67 #include "ppapi/cpp/dev/zoom_dev.h" |
| 75 #include "ppapi/cpp/image_data.h" | 68 #include "ppapi/cpp/image_data.h" |
| 76 #include "ppapi/cpp/input_event.h" | 69 #include "ppapi/cpp/input_event.h" |
| 77 #include "ppapi/cpp/module.h" | 70 #include "ppapi/cpp/module.h" |
| 78 #include "ppapi/cpp/mouse_lock.h" | 71 #include "ppapi/cpp/mouse_lock.h" |
| 79 #include "ppapi/cpp/rect.h" | 72 #include "ppapi/cpp/rect.h" |
| 80 | 73 |
| 81 using ppapi_proxy::BrowserPpp; | 74 using ppapi_proxy::BrowserPpp; |
| 82 | 75 |
| 83 namespace plugin { | 76 namespace plugin { |
| 84 | 77 |
| 85 namespace { | 78 namespace { |
| 86 | 79 |
| 87 bool GetReadyStateProperty(void* obj, SrpcParams* params) { | |
| 88 Plugin* plugin = static_cast<Plugin*>(obj); | |
| 89 params->outs()[0]->u.ival = plugin->nacl_ready_state(); | |
| 90 return true; | |
| 91 } | |
| 92 | |
| 93 const char* const kTypeAttribute = "type"; | 80 const char* const kTypeAttribute = "type"; |
| 94 // The "src" attribute of the <embed> tag. The value is expected to be either | 81 // The "src" attribute of the <embed> tag. The value is expected to be either |
| 95 // a URL or URI pointing to the manifest file (which is expected to contain | 82 // a URL or URI pointing to the manifest file (which is expected to contain |
| 96 // JSON matching ISAs with .nexe URLs). | 83 // JSON matching ISAs with .nexe URLs). |
| 97 const char* const kSrcManifestAttribute = "src"; | 84 const char* const kSrcManifestAttribute = "src"; |
| 98 // The "nacl" attribute of the <embed> tag. We use the value of this attribute | 85 // The "nacl" attribute of the <embed> tag. We use the value of this attribute |
| 99 // to find the manifest file when NaCl is registered as a plug-in for another | 86 // to find the manifest file when NaCl is registered as a plug-in for another |
| 100 // MIME type because the "src" attribute is used to supply us with the resource | 87 // MIME type because the "src" attribute is used to supply us with the resource |
| 101 // of that MIME type that we're supposed to display. | 88 // of that MIME type that we're supposed to display. |
| 102 const char* const kNaClManifestAttribute = "nacl"; | 89 const char* const kNaClManifestAttribute = "nacl"; |
| 103 // This is a pretty arbitrary limit on the byte size of the NaCl manfest file. | 90 // This is a pretty arbitrary limit on the byte size of the NaCl manfest file. |
| 104 // Note that the resulting string object has to have at least one byte extra | 91 // Note that the resulting string object has to have at least one byte extra |
| 105 // for the null termination character. | 92 // for the null termination character. |
| 106 const size_t kNaClManifestMaxFileBytes = 1024 * 1024; | 93 const size_t kNaClManifestMaxFileBytes = 1024 * 1024; |
| 107 | 94 |
| 108 // Define an argument name to enable 'dev' interfaces. To make sure it doesn't | 95 // Define an argument name to enable 'dev' interfaces. To make sure it doesn't |
| 109 // collide with any user-defined HTML attribute, make the first character '@'. | 96 // collide with any user-defined HTML attribute, make the first character '@'. |
| 110 const char* const kDevAttribute = "@dev"; | 97 const char* const kDevAttribute = "@dev"; |
| 111 | 98 |
| 112 // URL schemes that we treat in special ways. | 99 // URL schemes that we treat in special ways. |
| 113 const char* const kChromeExtensionUriScheme = "chrome-extension"; | 100 const char* const kChromeExtensionUriScheme = "chrome-extension"; |
| 114 const char* const kDataUriScheme = "data"; | 101 const char* const kDataUriScheme = "data"; |
| 115 | 102 |
| 116 // The key used to find the dictionary nexe URLs in the manifest file. | 103 // The key used to find the dictionary nexe URLs in the manifest file. |
| 117 const char* const kNexesKey = "nexes"; | 104 const char* const kNexesKey = "nexes"; |
| 118 | 105 |
| 119 bool GetLastError(void* obj, SrpcParams* params) { | |
| 120 NaClSrpcArg** outs = params->outs(); | |
| 121 PLUGIN_PRINTF(("GetLastError (obj=%p)\n", obj)); | |
| 122 | |
| 123 Plugin* plugin = static_cast<Plugin*>(obj); | |
| 124 outs[0]->arrays.str = strdup(plugin->last_error_string().c_str()); | |
| 125 return true; | |
| 126 } | |
| 127 | |
| 128 bool GetExitStatus(void* obj, SrpcParams* params) { | |
| 129 NaClSrpcArg** outs = params->outs(); | |
| 130 PLUGIN_PRINTF(("GetExitStatus (obj=%p)\n", obj)); | |
| 131 | |
| 132 Plugin* plugin = static_cast<Plugin*>(obj); | |
| 133 outs[0]->u.ival = plugin->exit_status(); | |
| 134 return true; | |
| 135 } | |
| 136 | |
| 137 // Up to 20 seconds | 106 // Up to 20 seconds |
| 138 const int64_t kTimeSmallMin = 1; // in ms | 107 const int64_t kTimeSmallMin = 1; // in ms |
| 139 const int64_t kTimeSmallMax = 20000; // in ms | 108 const int64_t kTimeSmallMax = 20000; // in ms |
| 140 const uint32_t kTimeSmallBuckets = 100; | 109 const uint32_t kTimeSmallBuckets = 100; |
| 141 | 110 |
| 142 // Up to 3 minutes, 20 seconds | 111 // Up to 3 minutes, 20 seconds |
| 143 const int64_t kTimeMediumMin = 10; // in ms | 112 const int64_t kTimeMediumMin = 10; // in ms |
| 144 const int64_t kTimeMediumMax = 200000; // in ms | 113 const int64_t kTimeMediumMax = 200000; // in ms |
| 145 const uint32_t kTimeMediumBuckets = 100; | 114 const uint32_t kTimeMediumBuckets = 100; |
| 146 | 115 |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 467 |
| 499 private: | 468 private: |
| 500 Plugin* plugin_; | 469 Plugin* plugin_; |
| 501 const PPP_Zoom_Dev* ppp_zoom_; | 470 const PPP_Zoom_Dev* ppp_zoom_; |
| 502 | 471 |
| 503 NACL_DISALLOW_COPY_AND_ASSIGN(ZoomAdapter); | 472 NACL_DISALLOW_COPY_AND_ASSIGN(ZoomAdapter); |
| 504 }; | 473 }; |
| 505 | 474 |
| 506 } // namespace | 475 } // namespace |
| 507 | 476 |
| 508 bool Plugin::ExperimentalJavaScriptApisAreEnabled() { | 477 static int const kAbiHeaderBuffer = 256; // must be at least EI_ABIVERSION + 1 |
| 509 return getenv("NACL_ENABLE_EXPERIMENTAL_JAVASCRIPT_APIS") != NULL; | 478 |
| 479 void Plugin::AddPropertyGet(const nacl::string& prop_name, |
| 480 Plugin::PropertyGetter getter) { |
| 481 PLUGIN_PRINTF(("Plugin::AddPropertyGet (prop_name='%s')\n", |
| 482 prop_name.c_str())); |
| 483 property_getters_[nacl::string(prop_name)] = getter; |
| 510 } | 484 } |
| 511 | 485 |
| 512 static int const kAbiHeaderBuffer = 256; // must be at least EI_ABIVERSION + 1 | 486 bool Plugin::HasProperty(const nacl::string& prop_name) { |
| 513 | 487 PLUGIN_PRINTF(("Plugin::HasProperty (prop_name=%s)\n", |
| 514 void Plugin::LoadMethods() { | 488 prop_name.c_str())); |
| 515 PLUGIN_PRINTF(("Plugin::LoadMethods ()\n")); | 489 return property_getters_[prop_name] != NULL; |
| 516 // Properties implemented by Plugin. | |
| 517 AddPropertyGet(GetReadyStateProperty, "readyState", "i"); | |
| 518 } | 490 } |
| 519 | 491 |
| 520 bool Plugin::HasMethod(uintptr_t method_id, CallType call_type) { | 492 bool Plugin::GetProperty(const nacl::string& prop_name, |
| 521 PLUGIN_PRINTF(("Plugin::HasMethod (method_id=%x)\n", | 493 NaClSrpcArg* prop_value) { |
| 522 static_cast<int>(method_id))); | 494 PLUGIN_PRINTF(("Plugin::GetProperty (prop_name=%s)\n", prop_name.c_str())); |
| 523 if (GetMethodInfo(method_id, call_type)) { | 495 |
| 524 PLUGIN_PRINTF(("true\n")); | 496 PropertyGetter getter = property_getters_[prop_name]; |
| 525 return true; | 497 if (NULL == getter) { |
| 526 } | |
| 527 if (!ExperimentalJavaScriptApisAreEnabled()) { | |
| 528 PLUGIN_PRINTF(("false\n")); | |
| 529 return false; | 498 return false; |
| 530 } | 499 } |
| 531 if (call_type != METHOD_CALL) { | 500 (this->*getter)(prop_value); |
| 532 // SRPC nexes can only export methods. | 501 return true; |
| 533 PLUGIN_PRINTF(("false\n")); | |
| 534 return false; | |
| 535 } | |
| 536 bool has_method = main_subprocess_.HasMethod(method_id); | |
| 537 PLUGIN_PRINTF(("%s\n", (has_method ? "true" : "false"))); | |
| 538 return has_method; | |
| 539 } | 502 } |
| 540 | 503 |
| 541 bool Plugin::InitParams(uintptr_t method_id, | 504 void Plugin::GetExitStatus(NaClSrpcArg* prop_value) { |
| 542 CallType call_type, | 505 PLUGIN_PRINTF(("GetExitStatus (this=%p)\n", reinterpret_cast<void*>(this))); |
| 543 SrpcParams* params) { | 506 prop_value->tag = NACL_SRPC_ARG_TYPE_INT; |
| 544 MethodInfo* method_info = GetMethodInfo(method_id, call_type); | 507 prop_value->u.ival = exit_status(); |
| 545 PLUGIN_PRINTF(("Plugin::InitParams (id=%"NACL_PRIxPTR", method_info=%p)\n", | |
| 546 method_id, method_info)); | |
| 547 if (NULL != method_info) { | |
| 548 return params->Init(method_info->ins(), method_info->outs()); | |
| 549 } | |
| 550 if (!ExperimentalJavaScriptApisAreEnabled()) { | |
| 551 return false; | |
| 552 } | |
| 553 if (call_type != METHOD_CALL) { | |
| 554 // SRPC nexes can only export methods. | |
| 555 return false; | |
| 556 } | |
| 557 return main_subprocess_.InitParams(method_id, params); | |
| 558 } | 508 } |
| 559 | 509 |
| 560 bool Plugin::Invoke(uintptr_t method_id, | 510 void Plugin::GetLastError(NaClSrpcArg* prop_value) { |
| 561 CallType call_type, | 511 PLUGIN_PRINTF(("GetLastError (this=%p)\n", reinterpret_cast<void*>(this))); |
| 562 SrpcParams* params) { | 512 prop_value->tag = NACL_SRPC_ARG_TYPE_STRING; |
| 563 MethodInfo* method_info = GetMethodInfo(method_id, call_type); | 513 prop_value->arrays.str = strdup(last_error_string().c_str()); |
| 564 | |
| 565 if (NULL != method_info && NULL != method_info->function_ptr()) { | |
| 566 return method_info->function_ptr()(static_cast<void*>(this), params); | |
| 567 } | |
| 568 if (!ExperimentalJavaScriptApisAreEnabled()) { | |
| 569 return false; | |
| 570 } | |
| 571 if (call_type != METHOD_CALL) { | |
| 572 // SRPC nexes can only export methods. | |
| 573 return false; | |
| 574 } | |
| 575 return main_subprocess_.Invoke(method_id, params); | |
| 576 } | 514 } |
| 577 | 515 |
| 578 bool Plugin::Init(BrowserInterface* browser_interface, | 516 void Plugin::GetReadyStateProperty(NaClSrpcArg* prop_value) { |
| 579 int argc, | 517 PLUGIN_PRINTF(("GetReadyState (this=%p)\n", reinterpret_cast<void*>(this))); |
| 580 char* argn[], | 518 prop_value->tag = NACL_SRPC_ARG_TYPE_INT; |
| 581 char* argv[]) { | 519 prop_value->u.ival = nacl_ready_state(); |
| 520 } |
| 521 |
| 522 bool Plugin::Init(int argc, char* argn[], char* argv[]) { |
| 582 PLUGIN_PRINTF(("Plugin::Init (instance=%p)\n", static_cast<void*>(this))); | 523 PLUGIN_PRINTF(("Plugin::Init (instance=%p)\n", static_cast<void*>(this))); |
| 583 | 524 |
| 584 #ifdef NACL_OSX | 525 #ifdef NACL_OSX |
| 585 // TODO(kochi): For crbug.com/102808, this is a stopgap solution for Lion | 526 // TODO(kochi): For crbug.com/102808, this is a stopgap solution for Lion |
| 586 // until we expose IME API to .nexe. This disables any IME interference | 527 // until we expose IME API to .nexe. This disables any IME interference |
| 587 // against key inputs, so you cannot use off-the-spot IME input for NaCl apps. | 528 // against key inputs, so you cannot use off-the-spot IME input for NaCl apps. |
| 588 // This makes discrepancy among platforms and therefore we should remove | 529 // This makes discrepancy among platforms and therefore we should remove |
| 589 // this hack when IME API is made available. | 530 // this hack when IME API is made available. |
| 590 // The default for non-Mac platforms is still off-the-spot IME mode. | 531 // The default for non-Mac platforms is still off-the-spot IME mode. |
| 591 pp::TextInput_Dev(this).SetTextInputType(PP_TEXTINPUT_TYPE_NONE); | 532 pp::TextInput_Dev(this).SetTextInputType(PP_TEXTINPUT_TYPE_NONE); |
| 592 #endif | 533 #endif |
| 593 | 534 |
| 594 browser_interface_ = browser_interface; | |
| 595 // Remember the embed/object argn/argv pairs. | 535 // Remember the embed/object argn/argv pairs. |
| 596 argn_ = new(std::nothrow) char*[argc]; | 536 argn_ = new char*[argc]; |
| 597 argv_ = new(std::nothrow) char*[argc]; | 537 argv_ = new char*[argc]; |
| 598 argc_ = 0; | 538 argc_ = 0; |
| 599 for (int i = 0; i < argc; ++i) { | 539 for (int i = 0; i < argc; ++i) { |
| 600 if (NULL != argn_ && NULL != argv_) { | 540 if (NULL != argn_ && NULL != argv_) { |
| 601 argn_[argc_] = strdup(argn[i]); | 541 argn_[argc_] = strdup(argn[i]); |
| 602 argv_[argc_] = strdup(argv[i]); | 542 argv_[argc_] = strdup(argv[i]); |
| 603 if (NULL == argn_[argc_] || NULL == argv_[argc_]) { | 543 if (NULL == argn_[argc_] || NULL == argv_[argc_]) { |
| 604 // Give up on passing arguments. | 544 // Give up on passing arguments. |
| 605 free(argn_[argc_]); | 545 free(argn_[argc_]); |
| 606 free(argv_[argc_]); | 546 free(argv_[argc_]); |
| 607 continue; | 547 continue; |
| 608 } | 548 } |
| 609 ++argc_; | 549 ++argc_; |
| 610 } | 550 } |
| 611 } | 551 } |
| 612 // TODO(sehr): this leaks strings if there is a subsequent failure. | 552 // TODO(sehr): this leaks strings if there is a subsequent failure. |
| 613 | 553 |
| 614 // Set up the factory used to produce DescWrappers. | 554 // Set up the factory used to produce DescWrappers. |
| 615 wrapper_factory_ = new nacl::DescWrapperFactory(); | 555 wrapper_factory_ = new nacl::DescWrapperFactory(); |
| 616 if (NULL == wrapper_factory_) { | 556 if (NULL == wrapper_factory_) { |
| 617 return false; | 557 return false; |
| 618 } | 558 } |
| 619 PLUGIN_PRINTF(("Plugin::Init (wrapper_factory=%p)\n", | 559 PLUGIN_PRINTF(("Plugin::Init (wrapper_factory=%p)\n", |
| 620 static_cast<void*>(wrapper_factory_))); | 560 static_cast<void*>(wrapper_factory_))); |
| 621 | 561 |
| 622 // Set up the scriptable methods for the plugin. | 562 // Export a property to allow us to get the exit status of a nexe. |
| 623 LoadMethods(); | 563 AddPropertyGet("exitStatus", &Plugin::GetExitStatus); |
| 564 // Export a property to allow us to get the last error description. |
| 565 AddPropertyGet("lastError", &Plugin::GetLastError); |
| 566 // Export a property to allow us to get the ready state of a nexe during load. |
| 567 AddPropertyGet("readyState", &Plugin::GetReadyStateProperty); |
| 624 | 568 |
| 625 PLUGIN_PRINTF(("Plugin::Init (return 1)\n")); | 569 PLUGIN_PRINTF(("Plugin::Init (return 1)\n")); |
| 626 // Return success. | 570 // Return success. |
| 627 return true; | 571 return true; |
| 628 } | 572 } |
| 629 | 573 |
| 630 void Plugin::ShutDownSubprocesses() { | 574 void Plugin::ShutDownSubprocesses() { |
| 631 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", | 575 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (this=%p)\n", |
| 632 static_cast<void*>(this))); | 576 static_cast<void*>(this))); |
| 633 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", | 577 PLUGIN_PRINTF(("Plugin::ShutDownSubprocesses (%s)\n", |
| (...skipping 29 matching lines...) Expand all Loading... |
| 663 bool service_runtime_started = | 607 bool service_runtime_started = |
| 664 new_service_runtime->Start(wrapper, error_info); | 608 new_service_runtime->Start(wrapper, error_info); |
| 665 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime_started=%d)\n", | 609 PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime_started=%d)\n", |
| 666 service_runtime_started)); | 610 service_runtime_started)); |
| 667 if (!service_runtime_started) { | 611 if (!service_runtime_started) { |
| 668 return false; | 612 return false; |
| 669 } | 613 } |
| 670 return true; | 614 return true; |
| 671 } | 615 } |
| 672 | 616 |
| 673 bool Plugin::StartSrpcServicesCommon(NaClSubprocess* subprocess, | |
| 674 ErrorInfo* error_info) { | |
| 675 if (!subprocess->StartSrpcServices()) { | |
| 676 error_info->SetReport(ERROR_SRPC_CONNECTION_FAIL, | |
| 677 "SRPC connection failure for " + | |
| 678 subprocess->description()); | |
| 679 return false; | |
| 680 } | |
| 681 PLUGIN_PRINTF(("Plugin::StartSrpcServicesCommon (established srpc_client " | |
| 682 "%p)\n", | |
| 683 static_cast<void*>(subprocess->srpc_client()))); | |
| 684 return true; | |
| 685 } | |
| 686 | |
| 687 bool Plugin::StartSrpcServices(NaClSubprocess* subprocess, | |
| 688 ErrorInfo* error_info) { | |
| 689 if (!StartSrpcServicesCommon(subprocess, error_info)) { | |
| 690 return false; | |
| 691 } | |
| 692 // TODO(jvoung): This next bit is likely not needed... | |
| 693 // If StartSrpcServices is only in the JS API that is just for SRPC nexes | |
| 694 // (namely __startSrpcServices), then attempts to start the JS proxy | |
| 695 // will fail anyway? | |
| 696 // If that is the case, by removing the following line, | |
| 697 // the StartSrpcServices == StartSrpcServicesCommon. | |
| 698 // We still need this function though, to launch helper SRPC nexes within | |
| 699 // the plugin. | |
| 700 return StartJSObjectProxy(subprocess, error_info); | |
| 701 } | |
| 702 | |
| 703 bool Plugin::StartJSObjectProxy(NaClSubprocess* subprocess, | |
| 704 ErrorInfo* error_info) { | |
| 705 if (!subprocess->StartJSObjectProxy(this, error_info)) { | |
| 706 // TODO(sehr,polina): rename the function and env var | |
| 707 // to ExperimentalJavaScriptApisAreEnabled. | |
| 708 if (error_info->error_code() == ERROR_START_PROXY_CHECK_PPP && | |
| 709 ExperimentalJavaScriptApisAreEnabled()) { | |
| 710 // It is not an error for the proxy to fail to find PPP methods if | |
| 711 // experimental APIs are enabled. This means we have an SRPC nexe. | |
| 712 error_info->Reset(); | |
| 713 } else { | |
| 714 return false; | |
| 715 } | |
| 716 } | |
| 717 return true; | |
| 718 } | |
| 719 | |
| 720 bool Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, | 617 bool Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, |
| 721 ErrorInfo* error_info, | 618 ErrorInfo* error_info, |
| 722 pp::CompletionCallback init_done_cb, | 619 pp::CompletionCallback init_done_cb, |
| 723 pp::CompletionCallback crash_cb) { | 620 pp::CompletionCallback crash_cb) { |
| 724 // Before forking a new sel_ldr process, ensure that we do not leak | 621 // Before forking a new sel_ldr process, ensure that we do not leak |
| 725 // the ServiceRuntime object for an existing subprocess, and that any | 622 // the ServiceRuntime object for an existing subprocess, and that any |
| 726 // associated listener threads do not go unjoined because if they | 623 // associated listener threads do not go unjoined because if they |
| 727 // outlive the Plugin object, they will not be memory safe. | 624 // outlive the Plugin object, they will not be memory safe. |
| 728 ShutDownSubprocesses(); | 625 ShutDownSubprocesses(); |
| 729 if (!LoadNaClModuleCommon(wrapper, &main_subprocess_, manifest_.get(), | 626 if (!LoadNaClModuleCommon(wrapper, &main_subprocess_, manifest_.get(), |
| 730 true, error_info, init_done_cb, crash_cb)) { | 627 true, error_info, init_done_cb, crash_cb)) { |
| 731 return false; | 628 return false; |
| 732 } | 629 } |
| 733 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", | 630 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", |
| 734 main_subprocess_.detailed_description().c_str())); | 631 main_subprocess_.detailed_description().c_str())); |
| 735 return true; | 632 return true; |
| 736 } | 633 } |
| 737 | 634 |
| 738 bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) { | 635 bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) { |
| 739 if (!(StartSrpcServicesCommon(&main_subprocess_, error_info) | 636 if (!main_subprocess_.StartSrpcServices()) { |
| 740 && StartJSObjectProxy(&main_subprocess_, error_info))) { | 637 error_info->SetReport(ERROR_SRPC_CONNECTION_FAIL, |
| 638 "SRPC connection failure for " + |
| 639 main_subprocess_.description()); |
| 640 return false; |
| 641 } |
| 642 if (!main_subprocess_.StartJSObjectProxy(this, error_info)) { |
| 741 return false; | 643 return false; |
| 742 } | 644 } |
| 743 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", | 645 PLUGIN_PRINTF(("Plugin::LoadNaClModule (%s)\n", |
| 744 main_subprocess_.detailed_description().c_str())); | 646 main_subprocess_.detailed_description().c_str())); |
| 745 return true; | 647 return true; |
| 746 } | 648 } |
| 747 | 649 |
| 748 NaClSubprocess* Plugin::LoadHelperNaClModule(nacl::DescWrapper* wrapper, | 650 NaClSubprocess* Plugin::LoadHelperNaClModule(nacl::DescWrapper* wrapper, |
| 749 const Manifest* manifest, | 651 const Manifest* manifest, |
| 750 ErrorInfo* error_info) { | 652 ErrorInfo* error_info) { |
| 751 nacl::scoped_ptr<NaClSubprocess> nacl_subprocess( | 653 nacl::scoped_ptr<NaClSubprocess> nacl_subprocess( |
| 752 new NaClSubprocess("helper module", browser_interface_, NULL, NULL)); | 654 new NaClSubprocess("helper module", NULL, NULL)); |
| 753 if (NULL == nacl_subprocess.get()) { | 655 if (NULL == nacl_subprocess.get()) { |
| 754 error_info->SetReport(ERROR_SEL_LDR_INIT, | 656 error_info->SetReport(ERROR_SEL_LDR_INIT, |
| 755 "unable to allocate helper subprocess."); | 657 "unable to allocate helper subprocess."); |
| 756 return NULL; | 658 return NULL; |
| 757 } | 659 } |
| 758 | 660 |
| 759 // Do not report UMA stats for translator-related nexes. | 661 // Do not report UMA stats for translator-related nexes. |
| 760 // TODO(sehr): define new UMA stats for translator related nexe events. | 662 // TODO(sehr): define new UMA stats for translator related nexe events. |
| 761 if (!(LoadNaClModuleCommon(wrapper, nacl_subprocess.get(), manifest, | 663 if (!LoadNaClModuleCommon(wrapper, nacl_subprocess.get(), manifest, |
| 762 false, error_info, | 664 false, error_info, |
| 763 pp::BlockUntilComplete(), | 665 pp::BlockUntilComplete(), |
| 764 pp::BlockUntilComplete()) | 666 pp::BlockUntilComplete())) { |
| 765 // We need not wait for the init_done callback. We can block | 667 return NULL; |
| 766 // here in StartSrpcServicesCommon, since helper NaCl modules | 668 } |
| 767 // are spawned from a private thread. | 669 // We need not wait for the init_done callback. We can block |
| 768 // | 670 // here in StartSrpcServices, since helper NaCl modules |
| 769 // TODO(bsy): if helper module crashes, we should abort. | 671 // are spawned from a private thread. |
| 770 // crash_cb is not used here, so we are relying on crashes | 672 // |
| 771 // being detected in StartSrpcServicesCommon or later. | 673 // TODO(bsy): if helper module crashes, we should abort. |
| 772 // | 674 // crash_cb is not used here, so we are relying on crashes |
| 773 // NB: More refactoring might be needed, however, if helper | 675 // being detected in StartSrpcServices or later. |
| 774 // NaCl modules have their own manifest. Currently the | 676 // |
| 775 // manifest is a per-plugin-instance object, not a per | 677 // NB: More refactoring might be needed, however, if helper |
| 776 // NaClSubprocess object. | 678 // NaCl modules have their own manifest. Currently the |
| 777 && StartSrpcServicesCommon(nacl_subprocess.get(), error_info))) { | 679 // manifest is a per-plugin-instance object, not a per |
| 680 // NaClSubprocess object. |
| 681 if (!nacl_subprocess->StartSrpcServices()) { |
| 682 error_info->SetReport(ERROR_SRPC_CONNECTION_FAIL, |
| 683 "SRPC connection failure for " + |
| 684 nacl_subprocess->description()); |
| 778 return NULL; | 685 return NULL; |
| 779 } | 686 } |
| 780 | 687 |
| 781 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (%s)\n", | 688 PLUGIN_PRINTF(("Plugin::LoadHelperNaClModule (%s)\n", |
| 782 nacl_subprocess.get()->detailed_description().c_str())); | 689 nacl_subprocess.get()->detailed_description().c_str())); |
| 783 | 690 |
| 784 return nacl_subprocess.release(); | 691 return nacl_subprocess.release(); |
| 785 } | 692 } |
| 786 | 693 |
| 787 char* Plugin::LookupArgument(const char* key) { | 694 char* Plugin::LookupArgument(const char* key) { |
| 788 char** keys = argn(); | 695 char** keys = argn(); |
| 789 for (int ii = 0, len = argc(); ii < len; ++ii) { | 696 for (int ii = 0, len = argc(); ii < len; ++ii) { |
| 790 if (!strcmp(keys[ii], key)) { | 697 if (!strcmp(keys[ii], key)) { |
| 791 return argv()[ii]; | 698 return argv()[ii]; |
| 792 } | 699 } |
| 793 } | 700 } |
| 794 return NULL; | 701 return NULL; |
| 795 } | 702 } |
| 796 | 703 |
| 797 void Plugin::AddPropertyGet(RpcFunction function_ptr, | |
| 798 const char* name, | |
| 799 const char* outs) { | |
| 800 uintptr_t method_id = browser_interface()->StringToIdentifier(name); | |
| 801 PLUGIN_PRINTF(("Plugin::AddPropertyGet (name='%s', id=%" | |
| 802 NACL_PRIxPTR")\n", name, method_id)); | |
| 803 MethodInfo* new_method = new MethodInfo(function_ptr, name, "", outs); | |
| 804 property_get_methods_.AddMethod(method_id, new_method); | |
| 805 } | |
| 806 | |
| 807 MethodInfo* Plugin::GetMethodInfo(uintptr_t method_id, CallType call_type) { | |
| 808 MethodInfo* method_info = NULL; | |
| 809 switch (call_type) { | |
| 810 case PROPERTY_GET: | |
| 811 method_info = property_get_methods_.GetMethod(method_id); | |
| 812 break; | |
| 813 case PROPERTY_SET: | |
| 814 case METHOD_CALL: | |
| 815 break; | |
| 816 } | |
| 817 PLUGIN_PRINTF(("Plugin::GetMethodInfo (id=%"NACL_PRIxPTR", " | |
| 818 "return %p)\n", method_id, static_cast<void*>(method_info))); | |
| 819 return method_info; | |
| 820 } | |
| 821 | |
| 822 // Suggested names for progress event types, per | 704 // Suggested names for progress event types, per |
| 823 // http://www.w3.org/TR/progress-events/ | 705 // http://www.w3.org/TR/progress-events/ |
| 824 const char* const Plugin::kProgressEventLoadStart = "loadstart"; | 706 const char* const Plugin::kProgressEventLoadStart = "loadstart"; |
| 825 const char* const Plugin::kProgressEventProgress = "progress"; | 707 const char* const Plugin::kProgressEventProgress = "progress"; |
| 826 const char* const Plugin::kProgressEventError = "error"; | 708 const char* const Plugin::kProgressEventError = "error"; |
| 827 const char* const Plugin::kProgressEventAbort = "abort"; | 709 const char* const Plugin::kProgressEventAbort = "abort"; |
| 828 const char* const Plugin::kProgressEventLoad = "load"; | 710 const char* const Plugin::kProgressEventLoad = "load"; |
| 829 const char* const Plugin::kProgressEventLoadEnd = "loadend"; | 711 const char* const Plugin::kProgressEventLoadEnd = "loadend"; |
| 830 // Define a NaCl specific event type for .nexe crashes. | 712 // Define a NaCl specific event type for .nexe crashes. |
| 831 const char* const Plugin::kProgressEventCrash = "crash"; | 713 const char* const Plugin::kProgressEventCrash = "crash"; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 } | 755 } |
| 874 | 756 |
| 875 | 757 |
| 876 Plugin* Plugin::New(PP_Instance pp_instance) { | 758 Plugin* Plugin::New(PP_Instance pp_instance) { |
| 877 PLUGIN_PRINTF(("Plugin::New (pp_instance=%"NACL_PRId32")\n", pp_instance)); | 759 PLUGIN_PRINTF(("Plugin::New (pp_instance=%"NACL_PRId32")\n", pp_instance)); |
| 878 #if NACL_WINDOWS && !defined(NACL_STANDALONE) | 760 #if NACL_WINDOWS && !defined(NACL_STANDALONE) |
| 879 if (!NaClHandlePassBrowserCtor()) { | 761 if (!NaClHandlePassBrowserCtor()) { |
| 880 return NULL; | 762 return NULL; |
| 881 } | 763 } |
| 882 #endif | 764 #endif |
| 883 Plugin* plugin = new(std::nothrow) Plugin(pp_instance); | 765 Plugin* plugin = new Plugin(pp_instance); |
| 884 PLUGIN_PRINTF(("Plugin::New (plugin=%p)\n", static_cast<void*>(plugin))); | 766 PLUGIN_PRINTF(("Plugin::New (plugin=%p)\n", static_cast<void*>(plugin))); |
| 885 if (plugin == NULL) { | 767 if (plugin == NULL) { |
| 886 return NULL; | 768 return NULL; |
| 887 } | 769 } |
| 888 return plugin; | 770 return plugin; |
| 889 } | 771 } |
| 890 | 772 |
| 891 | 773 |
| 892 // All failures of this function will show up as "Missing Plugin-in", so | 774 // All failures of this function will show up as "Missing Plugin-in", so |
| 893 // there is no need to log to JS console that there was an initialization | 775 // there is no need to log to JS console that there was an initialization |
| 894 // failure. Note that module loading functions will log their own errors. | 776 // failure. Note that module loading functions will log their own errors. |
| 895 bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { | 777 bool Plugin::Init(uint32_t argc, const char* argn[], const char* argv[]) { |
| 896 PLUGIN_PRINTF(("Plugin::Init (argc=%"NACL_PRIu32")\n", argc)); | 778 PLUGIN_PRINTF(("Plugin::Init (argc=%"NACL_PRIu32")\n", argc)); |
| 897 HistogramEnumerateOsArch(GetSandboxISA()); | 779 HistogramEnumerateOsArch(GetSandboxISA()); |
| 898 init_time_ = NaClGetTimeOfDayMicroseconds(); | 780 init_time_ = NaClGetTimeOfDayMicroseconds(); |
| 899 | 781 |
| 900 scoped_ptr<BrowserInterface> browser_interface( | 782 ScriptablePlugin* scriptable_plugin = ScriptablePlugin::NewPlugin(this); |
| 901 new(std::nothrow) BrowserInterface); | 783 if (scriptable_plugin == NULL) |
| 902 if (browser_interface == NULL) { | |
| 903 return false; | |
| 904 } | |
| 905 ScriptableHandle* handle = ScriptableHandle::NewPlugin(this); | |
| 906 if (handle == NULL) | |
| 907 return false; | 784 return false; |
| 908 | 785 |
| 909 set_scriptable_handle(handle); | 786 set_scriptable_plugin(scriptable_plugin); |
| 910 PLUGIN_PRINTF(("Plugin::Init (scriptable_handle=%p)\n", | 787 PLUGIN_PRINTF(("Plugin::Init (scriptable_handle=%p)\n", |
| 911 static_cast<void*>(scriptable_handle()))); | 788 static_cast<void*>(scriptable_plugin_))); |
| 912 url_util_ = pp::URLUtil_Dev::Get(); | 789 url_util_ = pp::URLUtil_Dev::Get(); |
| 913 if (url_util_ == NULL) | 790 if (url_util_ == NULL) |
| 914 return false; | 791 return false; |
| 915 | 792 |
| 916 PLUGIN_PRINTF(("Plugin::Init (url_util_=%p)\n", | 793 PLUGIN_PRINTF(("Plugin::Init (url_util_=%p)\n", |
| 917 static_cast<const void*>(url_util_))); | 794 static_cast<const void*>(url_util_))); |
| 918 | 795 |
| 919 bool status = Plugin::Init( | 796 bool status = Plugin::Init( |
| 920 browser_interface.release(), | |
| 921 static_cast<int>(argc), | 797 static_cast<int>(argc), |
| 922 // TODO(polina): Can we change the args on our end to be const to | 798 // TODO(polina): Can we change the args on our end to be const to |
| 923 // avoid these ugly casts? | 799 // avoid these ugly casts? |
| 924 const_cast<char**>(argn), | 800 const_cast<char**>(argn), |
| 925 const_cast<char**>(argv)); | 801 const_cast<char**>(argv)); |
| 926 if (status) { | 802 if (status) { |
| 927 // Look for the developer attribute; if it's present, enable 'dev' | 803 // Look for the developer attribute; if it's present, enable 'dev' |
| 928 // interfaces. | 804 // interfaces. |
| 929 const char* dev_settings = LookupArgument(kDevAttribute); | 805 const char* dev_settings = LookupArgument(kDevAttribute); |
| 930 enable_dev_interfaces_ = (dev_settings != NULL); | 806 enable_dev_interfaces_ = (dev_settings != NULL); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 " WARNING: 'nacl' property is incorrect. Use 'src'.\n")); | 841 " WARNING: 'nacl' property is incorrect. Use 'src'.\n")); |
| 966 } | 842 } |
| 967 } else { | 843 } else { |
| 968 // Issue a GET for the manifest_url. The manifest file will be parsed to | 844 // Issue a GET for the manifest_url. The manifest file will be parsed to |
| 969 // determine the nexe URL. | 845 // determine the nexe URL. |
| 970 // Sets src property to full manifest URL. | 846 // Sets src property to full manifest URL. |
| 971 RequestNaClManifest(manifest_url); | 847 RequestNaClManifest(manifest_url); |
| 972 } | 848 } |
| 973 } | 849 } |
| 974 | 850 |
| 975 // Export a property to allow us to get the last error description. | |
| 976 AddPropertyGet(GetLastError, "lastError", "s"); | |
| 977 // Export a property to allow us to get the nexe exit status. | |
| 978 AddPropertyGet(GetExitStatus, "exitStatus", "i"); | |
| 979 | |
| 980 PLUGIN_PRINTF(("Plugin::Init (status=%d)\n", status)); | 851 PLUGIN_PRINTF(("Plugin::Init (status=%d)\n", status)); |
| 981 return status; | 852 return status; |
| 982 } | 853 } |
| 983 | 854 |
| 984 | 855 |
| 985 Plugin::Plugin(PP_Instance pp_instance) | 856 Plugin::Plugin(PP_Instance pp_instance) |
| 986 : pp::InstancePrivate(pp_instance), | 857 : pp::InstancePrivate(pp_instance), |
| 987 browser_interface_(NULL), | 858 scriptable_plugin_(NULL), |
| 988 scriptable_handle_(NULL), | |
| 989 argc_(-1), | 859 argc_(-1), |
| 990 argn_(NULL), | 860 argn_(NULL), |
| 991 argv_(NULL), | 861 argv_(NULL), |
| 992 main_subprocess_("main subprocess", NULL, NULL, NULL), | 862 main_subprocess_("main subprocess", NULL, NULL), |
| 993 nacl_ready_state_(UNSENT), | 863 nacl_ready_state_(UNSENT), |
| 994 nexe_error_reported_(false), | 864 nexe_error_reported_(false), |
| 995 wrapper_factory_(NULL), | 865 wrapper_factory_(NULL), |
| 996 last_error_string_(""), | 866 last_error_string_(""), |
| 997 ppapi_proxy_(NULL), | 867 ppapi_proxy_(NULL), |
| 998 enable_dev_interfaces_(false), | 868 enable_dev_interfaces_(false), |
| 999 init_time_(0), | 869 init_time_(0), |
| 1000 ready_time_(0), | 870 ready_time_(0), |
| 1001 nexe_size_(0), | 871 nexe_size_(0), |
| 1002 time_of_last_progress_event_(0) { | 872 time_of_last_progress_event_(0) { |
| 1003 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" | 873 PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" |
| 1004 NACL_PRId32")\n", static_cast<void*>(this), pp_instance)); | 874 NACL_PRId32")\n", static_cast<void*>(this), pp_instance)); |
| 1005 callback_factory_.Initialize(this); | 875 callback_factory_.Initialize(this); |
| 1006 nexe_downloader_.Initialize(this); | 876 nexe_downloader_.Initialize(this); |
| 1007 } | 877 } |
| 1008 | 878 |
| 1009 | 879 |
| 1010 Plugin::~Plugin() { | 880 Plugin::~Plugin() { |
| 1011 int64_t shutdown_start = NaClGetTimeOfDayMicroseconds(); | 881 int64_t shutdown_start = NaClGetTimeOfDayMicroseconds(); |
| 1012 | 882 |
| 1013 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, scriptable_handle=%p)\n", | 883 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, scriptable_plugin=%p)\n", |
| 1014 static_cast<void*>(this), | 884 static_cast<void*>(this), |
| 1015 static_cast<void*>(scriptable_handle()))); | 885 static_cast<void*>(scriptable_plugin()))); |
| 1016 | 886 |
| 1017 // If the proxy has been shutdown before now, it's likely the plugin suffered | 887 // If the proxy has been shutdown before now, it's likely the plugin suffered |
| 1018 // an error while loading. | 888 // an error while loading. |
| 1019 if (ppapi_proxy_ != NULL) { | 889 if (ppapi_proxy_ != NULL) { |
| 1020 HistogramTimeLarge( | 890 HistogramTimeLarge( |
| 1021 "NaCl.ModuleUptime.Normal", | 891 "NaCl.ModuleUptime.Normal", |
| 1022 (shutdown_start - ready_time_) / NACL_MICROS_PER_MILLI); | 892 (shutdown_start - ready_time_) / NACL_MICROS_PER_MILLI); |
| 1023 } | 893 } |
| 1024 | 894 |
| 1025 #if NACL_WINDOWS && !defined(NACL_STANDALONE) | 895 #if NACL_WINDOWS && !defined(NACL_STANDALONE) |
| 1026 NaClHandlePassBrowserDtor(); | 896 NaClHandlePassBrowserDtor(); |
| 1027 #endif | 897 #endif |
| 1028 | 898 |
| 1029 url_downloaders_.erase(url_downloaders_.begin(), url_downloaders_.end()); | 899 url_downloaders_.erase(url_downloaders_.begin(), url_downloaders_.end()); |
| 1030 | 900 |
| 1031 ShutdownProxy(); | 901 ShutdownProxy(); |
| 1032 ScriptableHandle* scriptable_handle_ = scriptable_handle(); | 902 ScriptablePlugin* scriptable_plugin_ = scriptable_plugin(); |
| 1033 ScriptableHandle::Unref(&scriptable_handle_); | 903 ScriptablePlugin::Unref(&scriptable_plugin_); |
| 1034 | 904 |
| 1035 // ShutDownSubprocesses shuts down the main subprocess, which shuts | 905 // ShutDownSubprocesses shuts down the main subprocess, which shuts |
| 1036 // down the main ServiceRuntime object, which kills the subprocess. | 906 // down the main ServiceRuntime object, which kills the subprocess. |
| 1037 // As a side effect of the subprocess being killed, the reverse | 907 // As a side effect of the subprocess being killed, the reverse |
| 1038 // services thread(s) will get EOF on the reverse channel(s), and | 908 // services thread(s) will get EOF on the reverse channel(s), and |
| 1039 // the thread(s) will exit. In ServiceRuntime::Shutdown, we invoke | 909 // the thread(s) will exit. In ServiceRuntime::Shutdown, we invoke |
| 1040 // ReverseService::WaitForServiceThreadsToExit(), so that there will | 910 // ReverseService::WaitForServiceThreadsToExit(), so that there will |
| 1041 // not be an extent thread(s) hanging around. This means that the | 911 // not be an extent thread(s) hanging around. This means that the |
| 1042 // ~Plugin will block until this happens. This is a requirement, | 912 // ~Plugin will block until this happens. This is a requirement, |
| 1043 // since the renderer should be free to unload the plugin code, and | 913 // since the renderer should be free to unload the plugin code, and |
| 1044 // we cannot have threads running code that gets unloaded before | 914 // we cannot have threads running code that gets unloaded before |
| 1045 // they exit. | 915 // they exit. |
| 1046 // | 916 // |
| 1047 // By waiting for the threads here, we also ensure that the Plugin | 917 // By waiting for the threads here, we also ensure that the Plugin |
| 1048 // object and the subprocess and ServiceRuntime objects is not | 918 // object and the subprocess and ServiceRuntime objects is not |
| 1049 // (fully) destroyed while the threads are running, so resources | 919 // (fully) destroyed while the threads are running, so resources |
| 1050 // that are destroyed after ShutDownSubprocesses (below) are | 920 // that are destroyed after ShutDownSubprocesses (below) are |
| 1051 // guaranteed to be live and valid for access from the service | 921 // guaranteed to be live and valid for access from the service |
| 1052 // threads. | 922 // threads. |
| 1053 // | 923 // |
| 1054 // The main_subprocess object, which wraps the main service_runtime | 924 // The main_subprocess object, which wraps the main service_runtime |
| 1055 // object, is dtor'd implicitly after the explicit code below runs, | 925 // object, is dtor'd implicitly after the explicit code below runs, |
| 1056 // so the main service runtime object will not have been dtor'd, | 926 // so the main service runtime object will not have been dtor'd, |
| 1057 // though the Shutdown method may have been called, during the | 927 // though the Shutdown method may have been called, during the |
| 1058 // lifetime of the service threads. | 928 // lifetime of the service threads. |
| 1059 ShutDownSubprocesses(); | 929 ShutDownSubprocesses(); |
| 1060 | 930 |
| 1061 delete wrapper_factory_; | 931 delete wrapper_factory_; |
| 1062 delete browser_interface_; | |
| 1063 delete[] argv_; | 932 delete[] argv_; |
| 1064 delete[] argn_; | 933 delete[] argn_; |
| 1065 | 934 |
| 1066 HistogramTimeSmall( | 935 HistogramTimeSmall( |
| 1067 "NaCl.Perf.ShutdownTime.Total", | 936 "NaCl.Perf.ShutdownTime.Total", |
| 1068 (NaClGetTimeOfDayMicroseconds() - shutdown_start) | 937 (NaClGetTimeOfDayMicroseconds() - shutdown_start) |
| 1069 / NACL_MICROS_PER_MILLI); | 938 / NACL_MICROS_PER_MILLI); |
| 1070 | 939 |
| 1071 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, return)\n", | 940 PLUGIN_PRINTF(("Plugin::~Plugin (this=%p, return)\n", |
| 1072 static_cast<void*>(this))); | 941 static_cast<void*>(this))); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 ppapi_proxy_->ppp_messaging_interface()->HandleMessage( | 1007 ppapi_proxy_->ppp_messaging_interface()->HandleMessage( |
| 1139 pp_instance(), message.pp_var()); | 1008 pp_instance(), message.pp_var()); |
| 1140 } | 1009 } |
| 1141 } | 1010 } |
| 1142 | 1011 |
| 1143 | 1012 |
| 1144 pp::Var Plugin::GetInstanceObject() { | 1013 pp::Var Plugin::GetInstanceObject() { |
| 1145 PLUGIN_PRINTF(("Plugin::GetInstanceObject (this=%p)\n", | 1014 PLUGIN_PRINTF(("Plugin::GetInstanceObject (this=%p)\n", |
| 1146 static_cast<void*>(this))); | 1015 static_cast<void*>(this))); |
| 1147 // The browser will unref when it discards the var for this object. | 1016 // The browser will unref when it discards the var for this object. |
| 1148 ScriptableHandle* handle = | 1017 ScriptablePlugin* handle = |
| 1149 static_cast<ScriptableHandle*>(scriptable_handle()->AddRef()); | 1018 static_cast<ScriptablePlugin*>(scriptable_plugin()->AddRef()); |
| 1150 pp::Var* handle_var = handle->var(); | 1019 pp::Var* handle_var = handle->var(); |
| 1151 PLUGIN_PRINTF(("Plugin::GetInstanceObject (handle=%p, handle_var=%p)\n", | 1020 PLUGIN_PRINTF(("Plugin::GetInstanceObject (handle=%p, handle_var=%p)\n", |
| 1152 static_cast<void*>(handle), static_cast<void*>(handle_var))); | 1021 static_cast<void*>(handle), static_cast<void*>(handle_var))); |
| 1153 return *handle_var; // make a copy | 1022 return *handle_var; // make a copy |
| 1154 } | 1023 } |
| 1155 | 1024 |
| 1156 void Plugin::HistogramStartupTimeSmall(const std::string& name, float dt) { | 1025 void Plugin::HistogramStartupTimeSmall(const std::string& name, float dt) { |
| 1157 if (nexe_size_ > 0) { | 1026 if (nexe_size_ > 0) { |
| 1158 float size_in_MB = static_cast<float>(nexe_size_) / (1024.f * 1024.f); | 1027 float size_in_MB = static_cast<float>(nexe_size_) / (1024.f * 1024.f); |
| 1159 HistogramTimeSmall(name, static_cast<int64_t>(dt)); | 1028 HistogramTimeSmall(name, static_cast<int64_t>(dt)); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 if (NaClSrpcServiceMethodIndex(client_service, | 1218 if (NaClSrpcServiceMethodIndex(client_service, |
| 1350 "PPP_InitializeModule:ihs:i") == | 1219 "PPP_InitializeModule:ihs:i") == |
| 1351 kNaClSrpcInvalidMethodIndex) { | 1220 kNaClSrpcInvalidMethodIndex) { |
| 1352 error_info->SetReport( | 1221 error_info->SetReport( |
| 1353 ERROR_START_PROXY_CHECK_PPP, | 1222 ERROR_START_PROXY_CHECK_PPP, |
| 1354 "could not find PPP_InitializeModule() - toolchain version mismatch?"); | 1223 "could not find PPP_InitializeModule() - toolchain version mismatch?"); |
| 1355 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (%s)\n", | 1224 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (%s)\n", |
| 1356 error_info->message().c_str())); | 1225 error_info->message().c_str())); |
| 1357 return false; | 1226 return false; |
| 1358 } | 1227 } |
| 1359 nacl::scoped_ptr<BrowserPpp> ppapi_proxy( | 1228 nacl::scoped_ptr<BrowserPpp> ppapi_proxy(new BrowserPpp(srpc_channel, this)); |
| 1360 new(std::nothrow) BrowserPpp(srpc_channel, this)); | |
| 1361 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (ppapi_proxy=%p)\n", | 1229 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (ppapi_proxy=%p)\n", |
| 1362 static_cast<void*>(ppapi_proxy.get()))); | 1230 static_cast<void*>(ppapi_proxy.get()))); |
| 1363 if (ppapi_proxy.get() == NULL) { | 1231 if (ppapi_proxy.get() == NULL) { |
| 1364 error_info->SetReport(ERROR_START_PROXY_ALLOC, | 1232 error_info->SetReport(ERROR_START_PROXY_ALLOC, |
| 1365 "could not allocate proxy memory."); | 1233 "could not allocate proxy memory."); |
| 1366 return false; | 1234 return false; |
| 1367 } | 1235 } |
| 1368 pp::Module* module = pp::Module::Get(); | 1236 pp::Module* module = pp::Module::Get(); |
| 1369 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (module=%p)\n", | 1237 PLUGIN_PRINTF(("Plugin::StartProxiedExecution (module=%p)\n", |
| 1370 static_cast<void*>(module))); | 1238 static_cast<void*>(module))); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1393 did_create)); | 1261 did_create)); |
| 1394 if (did_create == PP_FALSE) { | 1262 if (did_create == PP_FALSE) { |
| 1395 error_info->SetReport(ERROR_START_PROXY_INSTANCE, | 1263 error_info->SetReport(ERROR_START_PROXY_INSTANCE, |
| 1396 "could not create instance."); | 1264 "could not create instance."); |
| 1397 return false; | 1265 return false; |
| 1398 } | 1266 } |
| 1399 | 1267 |
| 1400 ppapi_proxy_ = ppapi_proxy.release(); | 1268 ppapi_proxy_ = ppapi_proxy.release(); |
| 1401 | 1269 |
| 1402 // Create PPP* interface adapters to forward calls to .nexe. | 1270 // Create PPP* interface adapters to forward calls to .nexe. |
| 1403 find_adapter_.reset(new(std::nothrow) FindAdapter(this)); | 1271 find_adapter_.reset(new FindAdapter(this)); |
| 1404 mouse_lock_adapter_.reset(new(std::nothrow) MouseLockAdapter(this)); | 1272 mouse_lock_adapter_.reset(new MouseLockAdapter(this)); |
| 1405 printing_adapter_.reset(new(std::nothrow) PrintingAdapter(this)); | 1273 printing_adapter_.reset(new PrintingAdapter(this)); |
| 1406 selection_adapter_.reset(new(std::nothrow) SelectionAdapter(this)); | 1274 selection_adapter_.reset(new SelectionAdapter(this)); |
| 1407 widget_client_adapter_.reset(new(std::nothrow) WidgetClientAdapter(this)); | 1275 widget_client_adapter_.reset(new WidgetClientAdapter(this)); |
| 1408 zoom_adapter_.reset(new(std::nothrow) ZoomAdapter(this)); | 1276 zoom_adapter_.reset(new ZoomAdapter(this)); |
| 1409 | 1277 |
| 1410 // Replay missed events. | 1278 // Replay missed events. |
| 1411 if (!view_to_replay_.is_null()) { | 1279 if (!view_to_replay_.is_null()) { |
| 1412 DidChangeView(view_to_replay_); | 1280 DidChangeView(view_to_replay_); |
| 1413 view_to_replay_ = pp::View(); | 1281 view_to_replay_ = pp::View(); |
| 1414 } | 1282 } |
| 1415 if (!document_load_to_replay_.is_null()) { | 1283 if (!document_load_to_replay_.is_null()) { |
| 1416 HandleDocumentLoad(document_load_to_replay_); | 1284 HandleDocumentLoad(document_load_to_replay_); |
| 1417 document_load_to_replay_ = pp::URLLoader(); | 1285 document_load_to_replay_ = pp::URLLoader(); |
| 1418 } | 1286 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1434 if (nacl_ready_state() == DONE && !nexe_error_reported()) { // After loadEnd. | 1302 if (nacl_ready_state() == DONE && !nexe_error_reported()) { // After loadEnd. |
| 1435 int64_t crash_time = NaClGetTimeOfDayMicroseconds(); | 1303 int64_t crash_time = NaClGetTimeOfDayMicroseconds(); |
| 1436 // Crashes will be more likely near startup, so use a medium histogram | 1304 // Crashes will be more likely near startup, so use a medium histogram |
| 1437 // instead of a large one. | 1305 // instead of a large one. |
| 1438 HistogramTimeMedium( | 1306 HistogramTimeMedium( |
| 1439 "NaCl.ModuleUptime.Crash", | 1307 "NaCl.ModuleUptime.Crash", |
| 1440 (crash_time - ready_time_) / NACL_MICROS_PER_MILLI); | 1308 (crash_time - ready_time_) / NACL_MICROS_PER_MILLI); |
| 1441 | 1309 |
| 1442 nacl::string message = nacl::string("NaCl module crashed"); | 1310 nacl::string message = nacl::string("NaCl module crashed"); |
| 1443 set_last_error_string(message); | 1311 set_last_error_string(message); |
| 1444 browser_interface()->AddToConsole(this, message); | 1312 AddToConsole(message); |
| 1445 | 1313 |
| 1446 EnqueueProgressEvent(kProgressEventCrash); | 1314 EnqueueProgressEvent(kProgressEventCrash); |
| 1447 set_nexe_error_reported(true); | 1315 set_nexe_error_reported(true); |
| 1448 CHECK(ppapi_proxy_ == NULL || !ppapi_proxy_->is_valid()); | 1316 CHECK(ppapi_proxy_ == NULL || !ppapi_proxy_->is_valid()); |
| 1449 ShutdownProxy(); | 1317 ShutdownProxy(); |
| 1450 } | 1318 } |
| 1451 // else ReportLoadError() and ReportAbortError() will be used by loading code | 1319 // else ReportLoadError() and ReportAbortError() will be used by loading code |
| 1452 // to provide error handling and proxy shutdown. | 1320 // to provide error handling and proxy shutdown. |
| 1453 // | 1321 // |
| 1454 // NOTE: not all crashes during load will make it here. | 1322 // NOTE: not all crashes during load will make it here. |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 void Plugin::ReportLoadError(const ErrorInfo& error_info) { | 1684 void Plugin::ReportLoadError(const ErrorInfo& error_info) { |
| 1817 PLUGIN_PRINTF(("Plugin::ReportLoadError (error='%s')\n", | 1685 PLUGIN_PRINTF(("Plugin::ReportLoadError (error='%s')\n", |
| 1818 error_info.message().c_str())); | 1686 error_info.message().c_str())); |
| 1819 // Set the readyState attribute to indicate we need to start over. | 1687 // Set the readyState attribute to indicate we need to start over. |
| 1820 set_nacl_ready_state(DONE); | 1688 set_nacl_ready_state(DONE); |
| 1821 set_nexe_error_reported(true); | 1689 set_nexe_error_reported(true); |
| 1822 // Report an error in lastError and on the JavaScript console. | 1690 // Report an error in lastError and on the JavaScript console. |
| 1823 nacl::string message = nacl::string("NaCl module load failed: ") + | 1691 nacl::string message = nacl::string("NaCl module load failed: ") + |
| 1824 error_info.message(); | 1692 error_info.message(); |
| 1825 set_last_error_string(message); | 1693 set_last_error_string(message); |
| 1826 browser_interface()->AddToConsole(this, message); | 1694 AddToConsole(message); |
| 1827 ShutdownProxy(); | 1695 ShutdownProxy(); |
| 1828 // Inform JavaScript that loading encountered an error and is complete. | 1696 // Inform JavaScript that loading encountered an error and is complete. |
| 1829 EnqueueProgressEvent(kProgressEventError); | 1697 EnqueueProgressEvent(kProgressEventError); |
| 1830 EnqueueProgressEvent(kProgressEventLoadEnd); | 1698 EnqueueProgressEvent(kProgressEventLoadEnd); |
| 1831 | 1699 |
| 1832 // UMA | 1700 // UMA |
| 1833 HistogramEnumerateLoadStatus(error_info.error_code()); | 1701 HistogramEnumerateLoadStatus(error_info.error_code()); |
| 1834 } | 1702 } |
| 1835 | 1703 |
| 1836 | 1704 |
| 1837 void Plugin::ReportLoadAbort() { | 1705 void Plugin::ReportLoadAbort() { |
| 1838 PLUGIN_PRINTF(("Plugin::ReportLoadAbort\n")); | 1706 PLUGIN_PRINTF(("Plugin::ReportLoadAbort\n")); |
| 1839 // Set the readyState attribute to indicate we need to start over. | 1707 // Set the readyState attribute to indicate we need to start over. |
| 1840 set_nacl_ready_state(DONE); | 1708 set_nacl_ready_state(DONE); |
| 1841 set_nexe_error_reported(true); | 1709 set_nexe_error_reported(true); |
| 1842 // Report an error in lastError and on the JavaScript console. | 1710 // Report an error in lastError and on the JavaScript console. |
| 1843 nacl::string error_string("NaCl module load failed: user aborted"); | 1711 nacl::string error_string("NaCl module load failed: user aborted"); |
| 1844 set_last_error_string(error_string); | 1712 set_last_error_string(error_string); |
| 1845 browser_interface()->AddToConsole(this, error_string); | 1713 AddToConsole(error_string); |
| 1846 ShutdownProxy(); | 1714 ShutdownProxy(); |
| 1847 // Inform JavaScript that loading was aborted and is complete. | 1715 // Inform JavaScript that loading was aborted and is complete. |
| 1848 EnqueueProgressEvent(kProgressEventAbort); | 1716 EnqueueProgressEvent(kProgressEventAbort); |
| 1849 EnqueueProgressEvent(kProgressEventLoadEnd); | 1717 EnqueueProgressEvent(kProgressEventLoadEnd); |
| 1850 | 1718 |
| 1851 // UMA | 1719 // UMA |
| 1852 HistogramEnumerateLoadStatus(ERROR_LOAD_ABORTED); | 1720 HistogramEnumerateLoadStatus(ERROR_LOAD_ABORTED); |
| 1853 } | 1721 } |
| 1854 | 1722 |
| 1855 void Plugin::UpdateDownloadProgress( | 1723 void Plugin::UpdateDownloadProgress( |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 | 1905 |
| 2038 std::string scheme = canonicalized.AsString().substr(comps.scheme.begin, | 1906 std::string scheme = canonicalized.AsString().substr(comps.scheme.begin, |
| 2039 comps.scheme.len); | 1907 comps.scheme.len); |
| 2040 if (scheme == kChromeExtensionUriScheme) | 1908 if (scheme == kChromeExtensionUriScheme) |
| 2041 return SCHEME_CHROME_EXTENSION; | 1909 return SCHEME_CHROME_EXTENSION; |
| 2042 if (scheme == kDataUriScheme) | 1910 if (scheme == kDataUriScheme) |
| 2043 return SCHEME_DATA; | 1911 return SCHEME_DATA; |
| 2044 return SCHEME_OTHER; | 1912 return SCHEME_OTHER; |
| 2045 } | 1913 } |
| 2046 | 1914 |
| 1915 void Plugin::AddToConsole(const nacl::string& text) { |
| 1916 pp::Module* module = pp::Module::Get(); |
| 1917 const PPB_Var* var_interface = |
| 1918 static_cast<const PPB_Var*>( |
| 1919 module->GetBrowserInterface(PPB_VAR_INTERFACE)); |
| 1920 nacl::string prefix_string("NativeClient"); |
| 1921 PP_Var prefix = |
| 1922 var_interface->VarFromUtf8(prefix_string.c_str(), |
| 1923 static_cast<uint32_t>(prefix_string.size())); |
| 1924 PP_Var str = var_interface->VarFromUtf8(text.c_str(), |
| 1925 static_cast<uint32_t>(text.size())); |
| 1926 const PPB_Console_Dev* console_interface = |
| 1927 static_cast<const PPB_Console_Dev*>( |
| 1928 module->GetBrowserInterface(PPB_CONSOLE_DEV_INTERFACE)); |
| 1929 console_interface->LogWithSource(pp_instance(), PP_LOGLEVEL_LOG, prefix, str); |
| 1930 var_interface->Release(prefix); |
| 1931 var_interface->Release(str); |
| 1932 } |
| 1933 |
| 2047 } // namespace plugin | 1934 } // namespace plugin |
| OLD | NEW |