2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
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
42 * TODO: give some more details
45 #include "native_client/include/portability.h"
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"
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)
68 EMBED(EXPIRATION_MONTH
) "/"
69 EMBED(EXPIRATION_DAY
) "/"
70 EMBED(EXPIRATION_YEAR
)
75 char* NPP_GetMIMEDescription() {
76 return const_cast<char*>("application/x-nacl-srpc:nexe,nacl:NativeClient"
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()
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.
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
);
181 NPObject
* NPP_GetScriptableInstance(NPP instance
) {
182 printf("NPP_GetScriptableInstance\n");
183 if (instance
== NULL
) {
186 nacl::NPInstance
* module
= static_cast<nacl::NPInstance
*>(instance
->pdata
);
187 if (module
!= NULL
) {
188 return module
->GetScriptableInstance();
193 NPError
NPP_NewStream(NPP instance
, NPMIMEType type
,
194 NPStream
* stream
, NPBool seekable
,
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
) {
212 nacl::NPInstance
* module
= static_cast<nacl::NPInstance
*>(instance
->pdata
);
213 if (module
!= NULL
) {
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.
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
) {
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
);
238 module
->StreamAsFile(stream
, filename
);
239 FSDeleteObject(&ref
);
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
,
267 printf("NPP_URLNotify(%s)\n", url
);
268 if (instance
== NULL
) {
271 nacl::NPInstance
* module
= static_cast<nacl::NPInstance
*>(instance
->pdata
);
272 if (module
!= NULL
) {
273 module
->URLNotify(url
, reason
, notify_data
);
280 NPError
CheckExecutableVersion(NPP instance
, const char *filename
) {
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");
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
;
295 ret
= NPERR_INCOMPATIBLE_VERSION_ERROR
;
301 if (NPERR_NO_ERROR
!= ret
) {
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
);
312 alert
= "alert('Load failed: Generic file error.\\n');";
315 NPN_GetValue(instance
, NPNVWindowNPObject
, &window
);
317 script
.utf8characters
= alert
;
318 script
.utf8length
= strlen(script
.utf8characters
);
320 NPN_Evaluate(instance
, window
, &script
, &result
);