Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: webkit/tools/npapi_layout_test_plugin/PluginObject.cpp

Issue 5318009: Remove the forked npapi layout test plugin from the tree. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/webkit
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "PluginObject.h"
27
28 #include "TestObject.h"
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #ifdef WIN32
34 #define snprintf sprintf_s
35 #endif
36
37 static void logWithWindowObject(NPObject* windowObject, NPP instance, const char * message)
38 {
39 NPVariant consoleVariant;
40 if (!browser->getproperty(instance, windowObject, browser->getstringidentifi er("console"), &consoleVariant)) {
41 fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message);
42 return;
43 }
44
45 NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant);
46
47 NPVariant messageVariant;
48 STRINGZ_TO_NPVARIANT(message, messageVariant);
49
50 NPVariant result;
51 if (!browser->invoke(instance, consoleObject, browser->getstringidentifier(" log"), &messageVariant, 1, &result)) {
52 fprintf(stderr, "Failed to invoke console.log while logging: %s\n", mess age);
53 browser->releaseobject(consoleObject);
54 return;
55 }
56
57 browser->releasevariantvalue(&result);
58 browser->releaseobject(consoleObject);
59 }
60
61 static void logWithWindowObjectVariableArgs(NPObject* windowObject, NPP instance , const char* format, ...)
62 {
63 va_list args;
64 va_start(args, format);
65 char message[2048] = "PLUGIN: ";
66 vsprintf(message + strlen(message), format, args);
67 va_end(args);
68
69 logWithWindowObject(windowObject, instance, message);
70 }
71
72 void log(NPP instance, const char* format, ...)
73 {
74 va_list args;
75 va_start(args, format);
76 char message[2048] = "PLUGIN: ";
77 vsprintf(message + strlen(message), format, args);
78 va_end(args);
79
80 NPObject* windowObject = 0;
81 NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObjec t);
82 if (error != NPERR_NO_ERROR) {
83 fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message);
84 return;
85 }
86
87 logWithWindowObject(windowObject, instance, message);
88 browser->releaseobject(windowObject);
89 }
90
91 static void pluginInvalidate(NPObject*);
92 static bool pluginHasProperty(NPObject*, NPIdentifier name);
93 static bool pluginHasMethod(NPObject*, NPIdentifier name);
94 static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*);
95 static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*);
96 static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, ui nt32_t argCount, NPVariant* result);
97 static bool pluginInvokeDefault(NPObject*, const NPVariant* args, uint32_t argCo unt, NPVariant* result);
98 static NPObject* pluginAllocate(NPP npp, NPClass*);
99 static void pluginDeallocate(NPObject*);
100
101 NPNetscapeFuncs* browser;
102
103 static NPClass pluginClass = {
104 NP_CLASS_STRUCT_VERSION,
105 pluginAllocate,
106 pluginDeallocate,
107 pluginInvalidate,
108 pluginHasMethod,
109 pluginInvoke,
110 pluginInvokeDefault,
111 pluginHasProperty,
112 pluginGetProperty,
113 pluginSetProperty,
114 };
115
116 NPClass *getPluginClass(void)
117 {
118 return &pluginClass;
119 }
120
121 static bool identifiersInitialized = false;
122
123 #define ID_PROPERTY_PROPERTY 0
124 #define ID_PROPERTY_EVENT_LOGGING 1
125 #define ID_PROPERTY_HAS_STREAM 2
126 #define ID_PROPERTY_TEST_OBJECT 3
127 #define ID_PROPERTY_LOG_DESTROY 4
128 #define ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM 5
129 #define ID_PROPERTY_TEST_OBJECT_COUNT 6
130 #define ID_PROPERTY_THROW_EXCEPTION_PROPERTY 7
131 #define NUM_PROPERTY_IDENTIFIERS 8
132
133 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
134 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
135 "property",
136 "eventLoggingEnabled",
137 "hasStream",
138 "testObject",
139 "logDestroy",
140 "returnErrorFromNewStream",
141 "testObjectCount",
142 "testThrowExceptionProperty",
143 };
144
145 enum {
146 ID_TEST_CALLBACK_METHOD = 0,
147 ID_TEST_GETURL,
148 ID_REMOVE_DEFAULT_METHOD,
149 ID_TEST_DOM_ACCESS,
150 ID_TEST_GET_URL_NOTIFY,
151 ID_TEST_INVOKE_DEFAULT,
152 ID_DESTROY_STREAM,
153 ID_TEST_ENUMERATE,
154 ID_TEST_GETINTIDENTIFIER,
155 ID_TEST_GET_PROPERTY,
156 ID_TEST_EVALUATE,
157 ID_TEST_GET_PROPERTY_RETURN_VALUE,
158 ID_TEST_CALLBACK_METHOD_RET,
159 ID_TEST_CALLBACK_METHOD_RETURN,
160 ID_TEST_CREATE_TEST_OBJECT,
161 ID_TEST_PASS_TEST_OBJECT,
162 ID_TEST_CLONE_OBJECT,
163 ID_TEST_SCRIPT_OBJECT_INVOKE,
164 ID_TEST_IDENTIFIER_TO_STRING,
165 ID_TEST_IDENTIFIER_TO_INT,
166 ID_TEST_POSTURL_FILE,
167 ID_TEST_CALLBACK_AND_GET_VALUE,
168 ID_TEST_CONSTRUCT,
169 ID_DESTROY_NULL_STREAM,
170 ID_TEST_HAS_PROPERTY,
171 ID_TEST_HAS_METHOD,
172 ID_TEST_THROW_EXCEPTION_METHOD,
173 ID_TEST_FAIL_METHOD,
174 ID_TEST_GET_BROWSER_PROPERTY,
175 ID_TEST_SET_BROWSER_PROPERTY,
176 NUM_METHOD_IDENTIFIERS
177 };
178
179 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
180 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
181 "testCallback",
182 "getURL",
183 "removeDefaultMethod",
184 "testDOMAccess",
185 "getURLNotify",
186 "testInvokeDefault",
187 "destroyStream",
188 "testEnumerate",
189 "testGetIntIdentifier",
190 "testGetProperty",
191 "testEvaluate",
192 "testGetPropertyReturnValue",
193 "testCallbackRet", // Chrome bug 897451
194 "testCallbackReturn", // Chrome bug 897451
195 "testCreateTestObject", // Chrome bug 1093606
196 "testPassTestObject", // Chrome bug 1093606
197 "testCloneObject",
198 "testScriptObjectInvoke", // Chrome bug 1175346
199 "testIdentifierToString",
200 "testIdentifierToInt",
201 "testPostURLFile",
202 // Chrome bug http://code.google.com/p/chromium/issues/detail?id=4270
203 "testCallbackAndGetValue",
204 "testConstruct",
205 "destroyNullStream",
206 "testHasProperty",
207 "testHasMethod",
208 "testThrowException",
209 "testFail",
210 "testGetBrowserProperty",
211 "testSetBrowserProperty"
212 };
213
214 static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
215 {
216 size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
217 NPUTF8* result = (NPUTF8*)malloc(length + 1);
218 memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
219 result[length] = '\0';
220 return result;
221 }
222
223 static void initializeIdentifiers(void)
224 {
225 browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_ID ENTIFIERS, pluginPropertyIdentifiers);
226 browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTI FIERS, pluginMethodIdentifiers);
227 }
228
229 static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
230 {
231 for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
232 if (name == pluginPropertyIdentifiers[i])
233 return true;
234 return false;
235 }
236
237 static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
238 {
239 for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
240 if (name == pluginMethodIdentifiers[i])
241 return true;
242 return false;
243 }
244
245 static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* resul t)
246 {
247 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
248 if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
249 static const char* originalString = "property";
250 char* buf = static_cast<char*>(browser->memalloc(strlen(originalString) + 1));
251 strcpy(buf, originalString);
252 STRINGZ_TO_NPVARIANT(buf, *result);
253 return true;
254 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
255 BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result);
256 return true;
257 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
258 BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result);
259 return true;
260 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
261 BOOLEAN_TO_NPVARIANT(plugin->stream != 0, *result);
262 return true;
263 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
264 NPObject* testObject = plugin->testObject;
265 browser->retainobject(testObject);
266 OBJECT_TO_NPVARIANT(testObject, *result);
267 return true;
268 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_N EWSTREAM]) {
269 BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
270 return true;
271 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT_COUNT]) {
272 INT32_TO_NPVARIANT(getTestObjectCount(), *result);
273 return true;
274 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PRO PERTY]) {
275 browser->setexception(obj, "plugin object testThrowExceptionProperty SUC CESS");
276 return true;
277 }
278 return false;
279 }
280
281 static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant)
282 {
283 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
284 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
285 plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
286 return true;
287 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
288 plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
289 return true;
290 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_N EWSTREAM]) {
291 plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant);
292 return true;
293 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PRO PERTY]) {
294 browser->setexception(obj, "plugin object testThrowExceptionProperty SUC CESS");
295 return true;
296 }
297
298 return false;
299 }
300
301 static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVaria nt* result)
302 {
303 // Get plug-in's DOM element
304 NPObject* elementObject;
305 if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) = = NPERR_NO_ERROR) {
306 // Get style
307 NPVariant styleVariant;
308 NPIdentifier styleIdentifier = browser->getstringidentifier("style");
309 if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styl eVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
310 // Set style.border
311 NPIdentifier borderIdentifier = browser->getstringidentifier("border ");
312 NPVariant borderVariant;
313 STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
314 browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), bo rderIdentifier, &borderVariant);
315 browser->releasevariantvalue(&styleVariant);
316 }
317
318 browser->releaseobject(elementObject);
319 }
320 VOID_TO_NPVARIANT(*result);
321 return true;
322 }
323
324 static NPIdentifier stringVariantToIdentifier(NPVariant variant)
325 {
326 assert(NPVARIANT_IS_STRING(variant));
327 NPUTF8* utf8String = createCStringFromNPVariant(&variant);
328 NPIdentifier identifier = browser->getstringidentifier(utf8String);
329 free(utf8String);
330 return identifier;
331 }
332
333 static NPIdentifier int32VariantToIdentifier(NPVariant variant)
334 {
335 assert(NPVARIANT_IS_INT32(variant));
336 int32_t integer = NPVARIANT_TO_INT32(variant);
337 return browser->getintidentifier(integer);
338 }
339
340 static NPIdentifier doubleVariantToIdentifier(NPVariant variant)
341 {
342 assert(NPVARIANT_IS_DOUBLE(variant));
343 double value = NPVARIANT_TO_DOUBLE(variant);
344 // Sadly there is no "getdoubleidentifier"
345 int32_t integer = static_cast<int32_t>(value);
346 return browser->getintidentifier(integer);
347 }
348
349 static NPIdentifier variantToIdentifier(NPVariant variant)
350 {
351 if (NPVARIANT_IS_STRING(variant))
352 return stringVariantToIdentifier(variant);
353 else if (NPVARIANT_IS_INT32(variant))
354 return int32VariantToIdentifier(variant);
355 else if (NPVARIANT_IS_DOUBLE(variant))
356 return doubleVariantToIdentifier(variant);
357 return 0;
358 }
359
360 static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_ t argCount, NPVariant* result)
361 {
362 if (argCount != 1)
363 return true;
364 NPIdentifier identifier = variantToIdentifier(args[0]);
365 if (!identifier)
366 return true;
367 NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
368 if (!utf8String)
369 return true;
370 STRINGZ_TO_NPVARIANT(utf8String, *result);
371 return true;
372 }
373
374 static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
375 {
376 if (argCount != 1)
377 return false;
378 NPIdentifier identifier = variantToIdentifier(args[0]);
379 if (!identifier)
380 return false;
381 int32_t integer = browser->intfromidentifier(identifier);
382 INT32_TO_NPVARIANT(integer, *result);
383 return true;
384 }
385
386 static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argC ount, NPVariant* result)
387 {
388 if (argCount == 0 || !NPVARIANT_IS_STRING(args[0]))
389 return false;
390
391 NPObject* windowScriptObject;
392 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
393
394 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
395 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackStrin g);
396 free(callbackString);
397
398 NPVariant browserResult;
399 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &bro wserResult);
400 browser->releasevariantvalue(&browserResult);
401
402 VOID_TO_NPVARIANT(*result);
403 return true;
404 }
405
406 static bool testCallbackAndGetValue(PluginObject* obj, const NPVariant* args, ui nt32_t argCount, NPVariant* result)
407 {
408 NPP npp = obj->npp;
409 if (!testCallback(obj, args, argCount, result))
410 return false;
411
412 NPObject *global;
413 browser->getvalue(npp, NPNVWindowNPObject, &global);
414
415 VOID_TO_NPVARIANT(*result);
416 return true;
417 }
418
419 static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
420 {
421 if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(arg s[1])) {
422 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
423 NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
424 NPError npErr = browser->geturl(obj->npp, urlString, targetString);
425 free(urlString);
426 free(targetString);
427
428 INT32_TO_NPVARIANT(npErr, *result);
429 return true;
430 } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
431 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
432 NPError npErr = browser->geturl(obj->npp, urlString, 0);
433 free(urlString);
434
435 INT32_TO_NPVARIANT(npErr, *result);
436 return true;
437 }
438 return false;
439 }
440
441 static bool removeDefaultMethod(PluginObject*, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
442 {
443 pluginClass.invokeDefault = 0;
444 VOID_TO_NPVARIANT(*result);
445 return true;
446 }
447
448 static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argC ount, NPVariant* result)
449 {
450 if (argCount != 3 || !NPVARIANT_IS_STRING(args[0])
451 || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1]))
452 || !NPVARIANT_IS_STRING(args[2]))
453 return false;
454
455 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
456 NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVa riant(&args[1]) : NULL);
457 NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
458
459 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackStrin g);
460 browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier) ;
461
462 free(urlString);
463 free(targetString);
464 free(callbackString);
465
466 VOID_TO_NPVARIANT(*result);
467 return true;
468 }
469
470 static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
471 {
472 if (!NPVARIANT_IS_OBJECT(args[0]))
473 return false;
474
475 NPObject *callback = NPVARIANT_TO_OBJECT(args[0]);
476
477 NPVariant invokeArgs[1];
478 NPVariant browserResult;
479
480 STRINGZ_TO_NPVARIANT("test", invokeArgs[0]);
481 bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &bro wserResult);
482
483 if (retval)
484 browser->releasevariantvalue(&browserResult);
485
486 BOOLEAN_TO_NPVARIANT(retval, *result);
487 return true;
488 }
489
490 static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t arg Count, NPVariant* result)
491 {
492 NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_B REAK);
493 INT32_TO_NPVARIANT(npError, *result);
494 return true;
495 }
496
497 static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
498 {
499 NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK);
500 INT32_TO_NPVARIANT(npError, *result);
501 return true;
502 }
503
504 static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
505 {
506 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(a rgs[1]))
507 return false;
508
509 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
510 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyStrin g);
511 free(propertyString);
512
513 bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), p ropertyIdentifier);
514
515 BOOLEAN_TO_NPVARIANT(retval, *result);
516 return true;
517 }
518
519 static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t arg Count, NPVariant* result)
520 {
521 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(a rgs[1]))
522 return false;
523
524 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
525 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyStrin g);
526 free(propertyString);
527
528 bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), pro pertyIdentifier);
529
530 BOOLEAN_TO_NPVARIANT(retval, *result);
531 return true;
532 }
533
534 static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t arg Count, NPVariant* result)
535 {
536 if (argCount == 2 && NPVARIANT_IS_OBJECT(args[0]) && NPVARIANT_IS_OBJECT(arg s[1])) {
537 uint32_t count;
538 NPIdentifier* identifiers;
539
540 if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifi ers, &count)) {
541 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
542 NPIdentifier pushIdentifier = browser->getstringidentifier("push");
543
544 for (uint32_t i = 0; i < count; i++) {
545 NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
546
547 if (!string)
548 continue;
549
550 NPVariant args[1];
551 STRINGZ_TO_NPVARIANT(string, args[0]);
552 NPVariant browserResult;
553 browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &br owserResult);
554 browser->releasevariantvalue(&browserResult);
555 browser->memfree(string);
556 }
557
558 browser->memfree(identifiers);
559 }
560
561 VOID_TO_NPVARIANT(*result);
562 return true;
563 }
564 return false;
565 }
566
567 static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
568 {
569 if (argCount != 1)
570 return false;
571
572 NPIdentifier identifier;
573
574 if (NPVARIANT_IS_DOUBLE(args[0])) {
575 identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]) );
576 } else if (NPVARIANT_IS_INT32(args[0])) {
577 identifier = browser->getintidentifier((int)NPVARIANT_TO_INT32(args[0])) ;
578 } else {
579 return false;
580 }
581
582 INT32_TO_NPVARIANT(static_cast<int32_t>(reinterpret_cast<intptr_t>(identifie r)), *result);
583 return true;
584 }
585
586 static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
587 {
588 if (argCount == 0)
589 return false;
590
591 NPObject *object;
592 browser->getvalue(obj->npp, NPNVWindowNPObject, &object);
593
594 for (uint32_t i = 0; i < argCount; i++) {
595 assert(NPVARIANT_IS_STRING(args[i]));
596 NPUTF8* propertyString = createCStringFromNPVariant(&args[i]);
597 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyS tring);
598 free(propertyString);
599
600 NPVariant variant;
601 bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant);
602 browser->releaseobject(object);
603
604 if (!retval)
605 break;
606
607 if (i + 1 < argCount) {
608 assert(NPVARIANT_IS_OBJECT(variant));
609 object = NPVARIANT_TO_OBJECT(variant);
610 } else {
611 *result = variant;
612 return true;
613 }
614 }
615
616 VOID_TO_NPVARIANT(*result);
617 return false;
618 }
619
620 static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argC ount, NPVariant* result)
621 {
622 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
623 return false;
624 NPObject* windowScriptObject;
625 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
626
627 NPString s = NPVARIANT_TO_STRING(args[0]);
628
629 bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result);
630 browser->releaseobject(windowScriptObject);
631 return retval;
632 }
633
634 static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
635 {
636 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(a rgs[1]))
637 return false;
638
639 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
640 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyStrin g);
641 free(propertyString);
642
643 NPVariant variant;
644 bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), p ropertyIdentifier, &variant);
645 if (retval)
646 browser->releasevariantvalue(&variant);
647
648 BOOLEAN_TO_NPVARIANT(retval, *result);
649 return true;
650 }
651
652 static char* toCString(const NPString& string)
653 {
654 char* result = static_cast<char*>(malloc(string.UTF8Length + 1));
655 memcpy(result, string.UTF8Characters, string.UTF8Length);
656 result[string.UTF8Length] = '\0';
657
658 return result;
659 }
660
661 static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
662 {
663 if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(a rgs[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3]))
664 return false;
665
666 NPString urlString = NPVARIANT_TO_STRING(args[0]);
667 char* url = toCString(urlString);
668
669 NPString targetString = NPVARIANT_TO_STRING(args[1]);
670 char* target = toCString(targetString);
671
672 NPString pathString = NPVARIANT_TO_STRING(args[2]);
673 char* path = toCString(pathString);
674
675 NPString contentsString = NPVARIANT_TO_STRING(args[3]);
676
677 FILE* tempFile = fopen(path, "w");
678 if (!tempFile)
679 return false;
680
681 int written = fwrite(contentsString.UTF8Characters, contentsString.UTF8Lengt h, 1, tempFile);
682 fclose(tempFile);
683 if (written != 1)
684 return false;
685
686 NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Lengt h, path, true);
687
688 free(path);
689 free(target);
690 free(url);
691
692 BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
693 return true;
694 }
695
696 static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t arg Count, NPVariant* result)
697 {
698 if (!argCount || !NPVARIANT_IS_OBJECT(args[0]))
699 return false;
700
701 return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result);
702 }
703
704 // Helper function to notify the layout test controller that the test completed.
705 void notifyTestCompletion(NPP npp, NPObject* object)
706 {
707 NPVariant result;
708 NPString script;
709 script.UTF8Characters = "javascript:window.layoutTestController.notifyDone() ;";
710 script.UTF8Length = strlen("javascript:window.layoutTestController.notifyDon e();");
711 browser->evaluate(npp, object, &script, &result);
712 browser->releasevariantvalue(&result);
713 }
714
715 bool testDocumentOpen(NPP npp)
716 {
717 NPIdentifier documentId = browser->getstringidentifier("document");
718 NPIdentifier openId = browser->getstringidentifier("open");
719
720 NPObject *windowObject = NULL;
721 browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
722 if (!windowObject)
723 return false;
724
725 NPVariant docVariant;
726 browser->getproperty(npp, windowObject, documentId, &docVariant);
727 if (docVariant.type != NPVariantType_Object)
728 return false;
729
730 NPObject *documentObject = NPVARIANT_TO_OBJECT(docVariant);
731
732 NPVariant openArgs[2];
733 STRINGZ_TO_NPVARIANT("text/html", openArgs[0]);
734 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
735
736 NPVariant result;
737 browser->invoke(npp, documentObject, openId, openArgs, 2, &result);
738 browser->releaseobject(documentObject);
739
740 if (result.type == NPVariantType_Object) {
741 logWithWindowObjectVariableArgs(windowObject, npp, "DOCUMENT OPEN SUCCES S");
742 notifyTestCompletion(npp, result.value.objectValue);
743 browser->releaseobject(result.value.objectValue);
744 return true;
745 }
746
747 return false;
748 }
749
750 bool testWindowOpen(NPP npp)
751 {
752 NPIdentifier openId = browser->getstringidentifier("open");
753
754 NPObject *windowObject = NULL;
755 browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
756 if (!windowObject)
757 return false;
758
759 NPVariant openArgs[2];
760 STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]);
761 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
762
763 NPVariant result;
764 browser->invoke(npp, windowObject, openId, openArgs, 2, &result);
765 if (result.type == NPVariantType_Object) {
766 logWithWindowObjectVariableArgs(windowObject, npp, "WINDOW OPEN SUCCESS" );
767 notifyTestCompletion(npp, result.value.objectValue);
768 browser->releaseobject(result.value.objectValue);
769 return true;
770 }
771 return false;
772 }
773
774 static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* a rgs, uint32_t argCount, NPVariant* result)
775 {
776 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
777 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD])
778 return testCallback(plugin, args, argCount, result);
779 else if (name == pluginMethodIdentifiers[ID_TEST_GETURL])
780 return getURL(plugin, args, argCount, result);
781 else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD])
782 return removeDefaultMethod(plugin, args, argCount, result);
783 else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS])
784 return testDOMAccess(plugin, args, argCount, result);
785 else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY])
786 return getURLNotify(plugin, args, argCount, result);
787 else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT])
788 return testInvokeDefault(plugin, args, argCount, result);
789 else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE])
790 return testEnumerate(plugin, args, argCount, result);
791 else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM])
792 return destroyStream(plugin, args, argCount, result);
793 else if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER])
794 return testGetIntIdentifier(plugin, args, argCount, result);
795 else if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE])
796 return testEvaluate(plugin, args, argCount, result);
797 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY])
798 return testGetProperty(plugin, args, argCount, result);
799 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE])
800 return testGetPropertyReturnValue(plugin, args, argCount, result);
801 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING])
802 return testIdentifierToString(plugin, args, argCount, result);
803 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT])
804 return testIdentifierToInt(plugin, args, argCount, result);
805 else if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE])
806 return testPostURLFile(plugin, args, argCount, result);
807 else if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD_RET] ||
808 name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD_RETURN]) {
809 // call whatever method name we're given, and pass it the 'window' obj.
810 // we expect the function to return its argument.
811 if (argCount > 0 && NPVARIANT_IS_STRING(args[0])) {
812 NPObject *windowScriptObject;
813 browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObje ct);
814
815 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
816 NPIdentifier callbackIdentifier = browser->getstringidentifier(callb ackString);
817 free(callbackString);
818
819 NPVariant callbackArgs[1];
820 OBJECT_TO_NPVARIANT(windowScriptObject, callbackArgs[0]);
821
822 NPVariant browserResult;
823 browser->invoke(plugin->npp, windowScriptObject, callbackIdentifier,
824 callbackArgs, 1, &browserResult);
825
826 if (NPVARIANT_IS_OBJECT(browserResult)) {
827 // Now return the callbacks return value back to our caller.
828 // BUG 897451: This should be the same as the
829 // windowScriptObject, but its not (in Chrome) - or at least, it
830 // has a different refcount. This means Chrome will delete the
831 // object before returning it and the calling JS gets a garbage
832 // value. Firefox handles it fine.
833 OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(browserResult), *result) ;
834 } else {
835 browser->releasevariantvalue(&browserResult);
836 VOID_TO_NPVARIANT(*result);
837 }
838
839 return true;
840 }
841 } else if (name == pluginMethodIdentifiers[ID_TEST_CREATE_TEST_OBJECT]) {
842 NPObject *testObject = browser->createobject(plugin->npp, getTestClass() );
843 assert(testObject->referenceCount == 1);
844 OBJECT_TO_NPVARIANT(testObject, *result);
845 return true;
846 } else if (name == pluginMethodIdentifiers[ID_TEST_PASS_TEST_OBJECT]) {
847 // call whatever method name we're given, and pass it our second
848 // argument.
849 if (argCount > 1 && NPVARIANT_IS_STRING(args[0])) {
850 NPObject *windowScriptObject;
851 browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObje ct);
852
853 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
854 NPIdentifier callbackIdentifier = browser->getstringidentifier(callb ackString);
855 free(callbackString);
856
857 NPVariant browserResult;
858 browser->invoke(plugin->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &browserResult);
859 browser->releasevariantvalue(&browserResult);
860
861 VOID_TO_NPVARIANT(*result);
862 return true;
863 }
864 } else if (name == pluginMethodIdentifiers[ID_TEST_CLONE_OBJECT]) {
865 // Create another instance of the same class
866 NPObject *new_object = browser->createobject(plugin->npp, &pluginClass);
867 assert(new_object->referenceCount == 1);
868 OBJECT_TO_NPVARIANT(new_object, *result);
869 return true;
870 } else if (name == pluginMethodIdentifiers[ID_TEST_SCRIPT_OBJECT_INVOKE]) {
871 if (argCount > 1 && NPVARIANT_IS_STRING(args[0])) {
872 // Invoke a script callback to get a script NPObject. Then call
873 // a method on the script NPObject passing it a freshly created
874 // NPObject.
875 // Arguments:
876 // arg1: Callback that returns a script object.
877 // arg2: Name of the method to call on the script object returned
878 // from the callback
879 NPObject *windowScriptObject;
880 browser->getvalue(plugin->npp, NPNVWindowNPObject,
881 &windowScriptObject);
882
883 // Arg1 is the name of the callback
884 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
885 NPIdentifier callbackIdentifier =
886 browser->getstringidentifier(callbackString);
887 free(callbackString);
888
889 // Invoke a callback that returns a script object
890 NPVariant object_result;
891 browser->invoke(plugin->npp, windowScriptObject, callbackIdentifier,
892 &args[1], 1, &object_result);
893
894 // Script object returned
895 NPObject *script_object = object_result.value.objectValue;
896
897 // Arg2 is the name of the method to be called on the script object
898 NPUTF8* object_mehod_string = createCStringFromNPVariant(&args[1]);
899 NPIdentifier object_method =
900 browser->getstringidentifier(object_mehod_string);
901 free(object_mehod_string);
902
903 // Create a fresh NPObject to be passed as an argument
904 NPObject *object_arg = browser->createobject(plugin->npp, &pluginCla ss);
905 NPVariant invoke_args[1];
906 OBJECT_TO_NPVARIANT(object_arg, invoke_args[0]);
907
908 // Invoke the script method
909 NPVariant object_method_result;
910 browser->invoke(plugin->npp, script_object, object_method,
911 invoke_args, 1, &object_method_result);
912
913 browser->releasevariantvalue(&object_result);
914 VOID_TO_NPVARIANT(*result);
915 if (NPVARIANT_IS_OBJECT(object_method_result)) {
916 // Now return the callbacks return value back to our caller.
917 // BUG 897451: This should be the same as the
918 // windowScriptObject, but its not (in Chrome) - or at least, it
919 // has a different refcount. This means Chrome will delete the
920 // object before returning it and the calling JS gets a garbage
921 // value. Firefox handles it fine.
922 OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(object_method_result),
923 *result);
924 } else {
925 browser->releasevariantvalue(&object_method_result);
926 VOID_TO_NPVARIANT(*result);
927 }
928 return true;
929 }
930 } else if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_AND_GET_VALUE])
931 return testCallbackAndGetValue(plugin, args, argCount, result);
932 else if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT])
933 return testConstruct(plugin, args, argCount, result);
934 else if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
935 return destroyNullStream(plugin, args, argCount, result);
936 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY])
937 return testHasProperty(plugin, args, argCount, result);
938 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD])
939 return testHasMethod(plugin, args, argCount, result);
940 else if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
941 browser->setexception(header, "plugin object testThrowException SUCCESS" );
942 return true;
943 } else if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) {
944 browser->getproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVa riantToIdentifier(args[1]), result);
945 return true;
946 } else if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) {
947 browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVa riantToIdentifier(args[1]), &args[2]);
948 return true;
949 }// else if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD])
950 // return browser->invoke(plugin->npp, 0, name, args, argCount, result);
951
952 return false;
953 }
954
955 static bool pluginInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t a rgCount, NPVariant* result)
956 {
957 INT32_TO_NPVARIANT(1, *result);
958 return true;
959 }
960
961 static void pluginInvalidate(NPObject* obj)
962 {
963 }
964
965 static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
966 {
967 PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject));
968
969 if (!identifiersInitialized) {
970 identifiersInitialized = true;
971 initializeIdentifiers();
972 }
973
974 newInstance->npp = npp;
975 newInstance->testObject = browser->createobject(npp, getTestClass());
976 newInstance->eventLogging = false;
977 newInstance->onStreamLoad = 0;
978 newInstance->onStreamDestroy = 0;
979 newInstance->onURLNotify = 0;
980 newInstance->logDestroy = false;
981 newInstance->logSetWindow = false;
982 newInstance->returnErrorFromNewStream = false;
983 newInstance->stream = 0;
984
985 newInstance->firstUrl = NULL;
986 newInstance->firstHeaders = NULL;
987 newInstance->lastUrl = NULL;
988 newInstance->lastHeaders = NULL;
989
990 newInstance->testDocumentOpenInDestroyStream = false;
991 newInstance->testWindowOpen = false;
992 newInstance->testKeyboardFocusForPlugins = false;
993
994 newInstance->evaluateScriptOnMouseDownOrKeyDown = NULL;
995 newInstance->mouseDownForEvaluateScript = false;
996
997 return (NPObject*)newInstance;
998 }
999
1000 static void pluginDeallocate(NPObject* header)
1001 {
1002 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1003 browser->releaseobject(plugin->testObject);
1004
1005 free(plugin->firstUrl);
1006 free(plugin->firstHeaders);
1007 free(plugin->lastUrl);
1008 free(plugin->lastHeaders);
1009 free(plugin);
1010 }
1011
1012 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
1013 {
1014 assert(object);
1015
1016 NPVariant args[2];
1017
1018 NPObject *windowScriptObject;
1019 browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
1020
1021 NPIdentifier callbackIdentifier = notifyData;
1022
1023 INT32_TO_NPVARIANT(reason, args[0]);
1024
1025 char *strHdr = NULL;
1026 if (object->firstUrl && object->firstHeaders && object->lastUrl && object->l astHeaders) {
1027 // Format expected by JavaScript validator: four fields separated by \n\ n:
1028 // First URL; first header block; last URL; last header block.
1029 // Note that header blocks already end with \n due to how NPStream::head ers works.
1030 int len = strlen(object->firstUrl) + 2
1031 + strlen(object->firstHeaders) + 1
1032 + strlen(object->lastUrl) + 2
1033 + strlen(object->lastHeaders) + 1;
1034 strHdr = (char*)malloc(len + 1);
1035 snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
1036 object->firstUrl, object->firstHeaders, object->lastUrl, object ->lastHeaders);
1037 STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
1038 } else
1039 NULL_TO_NPVARIANT(args[1]);
1040
1041 NPVariant browserResult;
1042 browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2 , &browserResult);
1043 browser->releasevariantvalue(&browserResult);
1044
1045 free(strHdr);
1046 }
1047
1048 void notifyStream(PluginObject* object, const char *url, const char *headers)
1049 {
1050 if (object->firstUrl == NULL) {
1051 if (url)
1052 object->firstUrl = strdup(url);
1053 if (headers)
1054 object->firstHeaders = strdup(headers);
1055 } else {
1056 free(object->lastUrl);
1057 free(object->lastHeaders);
1058 object->lastUrl = (url ? strdup(url) : NULL);
1059 object->lastHeaders = (headers ? strdup(headers) : NULL);
1060 }
1061 }
1062
1063 void testNPRuntime(NPP npp)
1064 {
1065 NPObject* windowScriptObject;
1066 browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject);
1067
1068 // Invoke
1069 NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke");
1070 NPVariant args[7];
1071
1072 VOID_TO_NPVARIANT(args[0]);
1073 NULL_TO_NPVARIANT(args[1]);
1074 BOOLEAN_TO_NPVARIANT(true, args[2]);
1075 INT32_TO_NPVARIANT(242, args[3]);
1076 DOUBLE_TO_NPVARIANT(242.242, args[4]);
1077 STRINGZ_TO_NPVARIANT("Hello, World", args[5]);
1078 OBJECT_TO_NPVARIANT(windowScriptObject, args[6]);
1079
1080 NPVariant result;
1081 if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result) )
1082 browser->releasevariantvalue(&result);
1083
1084 browser->releaseobject(windowScriptObject);
1085 }
OLDNEW
« no previous file with comments | « webkit/tools/npapi_layout_test_plugin/PluginObject.h ('k') | webkit/tools/npapi_layout_test_plugin/TestObject.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698