imcplugin demo: Extend to support stat() call
[nativeclient.git] / npapi_plugin / npp_launcher.cc
blob1da96fe7e3ab1e3d133cee03160b67f8e3c27d12
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 /**
34 * @file
35 * Defines the basic API for the nacl browser plugin
37 * http://www.mozilla.org/projects/plugins/
38 * http://www.ssuet.edu.pk/taimoor/books/0-7897-1063-3/ch11.htm
40 * NOTE: This is mostly a wrapper for module specific functions defined
41 * elsewhere
42 * TODO: give some more details
45 #include "native_client/include/portability.h"
47 #include <stdio.h>
49 #include <new>
51 #include "native_client/include/elf.h"
52 #include "native_client/include/nacl_elf.h"
53 #include "native_client/npapi_plugin/npapi_bridge/npmodule.h"
54 #include "native_client/npapi_plugin/srpc/srpc.h"
55 #include "native_client/service_runtime/expiration.h"
56 #include "native_client/service_runtime/nrd_xfer_lib/nrd_all_modules.h"
57 #include "native_client/tools/npapi_runtime/nacl_npapi.h"
59 #define EXPAND(x) x
60 #define ENQUOTE(x) #x
61 #define EMBED(x) EXPAND(ENQUOTE(x))
63 const char kPluginName[] = "Native Client Plugin";
64 const char kPluginDescription[] = "Native Client Plugin was built on "
65 __DATE__ " at " __TIME__
66 #if defined(EXPIRATION_CHECK)
67 " and expires on "
68 EMBED(EXPIRATION_MONTH) "/"
69 EMBED(EXPIRATION_DAY) "/"
70 EMBED(EXPIRATION_YEAR)
71 " (mm/dd/yyyy)"
72 #endif
73 "";
75 char* NPP_GetMIMEDescription() {
76 return const_cast<char*>("application/x-nacl-srpc:nexe,nacl:NativeClient"
77 " Simple RPC module;"
78 "application/x-nacl-npapi:nexe,nacl:NativeClient"
79 " NPAPI bridge module");
80 // ";application/x-nacl-webidl:nexe,nacl:NativeClient Web IDL module"
83 // Invoked from NP_Initialize()
84 NPError NPP_Initialize() {
85 printf("NPP_Initialize\n");
86 if (NaClHasExpired()) {
87 return NPERR_INCOMPATIBLE_VERSION_ERROR;
89 NaClNrdAllModulesInit();
90 return NPERR_NO_ERROR;
93 // Invoked from NP_Shutdown()
94 void NPP_Shutdown() {
95 NaClNrdAllModulesFini();
96 printf("NPP_Shutdown\n");
99 NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16_t mode,
100 int16_t argc, char* argn[], char* argv[],
101 NPSavedData* saved) {
102 printf("NPP_New '%s'\n", plugin_type);
103 if (NaClHasExpired()) {
104 return NPERR_INCOMPATIBLE_VERSION_ERROR;
106 if (instance == NULL) {
107 return NPERR_INVALID_INSTANCE_ERROR;
109 if (strcmp(plugin_type, "application/x-nacl-npapi") == 0) {
110 instance->pdata = static_cast<nacl::NPInstance*>(
111 new(std::nothrow) nacl::NPModule(instance, argc, argn, argv));
112 } else if (strcmp(plugin_type, "application/x-nacl-srpc") == 0) {
113 instance->pdata = static_cast<nacl::NPInstance*>(
114 new(std::nothrow) nacl::SRPC_Plugin(instance, argc, argn, argv));
116 if (instance->pdata == NULL) {
117 return NPERR_OUT_OF_MEMORY_ERROR;
119 return NPERR_NO_ERROR;
122 NPError NPP_Destroy(NPP instance, NPSavedData** save) {
123 printf("NPP_Destroy\n");
124 if (instance == NULL) {
125 return NPERR_INVALID_INSTANCE_ERROR;
127 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
128 if (module != NULL) {
129 instance->pdata = NULL;
130 NPError nperr = module->Destroy(save); // module must delete itself.
131 return nperr;
133 return NPERR_NO_ERROR;
136 NPError NPP_SetWindow(NPP instance, NPWindow* window) {
137 printf("NPP_SetWindow\n");
138 if (instance == NULL) {
139 return NPERR_INVALID_INSTANCE_ERROR;
141 if (window == NULL) {
142 return NPERR_GENERIC_ERROR;
144 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
145 if (module != NULL) {
146 return module->SetWindow(window);
148 return NPERR_GENERIC_ERROR;
151 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
152 if (variable == NPPVpluginNameString) {
153 *static_cast<const char**>(value) = kPluginName;
154 return NPERR_NO_ERROR;
156 if (variable == NPPVpluginDescriptionString) {
157 *static_cast<const char**>(value) = kPluginDescription;
158 return NPERR_NO_ERROR;
160 if (instance == NULL) {
161 return NPERR_INVALID_INSTANCE_ERROR;
163 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
164 if (module != NULL) {
165 return module->GetValue(variable, value);
167 return NPERR_GENERIC_ERROR;
170 int16_t NPP_HandleEvent(NPP instance, void* event) {
171 if (instance == NULL) {
172 return NPERR_INVALID_INSTANCE_ERROR;
174 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
175 if (module != NULL) {
176 return module->HandleEvent(event);
178 return 0;
181 NPObject* NPP_GetScriptableInstance(NPP instance) {
182 printf("NPP_GetScriptableInstance\n");
183 if (instance == NULL) {
184 return NULL;
186 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
187 if (module != NULL) {
188 return module->GetScriptableInstance();
190 return NULL;
193 NPError NPP_NewStream(NPP instance, NPMIMEType type,
194 NPStream* stream, NPBool seekable,
195 uint16_t* stype) {
196 printf("NPP_NewStream\n");
197 if (instance == NULL) {
198 return NPERR_INVALID_INSTANCE_ERROR;
200 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
201 if (module != NULL) {
202 return module->NewStream(type, stream, seekable, stype);
204 return NPERR_GENERIC_ERROR;
207 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* filename) {
208 printf("NPP_StreamAsFile: %s\n", filename);
209 if (instance == NULL) {
210 return;
212 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
213 if (module != NULL) {
214 #if NACL_OSX
215 if (filename && filename[0] != '/') {
216 // The filename we were given is a "classic" pathname, which needs
217 // to be converted to a posix pathname.
218 size_t len = strlen(filename);
220 // Pascal strings are limited to no more than 255 bytes.
221 if (len < 256) {
222 FSSpec spec;
223 unsigned char pascal_pathname[256];
225 // Make a pascal string out of a C string.
226 memmove(pascal_pathname + 1, filename, len);
227 pascal_pathname[0] = static_cast<unsigned char>(len);
228 if (FSMakeFSSpec(0, 0, pascal_pathname, &spec) == noErr) {
229 FSRef ref;
230 if (FSpMakeFSRef(&spec, &ref) == noErr) {
231 static unsigned char posix_path[1024];
233 if (FSRefMakePath(&ref, posix_path, sizeof(posix_path)) == noErr) {
234 filename = reinterpret_cast<char*>(posix_path);
235 } else {
236 filename = NULL;
238 module->StreamAsFile(stream, filename);
239 FSDeleteObject(&ref);
240 return;
244 filename = NULL;
246 #endif // NACL_OSX
247 module->StreamAsFile(stream, filename);
251 // Note Safari running on OS X removes the loaded file at this point.
252 // To keep the file, it must be opened in NPP_StreamAsFile().
253 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
254 printf("NPP_DestroyStream %d\n", reason);
255 if (instance == NULL) {
256 return NPERR_INVALID_INSTANCE_ERROR;
258 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
259 if (module != NULL) {
260 return module->DestroyStream(stream, reason);
262 return NPERR_GENERIC_ERROR;
265 void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
266 void* notify_data) {
267 printf("NPP_URLNotify(%s)\n", url);
268 if (instance == NULL) {
269 return;
271 nacl::NPInstance* module = static_cast<nacl::NPInstance*>(instance->pdata);
272 if (module != NULL) {
273 module->URLNotify(url, reason, notify_data);
278 namespace nacl {
280 NPError CheckExecutableVersion(NPP instance, const char *filename) {
281 FILE *f;
282 NPError ret = NPERR_GENERIC_ERROR;
283 static uint8_t const kInvalidAbiVersion = UINT8_MAX;
284 uint8_t nacl_abi_version = kInvalidAbiVersion;
285 // initialize it, since the compiler does not know that the variable
286 // will not be used unless it is set by the fread.
288 f = fopen(filename, "rb");
289 if (NULL != f) {
290 if (0 == fseek(f, EI_ABIVERSION, SEEK_SET)) {
291 if (1 == fread(&nacl_abi_version, 1, 1, f)) {
292 if (EF_NACL_ABIVERSION == nacl_abi_version) {
293 ret = NPERR_NO_ERROR;
294 } else {
295 ret = NPERR_INCOMPATIBLE_VERSION_ERROR;
299 fclose(f);
301 if (NPERR_NO_ERROR != ret) {
302 const char *alert;
303 char buf[256];
305 if (NPERR_INCOMPATIBLE_VERSION_ERROR == ret) {
306 SNPRINTF(buf, sizeof buf,
307 "alert('Load failed: ABI version mismatch:"
308 " expected %d, got %d\\n');",
309 EF_NACL_ABIVERSION, nacl_abi_version);
310 alert = buf;
311 } else {
312 alert = "alert('Load failed: Generic file error.\\n');";
314 NPObject* window;
315 NPN_GetValue(instance, NPNVWindowNPObject, &window);
316 NPString script;
317 script.utf8characters = alert;
318 script.utf8length = strlen(script.utf8characters);
319 NPVariant result;
320 NPN_Evaluate(instance, window, &script, &result);
322 return ret;
325 } // namespace nacl