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