dom/plugins/test/testplugin/nptest.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:fd9ecba10fce
1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * Copyright (c) 2008, Mozilla Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the Mozilla Corporation nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contributor(s):
30 * Dave Townsend <dtownsend@oxymoronical.com>
31 * Josh Aas <josh@mozilla.com>
32 *
33 * ***** END LICENSE BLOCK ***** */
34
35 #include "nptest.h"
36 #include "nptest_utils.h"
37 #include "nptest_platform.h"
38
39 #include "mozilla/IntentionalCrash.h"
40
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <iostream>
45 #include <string>
46 #include <sstream>
47 #include <list>
48 #include <ctime>
49
50 #ifdef XP_WIN
51 #include <process.h>
52 #include <float.h>
53 #include <windows.h>
54 #define getpid _getpid
55 #define strcasecmp _stricmp
56 #else
57 #include <unistd.h>
58 #include <pthread.h>
59 #endif
60
61 #include "mozilla/NullPtr.h"
62
63 using namespace std;
64
65 #define PLUGIN_VERSION "1.0.0.0"
66 #define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
67 #define STATIC_ASSERT(condition) \
68 extern void np_static_assert(int arg[(condition) ? 1 : -1])
69
70 extern const char *sPluginName;
71 extern const char *sPluginDescription;
72 static char sPluginVersion[] = PLUGIN_VERSION;
73
74 //
75 // Intentional crash
76 //
77
78 int gCrashCount = 0;
79
80 static void Crash()
81 {
82 int *pi = nullptr;
83 *pi = 55; // Crash dereferencing null pointer
84 ++gCrashCount;
85 }
86
87 static void
88 IntentionalCrash()
89 {
90 mozilla::NoteIntentionalCrash("plugin");
91 Crash();
92 }
93
94 //
95 // static data
96 //
97
98 static NPNetscapeFuncs* sBrowserFuncs = nullptr;
99 static NPClass sNPClass;
100
101 void
102 asyncCallback(void* cookie);
103
104 //
105 // identifiers
106 //
107
108 typedef bool (* ScriptableFunction)
109 (NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
110
111 static bool npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
112 static bool npnInvokeTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
113 static bool npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
114 static bool setUndefinedValueTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
115 static bool identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
116 static bool timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
117 static bool queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
118 static bool lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
119 static bool hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
120 static bool getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
121 static bool getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
122 static bool getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
123 static bool startWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
124 static bool getInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
125 static bool stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
126 static bool getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
127 static bool getLastMouseY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
128 static bool getPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
129 static bool getWidthAtLastPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
130 static bool setInvalidateDuringPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
131 static bool setSlowPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
132 static bool getError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
133 static bool doInternalConsistencyCheck(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
134 static bool setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
135 static bool throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
136 static bool convertPointX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
137 static bool convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
138 static bool streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
139 static bool setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
140 static bool crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
141 static bool crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
142 static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
143 static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
144 static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
145 static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
146 static bool setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
147 static bool getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
148 static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
149 static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
150 static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
151 static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
152 static bool stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
153 static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
154 static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
155 static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
156 static bool crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
157 static bool destroySharedGfxStuff(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
158 static bool propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
159 static bool getTopLevelWindowActivationState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
160 static bool getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
161 static bool getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
162 static bool getFocusEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
163 static bool getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
164 static bool getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
165 static bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
166 static bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
167 static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
168 static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
169 static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
170 static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
171 static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
172 static bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
173 static bool queryContentsScaleFactor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
174
175 static const NPUTF8* sPluginMethodIdentifierNames[] = {
176 "npnEvaluateTest",
177 "npnInvokeTest",
178 "npnInvokeDefaultTest",
179 "setUndefinedValueTest",
180 "identifierToStringTest",
181 "timerTest",
182 "queryPrivateModeState",
183 "lastReportedPrivateModeState",
184 "hasWidget",
185 "getEdge",
186 "getClipRegionRectCount",
187 "getClipRegionRectEdge",
188 "startWatchingInstanceCount",
189 "getInstanceCount",
190 "stopWatchingInstanceCount",
191 "getLastMouseX",
192 "getLastMouseY",
193 "getPaintCount",
194 "getWidthAtLastPaint",
195 "setInvalidateDuringPaint",
196 "setSlowPaint",
197 "getError",
198 "doInternalConsistencyCheck",
199 "setColor",
200 "throwExceptionNextInvoke",
201 "convertPointX",
202 "convertPointY",
203 "streamTest",
204 "setPluginWantsAllStreams",
205 "crash",
206 "crashOnDestroy",
207 "getObjectValue",
208 "getJavaCodebase",
209 "checkObjectValue",
210 "enableFPExceptions",
211 "setCookie",
212 "getCookie",
213 "getAuthInfo",
214 "asyncCallbackTest",
215 "checkGCRace",
216 "hang",
217 "stall",
218 "getClipboardText",
219 "callOnDestroy",
220 "reinitWidget",
221 "crashInNestedLoop",
222 "destroySharedGfxStuff",
223 "propertyAndMethod",
224 "getTopLevelWindowActivationState",
225 "getTopLevelWindowActivationEventCount",
226 "getFocusState",
227 "getFocusEventCount",
228 "getEventModel",
229 "getReflector",
230 "isVisible",
231 "getWindowPosition",
232 "constructObject",
233 "setSitesWithData",
234 "setSitesWithDataCapabilities",
235 "getLastKeyText",
236 "getNPNVdocumentOrigin",
237 "getMouseUpEventCount",
238 "queryContentsScaleFactor"
239 };
240 static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
241 static const ScriptableFunction sPluginMethodFunctions[] = {
242 npnEvaluateTest,
243 npnInvokeTest,
244 npnInvokeDefaultTest,
245 setUndefinedValueTest,
246 identifierToStringTest,
247 timerTest,
248 queryPrivateModeState,
249 lastReportedPrivateModeState,
250 hasWidget,
251 getEdge,
252 getClipRegionRectCount,
253 getClipRegionRectEdge,
254 startWatchingInstanceCount,
255 getInstanceCount,
256 stopWatchingInstanceCount,
257 getLastMouseX,
258 getLastMouseY,
259 getPaintCount,
260 getWidthAtLastPaint,
261 setInvalidateDuringPaint,
262 setSlowPaint,
263 getError,
264 doInternalConsistencyCheck,
265 setColor,
266 throwExceptionNextInvoke,
267 convertPointX,
268 convertPointY,
269 streamTest,
270 setPluginWantsAllStreams,
271 crashPlugin,
272 crashOnDestroy,
273 getObjectValue,
274 getJavaCodebase,
275 checkObjectValue,
276 enableFPExceptions,
277 setCookie,
278 getCookie,
279 getAuthInfo,
280 asyncCallbackTest,
281 checkGCRace,
282 hangPlugin,
283 stallPlugin,
284 getClipboardText,
285 callOnDestroy,
286 reinitWidget,
287 crashPluginInNestedLoop,
288 destroySharedGfxStuff,
289 propertyAndMethod,
290 getTopLevelWindowActivationState,
291 getTopLevelWindowActivationEventCount,
292 getFocusState,
293 getFocusEventCount,
294 getEventModel,
295 getReflector,
296 isVisible,
297 getWindowPosition,
298 constructObject,
299 setSitesWithData,
300 setSitesWithDataCapabilities,
301 getLastKeyText,
302 getNPNVdocumentOrigin,
303 getMouseUpEventCount,
304 queryContentsScaleFactor
305 };
306
307 STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
308 ARRAY_LENGTH(sPluginMethodFunctions));
309
310 static const NPUTF8* sPluginPropertyIdentifierNames[] = {
311 "propertyAndMethod"
312 };
313 static NPIdentifier sPluginPropertyIdentifiers[ARRAY_LENGTH(sPluginPropertyIdentifierNames)];
314 static NPVariant sPluginPropertyValues[ARRAY_LENGTH(sPluginPropertyIdentifierNames)];
315
316 struct URLNotifyData
317 {
318 const char* cookie;
319 NPObject* writeCallback;
320 NPObject* notifyCallback;
321 NPObject* redirectCallback;
322 bool allowRedirects;
323 uint32_t size;
324 char* data;
325 };
326
327 static URLNotifyData kNotifyData = {
328 "static-cookie",
329 nullptr,
330 nullptr,
331 nullptr,
332 false,
333 0,
334 nullptr
335 };
336
337 static const char* SUCCESS_STRING = "pass";
338
339 static bool sIdentifiersInitialized = false;
340
341 struct timerEvent {
342 int32_t timerIdReceive;
343 int32_t timerIdSchedule;
344 uint32_t timerInterval;
345 bool timerRepeat;
346 int32_t timerIdUnschedule;
347 };
348 static timerEvent timerEvents[] = {
349 {-1, 0, 200, false, -1},
350 {0, 0, 400, false, -1},
351 {0, 0, 200, true, -1},
352 {0, 1, 400, true, -1},
353 {0, -1, 0, false, 0},
354 {1, -1, 0, false, -1},
355 {1, -1, 0, false, 1},
356 };
357 static uint32_t currentTimerEventCount = 0;
358 static uint32_t totalTimerEvents = sizeof(timerEvents) / sizeof(timerEvent);
359
360 /**
361 * Incremented for every startWatchingInstanceCount.
362 */
363 static int32_t sCurrentInstanceCountWatchGeneration = 0;
364 /**
365 * Tracks the number of instances created or destroyed since the last
366 * startWatchingInstanceCount.
367 */
368 static int32_t sInstanceCount = 0;
369 /**
370 * True when we've had a startWatchingInstanceCount with no corresponding
371 * stopWatchingInstanceCount.
372 */
373 static bool sWatchingInstanceCount = false;
374
375 /**
376 * A list representing sites for which the plugin has stored data. See
377 * NPP_ClearSiteData and NPP_GetSitesWithData.
378 */
379 struct siteData {
380 string site;
381 uint64_t flags;
382 uint64_t age;
383 };
384 static list<siteData>* sSitesWithData;
385 static bool sClearByAgeSupported;
386
387 static void initializeIdentifiers()
388 {
389 if (!sIdentifiersInitialized) {
390 NPN_GetStringIdentifiers(sPluginMethodIdentifierNames,
391 ARRAY_LENGTH(sPluginMethodIdentifierNames), sPluginMethodIdentifiers);
392 NPN_GetStringIdentifiers(sPluginPropertyIdentifierNames,
393 ARRAY_LENGTH(sPluginPropertyIdentifierNames), sPluginPropertyIdentifiers);
394
395 sIdentifiersInitialized = true;
396
397 // Check whether nullptr is handled in NPN_GetStringIdentifiers
398 NPIdentifier IDList[2];
399 static char const *const kIDNames[2] = { nullptr, "setCookie" };
400 NPN_GetStringIdentifiers(const_cast<const NPUTF8**>(kIDNames), 2, IDList);
401 }
402 }
403
404 static void clearIdentifiers()
405 {
406 memset(sPluginMethodIdentifiers, 0,
407 ARRAY_LENGTH(sPluginMethodIdentifiers) * sizeof(NPIdentifier));
408 memset(sPluginPropertyIdentifiers, 0,
409 ARRAY_LENGTH(sPluginPropertyIdentifiers) * sizeof(NPIdentifier));
410
411 sIdentifiersInitialized = false;
412 }
413
414 static void addRange(InstanceData* instanceData, const char* range)
415 {
416 char rangestr[16];
417 strncpy(rangestr, range, sizeof(rangestr));
418 const char* str1 = strtok(rangestr, ",");
419 const char* str2 = str1 ? strtok(nullptr, ",") : nullptr;
420 if (str1 && str2) {
421 TestRange* byterange = new TestRange;
422 byterange->offset = atoi(str1);
423 byterange->length = atoi(str2);
424 byterange->waiting = true;
425 byterange->next = instanceData->testrange;
426 instanceData->testrange = byterange;
427 }
428 }
429
430 static void sendBufferToFrame(NPP instance)
431 {
432 InstanceData* instanceData = (InstanceData*)(instance->pdata);
433 string outbuf;
434 if (!instanceData->npnNewStream) outbuf = "data:text/html,";
435 const char* buf = reinterpret_cast<char *>(instanceData->streamBuf);
436 int32_t bufsize = instanceData->streamBufSize;
437 if (instanceData->streamMode == NP_ASFILE ||
438 instanceData->streamMode == NP_ASFILEONLY) {
439 buf = reinterpret_cast<char *>(instanceData->fileBuf);
440 bufsize = instanceData->fileBufSize;
441 }
442 if (instanceData->err.str().length() > 0) {
443 outbuf.append(instanceData->err.str());
444 }
445 else if (bufsize > 0) {
446 outbuf.append(buf);
447 }
448 else {
449 outbuf.append("Error: no data in buffer");
450 }
451
452 if (instanceData->npnNewStream &&
453 instanceData->err.str().length() == 0) {
454 char typeHTML[] = "text/html";
455 NPStream* stream;
456 printf("calling NPN_NewStream...");
457 NPError err = NPN_NewStream(instance, typeHTML,
458 instanceData->frame.c_str(), &stream);
459 printf("return value %d\n", err);
460 if (err != NPERR_NO_ERROR) {
461 instanceData->err << "NPN_NewStream returned " << err;
462 return;
463 }
464
465 int32_t bytesToWrite = outbuf.length();
466 int32_t bytesWritten = 0;
467 while ((bytesToWrite - bytesWritten) > 0) {
468 int32_t numBytes = (bytesToWrite - bytesWritten) <
469 instanceData->streamChunkSize ?
470 bytesToWrite - bytesWritten : instanceData->streamChunkSize;
471 int32_t written = NPN_Write(instance, stream,
472 numBytes, (void*)(outbuf.c_str() + bytesWritten));
473 if (written <= 0) {
474 instanceData->err << "NPN_Write returned " << written;
475 break;
476 }
477 bytesWritten += numBytes;
478 printf("%d bytes written, total %d\n", written, bytesWritten);
479 }
480 err = NPN_DestroyStream(instance, stream, NPRES_DONE);
481 if (err != NPERR_NO_ERROR) {
482 instanceData->err << "NPN_DestroyStream returned " << err;
483 }
484 }
485 else {
486 // Convert CRLF to LF, and escape most other non-alphanumeric chars.
487 for (size_t i = 0; i < outbuf.length(); i++) {
488 if (outbuf[i] == '\n') {
489 outbuf.replace(i, 1, "%0a");
490 i += 2;
491 }
492 else if (outbuf[i] == '\r') {
493 outbuf.replace(i, 1, "");
494 i -= 1;
495 }
496 else {
497 int ascii = outbuf[i];
498 if (!((ascii >= ',' && ascii <= ';') ||
499 (ascii >= 'A' && ascii <= 'Z') ||
500 (ascii >= 'a' && ascii <= 'z'))) {
501 char hex[8];
502 sprintf(hex, "%%%x", ascii);
503 outbuf.replace(i, 1, hex);
504 i += 2;
505 }
506 }
507 }
508
509 NPError err = NPN_GetURL(instance, outbuf.c_str(),
510 instanceData->frame.c_str());
511 if (err != NPERR_NO_ERROR) {
512 instanceData->err << "NPN_GetURL returned " << err;
513 }
514 }
515 }
516
517 static void XPSleep(unsigned int seconds)
518 {
519 #ifdef XP_WIN
520 Sleep(1000 * seconds);
521 #else
522 sleep(seconds);
523 #endif
524 }
525
526 TestFunction
527 getFuncFromString(const char* funcname)
528 {
529 FunctionTable funcTable[] =
530 {
531 { FUNCTION_NPP_NEWSTREAM, "npp_newstream" },
532 { FUNCTION_NPP_WRITEREADY, "npp_writeready" },
533 { FUNCTION_NPP_WRITE, "npp_write" },
534 { FUNCTION_NPP_DESTROYSTREAM, "npp_destroystream" },
535 { FUNCTION_NPP_WRITE_RPC, "npp_write_rpc" },
536 { FUNCTION_NONE, nullptr }
537 };
538 int32_t i = 0;
539 while(funcTable[i].funcName) {
540 if (!strcmp(funcname, funcTable[i].funcName)) return funcTable[i].funcId;
541 i++;
542 }
543 return FUNCTION_NONE;
544 }
545
546 static void
547 DuplicateNPVariant(NPVariant& aDest, const NPVariant& aSrc)
548 {
549 if (NPVARIANT_IS_STRING(aSrc)) {
550 NPString src = NPVARIANT_TO_STRING(aSrc);
551 char* buf = new char[src.UTF8Length];
552 strncpy(buf, src.UTF8Characters, src.UTF8Length);
553 STRINGN_TO_NPVARIANT(buf, src.UTF8Length, aDest);
554 }
555 else if (NPVARIANT_IS_OBJECT(aSrc)) {
556 NPObject* obj =
557 NPN_RetainObject(NPVARIANT_TO_OBJECT(aSrc));
558 OBJECT_TO_NPVARIANT(obj, aDest);
559 }
560 else {
561 aDest = aSrc;
562 }
563 }
564
565 void
566 drawAsyncBitmapColor(InstanceData* instanceData)
567 {
568 NPP npp = instanceData->npp;
569
570 uint32_t *pixelData = (uint32_t*)instanceData->backBuffer->bitmap.data;
571
572 uint32_t rgba = instanceData->scriptableObject->drawColor;
573
574 unsigned char subpixels[4];
575 subpixels[0] = rgba & 0xFF;
576 subpixels[1] = (rgba & 0xFF00) >> 8;
577 subpixels[2] = (rgba & 0xFF0000) >> 16;
578 subpixels[3] = (rgba & 0xFF000000) >> 24;
579
580 subpixels[0] = uint8_t(float(subpixels[3] * subpixels[0]) / 0xFF);
581 subpixels[1] = uint8_t(float(subpixels[3] * subpixels[1]) / 0xFF);
582 subpixels[2] = uint8_t(float(subpixels[3] * subpixels[2]) / 0xFF);
583 uint32_t premultiplied;
584 memcpy(&premultiplied, subpixels, sizeof(premultiplied));
585
586 for (uint32_t* lastPixel = pixelData + instanceData->backBuffer->size.width * instanceData->backBuffer->size.height;
587 pixelData < lastPixel;
588 ++pixelData) {
589 *pixelData = premultiplied;
590 }
591
592 NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, nullptr);
593 NPAsyncSurface *oldFront = instanceData->frontBuffer;
594 instanceData->frontBuffer = instanceData->backBuffer;
595 instanceData->backBuffer = oldFront;
596 }
597
598 static bool bug813906(NPP npp, const char* const function, const char* const url, const char* const frame)
599 {
600 NPObject *windowObj = nullptr;
601 NPError err = NPN_GetValue(npp, NPNVWindowNPObject, &windowObj);
602 if (err != NPERR_NO_ERROR) {
603 return false;
604 }
605
606 NPVariant result;
607 bool res = NPN_Invoke(npp, windowObj, NPN_GetStringIdentifier(function), nullptr, 0, &result);
608 NPN_ReleaseObject(windowObj);
609 if (!res) {
610 return false;
611 }
612
613 NPN_ReleaseVariantValue(&result);
614
615 err = NPN_GetURL(npp, url, frame);
616 if (err != NPERR_NO_ERROR) {
617 err = NPN_GetURL(npp, "about:blank", frame);
618 return false;
619 }
620
621 return true;
622 }
623
624 //
625 // function signatures
626 //
627
628 NPObject* scriptableAllocate(NPP npp, NPClass* aClass);
629 void scriptableDeallocate(NPObject* npobj);
630 void scriptableInvalidate(NPObject* npobj);
631 bool scriptableHasMethod(NPObject* npobj, NPIdentifier name);
632 bool scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
633 bool scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
634 bool scriptableHasProperty(NPObject* npobj, NPIdentifier name);
635 bool scriptableGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result);
636 bool scriptableSetProperty(NPObject* npobj, NPIdentifier name, const NPVariant* value);
637 bool scriptableRemoveProperty(NPObject* npobj, NPIdentifier name);
638 bool scriptableEnumerate(NPObject* npobj, NPIdentifier** identifier, uint32_t* count);
639 bool scriptableConstruct(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
640
641 //
642 // npapi plugin functions
643 //
644
645 #ifdef XP_UNIX
646 NP_EXPORT(char*)
647 NP_GetPluginVersion()
648 {
649 return sPluginVersion;
650 }
651 #endif
652
653 extern const char *sMimeDescription;
654
655 #if defined(XP_UNIX)
656 NP_EXPORT(const char*) NP_GetMIMEDescription()
657 #elif defined(XP_WIN)
658 const char* NP_GetMIMEDescription()
659 #endif
660 {
661 return sMimeDescription;
662 }
663
664 #ifdef XP_UNIX
665 NP_EXPORT(NPError)
666 NP_GetValue(void* future, NPPVariable aVariable, void* aValue) {
667 switch (aVariable) {
668 case NPPVpluginNameString:
669 *((const char**)aValue) = sPluginName;
670 break;
671 case NPPVpluginDescriptionString:
672 *((const char**)aValue) = sPluginDescription;
673 break;
674 default:
675 return NPERR_INVALID_PARAM;
676 break;
677 }
678 return NPERR_NO_ERROR;
679 }
680 #endif
681
682 static bool fillPluginFunctionTable(NPPluginFuncs* pFuncs)
683 {
684 // Check the size of the provided structure based on the offset of the
685 // last member we need.
686 if (pFuncs->size < (offsetof(NPPluginFuncs, getsiteswithdata) + sizeof(void*)))
687 return false;
688
689 pFuncs->newp = NPP_New;
690 pFuncs->destroy = NPP_Destroy;
691 pFuncs->setwindow = NPP_SetWindow;
692 pFuncs->newstream = NPP_NewStream;
693 pFuncs->destroystream = NPP_DestroyStream;
694 pFuncs->asfile = NPP_StreamAsFile;
695 pFuncs->writeready = NPP_WriteReady;
696 pFuncs->write = NPP_Write;
697 pFuncs->print = NPP_Print;
698 pFuncs->event = NPP_HandleEvent;
699 pFuncs->urlnotify = NPP_URLNotify;
700 pFuncs->getvalue = NPP_GetValue;
701 pFuncs->setvalue = NPP_SetValue;
702 pFuncs->urlredirectnotify = NPP_URLRedirectNotify;
703 pFuncs->clearsitedata = NPP_ClearSiteData;
704 pFuncs->getsiteswithdata = NPP_GetSitesWithData;
705
706 return true;
707 }
708
709 #if defined(XP_MACOSX)
710 NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs)
711 #elif defined(XP_WIN)
712 NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs)
713 #elif defined(XP_UNIX)
714 NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs)
715 #endif
716 {
717 sBrowserFuncs = bFuncs;
718
719 initializeIdentifiers();
720
721 for (unsigned int i = 0; i < ARRAY_LENGTH(sPluginPropertyValues); i++) {
722 VOID_TO_NPVARIANT(sPluginPropertyValues[i]);
723 }
724
725 memset(&sNPClass, 0, sizeof(NPClass));
726 sNPClass.structVersion = NP_CLASS_STRUCT_VERSION;
727 sNPClass.allocate = (NPAllocateFunctionPtr)scriptableAllocate;
728 sNPClass.deallocate = (NPDeallocateFunctionPtr)scriptableDeallocate;
729 sNPClass.invalidate = (NPInvalidateFunctionPtr)scriptableInvalidate;
730 sNPClass.hasMethod = (NPHasMethodFunctionPtr)scriptableHasMethod;
731 sNPClass.invoke = (NPInvokeFunctionPtr)scriptableInvoke;
732 sNPClass.invokeDefault = (NPInvokeDefaultFunctionPtr)scriptableInvokeDefault;
733 sNPClass.hasProperty = (NPHasPropertyFunctionPtr)scriptableHasProperty;
734 sNPClass.getProperty = (NPGetPropertyFunctionPtr)scriptableGetProperty;
735 sNPClass.setProperty = (NPSetPropertyFunctionPtr)scriptableSetProperty;
736 sNPClass.removeProperty = (NPRemovePropertyFunctionPtr)scriptableRemoveProperty;
737 sNPClass.enumerate = (NPEnumerationFunctionPtr)scriptableEnumerate;
738 sNPClass.construct = (NPConstructFunctionPtr)scriptableConstruct;
739
740 #if defined(XP_UNIX) && !defined(XP_MACOSX)
741 if (!fillPluginFunctionTable(pFuncs)) {
742 return NPERR_INVALID_FUNCTABLE_ERROR;
743 }
744 #endif
745
746 return NPERR_NO_ERROR;
747 }
748
749 #if defined(XP_MACOSX)
750 NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs)
751 #elif defined(XP_WIN)
752 NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs)
753 #endif
754 #if defined(XP_MACOSX) || defined(XP_WIN)
755 {
756 if (!fillPluginFunctionTable(pFuncs)) {
757 return NPERR_INVALID_FUNCTABLE_ERROR;
758 }
759
760 return NPERR_NO_ERROR;
761 }
762 #endif
763
764 #if defined(XP_UNIX)
765 NP_EXPORT(NPError) NP_Shutdown()
766 #elif defined(XP_WIN)
767 NPError OSCALL NP_Shutdown()
768 #endif
769 {
770 clearIdentifiers();
771
772 for (unsigned int i = 0; i < ARRAY_LENGTH(sPluginPropertyValues); i++) {
773 NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
774 }
775
776 return NPERR_NO_ERROR;
777 }
778
779 NPError
780 NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
781 {
782 // Make sure our pdata field is nullptr at this point. If it isn't, that
783 // probably means the browser gave us uninitialized memory.
784 if (instance->pdata) {
785 printf("NPP_New called with non-NULL NPP->pdata pointer!\n");
786 return NPERR_GENERIC_ERROR;
787 }
788
789 // Make sure we can render this plugin
790 NPBool browserSupportsWindowless = false;
791 NPN_GetValue(instance, NPNVSupportsWindowless, &browserSupportsWindowless);
792 if (!browserSupportsWindowless && !pluginSupportsWindowMode()) {
793 printf("Windowless mode not supported by the browser, windowed mode not supported by the plugin!\n");
794 return NPERR_GENERIC_ERROR;
795 }
796
797 // set up our our instance data
798 InstanceData* instanceData = new InstanceData;
799 if (!instanceData)
800 return NPERR_OUT_OF_MEMORY_ERROR;
801 instanceData->npp = instance;
802 instanceData->streamMode = NP_ASFILEONLY;
803 instanceData->testFunction = FUNCTION_NONE;
804 instanceData->functionToFail = FUNCTION_NONE;
805 instanceData->failureCode = 0;
806 instanceData->callOnDestroy = nullptr;
807 instanceData->streamChunkSize = 1024;
808 instanceData->streamBuf = nullptr;
809 instanceData->streamBufSize = 0;
810 instanceData->fileBuf = nullptr;
811 instanceData->fileBufSize = 0;
812 instanceData->throwOnNextInvoke = false;
813 instanceData->runScriptOnPaint = false;
814 instanceData->dontTouchElement = false;
815 instanceData->testrange = nullptr;
816 instanceData->hasWidget = false;
817 instanceData->npnNewStream = false;
818 instanceData->invalidateDuringPaint = false;
819 instanceData->slowPaint = false;
820 instanceData->writeCount = 0;
821 instanceData->writeReadyCount = 0;
822 memset(&instanceData->window, 0, sizeof(instanceData->window));
823 instanceData->crashOnDestroy = false;
824 instanceData->cleanupWidget = true; // only used by nptest_gtk
825 instanceData->topLevelWindowActivationState = ACTIVATION_STATE_UNKNOWN;
826 instanceData->topLevelWindowActivationEventCount = 0;
827 instanceData->focusState = ACTIVATION_STATE_UNKNOWN;
828 instanceData->focusEventCount = 0;
829 instanceData->eventModel = 0;
830 instanceData->closeStream = false;
831 instanceData->wantsAllStreams = false;
832 instanceData->asyncDrawing = AD_NONE;
833 instanceData->frontBuffer = nullptr;
834 instanceData->backBuffer = nullptr;
835 instanceData->mouseUpEventCount = 0;
836 instanceData->bugMode = -1;
837 instance->pdata = instanceData;
838
839 TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
840 if (!scriptableObject) {
841 printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n");
842 free(instanceData);
843 return NPERR_GENERIC_ERROR;
844 }
845 scriptableObject->npp = instance;
846 scriptableObject->drawMode = DM_DEFAULT;
847 scriptableObject->drawColor = 0;
848 instanceData->scriptableObject = scriptableObject;
849
850 instanceData->instanceCountWatchGeneration = sCurrentInstanceCountWatchGeneration;
851
852 if (NP_FULL == mode) {
853 instanceData->streamMode = NP_SEEK;
854 instanceData->frame = "testframe";
855 addRange(instanceData, "100,100");
856 }
857
858 bool requestWindow = false;
859 // handle extra params
860 for (int i = 0; i < argc; i++) {
861 if (strcmp(argn[i], "drawmode") == 0) {
862 if (strcmp(argv[i], "solid") == 0)
863 scriptableObject->drawMode = DM_SOLID_COLOR;
864 }
865 else if (strcmp(argn[i], "color") == 0) {
866 scriptableObject->drawColor = parseHexColor(argv[i], strlen(argv[i]));
867 }
868 else if (strcmp(argn[i], "wmode") == 0) {
869 if (strcmp(argv[i], "window") == 0) {
870 requestWindow = true;
871 }
872 }
873 else if (strcmp(argn[i], "asyncmodel") == 0) {
874 if (strcmp(argv[i], "bitmap") == 0) {
875 if (pluginSupportsAsyncBitmapDrawing()) {
876 instanceData->asyncDrawing = AD_BITMAP;
877 }
878 }
879 if (strcmp(argv[i], "dxgi") == 0) {
880 if (pluginSupportsAsyncDXGIDrawing()) {
881 instanceData->asyncDrawing = AD_DXGI;
882 }
883 }
884 }
885 if (strcmp(argn[i], "streammode") == 0) {
886 if (strcmp(argv[i], "normal") == 0) {
887 instanceData->streamMode = NP_NORMAL;
888 }
889 else if ((strcmp(argv[i], "asfile") == 0) &&
890 strlen(argv[i]) == strlen("asfile")) {
891 instanceData->streamMode = NP_ASFILE;
892 }
893 else if (strcmp(argv[i], "asfileonly") == 0) {
894 instanceData->streamMode = NP_ASFILEONLY;
895 }
896 else if (strcmp(argv[i], "seek") == 0) {
897 instanceData->streamMode = NP_SEEK;
898 }
899 }
900 if (strcmp(argn[i], "streamchunksize") == 0) {
901 instanceData->streamChunkSize = atoi(argv[i]);
902 }
903 if (strcmp(argn[i], "failurecode") == 0) {
904 instanceData->failureCode = atoi(argv[i]);
905 }
906 if (strcmp(argn[i], "functiontofail") == 0) {
907 instanceData->functionToFail = getFuncFromString(argv[i]);
908 }
909 if (strcmp(argn[i], "geturl") == 0) {
910 instanceData->testUrl = argv[i];
911 instanceData->testFunction = FUNCTION_NPP_GETURL;
912 }
913 if (strcmp(argn[i], "posturl") == 0) {
914 instanceData->testUrl = argv[i];
915 instanceData->testFunction = FUNCTION_NPP_POSTURL;
916 }
917 if (strcmp(argn[i], "geturlnotify") == 0) {
918 instanceData->testUrl = argv[i];
919 instanceData->testFunction = FUNCTION_NPP_GETURLNOTIFY;
920 }
921 if (strcmp(argn[i], "postmode") == 0) {
922 if (strcmp(argv[i], "frame") == 0) {
923 instanceData->postMode = POSTMODE_FRAME;
924 }
925 else if (strcmp(argv[i], "stream") == 0) {
926 instanceData->postMode = POSTMODE_STREAM;
927 }
928 }
929 if (strcmp(argn[i], "frame") == 0) {
930 instanceData->frame = argv[i];
931 }
932 if (strcmp(argn[i], "range") == 0) {
933 string range = argv[i];
934 size_t semicolon = range.find(';');
935 while (semicolon != string::npos) {
936 addRange(instanceData, range.substr(0, semicolon).c_str());
937 if (semicolon == range.length()) {
938 range = "";
939 break;
940 }
941 range = range.substr(semicolon + 1);
942 semicolon = range.find(';');
943 }
944 if (range.length()) addRange(instanceData, range.c_str());
945 }
946 if (strcmp(argn[i], "newstream") == 0 &&
947 strcmp(argv[i], "true") == 0) {
948 instanceData->npnNewStream = true;
949 }
950 if (strcmp(argn[i], "newcrash") == 0) {
951 IntentionalCrash();
952 }
953 if (strcmp(argn[i], "paintscript") == 0) {
954 instanceData->runScriptOnPaint = true;
955 }
956
957 if (strcmp(argn[i], "donttouchelement") == 0) {
958 instanceData->dontTouchElement = true;
959 }
960 // "cleanupwidget" is only used with nptest_gtk, defaulting to true. It
961 // indicates whether the plugin should destroy its window in response to
962 // NPP_Destroy (or let the platform destroy the widget when the parent
963 // window gets destroyed).
964 if (strcmp(argn[i], "cleanupwidget") == 0 &&
965 strcmp(argv[i], "false") == 0) {
966 instanceData->cleanupWidget = false;
967 }
968 if (!strcmp(argn[i], "closestream")) {
969 instanceData->closeStream = true;
970 }
971 if (strcmp(argn[i], "bugmode") == 0) {
972 instanceData->bugMode = atoi(argv[i]);
973 }
974 // Try to emulate java's codebase handling: Use the last seen codebase
975 // value, regardless of whether it is in attributes or params.
976 if (strcasecmp(argn[i], "codebase") == 0) {
977 instanceData->javaCodebase = argv[i];
978 }
979 }
980
981 if (!browserSupportsWindowless || !pluginSupportsWindowlessMode()) {
982 requestWindow = true;
983 } else if (!pluginSupportsWindowMode()) {
984 requestWindow = false;
985 }
986 if (requestWindow) {
987 instanceData->hasWidget = true;
988 } else {
989 // NPPVpluginWindowBool should default to true, so we may as well
990 // test that by not setting it in the window case
991 NPN_SetValue(instance, NPPVpluginWindowBool, (void*)false);
992 }
993
994 if (scriptableObject->drawMode == DM_SOLID_COLOR &&
995 (scriptableObject->drawColor & 0xFF000000) != 0xFF000000) {
996 NPN_SetValue(instance, NPPVpluginTransparentBool, (void*)true);
997 }
998
999 if (instanceData->asyncDrawing == AD_BITMAP) {
1000 NPBool supportsAsyncBitmap = false;
1001 if ((NPN_GetValue(instance, NPNVsupportsAsyncBitmapSurfaceBool, &supportsAsyncBitmap) == NPERR_NO_ERROR) &&
1002 supportsAsyncBitmap) {
1003 NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncBitmapSurface);
1004 } else {
1005 instanceData->asyncDrawing = AD_NONE;
1006 }
1007 }
1008 #ifdef XP_WIN
1009 else if (instanceData->asyncDrawing == AD_DXGI) {
1010 NPBool supportsAsyncDXGI = false;
1011 if ((NPN_GetValue(instance, NPNVsupportsAsyncWindowsDXGISurfaceBool, &supportsAsyncDXGI) == NPERR_NO_ERROR) &&
1012 supportsAsyncDXGI) {
1013 NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncWindowsDXGISurface);
1014 } else {
1015 instanceData->asyncDrawing = AD_NONE;
1016 }
1017 }
1018 #endif
1019
1020 instanceData->lastReportedPrivateModeState = false;
1021 instanceData->lastMouseX = instanceData->lastMouseY = -1;
1022 instanceData->widthAtLastPaint = -1;
1023 instanceData->paintCount = 0;
1024
1025 // do platform-specific initialization
1026 NPError err = pluginInstanceInit(instanceData);
1027 if (err != NPERR_NO_ERROR) {
1028 NPN_ReleaseObject(scriptableObject);
1029 free(instanceData);
1030 return err;
1031 }
1032
1033 NPVariant variantTrue;
1034 BOOLEAN_TO_NPVARIANT(true, variantTrue);
1035 NPObject* o = nullptr;
1036
1037 // Set a property on NPNVPluginElementNPObject, unless the consumer explicitly
1038 // opted out of this behavior.
1039 if (!instanceData->dontTouchElement) {
1040 err = NPN_GetValue(instance, NPNVPluginElementNPObject, &o);
1041 if (err == NPERR_NO_ERROR) {
1042 NPN_SetProperty(instance, o,
1043 NPN_GetStringIdentifier("pluginFoundElement"), &variantTrue);
1044 NPN_ReleaseObject(o);
1045 o = nullptr;
1046 }
1047 }
1048
1049 // Set a property on NPNVWindowNPObject
1050 err = NPN_GetValue(instance, NPNVWindowNPObject, &o);
1051 if (err == NPERR_NO_ERROR) {
1052 NPN_SetProperty(instance, o,
1053 NPN_GetStringIdentifier("pluginFoundWindow"), &variantTrue);
1054 NPN_ReleaseObject(o);
1055 o = nullptr;
1056 }
1057
1058 ++sInstanceCount;
1059
1060 if (instanceData->testFunction == FUNCTION_NPP_GETURL) {
1061 NPError err = NPN_GetURL(instance, instanceData->testUrl.c_str(), nullptr);
1062 if (err != NPERR_NO_ERROR) {
1063 instanceData->err << "NPN_GetURL returned " << err;
1064 }
1065 }
1066 else if (instanceData->testFunction == FUNCTION_NPP_GETURLNOTIFY) {
1067 NPError err = NPN_GetURLNotify(instance, instanceData->testUrl.c_str(),
1068 nullptr, static_cast<void*>(&kNotifyData));
1069 if (err != NPERR_NO_ERROR) {
1070 instanceData->err << "NPN_GetURLNotify returned " << err;
1071 }
1072 }
1073
1074 if ((instanceData->bugMode == 813906) && instanceData->frame.length()) {
1075 bug813906(instance, "f", "browser.xul", instanceData->frame.c_str());
1076 }
1077
1078 return NPERR_NO_ERROR;
1079 }
1080
1081 NPError
1082 NPP_Destroy(NPP instance, NPSavedData** save)
1083 {
1084 printf("NPP_Destroy\n");
1085 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1086
1087 if (instanceData->crashOnDestroy)
1088 IntentionalCrash();
1089
1090 if (instanceData->callOnDestroy) {
1091 NPVariant result;
1092 NPN_InvokeDefault(instance, instanceData->callOnDestroy, nullptr, 0, &result);
1093 NPN_ReleaseVariantValue(&result);
1094 NPN_ReleaseObject(instanceData->callOnDestroy);
1095 }
1096
1097 if (instanceData->streamBuf) {
1098 free(instanceData->streamBuf);
1099 }
1100 if (instanceData->fileBuf) {
1101 free(instanceData->fileBuf);
1102 }
1103
1104 TestRange* currentrange = instanceData->testrange;
1105 TestRange* nextrange;
1106 while (currentrange != nullptr) {
1107 nextrange = reinterpret_cast<TestRange*>(currentrange->next);
1108 delete currentrange;
1109 currentrange = nextrange;
1110 }
1111
1112 if (instanceData->frontBuffer) {
1113 NPN_SetCurrentAsyncSurface(instance, nullptr, nullptr);
1114 NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
1115 NPN_MemFree(instanceData->frontBuffer);
1116 }
1117 if (instanceData->backBuffer) {
1118 NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
1119 NPN_MemFree(instanceData->backBuffer);
1120 }
1121
1122 pluginInstanceShutdown(instanceData);
1123 NPN_ReleaseObject(instanceData->scriptableObject);
1124
1125 if (sCurrentInstanceCountWatchGeneration == instanceData->instanceCountWatchGeneration) {
1126 --sInstanceCount;
1127 }
1128 delete instanceData;
1129
1130 return NPERR_NO_ERROR;
1131 }
1132
1133 NPError
1134 NPP_SetWindow(NPP instance, NPWindow* window)
1135 {
1136 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1137
1138 if (instanceData->scriptableObject->drawMode == DM_DEFAULT &&
1139 (instanceData->window.width != window->width ||
1140 instanceData->window.height != window->height)) {
1141 NPRect r;
1142 r.left = r.top = 0;
1143 r.right = window->width;
1144 r.bottom = window->height;
1145 NPN_InvalidateRect(instance, &r);
1146 }
1147
1148 void* oldWindow = instanceData->window.window;
1149 pluginDoSetWindow(instanceData, window);
1150 if (instanceData->hasWidget && oldWindow != instanceData->window.window) {
1151 pluginWidgetInit(instanceData, oldWindow);
1152 }
1153
1154 if (instanceData->asyncDrawing == AD_BITMAP) {
1155 if (instanceData->frontBuffer &&
1156 instanceData->frontBuffer->size.width >= 0 &&
1157 (uint32_t)instanceData->frontBuffer->size.width == window->width &&
1158 instanceData ->frontBuffer->size.height >= 0 &&
1159 (uint32_t)instanceData->frontBuffer->size.height == window->height) {
1160 return NPERR_NO_ERROR;
1161 }
1162 if (instanceData->frontBuffer) {
1163 NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
1164 NPN_MemFree(instanceData->frontBuffer);
1165 }
1166 if (instanceData->backBuffer) {
1167 NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
1168 NPN_MemFree(instanceData->backBuffer);
1169 }
1170 instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
1171 instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
1172
1173 NPSize size;
1174 size.width = window->width;
1175 size.height = window->height;
1176
1177 memcpy(instanceData->backBuffer, instanceData->frontBuffer, sizeof(NPAsyncSurface));
1178
1179 NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer);
1180 NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer);
1181
1182 drawAsyncBitmapColor(instanceData);
1183 }
1184 return NPERR_NO_ERROR;
1185 }
1186
1187 NPError
1188 NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype)
1189 {
1190 printf("NPP_NewStream\n");
1191 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1192
1193 if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM &&
1194 instanceData->failureCode) {
1195 instanceData->err << SUCCESS_STRING;
1196 if (instanceData->frame.length() > 0) {
1197 sendBufferToFrame(instance);
1198 }
1199 return instanceData->failureCode;
1200 }
1201
1202 if (stream->notifyData &&
1203 static_cast<URLNotifyData*>(stream->notifyData) != &kNotifyData) {
1204 // stream from streamTest
1205 *stype = NP_NORMAL;
1206 }
1207 else {
1208 *stype = instanceData->streamMode;
1209
1210 if (instanceData->streamBufSize) {
1211 free(instanceData->streamBuf);
1212 instanceData->streamBufSize = 0;
1213 if (instanceData->testFunction == FUNCTION_NPP_POSTURL &&
1214 instanceData->postMode == POSTMODE_STREAM) {
1215 instanceData->testFunction = FUNCTION_NPP_GETURL;
1216 }
1217 else {
1218 // We already got a stream and didn't ask for another one.
1219 instanceData->err << "Received unexpected multiple NPP_NewStream";
1220 }
1221 }
1222 }
1223 return NPERR_NO_ERROR;
1224 }
1225
1226 NPError
1227 NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
1228 {
1229 printf("NPP_DestroyStream\n");
1230 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1231
1232 if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) {
1233 instanceData->err << "NPP_DestroyStream called";
1234 }
1235
1236 if (instanceData->functionToFail == FUNCTION_NPP_WRITE) {
1237 if (instanceData->writeCount == 1)
1238 instanceData->err << SUCCESS_STRING;
1239 else
1240 instanceData->err << "NPP_Write called after returning -1";
1241 }
1242
1243 if (instanceData->functionToFail == FUNCTION_NPP_DESTROYSTREAM &&
1244 instanceData->failureCode) {
1245 instanceData->err << SUCCESS_STRING;
1246 if (instanceData->frame.length() > 0) {
1247 sendBufferToFrame(instance);
1248 }
1249 return instanceData->failureCode;
1250 }
1251
1252 URLNotifyData* nd = static_cast<URLNotifyData*>(stream->notifyData);
1253 if (nd && nd != &kNotifyData) {
1254 return NPERR_NO_ERROR;
1255 }
1256
1257 if (instanceData->streamMode == NP_ASFILE &&
1258 instanceData->functionToFail == FUNCTION_NONE) {
1259 if (!instanceData->streamBuf) {
1260 instanceData->err <<
1261 "Error: no data written with NPP_Write";
1262 return NPERR_GENERIC_ERROR;
1263 }
1264
1265 if (!instanceData->fileBuf) {
1266 instanceData->err <<
1267 "Error: no data written with NPP_StreamAsFile";
1268 return NPERR_GENERIC_ERROR;
1269 }
1270
1271 if (strcmp(reinterpret_cast<char *>(instanceData->fileBuf),
1272 reinterpret_cast<char *>(instanceData->streamBuf))) {
1273 instanceData->err <<
1274 "Error: data passed to NPP_Write and NPP_StreamAsFile differed";
1275 }
1276 }
1277 if (instanceData->frame.length() > 0 &&
1278 instanceData->testFunction != FUNCTION_NPP_GETURLNOTIFY &&
1279 instanceData->testFunction != FUNCTION_NPP_POSTURL) {
1280 sendBufferToFrame(instance);
1281 }
1282 if (instanceData->testFunction == FUNCTION_NPP_POSTURL) {
1283 NPError err = NPN_PostURL(instance, instanceData->testUrl.c_str(),
1284 instanceData->postMode == POSTMODE_FRAME ? instanceData->frame.c_str() : nullptr,
1285 instanceData->streamBufSize,
1286 reinterpret_cast<char *>(instanceData->streamBuf), false);
1287 if (err != NPERR_NO_ERROR)
1288 instanceData->err << "Error: NPN_PostURL returned error value " << err;
1289 }
1290 return NPERR_NO_ERROR;
1291 }
1292
1293 int32_t
1294 NPP_WriteReady(NPP instance, NPStream* stream)
1295 {
1296 printf("NPP_WriteReady\n");
1297 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1298 instanceData->writeReadyCount++;
1299 if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) {
1300 instanceData->err << "NPP_WriteReady called";
1301 }
1302
1303 // temporarily disabled per bug 519870
1304 //if (instanceData->writeReadyCount == 1) {
1305 // return 0;
1306 //}
1307
1308 return instanceData->streamChunkSize;
1309 }
1310
1311 int32_t
1312 NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer)
1313 {
1314 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1315 instanceData->writeCount++;
1316
1317 // temporarily disabled per bug 519870
1318 //if (instanceData->writeReadyCount == 1) {
1319 // instanceData->err << "NPP_Write called even though NPP_WriteReady " <<
1320 // "returned 0";
1321 //}
1322
1323 if (instanceData->functionToFail == FUNCTION_NPP_WRITE_RPC) {
1324 // Make an RPC call and pretend to consume the data
1325 NPObject* windowObject = nullptr;
1326 NPN_GetValue(instance, NPNVWindowNPObject, &windowObject);
1327 if (windowObject)
1328 NPN_ReleaseObject(windowObject);
1329
1330 return len;
1331 }
1332
1333 if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) {
1334 instanceData->err << "NPP_Write called";
1335 }
1336
1337 if (instanceData->functionToFail == FUNCTION_NPP_WRITE) {
1338 return -1;
1339 }
1340
1341 URLNotifyData* nd = static_cast<URLNotifyData*>(stream->notifyData);
1342
1343 if (nd && nd->writeCallback) {
1344 NPVariant args[1];
1345 STRINGN_TO_NPVARIANT(stream->url, strlen(stream->url), args[0]);
1346
1347 NPVariant result;
1348 NPN_InvokeDefault(instance, nd->writeCallback, args, 1, &result);
1349 NPN_ReleaseVariantValue(&result);
1350 }
1351
1352 if (nd && nd != &kNotifyData) {
1353 uint32_t newsize = nd->size + len;
1354 nd->data = (char*) realloc(nd->data, newsize);
1355 memcpy(nd->data + nd->size, buffer, len);
1356 nd->size = newsize;
1357 return len;
1358 }
1359
1360 if (instanceData->closeStream) {
1361 instanceData->closeStream = false;
1362 if (instanceData->testrange != nullptr) {
1363 NPN_RequestRead(stream, instanceData->testrange);
1364 }
1365 NPN_DestroyStream(instance, stream, NPRES_USER_BREAK);
1366 }
1367 else if (instanceData->streamMode == NP_SEEK &&
1368 stream->end != 0 &&
1369 stream->end == ((uint32_t)instanceData->streamBufSize + len)) {
1370 // If the complete stream has been written, and we're doing a seek test,
1371 // then call NPN_RequestRead.
1372 // prevent recursion
1373 instanceData->streamMode = NP_NORMAL;
1374
1375 if (instanceData->testrange != nullptr) {
1376 NPError err = NPN_RequestRead(stream, instanceData->testrange);
1377 if (err != NPERR_NO_ERROR) {
1378 instanceData->err << "NPN_RequestRead returned error %d" << err;
1379 }
1380 printf("called NPN_RequestRead, return %d\n", err);
1381 }
1382 }
1383
1384 char* streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
1385 if (offset + len <= instanceData->streamBufSize) {
1386 if (memcmp(buffer, streamBuf + offset, len)) {
1387 instanceData->err <<
1388 "Error: data written from NPN_RequestRead doesn't match";
1389 }
1390 else {
1391 printf("data matches!\n");
1392 }
1393 TestRange* range = instanceData->testrange;
1394 bool stillwaiting = false;
1395 while(range != nullptr) {
1396 if (offset == range->offset &&
1397 (uint32_t)len == range->length) {
1398 range->waiting = false;
1399 }
1400 if (range->waiting) stillwaiting = true;
1401 range = reinterpret_cast<TestRange*>(range->next);
1402 }
1403 if (!stillwaiting) {
1404 NPError err = NPN_DestroyStream(instance, stream, NPRES_DONE);
1405 if (err != NPERR_NO_ERROR) {
1406 instanceData->err << "Error: NPN_DestroyStream returned " << err;
1407 }
1408 }
1409 }
1410 else {
1411 if (instanceData->streamBufSize == 0) {
1412 instanceData->streamBuf = malloc(len + 1);
1413 streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
1414 }
1415 else {
1416 instanceData->streamBuf =
1417 realloc(reinterpret_cast<char *>(instanceData->streamBuf),
1418 instanceData->streamBufSize + len + 1);
1419 streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
1420 }
1421 memcpy(streamBuf + instanceData->streamBufSize, buffer, len);
1422 instanceData->streamBufSize = instanceData->streamBufSize + len;
1423 streamBuf[instanceData->streamBufSize] = '\0';
1424 }
1425 return len;
1426 }
1427
1428 void
1429 NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
1430 {
1431 printf("NPP_StreamAsFile, file=%s\n", fname);
1432 size_t size;
1433
1434 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1435
1436 if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM ||
1437 instanceData->functionToFail == FUNCTION_NPP_WRITE) {
1438 instanceData->err << "NPP_StreamAsFile called";
1439 }
1440
1441 if (!fname)
1442 return;
1443
1444 FILE *file = fopen(fname, "rb");
1445 if (file) {
1446 fseek(file, 0, SEEK_END);
1447 size = ftell(file);
1448 instanceData->fileBuf = malloc((int32_t)size + 1);
1449 char* buf = reinterpret_cast<char *>(instanceData->fileBuf);
1450 fseek(file, 0, SEEK_SET);
1451 size_t sizeRead = fread(instanceData->fileBuf, 1, size, file);
1452 if (sizeRead != size) {
1453 printf("Unable to read data from file\n");
1454 instanceData->err << "Unable to read data from file " << fname;
1455 }
1456 fclose(file);
1457 buf[size] = '\0';
1458 instanceData->fileBufSize = (int32_t)size;
1459 }
1460 else {
1461 printf("Unable to open file\n");
1462 instanceData->err << "Unable to open file " << fname;
1463 }
1464 }
1465
1466 void
1467 NPP_Print(NPP instance, NPPrint* platformPrint)
1468 {
1469 }
1470
1471 int16_t
1472 NPP_HandleEvent(NPP instance, void* event)
1473 {
1474 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1475 return pluginHandleEvent(instanceData, event);
1476 }
1477
1478 void
1479 NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
1480 {
1481 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1482 URLNotifyData* ndata = static_cast<URLNotifyData*>(notifyData);
1483
1484 printf("NPP_URLNotify called\n");
1485 if (&kNotifyData == ndata) {
1486 if (instanceData->frame.length() > 0) {
1487 sendBufferToFrame(instance);
1488 }
1489 }
1490 else if (!strcmp(ndata->cookie, "dynamic-cookie")) {
1491 if (ndata->notifyCallback) {
1492 NPVariant args[2];
1493 INT32_TO_NPVARIANT(reason, args[0]);
1494 if (ndata->data) {
1495 STRINGN_TO_NPVARIANT(ndata->data, ndata->size, args[1]);
1496 }
1497 else {
1498 STRINGN_TO_NPVARIANT("", 0, args[1]);
1499 }
1500
1501 NPVariant result;
1502 NPN_InvokeDefault(instance, ndata->notifyCallback, args, 2, &result);
1503 NPN_ReleaseVariantValue(&result);
1504 }
1505
1506 // clean up the URLNotifyData
1507 if (ndata->writeCallback) {
1508 NPN_ReleaseObject(ndata->writeCallback);
1509 }
1510 if (ndata->notifyCallback) {
1511 NPN_ReleaseObject(ndata->notifyCallback);
1512 }
1513 if (ndata->redirectCallback) {
1514 NPN_ReleaseObject(ndata->redirectCallback);
1515 }
1516 free(ndata->data);
1517 delete ndata;
1518 }
1519 else {
1520 printf("ERROR! NPP_URLNotify called with wrong cookie\n");
1521 instanceData->err << "Error: NPP_URLNotify called with wrong cookie";
1522 }
1523 }
1524
1525 NPError
1526 NPP_GetValue(NPP instance, NPPVariable variable, void* value)
1527 {
1528 InstanceData* instanceData = (InstanceData*)instance->pdata;
1529 if (variable == NPPVpluginScriptableNPObject) {
1530 NPObject* object = instanceData->scriptableObject;
1531 NPN_RetainObject(object);
1532 *((NPObject**)value) = object;
1533 return NPERR_NO_ERROR;
1534 }
1535 if (variable == NPPVpluginNeedsXEmbed) {
1536 // Only relevant for X plugins
1537 // use 4-byte writes like some plugins may do
1538 *(uint32_t*)value = instanceData->hasWidget;
1539 return NPERR_NO_ERROR;
1540 }
1541 if (variable == NPPVpluginWantsAllNetworkStreams) {
1542 // use 4-byte writes like some plugins may do
1543 *(uint32_t*)value = instanceData->wantsAllStreams;
1544 return NPERR_NO_ERROR;
1545 }
1546
1547 return NPERR_GENERIC_ERROR;
1548 }
1549
1550 NPError
1551 NPP_SetValue(NPP instance, NPNVariable variable, void* value)
1552 {
1553 if (variable == NPNVprivateModeBool) {
1554 InstanceData* instanceData = (InstanceData*)(instance->pdata);
1555 instanceData->lastReportedPrivateModeState = bool(*static_cast<NPBool*>(value));
1556 return NPERR_NO_ERROR;
1557 }
1558 return NPERR_GENERIC_ERROR;
1559 }
1560
1561 void
1562 NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData)
1563 {
1564 if (notifyData) {
1565 URLNotifyData* nd = static_cast<URLNotifyData*>(notifyData);
1566 if (nd->redirectCallback) {
1567 NPVariant args[2];
1568 STRINGN_TO_NPVARIANT(url, strlen(url), args[0]);
1569 INT32_TO_NPVARIANT(status, args[1]);
1570
1571 NPVariant result;
1572 NPN_InvokeDefault(instance, nd->redirectCallback, args, 2, &result);
1573 NPN_ReleaseVariantValue(&result);
1574 }
1575 NPN_URLRedirectResponse(instance, notifyData, nd->allowRedirects);
1576 return;
1577 }
1578 NPN_URLRedirectResponse(instance, notifyData, true);
1579 }
1580
1581 NPError
1582 NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge)
1583 {
1584 if (!sSitesWithData)
1585 return NPERR_NO_ERROR;
1586
1587 // Error condition: no support for clear-by-age
1588 if (!sClearByAgeSupported && maxAge != uint64_t(int64_t(-1)))
1589 return NPERR_TIME_RANGE_NOT_SUPPORTED;
1590
1591 // Iterate over list and remove matches
1592 list<siteData>::iterator iter = sSitesWithData->begin();
1593 list<siteData>::iterator end = sSitesWithData->end();
1594 while (iter != end) {
1595 const siteData& data = *iter;
1596 list<siteData>::iterator next = iter;
1597 ++next;
1598 if ((!site || data.site.compare(site) == 0) &&
1599 (flags == NP_CLEAR_ALL || data.flags & flags) &&
1600 data.age <= maxAge) {
1601 sSitesWithData->erase(iter);
1602 }
1603 iter = next;
1604 }
1605
1606 return NPERR_NO_ERROR;
1607 }
1608
1609 char**
1610 NPP_GetSitesWithData()
1611 {
1612 int length = 0;
1613 char** result;
1614
1615 if (sSitesWithData)
1616 length = sSitesWithData->size();
1617
1618 // Allocate the maximum possible size the list could be.
1619 result = static_cast<char**>(NPN_MemAlloc((length + 1) * sizeof(char*)));
1620 result[length] = nullptr;
1621
1622 if (length == 0) {
1623 // Represent the no site data case as an array of length 1 with a nullptr
1624 // entry.
1625 return result;
1626 }
1627
1628 // Iterate the list of stored data, and build a list of strings.
1629 list<string> sites;
1630 {
1631 list<siteData>::iterator iter = sSitesWithData->begin();
1632 list<siteData>::iterator end = sSitesWithData->end();
1633 for (; iter != end; ++iter) {
1634 const siteData& data = *iter;
1635 sites.push_back(data.site);
1636 }
1637 }
1638
1639 // Remove duplicate strings.
1640 sites.sort();
1641 sites.unique();
1642
1643 // Add strings to the result array, and null terminate.
1644 {
1645 int i = 0;
1646 list<string>::iterator iter = sites.begin();
1647 list<string>::iterator end = sites.end();
1648 for (; iter != end; ++iter, ++i) {
1649 const string& site = *iter;
1650 result[i] = static_cast<char*>(NPN_MemAlloc(site.length() + 1));
1651 memcpy(result[i], site.c_str(), site.length() + 1);
1652 }
1653 }
1654 result[sites.size()] = nullptr;
1655
1656 return result;
1657 }
1658
1659 //
1660 // npapi browser functions
1661 //
1662
1663 bool
1664 NPN_SetProperty(NPP instance, NPObject* obj, NPIdentifier propertyName, const NPVariant* value)
1665 {
1666 return sBrowserFuncs->setproperty(instance, obj, propertyName, value);
1667 }
1668
1669 NPIdentifier
1670 NPN_GetIntIdentifier(int32_t intid)
1671 {
1672 return sBrowserFuncs->getintidentifier(intid);
1673 }
1674
1675 NPIdentifier
1676 NPN_GetStringIdentifier(const NPUTF8* name)
1677 {
1678 return sBrowserFuncs->getstringidentifier(name);
1679 }
1680
1681 void
1682 NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
1683 {
1684 return sBrowserFuncs->getstringidentifiers(names, nameCount, identifiers);
1685 }
1686
1687 bool
1688 NPN_IdentifierIsString(NPIdentifier identifier)
1689 {
1690 return sBrowserFuncs->identifierisstring(identifier);
1691 }
1692
1693 NPUTF8*
1694 NPN_UTF8FromIdentifier(NPIdentifier identifier)
1695 {
1696 return sBrowserFuncs->utf8fromidentifier(identifier);
1697 }
1698
1699 int32_t
1700 NPN_IntFromIdentifier(NPIdentifier identifier)
1701 {
1702 return sBrowserFuncs->intfromidentifier(identifier);
1703 }
1704
1705 NPError
1706 NPN_GetValue(NPP instance, NPNVariable variable, void* value)
1707 {
1708 return sBrowserFuncs->getvalue(instance, variable, value);
1709 }
1710
1711 NPError
1712 NPN_SetValue(NPP instance, NPPVariable variable, void* value)
1713 {
1714 return sBrowserFuncs->setvalue(instance, variable, value);
1715 }
1716
1717 void
1718 NPN_InvalidateRect(NPP instance, NPRect* rect)
1719 {
1720 sBrowserFuncs->invalidaterect(instance, rect);
1721 }
1722
1723 bool
1724 NPN_HasProperty(NPP instance, NPObject* obj, NPIdentifier propertyName)
1725 {
1726 return sBrowserFuncs->hasproperty(instance, obj, propertyName);
1727 }
1728
1729 NPObject*
1730 NPN_CreateObject(NPP instance, NPClass* aClass)
1731 {
1732 return sBrowserFuncs->createobject(instance, aClass);
1733 }
1734
1735 bool
1736 NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
1737 {
1738 return sBrowserFuncs->invoke(npp, obj, methodName, args, argCount, result);
1739 }
1740
1741 bool
1742 NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result)
1743 {
1744 return sBrowserFuncs->invokeDefault(npp, obj, args, argCount, result);
1745 }
1746
1747 bool
1748 NPN_Construct(NPP npp, NPObject* npobj, const NPVariant* args,
1749 uint32_t argCount, NPVariant* result)
1750 {
1751 return sBrowserFuncs->construct(npp, npobj, args, argCount, result);
1752 }
1753
1754 const char*
1755 NPN_UserAgent(NPP instance)
1756 {
1757 return sBrowserFuncs->uagent(instance);
1758 }
1759
1760 NPObject*
1761 NPN_RetainObject(NPObject* obj)
1762 {
1763 return sBrowserFuncs->retainobject(obj);
1764 }
1765
1766 void
1767 NPN_ReleaseObject(NPObject* obj)
1768 {
1769 return sBrowserFuncs->releaseobject(obj);
1770 }
1771
1772 void*
1773 NPN_MemAlloc(uint32_t size)
1774 {
1775 return sBrowserFuncs->memalloc(size);
1776 }
1777
1778 char*
1779 NPN_StrDup(const char* str)
1780 {
1781 return strcpy((char*)sBrowserFuncs->memalloc(strlen(str) + 1), str);
1782 }
1783
1784 void
1785 NPN_MemFree(void* ptr)
1786 {
1787 return sBrowserFuncs->memfree(ptr);
1788 }
1789
1790 uint32_t
1791 NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
1792 {
1793 return sBrowserFuncs->scheduletimer(instance, interval, repeat, timerFunc);
1794 }
1795
1796 void
1797 NPN_UnscheduleTimer(NPP instance, uint32_t timerID)
1798 {
1799 return sBrowserFuncs->unscheduletimer(instance, timerID);
1800 }
1801
1802 void
1803 NPN_ReleaseVariantValue(NPVariant *variant)
1804 {
1805 return sBrowserFuncs->releasevariantvalue(variant);
1806 }
1807
1808 NPError
1809 NPN_GetURLNotify(NPP instance, const char* url, const char* target, void* notifyData)
1810 {
1811 return sBrowserFuncs->geturlnotify(instance, url, target, notifyData);
1812 }
1813
1814 NPError
1815 NPN_GetURL(NPP instance, const char* url, const char* target)
1816 {
1817 return sBrowserFuncs->geturl(instance, url, target);
1818 }
1819
1820 NPError
1821 NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
1822 {
1823 return sBrowserFuncs->requestread(stream, rangeList);
1824 }
1825
1826 NPError
1827 NPN_PostURLNotify(NPP instance, const char* url,
1828 const char* target, uint32_t len,
1829 const char* buf, NPBool file, void* notifyData)
1830 {
1831 return sBrowserFuncs->posturlnotify(instance, url, target, len, buf, file, notifyData);
1832 }
1833
1834 NPError
1835 NPN_PostURL(NPP instance, const char *url,
1836 const char *target, uint32_t len,
1837 const char *buf, NPBool file)
1838 {
1839 return sBrowserFuncs->posturl(instance, url, target, len, buf, file);
1840 }
1841
1842 NPError
1843 NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
1844 {
1845 return sBrowserFuncs->destroystream(instance, stream, reason);
1846 }
1847
1848 NPError
1849 NPN_NewStream(NPP instance,
1850 NPMIMEType type,
1851 const char* target,
1852 NPStream** stream)
1853 {
1854 return sBrowserFuncs->newstream(instance, type, target, stream);
1855 }
1856
1857 int32_t
1858 NPN_Write(NPP instance,
1859 NPStream* stream,
1860 int32_t len,
1861 void* buf)
1862 {
1863 return sBrowserFuncs->write(instance, stream, len, buf);
1864 }
1865
1866 bool
1867 NPN_Enumerate(NPP instance,
1868 NPObject *npobj,
1869 NPIdentifier **identifiers,
1870 uint32_t *identifierCount)
1871 {
1872 return sBrowserFuncs->enumerate(instance, npobj, identifiers,
1873 identifierCount);
1874 }
1875
1876 bool
1877 NPN_GetProperty(NPP instance,
1878 NPObject *npobj,
1879 NPIdentifier propertyName,
1880 NPVariant *result)
1881 {
1882 return sBrowserFuncs->getproperty(instance, npobj, propertyName, result);
1883 }
1884
1885 bool
1886 NPN_Evaluate(NPP instance, NPObject *npobj, NPString *script, NPVariant *result)
1887 {
1888 return sBrowserFuncs->evaluate(instance, npobj, script, result);
1889 }
1890
1891 void
1892 NPN_SetException(NPObject *npobj, const NPUTF8 *message)
1893 {
1894 return sBrowserFuncs->setexception(npobj, message);
1895 }
1896
1897 NPBool
1898 NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
1899 {
1900 return sBrowserFuncs->convertpoint(instance, sourceX, sourceY, sourceSpace, destX, destY, destSpace);
1901 }
1902
1903 NPError
1904 NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char *url, const char *value, uint32_t len)
1905 {
1906 return sBrowserFuncs->setvalueforurl(instance, variable, url, value, len);
1907 }
1908
1909 NPError
1910 NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char *url, char **value, uint32_t *len)
1911 {
1912 return sBrowserFuncs->getvalueforurl(instance, variable, url, value, len);
1913 }
1914
1915 NPError
1916 NPN_GetAuthenticationInfo(NPP instance,
1917 const char *protocol,
1918 const char *host, int32_t port,
1919 const char *scheme,
1920 const char *realm,
1921 char **username, uint32_t *ulen,
1922 char **password,
1923 uint32_t *plen)
1924 {
1925 return sBrowserFuncs->getauthenticationinfo(instance, protocol, host, port, scheme, realm,
1926 username, ulen, password, plen);
1927 }
1928
1929 void
1930 NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void*), void* userdata)
1931 {
1932 return sBrowserFuncs->pluginthreadasynccall(plugin, func, userdata);
1933 }
1934
1935 void
1936 NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow)
1937 {
1938 return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow);
1939 }
1940
1941 NPError
1942 NPN_InitAsyncSurface(NPP instance, NPSize *size, NPImageFormat format,
1943 void *initData, NPAsyncSurface *surface)
1944 {
1945 return sBrowserFuncs->initasyncsurface(instance, size, format, initData, surface);
1946 }
1947
1948 NPError
1949 NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface)
1950 {
1951 return sBrowserFuncs->finalizeasyncsurface(instance, surface);
1952 }
1953
1954 void
1955 NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
1956 {
1957 sBrowserFuncs->setcurrentasyncsurface(instance, surface, changed);
1958 }
1959
1960 //
1961 // npruntime object functions
1962 //
1963
1964 NPObject*
1965 scriptableAllocate(NPP npp, NPClass* aClass)
1966 {
1967 TestNPObject* object = (TestNPObject*)NPN_MemAlloc(sizeof(TestNPObject));
1968 if (!object)
1969 return nullptr;
1970 memset(object, 0, sizeof(TestNPObject));
1971 return object;
1972 }
1973
1974 void
1975 scriptableDeallocate(NPObject* npobj)
1976 {
1977 NPN_MemFree(npobj);
1978 }
1979
1980 void
1981 scriptableInvalidate(NPObject* npobj)
1982 {
1983 }
1984
1985 bool
1986 scriptableHasMethod(NPObject* npobj, NPIdentifier name)
1987 {
1988 for (int i = 0; i < int(ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) {
1989 if (name == sPluginMethodIdentifiers[i])
1990 return true;
1991 }
1992 return false;
1993 }
1994
1995 bool
1996 scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
1997 {
1998 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
1999 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2000 if (id->throwOnNextInvoke) {
2001 id->throwOnNextInvoke = false;
2002 if (argCount == 0) {
2003 NPN_SetException(npobj, nullptr);
2004 }
2005 else {
2006 for (uint32_t i = 0; i < argCount; i++) {
2007 const NPString* argstr = &NPVARIANT_TO_STRING(args[i]);
2008 NPN_SetException(npobj, argstr->UTF8Characters);
2009 }
2010 }
2011 return false;
2012 }
2013
2014 for (int i = 0; i < int(ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) {
2015 if (name == sPluginMethodIdentifiers[i])
2016 return sPluginMethodFunctions[i](npobj, args, argCount, result);
2017 }
2018 return false;
2019 }
2020
2021 bool
2022 scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2023 {
2024 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2025 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2026 if (id->throwOnNextInvoke) {
2027 id->throwOnNextInvoke = false;
2028 if (argCount == 0) {
2029 NPN_SetException(npobj, nullptr);
2030 }
2031 else {
2032 for (uint32_t i = 0; i < argCount; i++) {
2033 const NPString* argstr = &NPVARIANT_TO_STRING(args[i]);
2034 NPN_SetException(npobj, argstr->UTF8Characters);
2035 }
2036 }
2037 return false;
2038 }
2039
2040 ostringstream value;
2041 value << sPluginName;
2042 for (uint32_t i = 0; i < argCount; i++) {
2043 switch(args[i].type) {
2044 case NPVariantType_Int32:
2045 value << ";" << NPVARIANT_TO_INT32(args[i]);
2046 break;
2047 case NPVariantType_String: {
2048 const NPString* argstr = &NPVARIANT_TO_STRING(args[i]);
2049 value << ";" << argstr->UTF8Characters;
2050 break;
2051 }
2052 case NPVariantType_Void:
2053 value << ";undefined";
2054 break;
2055 case NPVariantType_Null:
2056 value << ";null";
2057 break;
2058 default:
2059 value << ";other";
2060 }
2061 }
2062
2063 char *outval = NPN_StrDup(value.str().c_str());
2064 STRINGZ_TO_NPVARIANT(outval, *result);
2065 return true;
2066 }
2067
2068 bool
2069 scriptableHasProperty(NPObject* npobj, NPIdentifier name)
2070 {
2071 if (NPN_IdentifierIsString(name)) {
2072 NPUTF8 *asUTF8 = NPN_UTF8FromIdentifier(name);
2073 if (NPN_GetStringIdentifier(asUTF8) != name) {
2074 Crash();
2075 }
2076 NPN_MemFree(asUTF8);
2077 }
2078 else {
2079 if (NPN_GetIntIdentifier(NPN_IntFromIdentifier(name)) != name) {
2080 Crash();
2081 }
2082 }
2083 for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
2084 if (name == sPluginPropertyIdentifiers[i]) {
2085 return true;
2086 }
2087 }
2088 return false;
2089 }
2090
2091 bool
2092 scriptableGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result)
2093 {
2094 for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
2095 if (name == sPluginPropertyIdentifiers[i]) {
2096 DuplicateNPVariant(*result, sPluginPropertyValues[i]);
2097 return true;
2098 }
2099 }
2100 return false;
2101 }
2102
2103 bool
2104 scriptableSetProperty(NPObject* npobj, NPIdentifier name, const NPVariant* value)
2105 {
2106 for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
2107 if (name == sPluginPropertyIdentifiers[i]) {
2108 NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
2109 DuplicateNPVariant(sPluginPropertyValues[i], *value);
2110 return true;
2111 }
2112 }
2113 return false;
2114 }
2115
2116 bool
2117 scriptableRemoveProperty(NPObject* npobj, NPIdentifier name)
2118 {
2119 for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
2120 if (name == sPluginPropertyIdentifiers[i]) {
2121 NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
2122 return true;
2123 }
2124 }
2125 return false;
2126 }
2127
2128 bool
2129 scriptableEnumerate(NPObject* npobj, NPIdentifier** identifier, uint32_t* count)
2130 {
2131 const int bufsize = sizeof(NPIdentifier) * ARRAY_LENGTH(sPluginMethodIdentifierNames);
2132 NPIdentifier* ids = (NPIdentifier*) NPN_MemAlloc(bufsize);
2133 if (!ids)
2134 return false;
2135
2136 memcpy(ids, sPluginMethodIdentifiers, bufsize);
2137 *identifier = ids;
2138 *count = ARRAY_LENGTH(sPluginMethodIdentifierNames);
2139 return true;
2140 }
2141
2142 bool
2143 scriptableConstruct(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2144 {
2145 return false;
2146 }
2147
2148 //
2149 // test functions
2150 //
2151
2152 static bool
2153 compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2)
2154 {
2155 bool success = true;
2156 InstanceData* id = static_cast<InstanceData*>(instance->pdata);
2157 if (var1->type != var2->type) {
2158 id->err << "Variant types don't match; got " << var1->type <<
2159 " expected " << var2->type;
2160 return false;
2161 }
2162
2163 switch (var1->type) {
2164 case NPVariantType_Int32: {
2165 int32_t result = NPVARIANT_TO_INT32(*var1);
2166 int32_t expected = NPVARIANT_TO_INT32(*var2);
2167 if (result != expected) {
2168 id->err << "Variant values don't match; got " << result <<
2169 " expected " << expected;
2170 success = false;
2171 }
2172 break;
2173 }
2174 case NPVariantType_Double: {
2175 double result = NPVARIANT_TO_DOUBLE(*var1);
2176 double expected = NPVARIANT_TO_DOUBLE(*var2);
2177 if (result != expected) {
2178 id->err << "Variant values don't match (double)";
2179 success = false;
2180 }
2181 break;
2182 }
2183 case NPVariantType_Void: {
2184 // void values are always equivalent
2185 break;
2186 }
2187 case NPVariantType_Null: {
2188 // null values are always equivalent
2189 break;
2190 }
2191 case NPVariantType_Bool: {
2192 bool result = NPVARIANT_TO_BOOLEAN(*var1);
2193 bool expected = NPVARIANT_TO_BOOLEAN(*var2);
2194 if (result != expected) {
2195 id->err << "Variant values don't match (bool)";
2196 success = false;
2197 }
2198 break;
2199 }
2200 case NPVariantType_String: {
2201 const NPString* result = &NPVARIANT_TO_STRING(*var1);
2202 const NPString* expected = &NPVARIANT_TO_STRING(*var2);
2203 if (strcmp(result->UTF8Characters, expected->UTF8Characters) ||
2204 strlen(result->UTF8Characters) != strlen(expected->UTF8Characters)) {
2205 id->err << "Variant values don't match; got " <<
2206 result->UTF8Characters << " expected " <<
2207 expected->UTF8Characters;
2208 success = false;
2209 }
2210 break;
2211 }
2212 case NPVariantType_Object: {
2213 uint32_t i, identifierCount = 0;
2214 NPIdentifier* identifiers;
2215 NPObject* result = NPVARIANT_TO_OBJECT(*var1);
2216 NPObject* expected = NPVARIANT_TO_OBJECT(*var2);
2217 bool enumerate_result = NPN_Enumerate(instance, expected,
2218 &identifiers, &identifierCount);
2219 if (!enumerate_result) {
2220 id->err << "NPN_Enumerate failed";
2221 success = false;
2222 }
2223 for (i = 0; i < identifierCount; i++) {
2224 NPVariant resultVariant, expectedVariant;
2225 if (!NPN_GetProperty(instance, expected, identifiers[i],
2226 &expectedVariant)) {
2227 id->err << "NPN_GetProperty returned false";
2228 success = false;
2229 }
2230 else {
2231 if (!NPN_HasProperty(instance, result, identifiers[i])) {
2232 id->err << "NPN_HasProperty returned false";
2233 success = false;
2234 }
2235 else {
2236 if (!NPN_GetProperty(instance, result, identifiers[i],
2237 &resultVariant)) {
2238 id->err << "NPN_GetProperty 2 returned false";
2239 success = false;
2240 }
2241 else {
2242 success = compareVariants(instance, &resultVariant,
2243 &expectedVariant);
2244 NPN_ReleaseVariantValue(&expectedVariant);
2245 }
2246 }
2247 NPN_ReleaseVariantValue(&resultVariant);
2248 }
2249 }
2250 break;
2251 }
2252 default:
2253 id->err << "Unknown variant type";
2254 success = false;
2255 }
2256
2257 return success;
2258 }
2259
2260 static bool
2261 throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2262 {
2263 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2264 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2265 id->throwOnNextInvoke = true;
2266 BOOLEAN_TO_NPVARIANT(true, *result);
2267 return true;
2268 }
2269
2270 static bool
2271 npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2272 {
2273 bool success = false;
2274 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2275
2276 NPObject* windowObject;
2277 NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
2278 if (!windowObject)
2279 return false;
2280
2281 NPIdentifier objectIdentifier = variantToIdentifier(args[0]);
2282 if (!objectIdentifier)
2283 return false;
2284
2285 NPVariant objectVariant;
2286 if (NPN_GetProperty(npp, windowObject, objectIdentifier,
2287 &objectVariant)) {
2288 if (NPVARIANT_IS_OBJECT(objectVariant)) {
2289 NPObject* selfObject = NPVARIANT_TO_OBJECT(objectVariant);
2290 if (selfObject != nullptr) {
2291 NPVariant resultVariant;
2292 if (NPN_InvokeDefault(npp, selfObject, argCount > 1 ? &args[1] : nullptr,
2293 argCount - 1, &resultVariant)) {
2294 *result = resultVariant;
2295 success = true;
2296 }
2297 }
2298 }
2299 NPN_ReleaseVariantValue(&objectVariant);
2300 }
2301
2302 NPN_ReleaseObject(windowObject);
2303 return success;
2304 }
2305
2306 static bool
2307 npnInvokeTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2308 {
2309 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2310 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2311 id->err.str("");
2312 if (argCount < 2)
2313 return false;
2314
2315 NPIdentifier function = variantToIdentifier(args[0]);
2316 if (!function)
2317 return false;
2318
2319 NPObject* windowObject;
2320 NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
2321 if (!windowObject)
2322 return false;
2323
2324 NPVariant invokeResult;
2325 bool invokeReturn = NPN_Invoke(npp, windowObject, function,
2326 argCount > 2 ? &args[2] : nullptr, argCount - 2, &invokeResult);
2327
2328 bool compareResult = compareVariants(npp, &invokeResult, &args[1]);
2329
2330 NPN_ReleaseObject(windowObject);
2331 NPN_ReleaseVariantValue(&invokeResult);
2332 BOOLEAN_TO_NPVARIANT(invokeReturn && compareResult, *result);
2333 return true;
2334 }
2335
2336 static bool
2337 npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2338 {
2339 bool success = false;
2340 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2341
2342 if (argCount != 1)
2343 return false;
2344
2345 if (!NPVARIANT_IS_STRING(args[0]))
2346 return false;
2347
2348 NPObject* windowObject;
2349 NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
2350 if (!windowObject)
2351 return false;
2352
2353 success = NPN_Evaluate(npp, windowObject, (NPString*)&NPVARIANT_TO_STRING(args[0]), result);
2354
2355 NPN_ReleaseObject(windowObject);
2356 return success;
2357 }
2358
2359 static bool
2360 setUndefinedValueTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2361 {
2362 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2363 NPError err = NPN_SetValue(npp, (NPPVariable)0x0, 0x0);
2364 BOOLEAN_TO_NPVARIANT((err == NPERR_NO_ERROR), *result);
2365 return true;
2366 }
2367
2368 static bool
2369 identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2370 {
2371 if (argCount != 1)
2372 return false;
2373 NPIdentifier identifier = variantToIdentifier(args[0]);
2374 if (!identifier)
2375 return false;
2376
2377 NPUTF8* utf8String = NPN_UTF8FromIdentifier(identifier);
2378 if (!utf8String)
2379 return false;
2380 STRINGZ_TO_NPVARIANT(utf8String, *result);
2381 return true;
2382 }
2383
2384 static bool
2385 queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2386 {
2387 if (argCount != 0)
2388 return false;
2389
2390 NPBool pms = false;
2391 NPN_GetValue(static_cast<TestNPObject*>(npobj)->npp, NPNVprivateModeBool, &pms);
2392 BOOLEAN_TO_NPVARIANT(pms, *result);
2393 return true;
2394 }
2395
2396 static bool
2397 lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2398 {
2399 if (argCount != 0)
2400 return false;
2401
2402 InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
2403 BOOLEAN_TO_NPVARIANT(id->lastReportedPrivateModeState, *result);
2404 return true;
2405 }
2406
2407 static bool
2408 hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2409 {
2410 if (argCount != 0)
2411 return false;
2412
2413 InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
2414 BOOLEAN_TO_NPVARIANT(id->hasWidget, *result);
2415 return true;
2416 }
2417
2418 static bool
2419 getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2420 {
2421 if (argCount != 1)
2422 return false;
2423 if (!NPVARIANT_IS_INT32(args[0]))
2424 return false;
2425 int32_t edge = NPVARIANT_TO_INT32(args[0]);
2426 if (edge < EDGE_LEFT || edge > EDGE_BOTTOM)
2427 return false;
2428
2429 InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
2430 int32_t r = pluginGetEdge(id, RectEdge(edge));
2431 if (r == NPTEST_INT32_ERROR)
2432 return false;
2433 INT32_TO_NPVARIANT(r, *result);
2434 return true;
2435 }
2436
2437 static bool
2438 getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2439 {
2440 if (argCount != 0)
2441 return false;
2442
2443 InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
2444 int32_t r = pluginGetClipRegionRectCount(id);
2445 if (r == NPTEST_INT32_ERROR)
2446 return false;
2447 INT32_TO_NPVARIANT(r, *result);
2448 return true;
2449 }
2450
2451 static bool
2452 getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2453 {
2454 if (argCount != 2)
2455 return false;
2456 if (!NPVARIANT_IS_INT32(args[0]))
2457 return false;
2458 int32_t rectIndex = NPVARIANT_TO_INT32(args[0]);
2459 if (rectIndex < 0)
2460 return false;
2461 if (!NPVARIANT_IS_INT32(args[1]))
2462 return false;
2463 int32_t edge = NPVARIANT_TO_INT32(args[1]);
2464 if (edge < EDGE_LEFT || edge > EDGE_BOTTOM)
2465 return false;
2466
2467 InstanceData* id = static_cast<InstanceData*>(static_cast<TestNPObject*>(npobj)->npp->pdata);
2468 int32_t r = pluginGetClipRegionRectEdge(id, rectIndex, RectEdge(edge));
2469 if (r == NPTEST_INT32_ERROR)
2470 return false;
2471 INT32_TO_NPVARIANT(r, *result);
2472 return true;
2473 }
2474
2475 static bool
2476 startWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2477 {
2478 if (argCount != 0)
2479 return false;
2480 if (sWatchingInstanceCount)
2481 return false;
2482
2483 sWatchingInstanceCount = true;
2484 sInstanceCount = 0;
2485 ++sCurrentInstanceCountWatchGeneration;
2486 return true;
2487 }
2488
2489 static bool
2490 getInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2491 {
2492 if (argCount != 0)
2493 return false;
2494 if (!sWatchingInstanceCount)
2495 return false;
2496
2497 INT32_TO_NPVARIANT(sInstanceCount, *result);
2498 return true;
2499 }
2500
2501 static bool
2502 stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2503 {
2504 if (argCount != 0)
2505 return false;
2506 if (!sWatchingInstanceCount)
2507 return false;
2508
2509 sWatchingInstanceCount = false;
2510 return true;
2511 }
2512
2513 static bool
2514 getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2515 {
2516 if (argCount != 0)
2517 return false;
2518
2519 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2520 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2521 INT32_TO_NPVARIANT(id->lastMouseX, *result);
2522 return true;
2523 }
2524
2525 static bool
2526 getLastMouseY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2527 {
2528 if (argCount != 0)
2529 return false;
2530
2531 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2532 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2533 INT32_TO_NPVARIANT(id->lastMouseY, *result);
2534 return true;
2535 }
2536
2537 static bool
2538 getPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2539 {
2540 if (argCount != 0)
2541 return false;
2542
2543 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2544 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2545 INT32_TO_NPVARIANT(id->paintCount, *result);
2546 return true;
2547 }
2548
2549 static bool
2550 getWidthAtLastPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2551 {
2552 if (argCount != 0)
2553 return false;
2554
2555 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2556 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2557 INT32_TO_NPVARIANT(id->widthAtLastPaint, *result);
2558 return true;
2559 }
2560
2561 static bool
2562 setInvalidateDuringPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2563 {
2564 if (argCount != 1)
2565 return false;
2566
2567 if (!NPVARIANT_IS_BOOLEAN(args[0]))
2568 return false;
2569 bool doInvalidate = NPVARIANT_TO_BOOLEAN(args[0]);
2570
2571 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2572 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2573 id->invalidateDuringPaint = doInvalidate;
2574 return true;
2575 }
2576
2577 static bool
2578 setSlowPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2579 {
2580 if (argCount != 1)
2581 return false;
2582
2583 if (!NPVARIANT_IS_BOOLEAN(args[0]))
2584 return false;
2585 bool slow = NPVARIANT_TO_BOOLEAN(args[0]);
2586
2587 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2588 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2589 id->slowPaint = slow;
2590 return true;
2591 }
2592
2593 static bool
2594 getError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2595 {
2596 if (argCount != 0)
2597 return false;
2598
2599 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2600 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2601 if (id->err.str().length() == 0) {
2602 char *outval = NPN_StrDup(SUCCESS_STRING);
2603 STRINGZ_TO_NPVARIANT(outval, *result);
2604 } else {
2605 char *outval = NPN_StrDup(id->err.str().c_str());
2606 STRINGZ_TO_NPVARIANT(outval, *result);
2607 }
2608 return true;
2609 }
2610
2611 static bool
2612 doInternalConsistencyCheck(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2613 {
2614 if (argCount != 0)
2615 return false;
2616
2617 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2618 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2619 string error;
2620 pluginDoInternalConsistencyCheck(id, error);
2621 NPUTF8* utf8String = (NPUTF8*)NPN_MemAlloc(error.length() + 1);
2622 if (!utf8String) {
2623 return false;
2624 }
2625 memcpy(utf8String, error.c_str(), error.length() + 1);
2626 STRINGZ_TO_NPVARIANT(utf8String, *result);
2627 return true;
2628 }
2629
2630 static bool
2631 convertPointX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2632 {
2633 if (argCount != 4)
2634 return false;
2635
2636 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2637
2638 if (!NPVARIANT_IS_INT32(args[0]))
2639 return false;
2640 int32_t sourceSpace = NPVARIANT_TO_INT32(args[0]);
2641
2642 if (!NPVARIANT_IS_INT32(args[1]))
2643 return false;
2644 double sourceX = static_cast<double>(NPVARIANT_TO_INT32(args[1]));
2645
2646 if (!NPVARIANT_IS_INT32(args[2]))
2647 return false;
2648 double sourceY = static_cast<double>(NPVARIANT_TO_INT32(args[2]));
2649
2650 if (!NPVARIANT_IS_INT32(args[3]))
2651 return false;
2652 int32_t destSpace = NPVARIANT_TO_INT32(args[3]);
2653
2654 double resultX, resultY;
2655 NPN_ConvertPoint(npp, sourceX, sourceY, (NPCoordinateSpace)sourceSpace, &resultX, &resultY, (NPCoordinateSpace)destSpace);
2656
2657 DOUBLE_TO_NPVARIANT(resultX, *result);
2658 return true;
2659 }
2660
2661 static bool
2662 convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2663 {
2664 if (argCount != 4)
2665 return false;
2666
2667 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2668
2669 if (!NPVARIANT_IS_INT32(args[0]))
2670 return false;
2671 int32_t sourceSpace = NPVARIANT_TO_INT32(args[0]);
2672
2673 if (!NPVARIANT_IS_INT32(args[1]))
2674 return false;
2675 double sourceX = static_cast<double>(NPVARIANT_TO_INT32(args[1]));
2676
2677 if (!NPVARIANT_IS_INT32(args[2]))
2678 return false;
2679 double sourceY = static_cast<double>(NPVARIANT_TO_INT32(args[2]));
2680
2681 if (!NPVARIANT_IS_INT32(args[3]))
2682 return false;
2683 int32_t destSpace = NPVARIANT_TO_INT32(args[3]);
2684
2685 double resultX, resultY;
2686 NPN_ConvertPoint(npp, sourceX, sourceY, (NPCoordinateSpace)sourceSpace, &resultX, &resultY, (NPCoordinateSpace)destSpace);
2687
2688 DOUBLE_TO_NPVARIANT(resultY, *result);
2689 return true;
2690 }
2691
2692 static bool
2693 streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2694 {
2695 // .streamTest(url, doPost, doNull, writeCallback, notifyCallback, redirectCallback, allowRedirects)
2696 if (7 != argCount)
2697 return false;
2698
2699 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2700
2701 if (!NPVARIANT_IS_STRING(args[0]))
2702 return false;
2703 NPString url = NPVARIANT_TO_STRING(args[0]);
2704
2705 if (!NPVARIANT_IS_BOOLEAN(args[1]))
2706 return false;
2707 bool doPost = NPVARIANT_TO_BOOLEAN(args[1]);
2708
2709 NPString postData = { nullptr, 0 };
2710 if (NPVARIANT_IS_STRING(args[2])) {
2711 postData = NPVARIANT_TO_STRING(args[2]);
2712 }
2713 else {
2714 if (!NPVARIANT_IS_NULL(args[2])) {
2715 return false;
2716 }
2717 }
2718
2719 NPObject* writeCallback = nullptr;
2720 if (NPVARIANT_IS_OBJECT(args[3])) {
2721 writeCallback = NPVARIANT_TO_OBJECT(args[3]);
2722 }
2723 else {
2724 if (!NPVARIANT_IS_NULL(args[3])) {
2725 return false;
2726 }
2727 }
2728
2729 NPObject* notifyCallback = nullptr;
2730 if (NPVARIANT_IS_OBJECT(args[4])) {
2731 notifyCallback = NPVARIANT_TO_OBJECT(args[4]);
2732 }
2733 else {
2734 if (!NPVARIANT_IS_NULL(args[4])) {
2735 return false;
2736 }
2737 }
2738
2739 NPObject* redirectCallback = nullptr;
2740 if (NPVARIANT_IS_OBJECT(args[5])) {
2741 redirectCallback = NPVARIANT_TO_OBJECT(args[5]);
2742 }
2743 else {
2744 if (!NPVARIANT_IS_NULL(args[5])) {
2745 return false;
2746 }
2747 }
2748
2749 if (!NPVARIANT_IS_BOOLEAN(args[6]))
2750 return false;
2751 bool allowRedirects = NPVARIANT_TO_BOOLEAN(args[6]);
2752
2753 URLNotifyData* ndata = new URLNotifyData;
2754 ndata->cookie = "dynamic-cookie";
2755 ndata->writeCallback = writeCallback;
2756 ndata->notifyCallback = notifyCallback;
2757 ndata->redirectCallback = redirectCallback;
2758 ndata->size = 0;
2759 ndata->data = nullptr;
2760 ndata->allowRedirects = allowRedirects;
2761
2762 /* null-terminate "url" */
2763 char* urlstr = (char*) malloc(url.UTF8Length + 1);
2764 strncpy(urlstr, url.UTF8Characters, url.UTF8Length);
2765 urlstr[url.UTF8Length] = '\0';
2766
2767 NPError err;
2768 if (doPost) {
2769 err = NPN_PostURLNotify(npp, urlstr, nullptr,
2770 postData.UTF8Length, postData.UTF8Characters,
2771 false, ndata);
2772 }
2773 else {
2774 err = NPN_GetURLNotify(npp, urlstr, nullptr, ndata);
2775 }
2776
2777 free(urlstr);
2778
2779 if (NPERR_NO_ERROR == err) {
2780 if (ndata->writeCallback) {
2781 NPN_RetainObject(ndata->writeCallback);
2782 }
2783 if (ndata->notifyCallback) {
2784 NPN_RetainObject(ndata->notifyCallback);
2785 }
2786 if (ndata->redirectCallback) {
2787 NPN_RetainObject(ndata->redirectCallback);
2788 }
2789 BOOLEAN_TO_NPVARIANT(true, *result);
2790 }
2791 else {
2792 delete ndata;
2793 BOOLEAN_TO_NPVARIANT(false, *result);
2794 }
2795
2796 return true;
2797 }
2798
2799 static bool
2800 setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2801 {
2802 if (1 != argCount)
2803 return false;
2804
2805 if (!NPVARIANT_IS_BOOLEAN(args[0]))
2806 return false;
2807 bool wantsAllStreams = NPVARIANT_TO_BOOLEAN(args[0]);
2808
2809 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2810 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2811
2812 id->wantsAllStreams = wantsAllStreams;
2813
2814 return true;
2815 }
2816
2817 static bool
2818 crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2819 {
2820 IntentionalCrash();
2821 VOID_TO_NPVARIANT(*result);
2822 return true;
2823 }
2824
2825 static bool
2826 crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2827 {
2828 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2829 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2830
2831 id->crashOnDestroy = true;
2832 VOID_TO_NPVARIANT(*result);
2833 return true;
2834 }
2835
2836 static bool
2837 setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2838 {
2839 if (argCount != 1)
2840 return false;
2841 if (!NPVARIANT_IS_STRING(args[0]))
2842 return false;
2843 const NPString* str = &NPVARIANT_TO_STRING(args[0]);
2844
2845 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2846 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2847
2848 id->scriptableObject->drawColor =
2849 parseHexColor(str->UTF8Characters, str->UTF8Length);
2850
2851 NPRect r;
2852 r.left = 0;
2853 r.top = 0;
2854 r.right = id->window.width;
2855 r.bottom = id->window.height;
2856 if (id->asyncDrawing == AD_NONE) {
2857 NPN_InvalidateRect(npp, &r);
2858 } else if (id->asyncDrawing == AD_BITMAP) {
2859 drawAsyncBitmapColor(id);
2860 }
2861 #ifdef XP_WIN
2862 else if (id->asyncDrawing == AD_DXGI) {
2863 pluginDrawAsyncDxgiColor(id);
2864 }
2865 #endif
2866
2867 VOID_TO_NPVARIANT(*result);
2868 return true;
2869 }
2870
2871 void notifyDidPaint(InstanceData* instanceData)
2872 {
2873 ++instanceData->paintCount;
2874 instanceData->widthAtLastPaint = instanceData->window.width;
2875
2876 if (instanceData->invalidateDuringPaint) {
2877 NPRect r;
2878 r.left = 0;
2879 r.top = 0;
2880 r.right = instanceData->window.width;
2881 r.bottom = instanceData->window.height;
2882 NPN_InvalidateRect(instanceData->npp, &r);
2883 }
2884
2885 if (instanceData->slowPaint) {
2886 XPSleep(1);
2887 }
2888
2889 if (instanceData->runScriptOnPaint) {
2890 NPObject* o = nullptr;
2891 NPN_GetValue(instanceData->npp, NPNVPluginElementNPObject, &o);
2892 if (o) {
2893 NPVariant param;
2894 STRINGZ_TO_NPVARIANT("paintscript", param);
2895 NPVariant result;
2896 NPN_Invoke(instanceData->npp, o, NPN_GetStringIdentifier("getAttribute"),
2897 &param, 1, &result);
2898
2899 if (NPVARIANT_IS_STRING(result)) {
2900 NPObject* windowObject;
2901 NPN_GetValue(instanceData->npp, NPNVWindowNPObject, &windowObject);
2902 if (windowObject) {
2903 NPVariant evalResult;
2904 NPN_Evaluate(instanceData->npp, windowObject,
2905 (NPString*)&NPVARIANT_TO_STRING(result), &evalResult);
2906 NPN_ReleaseVariantValue(&evalResult);
2907 NPN_ReleaseObject(windowObject);
2908 }
2909 }
2910
2911 NPN_ReleaseVariantValue(&result);
2912 NPN_ReleaseObject(o);
2913 }
2914 }
2915 }
2916
2917 static const NPClass kTestSharedNPClass = {
2918 NP_CLASS_STRUCT_VERSION,
2919 // Everything else is nullptr
2920 };
2921
2922 static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2923 {
2924 if (argCount != 0) {
2925 return false;
2926 }
2927
2928 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2929 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
2930
2931 char *outval = NPN_StrDup(id->javaCodebase.c_str());
2932 STRINGZ_TO_NPVARIANT(outval, *result);
2933 return true;
2934 }
2935
2936 static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2937 {
2938 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
2939
2940 NPObject* o = NPN_CreateObject(npp,
2941 const_cast<NPClass*>(&kTestSharedNPClass));
2942 if (!o)
2943 return false;
2944
2945 OBJECT_TO_NPVARIANT(o, *result);
2946 return true;
2947 }
2948
2949 static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2950 {
2951 VOID_TO_NPVARIANT(*result);
2952
2953 if (1 != argCount)
2954 return false;
2955
2956 if (!NPVARIANT_IS_OBJECT(args[0]))
2957 return false;
2958
2959 NPObject* o = NPVARIANT_TO_OBJECT(args[0]);
2960
2961 BOOLEAN_TO_NPVARIANT(o->_class == &kTestSharedNPClass, *result);
2962 return true;
2963 }
2964
2965 static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
2966 {
2967 VOID_TO_NPVARIANT(*result);
2968
2969 #if defined(XP_WIN) && defined(_M_IX86)
2970 _control87(0, _MCW_EM);
2971 return true;
2972 #else
2973 return false;
2974 #endif
2975 }
2976
2977 // caller is responsible for freeing return buffer
2978 static char* URLForInstanceWindow(NPP instance) {
2979 char *outString = nullptr;
2980
2981 NPObject* windowObject = nullptr;
2982 NPError err = NPN_GetValue(instance, NPNVWindowNPObject, &windowObject);
2983 if (err != NPERR_NO_ERROR || !windowObject)
2984 return nullptr;
2985
2986 NPIdentifier locationIdentifier = NPN_GetStringIdentifier("location");
2987 NPVariant locationVariant;
2988 if (NPN_GetProperty(instance, windowObject, locationIdentifier, &locationVariant)) {
2989 NPObject *locationObject = locationVariant.value.objectValue;
2990 if (locationObject) {
2991 NPIdentifier hrefIdentifier = NPN_GetStringIdentifier("href");
2992 NPVariant hrefVariant;
2993 if (NPN_GetProperty(instance, locationObject, hrefIdentifier, &hrefVariant)) {
2994 const NPString* hrefString = &NPVARIANT_TO_STRING(hrefVariant);
2995 if (hrefString) {
2996 outString = (char *)malloc(hrefString->UTF8Length + 1);
2997 if (outString) {
2998 strcpy(outString, hrefString->UTF8Characters);
2999 outString[hrefString->UTF8Length] = '\0';
3000 }
3001 }
3002 NPN_ReleaseVariantValue(&hrefVariant);
3003 }
3004 }
3005 NPN_ReleaseVariantValue(&locationVariant);
3006 }
3007
3008 NPN_ReleaseObject(windowObject);
3009
3010 return outString;
3011 }
3012
3013 static bool
3014 setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3015 {
3016 if (argCount != 1)
3017 return false;
3018 if (!NPVARIANT_IS_STRING(args[0]))
3019 return false;
3020 const NPString* cookie = &NPVARIANT_TO_STRING(args[0]);
3021
3022 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3023
3024 char* url = URLForInstanceWindow(npp);
3025 if (!url)
3026 return false;
3027 NPError err = NPN_SetValueForURL(npp, NPNURLVCookie, url, cookie->UTF8Characters, cookie->UTF8Length);
3028 free(url);
3029
3030 return (err == NPERR_NO_ERROR);
3031 }
3032
3033 static bool
3034 getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3035 {
3036 if (argCount != 0)
3037 return false;
3038
3039 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3040
3041 char* url = URLForInstanceWindow(npp);
3042 if (!url)
3043 return false;
3044 char* cookie = nullptr;
3045 unsigned int length = 0;
3046 NPError err = NPN_GetValueForURL(npp, NPNURLVCookie, url, &cookie, &length);
3047 free(url);
3048 if (err != NPERR_NO_ERROR || !cookie)
3049 return false;
3050
3051 STRINGZ_TO_NPVARIANT(cookie, *result);
3052 return true;
3053 }
3054
3055 static bool
3056 getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3057 {
3058 if (argCount != 5)
3059 return false;
3060
3061 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3062
3063 if (!NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) ||
3064 !NPVARIANT_IS_INT32(args[2]) || !NPVARIANT_IS_STRING(args[3]) ||
3065 !NPVARIANT_IS_STRING(args[4]))
3066 return false;
3067
3068 const NPString* protocol = &NPVARIANT_TO_STRING(args[0]);
3069 const NPString* host = &NPVARIANT_TO_STRING(args[1]);
3070 uint32_t port = NPVARIANT_TO_INT32(args[2]);
3071 const NPString* scheme = &NPVARIANT_TO_STRING(args[3]);
3072 const NPString* realm = &NPVARIANT_TO_STRING(args[4]);
3073
3074 char* username = nullptr;
3075 char* password = nullptr;
3076 uint32_t ulen = 0, plen = 0;
3077
3078 NPError err = NPN_GetAuthenticationInfo(npp,
3079 protocol->UTF8Characters,
3080 host->UTF8Characters,
3081 port,
3082 scheme->UTF8Characters,
3083 realm->UTF8Characters,
3084 &username,
3085 &ulen,
3086 &password,
3087 &plen);
3088
3089 if (err != NPERR_NO_ERROR) {
3090 return false;
3091 }
3092
3093 char* outstring = (char*)NPN_MemAlloc(ulen + plen + 2);
3094 memset(outstring, 0, ulen + plen + 2);
3095 strncpy(outstring, username, ulen);
3096 strcat(outstring, "|");
3097 strncat(outstring, password, plen);
3098
3099 STRINGZ_TO_NPVARIANT(outstring, *result);
3100
3101 NPN_MemFree(username);
3102 NPN_MemFree(password);
3103
3104 return true;
3105 }
3106
3107 static void timerCallback(NPP npp, uint32_t timerID)
3108 {
3109 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3110 currentTimerEventCount++;
3111 timerEvent event = timerEvents[currentTimerEventCount];
3112
3113 NPObject* windowObject;
3114 NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
3115 if (!windowObject)
3116 return;
3117
3118 NPVariant rval;
3119 if (timerID != id->timerID[event.timerIdReceive]) {
3120 id->timerTestResult = false;
3121 }
3122
3123 if (currentTimerEventCount == totalTimerEvents - 1) {
3124 NPVariant arg;
3125 BOOLEAN_TO_NPVARIANT(id->timerTestResult, arg);
3126 NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->timerTestScriptCallback.c_str()), &arg, 1, &rval);
3127 NPN_ReleaseVariantValue(&arg);
3128 }
3129
3130 NPN_ReleaseObject(windowObject);
3131
3132 if (event.timerIdSchedule > -1) {
3133 id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
3134 }
3135 if (event.timerIdUnschedule > -1) {
3136 NPN_UnscheduleTimer(npp, id->timerID[event.timerIdUnschedule]);
3137 }
3138 }
3139
3140 static bool
3141 timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3142 {
3143 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3144 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3145 currentTimerEventCount = 0;
3146
3147 if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
3148 return false;
3149 const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
3150 id->timerTestScriptCallback = argstr->UTF8Characters;
3151
3152 id->timerTestResult = true;
3153 timerEvent event = timerEvents[currentTimerEventCount];
3154
3155 id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
3156
3157 return id->timerID[event.timerIdSchedule] != 0;
3158 }
3159
3160 #ifdef XP_WIN
3161 void
3162 ThreadProc(void* cookie)
3163 #else
3164 void*
3165 ThreadProc(void* cookie)
3166 #endif
3167 {
3168 NPObject* npobj = (NPObject*)cookie;
3169 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3170 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3171 id->asyncTestPhase = 1;
3172 NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
3173 #ifndef XP_WIN
3174 return nullptr;
3175 #endif
3176 }
3177
3178 void
3179 asyncCallback(void* cookie)
3180 {
3181 NPObject* npobj = (NPObject*)cookie;
3182 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3183 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3184
3185 switch (id->asyncTestPhase) {
3186 // async callback triggered from same thread
3187 case 0:
3188 #ifdef XP_WIN
3189 if (_beginthread(ThreadProc, 0, (void*)npobj) == -1)
3190 id->asyncCallbackResult = false;
3191 #else
3192 pthread_t tid;
3193 if (pthread_create(&tid, 0, ThreadProc, (void*)npobj))
3194 id->asyncCallbackResult = false;
3195 #endif
3196 break;
3197
3198 // async callback triggered from different thread
3199 default:
3200 NPObject* windowObject;
3201 NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
3202 if (!windowObject)
3203 return;
3204 NPVariant arg, rval;
3205 BOOLEAN_TO_NPVARIANT(id->asyncCallbackResult, arg);
3206 NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->asyncTestScriptCallback.c_str()), &arg, 1, &rval);
3207 NPN_ReleaseVariantValue(&arg);
3208 NPN_ReleaseObject(windowObject);
3209 break;
3210 }
3211 }
3212
3213 static bool
3214 asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3215 {
3216 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3217 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3218
3219 if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
3220 return false;
3221 const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
3222 id->asyncTestScriptCallback = argstr->UTF8Characters;
3223
3224 id->asyncTestPhase = 0;
3225 id->asyncCallbackResult = true;
3226 NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
3227
3228 return true;
3229 }
3230
3231 static bool
3232 GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*)
3233 {
3234 return false;
3235 }
3236
3237 static bool
3238 GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount,
3239 NPVariant* result)
3240 {
3241 if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) ||
3242 35 != NPVARIANT_TO_INT32(args[0]))
3243 return false;
3244
3245 return true;
3246 }
3247
3248 static const NPClass kGCRaceClass = {
3249 NP_CLASS_STRUCT_VERSION,
3250 nullptr,
3251 nullptr,
3252 nullptr,
3253 nullptr,
3254 GCRaceInvoke,
3255 GCRaceInvokeDefault,
3256 nullptr,
3257 nullptr,
3258 nullptr,
3259 nullptr,
3260 nullptr,
3261 nullptr
3262 };
3263
3264 struct GCRaceData
3265 {
3266 GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc)
3267 : npp_(npp)
3268 , callback_(callback)
3269 , localFunc_(localFunc)
3270 {
3271 NPN_RetainObject(callback_);
3272 NPN_RetainObject(localFunc_);
3273 }
3274
3275 ~GCRaceData()
3276 {
3277 NPN_ReleaseObject(callback_);
3278 NPN_ReleaseObject(localFunc_);
3279 }
3280
3281 NPP npp_;
3282 NPObject* callback_;
3283 NPObject* localFunc_;
3284 };
3285
3286 static void
3287 FinishGCRace(void* closure)
3288 {
3289 GCRaceData* rd = static_cast<GCRaceData*>(closure);
3290
3291 XPSleep(5);
3292
3293 NPVariant arg;
3294 OBJECT_TO_NPVARIANT(rd->localFunc_, arg);
3295
3296 NPVariant result;
3297 bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result);
3298 if (!ok)
3299 return;
3300
3301 NPN_ReleaseVariantValue(&result);
3302 delete rd;
3303 }
3304
3305 bool
3306 checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3307 NPVariant* result)
3308 {
3309 if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0]))
3310 return false;
3311
3312 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3313
3314 NPObject* localFunc =
3315 NPN_CreateObject(npp, const_cast<NPClass*>(&kGCRaceClass));
3316
3317 GCRaceData* rd =
3318 new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc);
3319 NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd);
3320
3321 OBJECT_TO_NPVARIANT(localFunc, *result);
3322 return true;
3323 }
3324
3325 bool
3326 hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3327 NPVariant* result)
3328 {
3329 mozilla::NoteIntentionalCrash("plugin");
3330
3331 bool busyHang = false;
3332 if ((argCount == 1) && NPVARIANT_IS_BOOLEAN(args[0])) {
3333 busyHang = NPVARIANT_TO_BOOLEAN(args[0]);
3334 }
3335
3336 if (busyHang) {
3337 const time_t start = std::time(nullptr);
3338 while ((std::time(nullptr) - start) < 100000) {
3339 volatile int dummy = 0;
3340 for (int i=0; i<1000; ++i) {
3341 dummy++;
3342 }
3343 }
3344 } else {
3345 #ifdef XP_WIN
3346 Sleep(100000000);
3347 Sleep(100000000);
3348 #else
3349 pause();
3350 pause();
3351 #endif
3352 }
3353
3354 // NB: returning true here means that we weren't terminated, and
3355 // thus the hang detection/handling didn't work correctly. The
3356 // test harness will succeed in calling this function, and the
3357 // test will fail.
3358 return true;
3359 }
3360
3361 bool
3362 stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3363 NPVariant* result)
3364 {
3365 uint32_t stallTimeSeconds = 0;
3366 if ((argCount == 1) && NPVARIANT_IS_INT32(args[0])) {
3367 stallTimeSeconds = (uint32_t) NPVARIANT_TO_INT32(args[0]);
3368 }
3369
3370 #ifdef XP_WIN
3371 Sleep(stallTimeSeconds * 1000U);
3372 #else
3373 sleep(stallTimeSeconds);
3374 #endif
3375
3376 return true;
3377 }
3378
3379 #if defined(MOZ_WIDGET_GTK)
3380 bool
3381 getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3382 NPVariant* result)
3383 {
3384 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3385 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3386 string sel = pluginGetClipboardText(id);
3387
3388 uint32_t len = sel.size();
3389 char* selCopy = static_cast<char*>(NPN_MemAlloc(1 + len));
3390 if (!selCopy)
3391 return false;
3392
3393 memcpy(selCopy, sel.c_str(), len);
3394 selCopy[len] = '\0';
3395
3396 STRINGN_TO_NPVARIANT(selCopy, len, *result);
3397 // *result owns str now
3398
3399 return true;
3400 }
3401
3402 bool
3403 crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args,
3404 uint32_t argCount, NPVariant* result)
3405 {
3406 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3407 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3408 return pluginCrashInNestedLoop(id);
3409 }
3410
3411 bool
3412 destroySharedGfxStuff(NPObject* npobj, const NPVariant* args,
3413 uint32_t argCount, NPVariant* result)
3414 {
3415 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3416 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3417 return pluginDestroySharedGfxStuff(id);
3418 }
3419
3420 #else
3421 bool
3422 getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3423 NPVariant* result)
3424 {
3425 // XXX Not implemented!
3426 return false;
3427 }
3428
3429 bool
3430 crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args,
3431 uint32_t argCount, NPVariant* result)
3432 {
3433 // XXX Not implemented!
3434 return false;
3435 }
3436
3437 bool
3438 destroySharedGfxStuff(NPObject* npobj, const NPVariant* args,
3439 uint32_t argCount, NPVariant* result)
3440 {
3441 // XXX Not implemented!
3442 return false;
3443 }
3444 #endif
3445
3446 bool
3447 callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3448 {
3449 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3450 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3451
3452 if (id->callOnDestroy)
3453 return false;
3454
3455 if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0]))
3456 return false;
3457
3458 id->callOnDestroy = NPVARIANT_TO_OBJECT(args[0]);
3459 NPN_RetainObject(id->callOnDestroy);
3460
3461 return true;
3462 }
3463
3464 // On Linux at least, a windowed plugin resize causes Flash Player to
3465 // reconnect to the browser window. This method simulates that.
3466 bool
3467 reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3468 NPVariant* result)
3469 {
3470 if (argCount != 0)
3471 return false;
3472
3473 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3474 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3475
3476 if (!id->hasWidget)
3477 return false;
3478
3479 pluginWidgetInit(id, id->window.window);
3480 return true;
3481 }
3482
3483 bool
3484 propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3485 NPVariant* result)
3486 {
3487 INT32_TO_NPVARIANT(5, *result);
3488 return true;
3489 }
3490
3491 // Returns top-level window activation state as indicated by Cocoa NPAPI's
3492 // NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not.
3493 // Throws an exception if no events have been received and thus this state
3494 // is unknown.
3495 bool
3496 getTopLevelWindowActivationState(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3497 NPVariant* result)
3498 {
3499 if (argCount != 0)
3500 return false;
3501
3502 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3503 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3504
3505 // Throw an exception for unknown state.
3506 if (id->topLevelWindowActivationState == ACTIVATION_STATE_UNKNOWN) {
3507 return false;
3508 }
3509
3510 if (id->topLevelWindowActivationState == ACTIVATION_STATE_ACTIVATED) {
3511 BOOLEAN_TO_NPVARIANT(true, *result);
3512 } else if (id->topLevelWindowActivationState == ACTIVATION_STATE_DEACTIVATED) {
3513 BOOLEAN_TO_NPVARIANT(false, *result);
3514 }
3515
3516 return true;
3517 }
3518
3519 bool
3520 getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3521 NPVariant* result)
3522 {
3523 if (argCount != 0)
3524 return false;
3525
3526 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3527 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3528
3529 INT32_TO_NPVARIANT(id->topLevelWindowActivationEventCount, *result);
3530
3531 return true;
3532 }
3533
3534 // Returns top-level window activation state as indicated by Cocoa NPAPI's
3535 // NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not.
3536 // Throws an exception if no events have been received and thus this state
3537 // is unknown.
3538 bool
3539 getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3540 NPVariant* result)
3541 {
3542 if (argCount != 0)
3543 return false;
3544
3545 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3546 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3547
3548 // Throw an exception for unknown state.
3549 if (id->focusState == ACTIVATION_STATE_UNKNOWN) {
3550 return false;
3551 }
3552
3553 if (id->focusState == ACTIVATION_STATE_ACTIVATED) {
3554 BOOLEAN_TO_NPVARIANT(true, *result);
3555 } else if (id->focusState == ACTIVATION_STATE_DEACTIVATED) {
3556 BOOLEAN_TO_NPVARIANT(false, *result);
3557 }
3558
3559 return true;
3560 }
3561
3562 bool
3563 getFocusEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3564 NPVariant* result)
3565 {
3566 if (argCount != 0)
3567 return false;
3568
3569 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3570 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3571
3572 INT32_TO_NPVARIANT(id->focusEventCount, *result);
3573
3574 return true;
3575 }
3576
3577 bool
3578 getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3579 NPVariant* result)
3580 {
3581 if (argCount != 0)
3582 return false;
3583
3584 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3585 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3586
3587 INT32_TO_NPVARIANT(id->eventModel, *result);
3588
3589 return true;
3590 }
3591
3592 static bool
3593 ReflectorHasMethod(NPObject* npobj, NPIdentifier name)
3594 {
3595 return false;
3596 }
3597
3598 static bool
3599 ReflectorHasProperty(NPObject* npobj, NPIdentifier name)
3600 {
3601 return true;
3602 }
3603
3604 static bool
3605 ReflectorGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result)
3606 {
3607 if (NPN_IdentifierIsString(name)) {
3608 char* s = NPN_UTF8FromIdentifier(name);
3609 STRINGZ_TO_NPVARIANT(s, *result);
3610 return true;
3611 }
3612
3613 INT32_TO_NPVARIANT(NPN_IntFromIdentifier(name), *result);
3614 return true;
3615 }
3616
3617 static const NPClass kReflectorNPClass = {
3618 NP_CLASS_STRUCT_VERSION,
3619 nullptr,
3620 nullptr,
3621 nullptr,
3622 ReflectorHasMethod,
3623 nullptr,
3624 nullptr,
3625 ReflectorHasProperty,
3626 ReflectorGetProperty,
3627 nullptr,
3628 nullptr,
3629 nullptr,
3630 nullptr
3631 };
3632
3633 bool
3634 getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3635 {
3636 if (0 != argCount)
3637 return false;
3638
3639 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3640
3641 NPObject* reflector =
3642 NPN_CreateObject(npp,
3643 const_cast<NPClass*>(&kReflectorNPClass)); // retains
3644 OBJECT_TO_NPVARIANT(reflector, *result);
3645 return true;
3646 }
3647
3648 bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3649 {
3650 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3651 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3652
3653 BOOLEAN_TO_NPVARIANT(id->window.clipRect.top != 0 ||
3654 id->window.clipRect.left != 0 ||
3655 id->window.clipRect.bottom != 0 ||
3656 id->window.clipRect.right != 0, *result);
3657 return true;
3658 }
3659
3660 bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3661 {
3662 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3663 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3664
3665 NPObject* window = nullptr;
3666 NPError err = NPN_GetValue(npp, NPNVWindowNPObject, &window);
3667 if (NPERR_NO_ERROR != err || !window)
3668 return false;
3669
3670 NPIdentifier arrayID = NPN_GetStringIdentifier("Array");
3671 NPVariant arrayFunctionV;
3672 bool ok = NPN_GetProperty(npp, window, arrayID, &arrayFunctionV);
3673
3674 NPN_ReleaseObject(window);
3675
3676 if (!ok)
3677 return false;
3678
3679 if (!NPVARIANT_IS_OBJECT(arrayFunctionV)) {
3680 NPN_ReleaseVariantValue(&arrayFunctionV);
3681 return false;
3682 }
3683 NPObject* arrayFunction = NPVARIANT_TO_OBJECT(arrayFunctionV);
3684
3685 NPVariant elements[4];
3686 INT32_TO_NPVARIANT(id->window.x, elements[0]);
3687 INT32_TO_NPVARIANT(id->window.y, elements[1]);
3688 INT32_TO_NPVARIANT(id->window.width, elements[2]);
3689 INT32_TO_NPVARIANT(id->window.height, elements[3]);
3690
3691 ok = NPN_InvokeDefault(npp, arrayFunction, elements, 4, result);
3692
3693 NPN_ReleaseObject(arrayFunction);
3694
3695 return ok;
3696 }
3697
3698 bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3699 {
3700 if (argCount == 0 || !NPVARIANT_IS_OBJECT(args[0]))
3701 return false;
3702
3703 NPObject* ctor = NPVARIANT_TO_OBJECT(args[0]);
3704
3705 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3706
3707 return NPN_Construct(npp, ctor, args + 1, argCount - 1, result);
3708 }
3709
3710 bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3711 {
3712 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
3713 return false;
3714
3715 // Clear existing data.
3716 delete sSitesWithData;
3717
3718 const NPString* str = &NPVARIANT_TO_STRING(args[0]);
3719 if (str->UTF8Length == 0)
3720 return true;
3721
3722 // Parse the comma-delimited string into a vector.
3723 sSitesWithData = new list<siteData>;
3724 const char* iterator = str->UTF8Characters;
3725 const char* end = iterator + str->UTF8Length;
3726 while (1) {
3727 const char* next = strchr(iterator, ',');
3728 if (!next)
3729 next = end;
3730
3731 // Parse out the three tokens into a siteData struct.
3732 const char* siteEnd = strchr(iterator, ':');
3733 *((char*) siteEnd) = '\0';
3734 const char* flagsEnd = strchr(siteEnd + 1, ':');
3735 *((char*) flagsEnd) = '\0';
3736 *((char*) next) = '\0';
3737
3738 siteData data;
3739 data.site = string(iterator);
3740 data.flags = atoi(siteEnd + 1);
3741 data.age = atoi(flagsEnd + 1);
3742
3743 sSitesWithData->push_back(data);
3744
3745 if (next == end)
3746 break;
3747
3748 iterator = next + 1;
3749 }
3750
3751 return true;
3752 }
3753
3754 bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3755 {
3756 if (argCount != 1 || !NPVARIANT_IS_BOOLEAN(args[0]))
3757 return false;
3758
3759 sClearByAgeSupported = NPVARIANT_TO_BOOLEAN(args[0]);
3760 return true;
3761 }
3762
3763 bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3764 NPVariant* result)
3765 {
3766 if (argCount != 0) {
3767 return false;
3768 }
3769
3770 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3771 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3772
3773 char *outval = NPN_StrDup(id->lastKeyText.c_str());
3774 STRINGZ_TO_NPVARIANT(outval, *result);
3775 return true;
3776 }
3777
3778 bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
3779 NPVariant* result)
3780 {
3781 if (argCount != 0) {
3782 return false;
3783 }
3784
3785 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3786
3787 char *origin = nullptr;
3788 NPError err = NPN_GetValue(npp, NPNVdocumentOrigin, &origin);
3789 if (err != NPERR_NO_ERROR) {
3790 return false;
3791 }
3792
3793 STRINGZ_TO_NPVARIANT(origin, *result);
3794 return true;
3795 }
3796
3797 bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3798 {
3799 if (argCount != 0) {
3800 return false;
3801 }
3802
3803 NPP npp = static_cast<TestNPObject*>(npobj)->npp;
3804 InstanceData* id = static_cast<InstanceData*>(npp->pdata);
3805 INT32_TO_NPVARIANT(id->mouseUpEventCount, *result);
3806 return true;
3807 }
3808
3809 bool queryContentsScaleFactor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
3810 {
3811 if (argCount != 0)
3812 return false;
3813
3814 double scaleFactor = 1.0;
3815 #if defined(XP_MACOSX)
3816 NPError err = NPN_GetValue(static_cast<TestNPObject*>(npobj)->npp,
3817 NPNVcontentsScaleFactor, &scaleFactor);
3818 if (err != NPERR_NO_ERROR) {
3819 return false;
3820 }
3821 #endif
3822 DOUBLE_TO_NPVARIANT(scaleFactor, *result);
3823 return true;
3824 }

mercurial