Merge branch 'upstream'
[nativeclient.git] / tools / npapi_runtime / npnavigator.cc
blobe5b8e28161bed21acb05e4bf9461fea6697762fb
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // NaCl-NPAPI Interface
35 #include "native_client/tools/npapi_runtime/npnavigator.h"
37 #include <stdlib.h>
39 #include "native_client/tools/npapi_runtime/nacl_npapi.h"
41 namespace nacl {
43 NPNavigator::NPNavigator(NPP npp, int* argc, char* argv[])
44 : NPBridge(npp),
45 argc_(argc),
46 argv_(argv),
47 notify_(0),
48 notify_data_(NULL),
49 bitmap_shm_(kInvalidHtpHandle) {
50 if (3 <= *argc_) {
51 // The last two arguments are the handle number for the connection to the
52 // plungin, and for the size of NPVariant in the plugin.
53 #if NACL_WINDOWS
54 set_channel(reinterpret_cast<Handle>(_strtoui64(argv[*argc - 2],
55 NULL, 10)));
56 set_peer_npvariant_size(strtol(argv[*argc - 1], NULL, 10));
57 #else
58 set_channel(static_cast<Handle>(strtol(argv[*argc - 2], NULL, 10)));
59 set_peer_npvariant_size(strtol(argv[*argc - 1], NULL, 10));
60 #endif
61 *argc_ -= 2;
65 NPNavigator::~NPNavigator() {
66 std::set<const NPUTF8*, StringCompare>::iterator i;
67 for (i = string_set_.begin(); i != string_set_.end(); ++i) {
68 free(const_cast<char*>(*i));
70 Close(bitmap_shm_);
73 int NPNavigator::Dispatch(RpcHeader* request, int len) {
74 int result;
75 switch (request->type) {
76 case RPC_NEW:
77 result = New(request, len);
78 break;
79 case RPC_DESTROY:
80 result = Destroy(request, len);
81 break;
82 case RPC_NOTIFY_URL:
83 return URLNotify(request, len);
84 break;
85 default:
86 return NPBridge::Dispatch(request, len);
87 break;
89 return result;
92 int NPNavigator::New(RpcHeader* request, int len) {
93 RpcArg arg(this, request, len);
94 arg.Step(sizeof(RpcHeader));
95 NPSize* window_size = arg.GetSize();
96 if (0 < arg.GetHandleCount()) {
97 bitmap_shm_ = arg.GetHandle();
98 arg.CloseUnusedHandles();
101 set_peer_pid(request->pid);
102 IOVec vecv[2];
103 IOVec* vecp = vecv;
104 vecp->base = request;
105 vecp->length = sizeof(RpcHeader);
106 ++vecp;
107 int argc = 0;
108 char* argn[kMaxArg / 2];
109 char* argv[kMaxArg / 2];
110 for (int i = 1; i < *argc_; ++argc) {
111 argn[argc] = argv_[i++];
112 argv[argc] = argv_[i++];
114 request->error_code = NPP_New(
115 const_cast<char *>("application/nacl-npapi-plugin"),
116 npp(),
117 0, // TBD mode
118 argc, argn, argv,
119 NULL);
121 if (request->error_code == NPERR_NO_ERROR) {
122 NPObject* object = NPP_GetScriptableInstance(npp());
123 if (object) {
124 NPCapability capability;
125 CreateStub(object, &capability);
126 vecp->base = &capability;
127 vecp->length = sizeof capability;
128 ++vecp;
131 if (bitmap_shm_ != kInvalidHtpHandle &&
132 0 < window_size->width && window_size->height) {
133 window_.window = reinterpret_cast<void*>(bitmap_shm_);
134 window_.x = 0;
135 window_.y = 0;
136 window_.width = window_size->width;
137 window_.height = window_size->height;
138 window_.clipRect.top = 0;
139 window_.clipRect.left = 0;
140 window_.clipRect.right = window_.width;
141 window_.clipRect.bottom = window_.height;
142 window_.type = NPWindowTypeDrawable;
143 NPP_SetWindow(npp(), &window_);
147 return Respond(request, vecv, vecp - vecv);
150 int NPNavigator::Destroy(RpcHeader* request, int len) {
151 IOVec vecv[1];
152 IOVec* vecp = vecv;
153 vecp->base = request;
154 vecp->length = sizeof(RpcHeader);
155 ++vecp;
156 request->error_code = NPP_Destroy(npp(), NULL);
157 return Respond(request, vecv, vecp - vecv);
160 int NPNavigator::GetPluginScriptableObject(RpcHeader* request, int len) {
161 IOVec vecv[1];
162 IOVec* vecp = vecv;
163 vecp->base = request;
164 vecp->length = sizeof(RpcHeader);
165 ++vecp;
166 return Respond(request, vecv, vecp - vecv);
169 void NPNavigator::SetStatus(const char* message) {
170 RpcHeader request;
171 request.type = RPC_SET_STATUS;
172 IOVec vecv[2];
173 IOVec* vecp = vecv;
174 vecp->base = &request;
175 vecp->length = sizeof request;
176 ++vecp;
177 vecp->base = const_cast<char*>(message);
178 vecp->length = strlen(message) + 1;
179 ++vecp;
180 Request(&request, vecv, vecp - vecv, NULL);
183 NPError NPNavigator::GetValue(nacl::RpcType type, void* value) {
184 RpcHeader request;
185 request.type = type;
186 IOVec vecv[1];
187 IOVec* vecp = vecv;
188 vecp->base = &request;
189 vecp->length = sizeof request;
190 ++vecp;
191 int length;
192 RpcHeader* reply = Request(&request, vecv, vecp - vecv, &length);
193 if (reply == NULL) {
194 return NPERR_GENERIC_ERROR;
196 RpcArg result(this, reply, length);
197 result.Step(sizeof(RpcHeader));
198 if (reply->error_code == NPERR_NO_ERROR) {
199 *static_cast<NPObject**>(value) = result.GetObject();
201 return reply->error_code;
204 void NPNavigator::InvalidateRect(NPRect* invalid_rect) {
205 RpcHeader request;
206 request.type = RPC_INVALIDATE_RECT;
207 IOVec vecv[2];
208 IOVec* vecp = vecv;
209 vecp->base = &request;
210 vecp->length = sizeof request;
211 ++vecp;
212 vecp->base = invalid_rect;
213 vecp->length = sizeof(*invalid_rect);
214 ++vecp;
215 int length;
216 Request(&request, vecv, vecp - vecv, &length);
219 void NPNavigator::ForceRedraw() {
220 RpcHeader request;
221 request.type = RPC_FORCE_REDRAW;
222 IOVec vecv[1];
223 IOVec* vecp = vecv;
224 vecp->base = &request;
225 vecp->length = sizeof request;
226 ++vecp;
227 int length;
228 Request(&request, vecv, vecp - vecv, &length);
231 NPObject* NPNavigator::CreateArray() {
232 RpcHeader request;
233 request.type = RPC_CREATE_ARRAY;
234 IOVec vecv[1];
235 IOVec* vecp = vecv;
236 vecp->base = &request;
237 vecp->length = sizeof request;
238 ++vecp;
239 int length;
240 RpcHeader* reply = Request(&request, vecv, vecp - vecv, &length);
241 if (reply == NULL) {
242 return NULL;
244 RpcArg result(this, reply, length);
245 result.Step(sizeof request);
246 return result.GetObject();
249 NPError NPNavigator::OpenURL(const char* url, void* notify_data,
250 void (*notify)(const char* url, void* notify_data,
251 HtpHandle handle)) {
252 if (notify_ != NULL || url == NULL || notify == NULL) {
253 return NPERR_GENERIC_ERROR;
256 RpcHeader request;
257 request.type = RPC_OPEN_URL;
258 IOVec vecv[2];
259 IOVec* vecp = vecv;
260 vecp->base = &request;
261 vecp->length = sizeof request;
262 ++vecp;
263 vecp->base = const_cast<char*>(url);
264 vecp->length = strlen(url) + 1;
265 ++vecp;
266 int length;
267 RpcHeader* reply = Request(&request, vecv, vecp - vecv, &length);
268 if (reply == NULL) {
269 return NPERR_GENERIC_ERROR;
271 NPError nperr = static_cast<NPError>(reply->error_code);
272 if (nperr == NPERR_NO_ERROR) {
273 notify_ = notify;
274 notify_data_ = notify_data;
275 #if NACL_WINDOWS
276 url_ = _strdup(url);
277 #else
278 url_ = strdup(url);
279 #endif // NACL_WINDOWS
281 return nperr;
284 int NPNavigator::URLNotify(RpcHeader* request, int len) {
285 IOVec vecv[1];
286 IOVec* vecp = vecv;
287 vecp->base = request;
288 vecp->length = sizeof(RpcHeader);
289 ++vecp;
291 RpcArg arg(this, request, len);
292 HtpHandle received_handle = kInvalidHtpHandle;
293 if (0 < arg.GetHandleCount()) {
294 received_handle = arg.GetHandle();
295 arg.CloseUnusedHandles();
297 arg.Step(sizeof(RpcHeader));
298 uint32_t reason = request->error_code;
299 if (reason != NPRES_DONE) {
300 Close(received_handle);
301 HtpHandle received_handle = kInvalidHtpHandle;
303 if (notify_) {
304 notify_(url_, notify_data_, received_handle);
305 notify_ = 0;
306 notify_data_ = NULL;
307 free(url_);
308 url_ = 0;
310 clear_handle_count();
311 return Respond(request, vecv, vecp - vecv);
314 const NPUTF8* NPNavigator::GetStringIdentifier(const NPUTF8* name) {
315 std::set<const NPUTF8*, StringCompare>::iterator i;
316 i = string_set_.find(name);
317 if (i != string_set_.end()) {
318 return *i;
320 #if NACL_WINDOWS
321 name = _strdup(name);
322 #else
323 name = strdup(name);
324 #endif // NACL_WINDOWS
325 if (!name) {
326 return NULL;
328 std::pair<std::set<const NPUTF8*, StringCompare>::iterator, bool> result;
329 result = string_set_.insert(name);
330 return *result.first;
333 } // namespace nacl