|
1 /* |
|
2 IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in |
|
3 consideration of your agreement to the following terms, and your use, installation, |
|
4 modification or redistribution of this Apple software constitutes acceptance of these |
|
5 terms. If you do not agree with these terms, please do not use, install, modify or |
|
6 redistribute this Apple software. |
|
7 |
|
8 In consideration of your agreement to abide by the following terms, and subject to these |
|
9 terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in |
|
10 this original Apple software (the "Apple Software"), to use, reproduce, modify and |
|
11 redistribute the Apple Software, with or without modifications, in source and/or binary |
|
12 forms; provided that if you redistribute the Apple Software in its entirety and without |
|
13 modifications, you must retain this notice and the following text and disclaimers in all |
|
14 such redistributions of the Apple Software. Neither the name, trademarks, service marks |
|
15 or logos of Apple Computer, Inc. may be used to endorse or promote products derived from |
|
16 the Apple Software without specific prior written permission from Apple. Except as expressly |
|
17 stated in this notice, no other rights or licenses, express or implied, are granted by Apple |
|
18 herein, including but not limited to any patent rights that may be infringed by your |
|
19 derivative works or by other works in which the Apple Software may be incorporated. |
|
20 |
|
21 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, |
|
22 EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, |
|
23 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS |
|
24 USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
|
25 |
|
26 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL |
|
27 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, |
|
29 REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND |
|
30 WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR |
|
31 OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
32 */ |
|
33 |
|
34 #include "PluginObject.h" |
|
35 |
|
36 #include "TestObject.h" |
|
37 #include <assert.h> |
|
38 #include <stdio.h> |
|
39 |
|
40 static void pluginInvalidate(NPObject *obj); |
|
41 static bool pluginHasProperty(NPObject *obj, NPIdentifier name); |
|
42 static bool pluginHasMethod(NPObject *obj, NPIdentifier name); |
|
43 static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant); |
|
44 static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant); |
|
45 static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result); |
|
46 static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result); |
|
47 static NPObject *pluginAllocate(NPP npp, NPClass *theClass); |
|
48 static void pluginDeallocate(NPObject *obj); |
|
49 |
|
50 NPNetscapeFuncs *browser; |
|
51 |
|
52 static NPClass pluginClass = { |
|
53 NP_CLASS_STRUCT_VERSION, |
|
54 pluginAllocate, |
|
55 pluginDeallocate, |
|
56 pluginInvalidate, |
|
57 pluginHasMethod, |
|
58 pluginInvoke, |
|
59 pluginInvokeDefault, |
|
60 pluginHasProperty, |
|
61 pluginGetProperty, |
|
62 pluginSetProperty, |
|
63 }; |
|
64 |
|
65 NPClass *getPluginClass(void) |
|
66 { |
|
67 return &pluginClass; |
|
68 } |
|
69 |
|
70 static bool identifiersInitialized = false; |
|
71 |
|
72 #define ID_PROPERTY_PROPERTY 0 |
|
73 #define ID_PROPERTY_EVENT_LOGGING 1 |
|
74 #define ID_PROPERTY_HAS_STREAM 2 |
|
75 #define ID_PROPERTY_TEST_OBJECT 3 |
|
76 #define ID_PROPERTY_LOG_DESTROY 4 |
|
77 #define NUM_PROPERTY_IDENTIFIERS 5 |
|
78 |
|
79 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; |
|
80 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = { |
|
81 "property", |
|
82 "eventLoggingEnabled", |
|
83 "hasStream", |
|
84 "testObject", |
|
85 "logDestroy", |
|
86 }; |
|
87 |
|
88 #define ID_TEST_CALLBACK_METHOD 0 |
|
89 #define ID_TEST_GETURL 1 |
|
90 #define ID_REMOVE_DEFAULT_METHOD 2 |
|
91 #define ID_TEST_DOM_ACCESS 3 |
|
92 #define ID_TEST_GET_URL_NOTIFY 4 |
|
93 #define ID_TEST_INVOKE_DEFAULT 5 |
|
94 #define ID_DESTROY_STREAM 6 |
|
95 #define ID_TEST_ENUMERATE 7 |
|
96 #define NUM_METHOD_IDENTIFIERS 8 |
|
97 |
|
98 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; |
|
99 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { |
|
100 "testCallback", |
|
101 "getURL", |
|
102 "removeDefaultMethod", |
|
103 "testDOMAccess", |
|
104 "getURLNotify", |
|
105 "testInvokeDefault", |
|
106 "destroyStream", |
|
107 "testEnumerate" |
|
108 }; |
|
109 |
|
110 static NPUTF8* createCStringFromNPVariant(const NPVariant *variant) |
|
111 { |
|
112 size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length; |
|
113 NPUTF8* result = (NPUTF8*)malloc(length + 1); |
|
114 memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length); |
|
115 result[length] = '\0'; |
|
116 return result; |
|
117 } |
|
118 |
|
119 static void initializeIdentifiers(void) |
|
120 { |
|
121 browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers); |
|
122 browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers); |
|
123 } |
|
124 |
|
125 static bool pluginHasProperty(NPObject *obj, NPIdentifier name) |
|
126 { |
|
127 for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) |
|
128 if (name == pluginPropertyIdentifiers[i]) |
|
129 return true; |
|
130 return false; |
|
131 } |
|
132 |
|
133 static bool pluginHasMethod(NPObject *obj, NPIdentifier name) |
|
134 { |
|
135 for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) |
|
136 if (name == pluginMethodIdentifiers[i]) |
|
137 return true; |
|
138 return false; |
|
139 } |
|
140 |
|
141 static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant) |
|
142 { |
|
143 if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) { |
|
144 STRINGZ_TO_NPVARIANT("property", *variant); |
|
145 return true; |
|
146 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { |
|
147 BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->eventLogging, *variant); |
|
148 return true; |
|
149 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { |
|
150 BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->logDestroy, *variant); |
|
151 return true; |
|
152 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) { |
|
153 BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->stream != 0, *variant); |
|
154 return true; |
|
155 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) { |
|
156 NPObject *testObject = ((PluginObject *)obj)->testObject; |
|
157 browser->retainobject(testObject); |
|
158 OBJECT_TO_NPVARIANT(testObject, *variant); |
|
159 return true; |
|
160 } |
|
161 return false; |
|
162 } |
|
163 |
|
164 static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant) |
|
165 { |
|
166 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { |
|
167 ((PluginObject *)obj)->eventLogging = NPVARIANT_TO_BOOLEAN(*variant); |
|
168 return true; |
|
169 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { |
|
170 ((PluginObject *)obj)->logDestroy = NPVARIANT_TO_BOOLEAN(*variant); |
|
171 return true; |
|
172 } |
|
173 |
|
174 return false; |
|
175 } |
|
176 |
|
177 static void testDOMAccess(PluginObject *obj) |
|
178 { |
|
179 // Get plug-in's DOM element |
|
180 NPObject *elementObject; |
|
181 if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) { |
|
182 // Get style |
|
183 NPVariant styleVariant; |
|
184 NPIdentifier styleIdentifier = browser->getstringidentifier("style"); |
|
185 if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) { |
|
186 // Set style.border |
|
187 NPIdentifier borderIdentifier = browser->getstringidentifier("border"); |
|
188 NPVariant borderVariant; |
|
189 STRINGZ_TO_NPVARIANT("3px solid red", borderVariant); |
|
190 browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant); |
|
191 browser->releasevariantvalue(&styleVariant); |
|
192 } |
|
193 |
|
194 browser->releaseobject(elementObject); |
|
195 } |
|
196 } |
|
197 |
|
198 static bool pluginInvoke(NPObject *header, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) |
|
199 { |
|
200 PluginObject *obj = (PluginObject *)header; |
|
201 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD]) { |
|
202 // call whatever method name we're given |
|
203 if (argCount > 0 && NPVARIANT_IS_STRING(args[0])) { |
|
204 NPObject *windowScriptObject; |
|
205 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); |
|
206 |
|
207 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); |
|
208 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); |
|
209 free(callbackString); |
|
210 |
|
211 NPVariant browserResult; |
|
212 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult); |
|
213 browser->releasevariantvalue(&browserResult); |
|
214 |
|
215 VOID_TO_NPVARIANT(*result); |
|
216 return true; |
|
217 } |
|
218 } else if (name == pluginMethodIdentifiers[ID_TEST_GETURL]) { |
|
219 if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) { |
|
220 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); |
|
221 NPUTF8* targetString = createCStringFromNPVariant(&args[1]); |
|
222 browser->geturl(obj->npp, urlString, targetString); |
|
223 free(urlString); |
|
224 free(targetString); |
|
225 |
|
226 VOID_TO_NPVARIANT(*result); |
|
227 return true; |
|
228 } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) { |
|
229 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); |
|
230 browser->geturl(obj->npp, urlString, 0); |
|
231 free(urlString); |
|
232 |
|
233 VOID_TO_NPVARIANT(*result); |
|
234 return true; |
|
235 } |
|
236 } else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD]) { |
|
237 pluginClass.invokeDefault = 0; |
|
238 VOID_TO_NPVARIANT(*result); |
|
239 return true; |
|
240 } else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS]) { |
|
241 testDOMAccess(obj); |
|
242 VOID_TO_NPVARIANT(*result); |
|
243 return true; |
|
244 } else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY]) { |
|
245 if (argCount == 3 |
|
246 && NPVARIANT_IS_STRING(args[0]) |
|
247 && (NPVARIANT_IS_STRING(args[1]) || NPVARIANT_IS_NULL(args[1])) |
|
248 && NPVARIANT_IS_STRING(args[2])) { |
|
249 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); |
|
250 NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : NULL); |
|
251 NPUTF8* callbackString = createCStringFromNPVariant(&args[2]); |
|
252 |
|
253 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); |
|
254 browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier); |
|
255 |
|
256 free(urlString); |
|
257 free(targetString); |
|
258 free(callbackString); |
|
259 |
|
260 VOID_TO_NPVARIANT(*result); |
|
261 return true; |
|
262 } |
|
263 } else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT] && NPVARIANT_IS_OBJECT(args[0])) { |
|
264 NPObject *callback = NPVARIANT_TO_OBJECT(args[0]); |
|
265 |
|
266 NPVariant args[1]; |
|
267 NPVariant browserResult; |
|
268 |
|
269 STRINGZ_TO_NPVARIANT("test", args[0]); |
|
270 bool retval = browser->invokeDefault(obj->npp, callback, args, 1, &browserResult); |
|
271 |
|
272 if (retval) |
|
273 browser->releasevariantvalue(&browserResult); |
|
274 |
|
275 BOOLEAN_TO_NPVARIANT(retval, *result); |
|
276 return true; |
|
277 } else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE]) { |
|
278 if (argCount == 2 && NPVARIANT_IS_OBJECT(args[0]) && NPVARIANT_IS_OBJECT(args[1])) { |
|
279 uint32_t count; |
|
280 NPIdentifier* identifiers; |
|
281 |
|
282 if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) { |
|
283 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]); |
|
284 NPIdentifier pushIdentifier = browser->getstringidentifier("push"); |
|
285 |
|
286 for (uint32_t i = 0; i < count; i++) { |
|
287 NPUTF8* string = browser->utf8fromidentifier(identifiers[i]); |
|
288 |
|
289 if (!string) |
|
290 continue; |
|
291 |
|
292 NPVariant args[1]; |
|
293 STRINGZ_TO_NPVARIANT(string, args[0]); |
|
294 NPVariant browserResult; |
|
295 browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult); |
|
296 browser->releasevariantvalue(&browserResult); |
|
297 browser->memfree(string); |
|
298 } |
|
299 |
|
300 browser->memfree(identifiers); |
|
301 } |
|
302 |
|
303 VOID_TO_NPVARIANT(*result); |
|
304 return true; |
|
305 } |
|
306 } else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM]) { |
|
307 NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK); |
|
308 INT32_TO_NPVARIANT(npError, *result); |
|
309 return true; |
|
310 } |
|
311 return false; |
|
312 } |
|
313 |
|
314 static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result) |
|
315 { |
|
316 INT32_TO_NPVARIANT(1, *result); |
|
317 return true; |
|
318 } |
|
319 |
|
320 static void pluginInvalidate(NPObject *obj) |
|
321 { |
|
322 } |
|
323 |
|
324 static NPObject *pluginAllocate(NPP npp, NPClass *theClass) |
|
325 { |
|
326 PluginObject *newInstance = (PluginObject*)malloc(sizeof(PluginObject)); |
|
327 |
|
328 if (!identifiersInitialized) { |
|
329 identifiersInitialized = true; |
|
330 initializeIdentifiers(); |
|
331 } |
|
332 |
|
333 newInstance->npp = npp; |
|
334 newInstance->testObject = browser->createobject(npp, getTestClass()); |
|
335 newInstance->eventLogging = FALSE; |
|
336 newInstance->logDestroy = FALSE; |
|
337 newInstance->logSetWindow = FALSE; |
|
338 newInstance->returnErrorFromNewStream = FALSE; |
|
339 newInstance->stream = 0; |
|
340 |
|
341 newInstance->firstUrl = NULL; |
|
342 newInstance->firstHeaders = NULL; |
|
343 newInstance->lastUrl = NULL; |
|
344 newInstance->lastHeaders = NULL; |
|
345 |
|
346 return (NPObject *)newInstance; |
|
347 } |
|
348 |
|
349 static void pluginDeallocate(NPObject *header) |
|
350 { |
|
351 PluginObject* obj = (PluginObject*)header; |
|
352 |
|
353 browser->releaseobject(obj->testObject); |
|
354 |
|
355 free(obj->firstUrl); |
|
356 free(obj->firstHeaders); |
|
357 free(obj->lastUrl); |
|
358 free(obj->lastHeaders); |
|
359 |
|
360 free(obj); |
|
361 } |
|
362 |
|
363 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData) |
|
364 { |
|
365 assert(object); |
|
366 |
|
367 NPVariant args[2]; |
|
368 |
|
369 NPObject *windowScriptObject; |
|
370 browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject); |
|
371 |
|
372 NPIdentifier callbackIdentifier = notifyData; |
|
373 |
|
374 INT32_TO_NPVARIANT(reason, args[0]); |
|
375 |
|
376 char *strHdr = NULL; |
|
377 if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) { |
|
378 // Format expected by JavaScript validator: four fields separated by \n\n: |
|
379 // First URL; first header block; last URL; last header block. |
|
380 // Note that header blocks already end with \n due to how NPStream::headers works. |
|
381 int len = strlen(object->firstUrl) + 2 |
|
382 + strlen(object->firstHeaders) + 1 |
|
383 + strlen(object->lastUrl) + 2 |
|
384 + strlen(object->lastHeaders) + 1; |
|
385 strHdr = (char*)malloc(len + 1); |
|
386 snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n", |
|
387 object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders); |
|
388 STRINGN_TO_NPVARIANT(strHdr, len, args[1]); |
|
389 } else |
|
390 NULL_TO_NPVARIANT(args[1]); |
|
391 |
|
392 NPVariant browserResult; |
|
393 browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult); |
|
394 browser->releasevariantvalue(&browserResult); |
|
395 |
|
396 free(strHdr); |
|
397 } |
|
398 |
|
399 void notifyStream(PluginObject* object, const char *url, const char *headers) |
|
400 { |
|
401 if (object->firstUrl == NULL) { |
|
402 if (url) |
|
403 object->firstUrl = strdup(url); |
|
404 if (headers) |
|
405 object->firstHeaders = strdup(headers); |
|
406 } else { |
|
407 free(object->lastUrl); |
|
408 free(object->lastHeaders); |
|
409 object->lastUrl = (url ? strdup(url) : NULL); |
|
410 object->lastHeaders = (headers ? strdup(headers) : NULL); |
|
411 } |
|
412 } |