OLD | NEW |
| (Empty) |
1 // Copyright 2010 The Ginsu Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 // TODO(dspringer): This file will disappear when we migrate to Pepper V2. | |
6 | |
7 #include <nacl/npupp.h> | |
8 | |
9 #include <stdlib.h> | |
10 #include <sys/mman.h> | |
11 #include <sys/stat.h> | |
12 #include <cstring> | |
13 | |
14 #include "c_salt/instance.h" | |
15 #include "c_salt/module.h" | |
16 #include "c_salt/scripting_bridge.h" | |
17 #include "c_salt/scripting_bridge_ptrs.h" | |
18 | |
19 namespace { | |
20 bool MapStreamToMemory(NPStream* stream, | |
21 const char* fname, | |
22 char** data, | |
23 size_t* data_length); | |
24 } | |
25 using c_salt::Instance; | |
26 using c_salt::Module; | |
27 | |
28 NPError NPP_New(NPMIMEType mime_type, | |
29 NPP instance, | |
30 uint16_t mode, | |
31 int16_t argc, | |
32 char* argn[], | |
33 char* argv[], | |
34 NPSavedData* saved) { | |
35 extern void InitializePepperExtensions(NPP instance); | |
36 if (instance == NULL) { | |
37 return NPERR_INVALID_INSTANCE_ERROR; | |
38 } | |
39 | |
40 InitializePepperExtensions(instance); | |
41 | |
42 // Build the attribute key/value map. | |
43 // TODO(dspringer): Add this implementation when we switch to Pepper V2. | |
44 // std::map<std::string, std::string> attribute_dict; | |
45 // while (--argc) { | |
46 // attribute_dict[argn[argc]] = argv[argc]; | |
47 // } | |
48 Instance* module_instance = | |
49 Module::GetModuleSingleton().CreateInstance(instance); | |
50 if (module_instance == NULL) { | |
51 return NPERR_OUT_OF_MEMORY_ERROR; | |
52 } | |
53 // module_instance->SetAttributes(attribute_dict); | |
54 instance->pdata = reinterpret_cast<void*>(module_instance); | |
55 return NPERR_NO_ERROR; | |
56 } | |
57 | |
58 NPError NPP_Destroy(NPP instance, NPSavedData** save) { | |
59 if (instance == NULL) { | |
60 return NPERR_INVALID_INSTANCE_ERROR; | |
61 } | |
62 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
63 if (module_instance != NULL) { | |
64 delete module_instance; | |
65 } | |
66 return NPERR_NO_ERROR; | |
67 } | |
68 | |
69 // NPP_GetScriptableInstance returns the NPObject pointer that corresponds to | |
70 // NPPVpluginScriptableNPObject queried by NPP_GetValue() from the browser. | |
71 NPObject* NPP_GetScriptableInstance(NPP instance) { | |
72 if (instance == NULL || instance->pdata == NULL) { | |
73 return NULL; | |
74 } | |
75 | |
76 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
77 if (!module_instance) { | |
78 return NULL; | |
79 } | |
80 c_salt::SharedScriptingBridge bridge | |
81 = module_instance->GetScriptingBridge().lock(); | |
82 if (bridge) { | |
83 return bridge->CopyBrowserBinding(); | |
84 } else { | |
85 // The shared pointer expired, which means the browser was done with it. | |
86 // This shouldn't really happen, but we can just return NULL. | |
87 return NULL; | |
88 } | |
89 return NULL; | |
90 } | |
91 | |
92 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { | |
93 if (NPPVpluginScriptableNPObject == variable) { | |
94 NPObject* scriptable_object = NPP_GetScriptableInstance(instance); | |
95 if (scriptable_object == NULL) | |
96 return NPERR_INVALID_INSTANCE_ERROR; | |
97 *reinterpret_cast<NPObject**>(value) = scriptable_object; | |
98 return NPERR_NO_ERROR; | |
99 } | |
100 return NPERR_INVALID_PARAM; | |
101 } | |
102 | |
103 int16_t NPP_HandleEvent(NPP instance, void* event) { | |
104 if (instance == NULL) { | |
105 return 0; | |
106 } | |
107 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
108 if (!module_instance) | |
109 return 0; | |
110 return module_instance->ReceiveEvent( | |
111 *reinterpret_cast<const NPPepperEvent*>(event)) ? 1 : 0; | |
112 } | |
113 | |
114 NPError NPP_SetWindow(NPP instance, NPWindow* window) { | |
115 if (instance == NULL) { | |
116 return NPERR_INVALID_INSTANCE_ERROR; | |
117 } | |
118 if (window == NULL) { | |
119 return NPERR_GENERIC_ERROR; | |
120 } | |
121 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
122 if (!module_instance) | |
123 return NPERR_INVALID_INSTANCE_ERROR; | |
124 // The first call to NPP_SetWindow indicates that the instance is all loaded | |
125 // up and Pepper devices are ready for use. | |
126 if (!module_instance->is_loaded()) { | |
127 module_instance->InstanceDidLoad(window->width, window->height); | |
128 module_instance->set_is_loaded(true); | |
129 } | |
130 module_instance->WindowDidChangeSize(window->width, window->height); | |
131 return NPERR_NO_ERROR; | |
132 } | |
133 | |
134 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { | |
135 if (NULL != stream) { | |
136 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
137 if (NULL != module_instance) { | |
138 char* data = NULL; | |
139 size_t data_length = 0; | |
140 if (MapStreamToMemory(stream, fname, &data, &data_length)) { | |
141 module_instance->OnURLLoaded(data, data_length); | |
142 } else { | |
143 module_instance->OnURLLoadFailed(Instance::URLLDR_INTERNAL_ERROR); | |
144 } | |
145 } | |
146 } | |
147 } | |
148 | |
149 void NPP_URLNotify(NPP instance, | |
150 const char* url, | |
151 NPReason reason, | |
152 void* notifyData) { | |
153 Instance* module_instance = static_cast<Instance*>(instance->pdata); | |
154 if ((NULL != module_instance) && (NPRES_DONE != reason)) { | |
155 Instance::URLLoaderErrorCode error_code = Instance::URLLDR_INTERNAL_ERROR; | |
156 switch (reason) { | |
157 case NPRES_NETWORK_ERR: { | |
158 error_code = Instance::URLLDR_NETWORK_ERROR; | |
159 break; | |
160 } | |
161 case NPRES_USER_BREAK: { | |
162 error_code = Instance::URLLDR_USER_BREAK; | |
163 break; | |
164 } | |
165 } | |
166 module_instance->OnURLLoadFailed(error_code); | |
167 } | |
168 } | |
169 | |
170 extern "C" { | |
171 NPError InitializePepperGateFunctions(NPPluginFuncs* plugin_funcs) { | |
172 std::memset(plugin_funcs, 0, sizeof(*plugin_funcs)); | |
173 plugin_funcs->version = NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; | |
174 plugin_funcs->size = sizeof(*plugin_funcs); | |
175 plugin_funcs->newp = NPP_New; | |
176 plugin_funcs->destroy = NPP_Destroy; | |
177 plugin_funcs->setwindow = NPP_SetWindow; | |
178 plugin_funcs->event = NPP_HandleEvent; | |
179 plugin_funcs->getvalue = NPP_GetValue; | |
180 plugin_funcs->asfile = NPP_StreamAsFile; | |
181 plugin_funcs->urlnotify = NPP_URLNotify; | |
182 return NPERR_NO_ERROR; | |
183 } | |
184 } // extern "C" | |
185 | |
186 namespace { | |
187 bool MapStreamToMemory(NPStream* stream, | |
188 const char* fname, | |
189 char** data, | |
190 size_t* data_length) { | |
191 // |fname| is actually a pointer to a file descriptor. | |
192 const int fd = *reinterpret_cast<const int*>(fname); | |
193 if (NULL == stream) { | |
194 return false; | |
195 } | |
196 if (-1 == fd) { | |
197 return false; | |
198 } | |
199 struct stat stb; | |
200 if (-1 == fstat(fd, &stb)) { | |
201 return false; | |
202 } | |
203 if ((stb.st_mode & S_IFMT) != S_IFSHM) { | |
204 return false; | |
205 } | |
206 // Chrome integration returns a shared memory descriptor for this now. | |
207 *data = reinterpret_cast<char *>(mmap(NULL, | |
208 stream->end, | |
209 PROT_READ, | |
210 MAP_SHARED, | |
211 fd, | |
212 0)); | |
213 if (MAP_FAILED == *data) { | |
214 return false; | |
215 } | |
216 *data_length = stream->end; | |
217 return true; | |
218 } | |
219 } // namespace | |
220 | |
OLD | NEW |