| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 | 7 |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 | 11 |
| 12 #include "native_client/src/shared/platform/nacl_log.h" | 12 #include "native_client/src/shared/platform/nacl_log.h" |
| 13 #include "native_client/src/trusted/plugin/browser_interface.h" | |
| 14 #include "native_client/src/trusted/plugin/desc_based_handle.h" | |
| 15 #include "native_client/src/trusted/plugin/plugin.h" | 13 #include "native_client/src/trusted/plugin/plugin.h" |
| 16 #include "native_client/src/trusted/plugin/scriptable_handle.h" | |
| 17 #include "native_client/src/trusted/plugin/srpc_client.h" | 14 #include "native_client/src/trusted/plugin/srpc_client.h" |
| 15 #include "native_client/src/trusted/plugin/srpc_params.h" |
| 18 #include "native_client/src/trusted/plugin/utility.h" | 16 #include "native_client/src/trusted/plugin/utility.h" |
| 19 | 17 |
| 20 namespace plugin { | 18 namespace plugin { |
| 21 | 19 |
| 20 typedef bool (*RpcFunction)(void* obj, SrpcParams* params); |
| 21 |
| 22 // MethodInfo records the method names and type signatures of an SRPC server. |
| 23 class MethodInfo { |
| 24 public: |
| 25 // statically defined method - called through a pointer |
| 26 MethodInfo(const RpcFunction function_ptr, |
| 27 const char* name, |
| 28 const char* ins, |
| 29 const char* outs, |
| 30 // index is set to UINT_MAX for methods implemented by the plugin, |
| 31 // All methods implemented by nacl modules have indexes |
| 32 // that are lower than UINT_MAX. |
| 33 const uint32_t index = UINT_MAX) : |
| 34 function_ptr_(function_ptr), |
| 35 name_(STRDUP(name)), |
| 36 ins_(STRDUP(ins)), |
| 37 outs_(STRDUP(outs)), |
| 38 index_(index) { } |
| 39 |
| 40 ~MethodInfo() { |
| 41 free(reinterpret_cast<void*>(name_)); |
| 42 free(reinterpret_cast<void*>(ins_)); |
| 43 free(reinterpret_cast<void*>(outs_)); |
| 44 } |
| 45 |
| 46 RpcFunction function_ptr() const { return function_ptr_; } |
| 47 char* name() const { return name_; } |
| 48 char* ins() const { return ins_; } |
| 49 char* outs() const { return outs_; } |
| 50 uint32_t index() const { return index_; } |
| 51 |
| 52 private: |
| 53 NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo); |
| 54 RpcFunction function_ptr_; |
| 55 char* name_; |
| 56 char* ins_; |
| 57 char* outs_; |
| 58 uint32_t index_; |
| 59 }; |
| 60 |
| 22 SrpcClient::SrpcClient() | 61 SrpcClient::SrpcClient() |
| 23 : srpc_channel_initialised_(false), | 62 : srpc_channel_initialised_(false) { |
| 24 browser_interface_(NULL) { | |
| 25 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", | 63 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", |
| 26 static_cast<void*>(this))); | 64 static_cast<void*>(this))); |
| 27 NaClSrpcChannelInitialize(&srpc_channel_); | 65 NaClSrpcChannelInitialize(&srpc_channel_); |
| 28 } | 66 } |
| 29 | 67 |
| 30 SrpcClient* SrpcClient::New(Plugin* plugin, nacl::DescWrapper* wrapper) { | 68 SrpcClient* SrpcClient::New(nacl::DescWrapper* wrapper) { |
| 31 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); | 69 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); |
| 32 if (!srpc_client->Init(plugin->browser_interface(), wrapper)) { | 70 if (!srpc_client->Init(wrapper)) { |
| 33 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); | 71 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); |
| 34 return NULL; | 72 return NULL; |
| 35 } | 73 } |
| 36 return srpc_client.release(); | 74 return srpc_client.release(); |
| 37 } | 75 } |
| 38 | 76 |
| 39 bool SrpcClient::Init(BrowserInterface* browser_interface, | 77 bool SrpcClient::Init(nacl::DescWrapper* wrapper) { |
| 40 nacl::DescWrapper* wrapper) { | 78 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n", |
| 41 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, browser_interface=%p, wrapper=%p)" | 79 static_cast<void*>(this), |
| 42 "\n", static_cast<void*>(this), | |
| 43 static_cast<void*>(browser_interface), | |
| 44 static_cast<void*>(wrapper))); | 80 static_cast<void*>(wrapper))); |
| 45 // Open the channel to pass RPC information back and forth | 81 // Open the channel to pass RPC information back and forth |
| 46 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { | 82 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { |
| 47 return false; | 83 return false; |
| 48 } | 84 } |
| 49 srpc_channel_initialised_ = true; | 85 srpc_channel_initialised_ = true; |
| 50 browser_interface_ = browser_interface; | |
| 51 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); | 86 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); |
| 52 // Record the method names in a convenient way for later dispatches. | 87 // Record the method names in a convenient way for later dispatches. |
| 53 GetMethods(); | 88 GetMethods(); |
| 54 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); | 89 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); |
| 55 return true; | 90 return true; |
| 56 } | 91 } |
| 57 | 92 |
| 58 SrpcClient::~SrpcClient() { | 93 SrpcClient::~SrpcClient() { |
| 59 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", | 94 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", |
| 60 static_cast<void*>(this), srpc_channel_initialised_)); | 95 static_cast<void*>(this), srpc_channel_initialised_)); |
| 61 // And delete the connection. | 96 // And delete the connection. |
| 62 if (srpc_channel_initialised_) { | 97 if (srpc_channel_initialised_) { |
| 63 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); | 98 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); |
| 64 NaClSrpcDtor(&srpc_channel_); | 99 NaClSrpcDtor(&srpc_channel_); |
| 65 } | 100 } |
| 66 for (Methods::iterator iter = methods_.begin(); | 101 for (Methods::iterator iter = methods_.begin(); |
| 67 iter != methods_.end(); | 102 iter != methods_.end(); |
| 68 ++iter) { | 103 ++iter) { |
| 69 delete iter->second; | 104 delete iter->second; |
| 70 } | 105 } |
| 71 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); | 106 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); |
| 72 } | 107 } |
| 73 | 108 |
| 74 bool SrpcClient::StartJSObjectProxy(Plugin* plugin, | 109 bool SrpcClient::StartJSObjectProxy(Plugin* plugin, ErrorInfo *error_info) { |
| 75 ErrorInfo *error_info) { | |
| 76 // Start up PPAPI interaction if the plugin determines that the | 110 // Start up PPAPI interaction if the plugin determines that the |
| 77 // requisite methods are exported. | 111 // requisite methods are exported. |
| 78 return plugin->StartProxiedExecution(&srpc_channel_, error_info); | 112 return plugin->StartProxiedExecution(&srpc_channel_, error_info); |
| 79 } | 113 } |
| 80 | 114 |
| 81 void SrpcClient::GetMethods() { | 115 void SrpcClient::GetMethods() { |
| 82 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", | 116 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", |
| 83 static_cast<void*>(this))); | 117 static_cast<void*>(this))); |
| 84 if (NULL == srpc_channel_.client) { | 118 if (NULL == srpc_channel_.client) { |
| 85 return; | 119 return; |
| 86 } | 120 } |
| 87 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); | 121 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); |
| 88 // Intern the methods into a mapping from identifiers to MethodInfo. | 122 // Intern the methods into a mapping from identifiers to MethodInfo. |
| 89 for (uint32_t i = 0; i < method_count; ++i) { | 123 for (uint32_t i = 0; i < method_count; ++i) { |
| 90 int retval; | 124 int retval; |
| 91 const char* name; | 125 const char* method_name; |
| 92 const char* input_types; | 126 const char* input_types; |
| 93 const char* output_types; | 127 const char* output_types; |
| 94 | 128 |
| 95 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, | 129 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, |
| 96 i, | 130 i, |
| 97 &name, | 131 &method_name, |
| 98 &input_types, | 132 &input_types, |
| 99 &output_types); | 133 &output_types); |
| 100 if (!retval) { | 134 if (!retval) { |
| 101 return; | 135 return; |
| 102 } | 136 } |
| 103 if (!IsValidIdentifierString(name, NULL)) { | 137 if (!IsValidIdentifierString(method_name, NULL)) { |
| 104 // If name is not an ECMAScript identifier, do not enter it into the | 138 // If name is not an ECMAScript identifier, do not enter it into the |
| 105 // methods_ table. | 139 // methods_ table. |
| 106 continue; | 140 continue; |
| 107 } | 141 } |
| 108 uintptr_t ident = browser_interface_->StringToIdentifier(name); | |
| 109 MethodInfo* method_info = | 142 MethodInfo* method_info = |
| 110 new MethodInfo(NULL, name, input_types, output_types, i); | 143 new MethodInfo(NULL, method_name, input_types, output_types, i); |
| 111 if (NULL == method_info) { | 144 if (NULL == method_info) { |
| 112 return; | 145 return; |
| 113 } | 146 } |
| 114 // Install in the map only if successfully read. | 147 // Install in the map only if successfully read. |
| 115 methods_[ident] = method_info; | 148 methods_[method_name] = method_info; |
| 116 } | 149 } |
| 117 } | 150 } |
| 118 | 151 |
| 119 bool SrpcClient::HasMethod(uintptr_t method_id) { | 152 bool SrpcClient::HasMethod(const nacl::string& method_name) { |
| 120 bool has_method = (NULL != methods_[method_id]); | 153 bool has_method = (NULL != methods_[method_name]); |
| 121 PLUGIN_PRINTF(("SrpcClient::HasMethod (this=%p, return %d)\n", | 154 PLUGIN_PRINTF(( |
| 122 static_cast<void*>(this), has_method)); | 155 "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n", |
| 156 static_cast<void*>(this), method_name.c_str(), has_method)); |
| 123 return has_method; | 157 return has_method; |
| 124 } | 158 } |
| 125 | 159 |
| 126 bool SrpcClient::InitParams(uintptr_t method_id, SrpcParams* params) { | 160 bool SrpcClient::InitParams(const nacl::string& method_name, |
| 127 MethodInfo* method_info = methods_[method_id]; | 161 SrpcParams* params) { |
| 162 MethodInfo* method_info = methods_[method_name]; |
| 128 if (method_info) { | 163 if (method_info) { |
| 129 return params->Init(method_info->ins(), method_info->outs()); | 164 return params->Init(method_info->ins(), method_info->outs()); |
| 130 } | 165 } |
| 131 return false; | 166 return false; |
| 132 } | 167 } |
| 133 | 168 |
| 134 bool SrpcClient::Invoke(uintptr_t method_id, | 169 bool SrpcClient::Invoke(const nacl::string& method_name, SrpcParams* params) { |
| 135 SrpcParams* params) { | |
| 136 // It would be better if we could set the exception on each detailed failure | 170 // It would be better if we could set the exception on each detailed failure |
| 137 // case. However, there are calls to Invoke from within the plugin itself, | 171 // case. However, there are calls to Invoke from within the plugin itself, |
| 138 // and these could leave residual exceptions pending. This seems to be | 172 // and these could leave residual exceptions pending. This seems to be |
| 139 // happening specifically with hard_shutdowns. | 173 // happening specifically with hard_shutdowns. |
| 140 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", | 174 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", |
| 141 static_cast<void*>(this), | 175 static_cast<void*>(this), |
| 142 browser_interface_->IdentifierToString(method_id).c_str(), | 176 method_name.c_str(), |
| 143 static_cast<void*>(params))); | 177 static_cast<void*>(params))); |
| 144 | 178 |
| 145 // Ensure Invoke was called with an identifier that had a binding. | 179 // Ensure Invoke was called with a method name that has a binding. |
| 146 if (NULL == methods_[method_id]) { | 180 if (NULL == methods_[method_name]) { |
| 147 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); | 181 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); |
| 148 return false; | 182 return false; |
| 149 } | 183 } |
| 150 | 184 |
| 151 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); | 185 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); |
| 152 // Call the method | 186 // Call the method |
| 153 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, | 187 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, |
| 154 methods_[method_id]->index(), | 188 methods_[method_name]->index(), |
| 155 params->ins(), | 189 params->ins(), |
| 156 params->outs()); | 190 params->outs()); |
| 157 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", err)); | 191 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", err)); |
| 158 if (NACL_SRPC_RESULT_OK != err) { | 192 if (NACL_SRPC_RESULT_OK != err) { |
| 159 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", | 193 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", |
| 160 NaClSrpcErrorString(err))); | 194 NaClSrpcErrorString(err))); |
| 161 return false; | 195 return false; |
| 162 } | 196 } |
| 163 | 197 |
| 164 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); | 198 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); |
| 165 return true; | 199 return true; |
| 166 } | 200 } |
| 167 | 201 |
| 168 void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) { | 202 void SrpcClient::AttachService(NaClSrpcService* service, void* instance_data) { |
| 169 srpc_channel_.server = service; | 203 srpc_channel_.server = service; |
| 170 srpc_channel_.server_instance_data = instance_data; | 204 srpc_channel_.server_instance_data = instance_data; |
| 171 } | 205 } |
| 172 | 206 |
| 173 } // namespace plugin | 207 } // namespace plugin |
| OLD | NEW |