Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / nacl / renderer / plugin / srpc_client.cc
blob4c9b4c919cbe318aac59fbad53475110fefff82e
1 /*
2 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
7 #include "components/nacl/renderer/plugin/srpc_client.h"
9 #include <string.h>
11 #include "components/nacl/renderer/plugin/plugin.h"
12 #include "components/nacl/renderer/plugin/srpc_params.h"
13 #include "components/nacl/renderer/plugin/utility.h"
14 #include "native_client/src/shared/platform/nacl_log.h"
16 namespace plugin {
18 typedef bool (*RpcFunction)(void* obj, SrpcParams* params);
20 // MethodInfo records the method names and type signatures of an SRPC server.
21 class MethodInfo {
22 public:
23 // statically defined method - called through a pointer
24 MethodInfo(const RpcFunction function_ptr,
25 const char* name,
26 const char* ins,
27 const char* outs,
28 // index is set to UINT_MAX for methods implemented by the plugin,
29 // All methods implemented by nacl modules have indexes
30 // that are lower than UINT_MAX.
31 const uint32_t index = UINT_MAX) :
32 function_ptr_(function_ptr),
33 name_(STRDUP(name)),
34 ins_(STRDUP(ins)),
35 outs_(STRDUP(outs)),
36 index_(index) { }
38 ~MethodInfo() {
39 free(reinterpret_cast<void*>(name_));
40 free(reinterpret_cast<void*>(ins_));
41 free(reinterpret_cast<void*>(outs_));
44 RpcFunction function_ptr() const { return function_ptr_; }
45 char* name() const { return name_; }
46 char* ins() const { return ins_; }
47 char* outs() const { return outs_; }
48 uint32_t index() const { return index_; }
50 private:
51 NACL_DISALLOW_COPY_AND_ASSIGN(MethodInfo);
52 RpcFunction function_ptr_;
53 char* name_;
54 char* ins_;
55 char* outs_;
56 uint32_t index_;
59 SrpcClient::SrpcClient()
60 : srpc_channel_initialised_(false) {
61 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n",
62 static_cast<void*>(this)));
63 NaClSrpcChannelInitialize(&srpc_channel_);
66 SrpcClient* SrpcClient::New(nacl::DescWrapper* wrapper) {
67 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient());
68 if (!srpc_client->Init(wrapper)) {
69 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n"));
70 return NULL;
72 return srpc_client.release();
75 bool SrpcClient::Init(nacl::DescWrapper* wrapper) {
76 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, wrapper=%p)\n",
77 static_cast<void*>(this),
78 static_cast<void*>(wrapper)));
79 // Open the channel to pass RPC information back and forth
80 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) {
81 return false;
83 srpc_channel_initialised_ = true;
84 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n"));
85 // Record the method names in a convenient way for later dispatches.
86 GetMethods();
87 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n"));
88 return true;
91 SrpcClient::~SrpcClient() {
92 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n",
93 static_cast<void*>(this), srpc_channel_initialised_));
94 // And delete the connection.
95 if (srpc_channel_initialised_) {
96 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n"));
97 NaClSrpcDtor(&srpc_channel_);
99 for (Methods::iterator iter = methods_.begin();
100 iter != methods_.end();
101 ++iter) {
102 delete iter->second;
104 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n"));
107 void SrpcClient::GetMethods() {
108 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n",
109 static_cast<void*>(this)));
110 if (NULL == srpc_channel_.client) {
111 return;
113 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client);
114 // Intern the methods into a mapping from identifiers to MethodInfo.
115 for (uint32_t i = 0; i < method_count; ++i) {
116 int retval;
117 const char* method_name;
118 const char* input_types;
119 const char* output_types;
121 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client,
123 &method_name,
124 &input_types,
125 &output_types);
126 if (!retval) {
127 return;
129 if (!IsValidIdentifierString(method_name, NULL)) {
130 // If name is not an ECMAScript identifier, do not enter it into the
131 // methods_ table.
132 continue;
134 MethodInfo* method_info =
135 new MethodInfo(NULL, method_name, input_types, output_types, i);
136 if (NULL == method_info) {
137 return;
139 // Install in the map only if successfully read.
140 methods_[method_name] = method_info;
144 bool SrpcClient::HasMethod(const std::string& method_name) {
145 bool has_method = (NULL != methods_[method_name]);
146 PLUGIN_PRINTF((
147 "SrpcClient::HasMethod (this=%p, method_name='%s', return %d)\n",
148 static_cast<void*>(this), method_name.c_str(), has_method));
149 return has_method;
152 bool SrpcClient::InitParams(const std::string& method_name,
153 SrpcParams* params) {
154 MethodInfo* method_info = methods_[method_name];
155 if (method_info) {
156 return params->Init(method_info->ins(), method_info->outs());
158 return false;
161 bool SrpcClient::Invoke(const std::string& method_name, SrpcParams* params) {
162 // It would be better if we could set the exception on each detailed failure
163 // case. However, there are calls to Invoke from within the plugin itself,
164 // and these could leave residual exceptions pending. This seems to be
165 // happening specifically with hard_shutdowns.
166 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n",
167 static_cast<void*>(this),
168 method_name.c_str(),
169 static_cast<void*>(params)));
171 // Ensure Invoke was called with a method name that has a binding.
172 if (NULL == methods_[method_name]) {
173 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n"));
174 return false;
177 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n"));
178 // Call the method
179 last_error_ = NaClSrpcInvokeV(&srpc_channel_,
180 methods_[method_name]->index(),
181 params->ins(),
182 params->outs());
183 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", last_error_));
184 if (NACL_SRPC_RESULT_OK != last_error_) {
185 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n",
186 NaClSrpcErrorString(last_error_)));
187 return false;
190 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n"));
191 return true;
194 } // namespace plugin