OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2011 The Native Client 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 */ | |
6 | |
7 | |
8 #include <string.h> | |
9 | |
10 #include <map> | |
11 | |
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" | |
16 #include "native_client/src/trusted/plugin/scriptable_handle.h" | |
17 #include "native_client/src/trusted/plugin/srpc_client.h" | |
18 #include "native_client/src/trusted/plugin/utility.h" | |
19 | |
20 namespace plugin { | |
21 | |
22 SrpcClient::SrpcClient() | |
23 : srpc_channel_initialised_(false), | |
24 browser_interface_(NULL) { | |
25 PLUGIN_PRINTF(("SrpcClient::SrpcClient (this=%p)\n", | |
26 static_cast<void*>(this))); | |
27 NaClSrpcChannelInitialize(&srpc_channel_); | |
28 } | |
29 | |
30 SrpcClient* SrpcClient::New(Plugin* plugin, nacl::DescWrapper* wrapper) { | |
31 nacl::scoped_ptr<SrpcClient> srpc_client(new SrpcClient()); | |
32 if (!srpc_client->Init(plugin->browser_interface(), wrapper)) { | |
33 PLUGIN_PRINTF(("SrpcClient::New (SrpcClient::Init failed)\n")); | |
34 return NULL; | |
35 } | |
36 return srpc_client.release(); | |
37 } | |
38 | |
39 bool SrpcClient::Init(BrowserInterface* browser_interface, | |
40 nacl::DescWrapper* wrapper) { | |
41 PLUGIN_PRINTF(("SrpcClient::Init (this=%p, browser_interface=%p, wrapper=%p)" | |
42 "\n", static_cast<void*>(this), | |
43 static_cast<void*>(browser_interface), | |
44 static_cast<void*>(wrapper))); | |
45 // Open the channel to pass RPC information back and forth | |
46 if (!NaClSrpcClientCtor(&srpc_channel_, wrapper->desc())) { | |
47 return false; | |
48 } | |
49 srpc_channel_initialised_ = true; | |
50 browser_interface_ = browser_interface; | |
51 PLUGIN_PRINTF(("SrpcClient::Init (Ctor worked)\n")); | |
52 // Record the method names in a convenient way for later dispatches. | |
53 GetMethods(); | |
54 PLUGIN_PRINTF(("SrpcClient::Init (GetMethods worked)\n")); | |
55 return true; | |
56 } | |
57 | |
58 SrpcClient::~SrpcClient() { | |
59 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (this=%p, has_srpc_channel=%d)\n", | |
60 static_cast<void*>(this), srpc_channel_initialised_)); | |
61 // And delete the connection. | |
62 if (srpc_channel_initialised_) { | |
63 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (destroying srpc_channel)\n")); | |
64 NaClSrpcDtor(&srpc_channel_); | |
65 } | |
66 for (Methods::iterator iter = methods_.begin(); | |
67 iter != methods_.end(); | |
68 ++iter) { | |
69 delete iter->second; | |
70 } | |
71 PLUGIN_PRINTF(("SrpcClient::~SrpcClient (return)\n")); | |
72 } | |
73 | |
74 bool SrpcClient::StartJSObjectProxy(Plugin* plugin, | |
75 ErrorInfo *error_info) { | |
76 // Start up PPAPI interaction if the plugin determines that the | |
77 // requisite methods are exported. | |
78 return plugin->StartProxiedExecution(&srpc_channel_, error_info); | |
79 } | |
80 | |
81 void SrpcClient::GetMethods() { | |
82 PLUGIN_PRINTF(("SrpcClient::GetMethods (this=%p)\n", | |
83 static_cast<void*>(this))); | |
84 if (NULL == srpc_channel_.client) { | |
85 return; | |
86 } | |
87 uint32_t method_count = NaClSrpcServiceMethodCount(srpc_channel_.client); | |
88 // Intern the methods into a mapping from identifiers to MethodInfo. | |
89 for (uint32_t i = 0; i < method_count; ++i) { | |
90 int retval; | |
91 const char* name; | |
92 const char* input_types; | |
93 const char* output_types; | |
94 | |
95 retval = NaClSrpcServiceMethodNameAndTypes(srpc_channel_.client, | |
96 i, | |
97 &name, | |
98 &input_types, | |
99 &output_types); | |
100 if (!IsValidIdentifierString(name, NULL)) { | |
101 // If name is not an ECMAScript identifier, do not enter it into the | |
102 // methods_ table. | |
103 continue; | |
104 } | |
105 uintptr_t ident = browser_interface_->StringToIdentifier(name); | |
106 MethodInfo* method_info = | |
107 new MethodInfo(NULL, name, input_types, output_types, i); | |
108 if (NULL == method_info) { | |
109 return; | |
110 } | |
111 // Install in the map only if successfully read. | |
112 methods_[ident] = method_info; | |
113 } | |
114 } | |
115 | |
116 bool SrpcClient::HasMethod(uintptr_t method_id) { | |
117 bool has_method = (NULL != methods_[method_id]); | |
118 PLUGIN_PRINTF(("SrpcClient::HasMethod (this=%p, return %d)\n", | |
119 static_cast<void*>(this), has_method)); | |
120 return has_method; | |
121 } | |
122 | |
123 bool SrpcClient::InitParams(uintptr_t method_id, SrpcParams* params) { | |
124 MethodInfo* method_info = methods_[method_id]; | |
125 if (method_info) { | |
126 return params->Init(method_info->ins(), method_info->outs()); | |
127 } | |
128 return false; | |
129 } | |
130 | |
131 bool SrpcClient::Invoke(uintptr_t method_id, | |
132 SrpcParams* params) { | |
133 // It would be better if we could set the exception on each detailed failure | |
134 // case. However, there are calls to Invoke from within the plugin itself, | |
135 // and these could leave residual exceptions pending. This seems to be | |
136 // happening specifically with hard_shutdowns. | |
137 PLUGIN_PRINTF(("SrpcClient::Invoke (this=%p, method_name='%s', params=%p)\n", | |
138 static_cast<void*>(this), | |
139 browser_interface_->IdentifierToString(method_id).c_str(), | |
140 static_cast<void*>(params))); | |
141 | |
142 // Ensure Invoke was called with an identifier that had a binding. | |
143 if (NULL == methods_[method_id]) { | |
144 PLUGIN_PRINTF(("SrpcClient::Invoke (ident not in methods_)\n")); | |
145 return false; | |
146 } | |
147 | |
148 PLUGIN_PRINTF(("SrpcClient::Invoke (sending the rpc)\n")); | |
149 // Call the method | |
150 NaClSrpcError err = NaClSrpcInvokeV(&srpc_channel_, | |
151 methods_[method_id]->index(), | |
152 params->ins(), | |
153 params->outs()); | |
154 PLUGIN_PRINTF(("SrpcClient::Invoke (response=%d)\n", err)); | |
155 if (NACL_SRPC_RESULT_OK != err) { | |
156 PLUGIN_PRINTF(("SrpcClient::Invoke (err='%s', return 0)\n", | |
157 NaClSrpcErrorString(err))); | |
158 return false; | |
159 } | |
160 | |
161 PLUGIN_PRINTF(("SrpcClient::Invoke (return 1)\n")); | |
162 return true; | |
163 } | |
164 | |
165 } // namespace plugin | |
OLD | NEW |