source: trunk/icedtea-web/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc

Last change on this file was 429, checked in by dmik, 11 years ago

icedtea-web: Merge version 1.5.1 from vendor to trunk.

File size: 42.8 KB
Line 
1/* IcedTeaJavaRequestProcessor.cc
2
3 Copyright (C) 2009, 2010 Red Hat
4
5This file is part of IcedTea.
6
7IcedTea is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12IcedTea is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with IcedTea; see the file COPYING. If not, write to the
19Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301 USA.
21
22Linking this library statically or dynamically with other modules is
23making a combined work based on this library. Thus, the terms and
24conditions of the GNU General Public License cover the whole
25combination.
26
27As a special exception, the copyright holders of this library give you
28permission to link this library with independent modules to produce an
29executable, regardless of the license terms of these independent
30modules, and to copy and distribute the resulting executable under
31terms of your choice, provided that you also meet, for each linked
32independent module, the terms and conditions of the license of that
33module. An independent module is a module which is not derived from
34or based on this library. If you modify this library, you may extend
35this exception to your version of the library, but you are not
36obligated to do so. If you do not wish to do so, delete this
37exception statement from your version. */
38
39#ifdef __EMX__
40#include <unistd.h> // usleep
41#endif
42
43#include <typeinfo>
44
45#include "IcedTeaJavaRequestProcessor.h"
46#include "IcedTeaScriptablePluginObject.h"
47
48/*
49 * This class processes LiveConnect requests from JavaScript to Java.
50 *
51 * It sends the requests to Java, gets the return information, and sends it
52 * back to the browser/JavaScript
53 */
54
55/**
56 * Processes return information from JavaSide (return messages of requests)
57 *
58 * @param message The message request to process
59 * @return boolean indicating whether the message is serviceable by this object
60 */
61
62bool
63JavaRequestProcessor::newMessageOnBus(const char* message)
64{
65
66 // Anything we are waiting for _MUST_ have and instance id and reference #
67 std::vector<std::string*>* message_parts = IcedTeaPluginUtilities::strSplit(message, " ");
68
69 IcedTeaPluginUtilities::printStringPtrVector("JavaRequest::newMessageOnBus:", message_parts);
70
71 if (*(message_parts->at(0)) == "context" && *(message_parts->at(2)) == "reference")
72 if (atoi(message_parts->at(1)->c_str()) == this->instance && atoi(message_parts->at(3)->c_str()) == this->reference)
73 {
74 // Gather the results
75
76 // Let's get errors out of the way first
77 if (!message_parts->at(4)->find("Error"))
78 {
79 for (int i=5; i < message_parts->size(); i++)
80 {
81 result->error_msg->append(*(message_parts->at(i)));
82 result->error_msg->append(" ");
83 }
84
85 PLUGIN_ERROR("Error on Java side: %s\n", result->error_msg->c_str());
86
87 result->error_occurred = true;
88 result_ready = true;
89 }
90 else if (!message_parts->at(4)->find("GetStringUTFChars") ||
91 !message_parts->at(4)->find("GetToStringValue"))
92 {
93 // first item is length, and it is radix 10
94 int length = strtol(message_parts->at(5)->c_str(), NULL, 10);
95
96 IcedTeaPluginUtilities::getUTF8String(length, 6 /* start at */, message_parts, result->return_string);
97 result_ready = true;
98 }
99 else if (!message_parts->at(4)->find("GetStringChars")) // GetStringChars (UTF-16LE/UCS-2)
100 {
101 // first item is length, and it is radix 10
102 int length = strtol(message_parts->at(5)->c_str(), NULL, 10);
103
104 IcedTeaPluginUtilities::getUTF16LEString(length, 6 /* start at */, message_parts, result->return_wstring);
105 result_ready = true;
106 } else if (!message_parts->at(4)->find("FindClass") ||
107 !message_parts->at(4)->find("GetClassName") ||
108 !message_parts->at(4)->find("GetClassID") ||
109 !message_parts->at(4)->find("GetMethodID") ||
110 !message_parts->at(4)->find("GetStaticMethodID") ||
111 !message_parts->at(4)->find("GetObjectClass") ||
112 !message_parts->at(4)->find("NewObject") ||
113 !message_parts->at(4)->find("NewStringUTF") ||
114 !message_parts->at(4)->find("HasPackage") ||
115 !message_parts->at(4)->find("HasMethod") ||
116 !message_parts->at(4)->find("HasField") ||
117 !message_parts->at(4)->find("GetStaticFieldID") ||
118 !message_parts->at(4)->find("GetFieldID") ||
119 !message_parts->at(4)->find("GetJavaObject") ||
120 !message_parts->at(4)->find("IsInstanceOf") ||
121 !message_parts->at(4)->find("NewArray"))
122 {
123 result->return_identifier = atoi(message_parts->at(5)->c_str());
124 result->return_string->append(*(message_parts->at(5))); // store it as a string as well, for easy access
125 result_ready = true;
126 } else if (!message_parts->at(4)->find("DeleteLocalRef") ||
127 !message_parts->at(4)->find("NewGlobalRef"))
128 {
129 result_ready = true; // nothing else to do
130 } else if (!message_parts->at(4)->find("CallMethod") ||
131 !message_parts->at(4)->find("CallStaticMethod") ||
132 !message_parts->at(4)->find("GetField") ||
133 !message_parts->at(4)->find("GetStaticField") ||
134 !message_parts->at(4)->find("GetValue") ||
135 !message_parts->at(4)->find("GetObjectArrayElement"))
136 {
137
138 if (!message_parts->at(5)->find("literalreturn") || !message_parts->at(5)->find("jsobject"))
139 {
140 // literal returns don't have a corresponding jni id
141 result->return_identifier = 0;
142 result->return_string->append(*(message_parts->at(5)));
143 result->return_string->append(" ");
144 result->return_string->append(*(message_parts->at(6)));
145
146 } else
147 {
148 // Else it is a complex object
149
150 result->return_identifier = atoi(message_parts->at(5)->c_str());
151 result->return_string->append(*(message_parts->at(5))); // store it as a string as well, for easy access
152 }
153
154 result_ready = true;
155 } else if (!message_parts->at(4)->find("GetArrayLength"))
156 {
157 result->return_identifier = 0; // length is not an "identifier"
158 result->return_string->append(*(message_parts->at(5)));
159 result_ready = true;
160 } else if (!message_parts->at(4)->find("SetField") ||
161 !message_parts->at(4)->find("SetObjectArrayElement"))
162 {
163
164 // nothing to do
165
166 result->return_identifier = 0;
167 result_ready = true;
168 }
169
170 IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
171 return true;
172 }
173
174 IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
175 return false;
176}
177
178/**
179 * Constructor.
180 *
181 * Initializes the result data structure (heap)
182 */
183
184JavaRequestProcessor::JavaRequestProcessor()
185{
186 PLUGIN_DEBUG("JavaRequestProcessor constructor\n");
187
188 // caller frees this
189 result = new JavaResultData();
190 result->error_msg = new std::string();
191 result->return_identifier = 0;
192 result->return_string = new std::string();
193 result->return_wstring = new std::wstring();
194 result->error_occurred = false;
195
196 result_ready = false;
197}
198
199/**
200 * Destructor
201 *
202 * Frees memory used by the result struct
203 */
204
205JavaRequestProcessor::~JavaRequestProcessor()
206{
207 PLUGIN_DEBUG("JavaRequestProcessor::~JavaRequestProcessor\n");
208
209 if (result)
210 {
211 if (result->error_msg)
212 delete result->error_msg;
213
214 if (result->return_string)
215 delete result->return_string;
216
217 if (result->return_wstring)
218 delete result->return_wstring;
219
220 delete result;
221 }
222}
223
224/**
225 * Resets the results
226 */
227void
228JavaRequestProcessor::resetResult()
229{
230 // caller frees this
231 result->error_msg->clear();
232 result->return_identifier = 0;
233 result->return_string->clear();
234 result->return_wstring->clear();
235 result->error_occurred = false;
236
237 result_ready = false;
238}
239
240void
241JavaRequestProcessor::postAndWaitForResponse(std::string message)
242{
243 struct timespec t;
244#ifdef __OS2__
245 t.tv_sec = time(NULL);
246 t.tv_nsec = 0;
247#else
248 clock_gettime(CLOCK_REALTIME, &t);
249#endif
250 t.tv_sec += REQUESTTIMEOUT; // 1 minute timeout
251
252 // Clear the result
253 resetResult();
254
255 java_to_plugin_bus->subscribe(this);
256 plugin_to_java_bus->post(message.c_str());
257
258 // Wait for result to be filled in.
259 struct timespec curr_t;
260#ifdef __OS2__
261 curr_t.tv_sec = curr_t.tv_nsec = 0;
262#endif
263
264 bool isPluginThread = false;
265
266 if (pthread_self() == itnp_plugin_thread_id)
267 {
268 isPluginThread = true;
269 PLUGIN_DEBUG("JRP is in plug-in thread...\n");
270 }
271
272 do
273 {
274#ifdef __OS2__
275 curr_t.tv_sec = time(NULL);
276#else
277 clock_gettime(CLOCK_REALTIME, &curr_t);
278#endif
279
280 if (!result_ready && (curr_t.tv_sec < t.tv_sec))
281 {
282 if (isPluginThread)
283 {
284 processAsyncCallQueue(NULL);
285
286 // Let the browser run its pending events too
287 if (g_main_context_pending(NULL))
288 {
289 g_main_context_iteration(NULL, false);
290 } else
291 {
292 usleep(1000); // 1ms
293 }
294 } else
295 {
296 usleep(1000); // 1ms
297 }
298 }
299 else
300 {
301 break;
302 }
303 } while (1);
304
305 if (curr_t.tv_sec >= t.tv_sec)
306 {
307 result->error_occurred = true;
308 result->error_msg->append("Error: Timed out when waiting for response");
309
310 // Report error
311 PLUGIN_DEBUG("Error: Timed out when waiting for response to %s\n", message.c_str());
312 }
313
314 java_to_plugin_bus->unSubscribe(this);
315}
316
317/**
318 * Given an object id, fetches the toString() value from Java
319 *
320 * @param object_id The ID of the object
321 * @return A JavaResultData struct containing the result of the request
322 */
323
324JavaResultData*
325JavaRequestProcessor::getToStringValue(std::string object_id)
326{
327 std::string message = std::string();
328
329 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
330 this->reference = IcedTeaPluginUtilities::getReference();
331
332 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
333
334 message.append(" GetToStringValue "); // get it in UTF8
335 message.append(object_id);
336
337 postAndWaitForResponse(message);
338
339 IcedTeaPluginUtilities::releaseReference();
340
341 return result;
342}
343
344/**
345 * Given an object id, fetches the value of that ID from Java
346 *
347 * @param object_id The ID of the object
348 * @return A JavaResultData struct containing the result of the request
349 */
350
351JavaResultData*
352JavaRequestProcessor::getValue(std::string object_id)
353{
354 std::string message = std::string();
355
356 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
357 this->reference = IcedTeaPluginUtilities::getReference();
358
359 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
360
361 message.append(" GetValue "); // get it in UTF8
362 message.append(object_id);
363
364 postAndWaitForResponse(message);
365
366 IcedTeaPluginUtilities::releaseReference();
367
368 return result;
369}
370
371/**
372 * Given a string id, fetches the actual string from Java side
373 *
374 * @param string_id The ID of the string
375 * @return A JavaResultData struct containing the result of the request
376 */
377
378JavaResultData*
379JavaRequestProcessor::getString(std::string string_id)
380{
381 std::string message = std::string();
382
383 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
384 this->reference = IcedTeaPluginUtilities::getReference();
385
386 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
387
388 message.append(" GetStringUTFChars "); // get it in UTF8
389 message.append(string_id);
390
391 postAndWaitForResponse(message);
392
393 IcedTeaPluginUtilities::releaseReference();
394
395 return result;
396}
397
398/**
399 * Decrements reference count by 1
400 *
401 * @param object_id The ID of the object
402 */
403
404void
405JavaRequestProcessor::deleteReference(std::string object_id)
406{
407 std::string message = std::string();
408
409 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
410 this->reference = IcedTeaPluginUtilities::getReference();
411
412 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
413
414 message.append(" DeleteLocalRef ");
415 message.append(object_id);
416
417 postAndWaitForResponse(message);
418
419 IcedTeaPluginUtilities::releaseReference();
420}
421
422/**
423 * Increments reference count by 1
424 *
425 * @param object_id The ID of the object
426 */
427
428void
429JavaRequestProcessor::addReference(std::string object_id)
430{
431 std::string message = std::string();
432
433 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
434 this->reference = IcedTeaPluginUtilities::getReference();
435
436 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
437
438 message.append(" NewGlobalRef ");
439 message.append(object_id);
440
441 postAndWaitForResponse(message);
442
443 IcedTeaPluginUtilities::releaseReference();
444
445}
446
447JavaResultData*
448JavaRequestProcessor::findClass(int plugin_instance_id,
449 std::string name)
450{
451 std::string message = std::string();
452 std::string plugin_instance_id_str = std::string();
453
454 IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
455
456 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
457 this->reference = IcedTeaPluginUtilities::getReference();
458
459 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
460
461 message.append(" FindClass ");
462 message.append(plugin_instance_id_str);
463 message.append(" ");
464 message.append(name);
465
466 postAndWaitForResponse(message);
467
468 return result;
469}
470
471JavaResultData*
472JavaRequestProcessor::getClassName(std::string objectID)
473{
474 std::string message = std::string();
475
476 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
477 this->reference = IcedTeaPluginUtilities::getReference();
478
479 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
480
481 message.append(" GetClassName ");
482 message.append(objectID);
483
484 postAndWaitForResponse(message);
485
486 return result;
487}
488
489JavaResultData*
490JavaRequestProcessor::getClassID(std::string objectID)
491{
492 std::string message = std::string();
493
494 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
495 this->reference = IcedTeaPluginUtilities::getReference();
496
497 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
498
499 message.append(" GetClassID ");
500 message.append(objectID);
501
502 postAndWaitForResponse(message);
503
504 return result;
505}
506
507JavaResultData*
508JavaRequestProcessor::getArrayLength(std::string objectID)
509{
510 std::string message = std::string();
511
512 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
513 this->reference = IcedTeaPluginUtilities::getReference();
514
515 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
516
517 message.append(" GetArrayLength ");
518 message.append(objectID);
519
520 postAndWaitForResponse(message);
521
522 return result;
523}
524
525JavaResultData*
526JavaRequestProcessor::getSlot(std::string objectID, std::string index)
527{
528 std::string message = std::string();
529 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
530 this->reference = IcedTeaPluginUtilities::getReference();
531
532 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
533
534 message.append(" GetObjectArrayElement ");
535 message.append(objectID);
536 message.append(" ");
537 message.append(index);
538
539 postAndWaitForResponse(message);
540
541 return result;
542}
543
544JavaResultData*
545JavaRequestProcessor::setSlot(std::string objectID,
546 std::string index,
547 std::string value_id)
548{
549 std::string message = std::string();
550
551 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
552 this->reference = IcedTeaPluginUtilities::getReference();
553
554 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
555
556 message.append(" SetObjectArrayElement ");
557 message.append(objectID);
558 message.append(" ");
559 message.append(index);
560 message.append(" ");
561 message.append(value_id);
562
563 postAndWaitForResponse(message);
564
565 IcedTeaPluginUtilities::releaseReference();
566
567 return result;
568}
569
570JavaResultData*
571JavaRequestProcessor::newArray(std::string array_class,
572 std::string length)
573{
574 std::string message = std::string();
575
576 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
577 this->reference = IcedTeaPluginUtilities::getReference();
578
579 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
580
581 message.append(" NewArray ");
582 message.append(array_class);
583 message.append(" ");
584 message.append(length);
585
586 postAndWaitForResponse(message);
587
588 IcedTeaPluginUtilities::releaseReference();
589
590 return result;
591}
592
593JavaResultData*
594JavaRequestProcessor::getFieldID(std::string classID, std::string fieldName)
595{
596 JavaResultData* java_result;
597 JavaRequestProcessor* java_request = new JavaRequestProcessor();
598 std::string message = std::string();
599
600 java_result = java_request->newString(fieldName);
601
602 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
603 this->reference = IcedTeaPluginUtilities::getReference();
604
605 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
606 message.append(" GetFieldID ");
607 message.append(classID);
608 message.append(" ");
609 message.append(java_result->return_string->c_str());
610
611 postAndWaitForResponse(message);
612
613 IcedTeaPluginUtilities::releaseReference();
614
615 delete java_request;
616
617 return result;
618}
619
620JavaResultData*
621JavaRequestProcessor::getStaticFieldID(std::string classID, std::string fieldName)
622{
623 JavaResultData* java_result;
624 JavaRequestProcessor* java_request = new JavaRequestProcessor();
625 std::string message = std::string();
626
627 java_result = java_request->newString(fieldName);
628
629 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
630 this->reference = IcedTeaPluginUtilities::getReference();
631
632 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
633 message.append(" GetStaticFieldID ");
634 message.append(classID);
635 message.append(" ");
636 message.append(java_result->return_string->c_str());
637
638 postAndWaitForResponse(message);
639
640 IcedTeaPluginUtilities::releaseReference();
641
642 delete java_request;
643
644 return result;
645}
646
647JavaResultData*
648JavaRequestProcessor::getField(std::string source,
649 std::string classID,
650 std::string objectID,
651 std::string fieldName)
652{
653 JavaResultData* java_result;
654 JavaRequestProcessor* java_request = new JavaRequestProcessor();
655 std::string message = std::string();
656
657 java_result = java_request->getFieldID(classID, fieldName);
658
659 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
660 this->reference = IcedTeaPluginUtilities::getReference();
661
662 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
663 message.append(" GetField ");
664 message.append(objectID);
665 message.append(" ");
666 message.append(java_result->return_string->c_str());
667
668 postAndWaitForResponse(message);
669
670 IcedTeaPluginUtilities::releaseReference();
671
672 delete java_request;
673
674 return result;
675}
676
677JavaResultData*
678JavaRequestProcessor::getStaticField(std::string source, std::string classID,
679 std::string fieldName)
680{
681 JavaResultData* java_result;
682 JavaRequestProcessor* java_request = new JavaRequestProcessor();
683 std::string message = std::string();
684
685 java_result = java_request->getStaticFieldID(classID, fieldName);
686
687 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
688 this->reference = IcedTeaPluginUtilities::getReference();
689
690 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
691 message.append(" GetStaticField ");
692 message.append(classID);
693 message.append(" ");
694 message.append(java_result->return_string->c_str());
695
696 postAndWaitForResponse(message);
697
698 IcedTeaPluginUtilities::releaseReference();
699
700 delete java_request;
701
702 return result;
703}
704
705
706JavaResultData*
707JavaRequestProcessor::set(std::string source,
708 bool isStatic,
709 std::string classID,
710 std::string objectID,
711 std::string fieldName,
712 std::string value_id)
713{
714 JavaResultData* java_result;
715 JavaRequestProcessor java_request = JavaRequestProcessor();
716 std::string message = std::string();
717
718 java_result = java_request.getFieldID(classID, fieldName);
719
720 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
721 this->reference = IcedTeaPluginUtilities::getReference();
722
723 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
724
725 if (isStatic)
726 {
727 message.append(" SetStaticField ");
728 message.append(classID);
729 } else
730 {
731 message.append(" SetField ");
732 message.append(objectID);
733 }
734
735 message.append(" ");
736 message.append(java_result->return_string->c_str());
737 message.append(" ");
738 message.append(value_id);
739
740 postAndWaitForResponse(message);
741
742 IcedTeaPluginUtilities::releaseReference();
743
744 return result;
745}
746
747JavaResultData*
748JavaRequestProcessor::setStaticField(std::string source,
749 std::string classID,
750 std::string fieldName,
751 std::string value_id)
752{
753 return set(source, true, classID, "", fieldName, value_id);
754}
755
756JavaResultData*
757JavaRequestProcessor::setField(std::string source,
758 std::string classID,
759 std::string objectID,
760 std::string fieldName,
761 std::string value_id)
762{
763 return set(source, false, classID, objectID, fieldName, value_id);
764}
765
766JavaResultData*
767JavaRequestProcessor::getMethodID(std::string classID, NPIdentifier methodName,
768 std::vector<std::string> args)
769{
770 std::string message, signature = "(";
771
772 // FIXME: Need to determine how to extract array types and complex java objects
773 for (int i=0; i < args.size(); i++)
774 {
775 signature += args[i];
776 }
777
778 signature += ")";
779
780 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
781 this->reference = IcedTeaPluginUtilities::getReference();
782
783 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
784 message += " GetMethodID " + classID + " ";
785 message += IcedTeaPluginUtilities::NPIdentifierAsString(methodName) + " ";
786 message += signature;
787
788 postAndWaitForResponse(message);
789
790 IcedTeaPluginUtilities::releaseReference();
791
792 return result;
793}
794
795JavaResultData*
796JavaRequestProcessor::getStaticMethodID(std::string classID, NPIdentifier methodName,
797 std::vector<std::string> args)
798{
799 std::string message, signature = "(";
800
801 // FIXME: Need to determine how to extract array types and complex java objects
802 for (int i=0; i < args.size(); i++)
803 {
804 signature += args[i];
805 }
806
807 signature += ")";
808
809 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
810 this->reference = IcedTeaPluginUtilities::getReference();
811
812 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
813 message += " GetStaticMethodID " + classID + " ";
814 message += IcedTeaPluginUtilities::NPIdentifierAsString(methodName) + " ";
815 message += signature;
816
817 postAndWaitForResponse(message);
818
819 IcedTeaPluginUtilities::releaseReference();
820
821 return result;
822}
823
824void
825getArrayTypeForJava(NPP instance, NPVariant element, std::string* type)
826{
827
828 if (NPVARIANT_IS_BOOLEAN(element)) {
829 type->append("string");
830 } else if (NPVARIANT_IS_INT32(element)) {
831 type->append("string");
832 } else if (NPVARIANT_IS_DOUBLE(element)) {
833 type->append("string");
834 } else if (NPVARIANT_IS_STRING(element)) {
835 type->append("string");
836 } else if (NPVARIANT_IS_OBJECT(element)) {
837
838 NPObject* first_element_obj = NPVARIANT_TO_OBJECT(element);
839 if (IcedTeaScriptableJavaPackageObject::is_valid_java_object(first_element_obj))
840 {
841 std::string class_id = std::string(((IcedTeaScriptableJavaObject*) first_element_obj)->getClassID());
842 type->append(class_id);
843 } else
844 {
845 type->append("jsobject");
846 }
847 } else {
848 type->append("jsobject"); // Else it is a string
849 }
850}
851
852void
853createJavaObjectFromVariant(NPP instance, NPVariant variant, std::string* id)
854{
855 JavaResultData* java_result;
856
857 std::string className;
858 std::string jsObjectClassID = std::string();
859 std::string jsObjectConstructorID = std::string();
860
861 std::string stringArg = std::string();
862 std::vector<std::string> args = std::vector<std::string>();
863
864 JavaRequestProcessor java_request = JavaRequestProcessor();
865 bool alreadyCreated = false;
866
867 if (NPVARIANT_IS_VOID(variant))
868 {
869 PLUGIN_DEBUG("VOID %d\n", variant);
870 id->append("0");
871 return; // no need to go further
872 } else if (NPVARIANT_IS_NULL(variant))
873 {
874 PLUGIN_DEBUG("NULL\n", variant);
875 id->append("0");
876 return; // no need to go further
877 } else if (NPVARIANT_IS_BOOLEAN(variant))
878 {
879 className = "java.lang.Boolean";
880
881 if (NPVARIANT_TO_BOOLEAN(variant))
882 stringArg = "true";
883 else
884 stringArg = "false";
885
886 } else if (NPVARIANT_IS_INT32(variant))
887 {
888 className = "java.lang.Integer";
889
890 char* valueStr = (char*) malloc(sizeof(char)*32);
891 sprintf(valueStr, "%d", NPVARIANT_TO_INT32(variant));
892 stringArg += valueStr;
893 free(valueStr);
894 } else if (NPVARIANT_IS_DOUBLE(variant))
895 {
896 className = "java.lang.Double";
897
898 char* valueStr = (char*) malloc(sizeof(char)*1024);
899 sprintf(valueStr, "%f", NPVARIANT_TO_DOUBLE(variant));
900 stringArg += valueStr;
901 free(valueStr);
902 } else if (NPVARIANT_IS_STRING(variant))
903 {
904 className = "java.lang.String";
905 stringArg = IcedTeaPluginUtilities::NPVariantAsString(variant);
906 } else if (NPVARIANT_IS_OBJECT(variant))
907 {
908
909 NPObject* obj = NPVARIANT_TO_OBJECT(variant);
910 if (IcedTeaScriptableJavaPackageObject::is_valid_java_object(obj))
911 {
912 PLUGIN_DEBUG("NPObject is a Java object\n");
913 alreadyCreated = true;
914 } else
915 {
916 PLUGIN_DEBUG("NPObject is not a Java object\n");
917 NPIdentifier length_id = browser_functions.getstringidentifier("length");
918 bool isJSObjectArray = false;
919
920 // FIXME: We currently only handle <= 2 dim arrays. Do we really need more though?
921
922 // Is it an array?
923 if (IcedTeaPluginUtilities::isObjectJSArray(instance, obj)) {
924 PLUGIN_DEBUG("NPObject is an array\n");
925
926 std::string array_id = std::string();
927 std::string java_array_type = std::string();
928 NPVariant length = NPVariant();
929 browser_functions.getproperty(instance, obj, length_id, &length);
930
931 std::string length_str = std::string();
932 IcedTeaPluginUtilities::itoa(NPVARIANT_TO_INT32(length), &length_str);
933
934 if (NPVARIANT_TO_INT32(length) >= 0)
935 {
936 NPIdentifier id_0 = browser_functions.getintidentifier(0);
937 NPVariant first_element = NPVariant();
938 browser_functions.getproperty(instance, obj, id_0, &first_element);
939
940 // Check for multi-dim array
941 if (NPVARIANT_IS_OBJECT(first_element) &&
942 IcedTeaPluginUtilities::isObjectJSArray(instance, NPVARIANT_TO_OBJECT(first_element))) {
943
944 NPVariant first_nested_element = NPVariant();
945 browser_functions.getproperty(instance, NPVARIANT_TO_OBJECT(first_element), id_0, &first_nested_element);
946
947 getArrayTypeForJava(instance, first_nested_element, &java_array_type);
948
949 length_str.append(" 0"); // secondary array is created on the fly
950 } else
951 {
952 getArrayTypeForJava(instance, first_element, &java_array_type);
953 }
954 }
955
956 // For JSObject arrays, we create a regular object (accessible via JSObject.getSlot())
957 if (NPVARIANT_TO_INT32(length) < 0 || !java_array_type.compare("jsobject"))
958 {
959 isJSObjectArray = true;
960 goto createRegularObject;
961 }
962
963 java_result = java_request.newArray(java_array_type, length_str);
964
965 if (java_result->error_occurred) {
966 PLUGIN_ERROR("Unable to create array\n");
967 id->append("-1");
968 return;
969 }
970
971 id->append(*(java_result->return_string));
972
973 NPIdentifier index_id = NPIdentifier();
974 for (int i=0; i < NPVARIANT_TO_INT32(length); i++)
975 {
976 NPVariant value = NPVariant();
977
978 index_id = browser_functions.getintidentifier(i);
979 browser_functions.getproperty(instance, obj, index_id, &value);
980
981 std::string value_id = std::string();
982 createJavaObjectFromVariant(instance, value, &value_id);
983
984 if (value_id == "-1") {
985 PLUGIN_ERROR("Unable to populate array\n");
986 id->clear();
987 id->append("-1");
988 return;
989 }
990
991 std::string value_str = std::string();
992 IcedTeaPluginUtilities::itoa(i, &value_str);
993 java_result = java_request.setSlot(*id, value_str, value_id);
994
995 }
996
997 // Got here => no errors above. We're good to return!
998 return;
999 }
1000
1001 createRegularObject:
1002 if (!IcedTeaPluginUtilities::isObjectJSArray(instance, obj) || isJSObjectArray) // Else it is not an array
1003 {
1004
1005 NPVariant* variant_copy = new NPVariant();
1006 OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(variant), *variant_copy);
1007
1008 className = "netscape.javascript.JSObject";
1009 IcedTeaPluginUtilities::JSIDToString(variant_copy, &stringArg);
1010 browser_functions.retainobject(NPVARIANT_TO_OBJECT(variant));
1011
1012 std::string jsObjectClassID = std::string();
1013 std::string jsObjectConstructorID = std::string();
1014 std::vector<std::string> args = std::vector<std::string>();
1015
1016 java_result = java_request.findClass(0, "netscape.javascript.JSObject");
1017
1018 // the result we want is in result_string (assuming there was no error)
1019 if (java_result->error_occurred)
1020 {
1021 PLUGIN_ERROR("Unable to get JSObject class id\n");
1022 id->clear();
1023 id->append("-1");
1024 return;
1025 }
1026
1027 jsObjectClassID.append(*(java_result->return_string));
1028 args.push_back("J");
1029
1030 java_result = java_request.getMethodID(jsObjectClassID,
1031 browser_functions.getstringidentifier("<init>"),
1032 args);
1033
1034 // the result we want is in result_string (assuming there was no error)
1035 if (java_result->error_occurred)
1036 {
1037 PLUGIN_ERROR("Unable to get JSObject constructor id\n");
1038 id->clear();
1039 id->append("-1");
1040 return;
1041 }
1042
1043 jsObjectConstructorID.append(*(java_result->return_string));
1044
1045 // We have the method id. Now create a new object.
1046
1047 args.clear();
1048 args.push_back(stringArg);
1049 java_result = java_request.newObjectWithConstructor("",
1050 jsObjectClassID,
1051 jsObjectConstructorID,
1052 args);
1053
1054 // Store the instance ID for future reference
1055 IcedTeaPluginUtilities::storeInstanceID(variant_copy, instance);
1056
1057 // the result we want is in result_string (assuming there was no error)
1058 // the result we want is in result_string (assuming there was no error)
1059 if (java_result->error_occurred)
1060 {
1061 PLUGIN_ERROR("Unable to create JSObject\n");
1062 id->clear();
1063 id->append("-1");
1064 return;
1065 }
1066
1067 id->append(*(java_result->return_string));
1068 return;
1069 }
1070 }
1071 }
1072
1073 if (!alreadyCreated) {
1074 java_result = java_request.findClass(0, className);
1075
1076 // the result we want is in result_string (assuming there was no error)
1077 if (java_result->error_occurred) {
1078 PLUGIN_ERROR("Unable to find classid for %s\n", className.c_str());
1079 id->append("-1");
1080 return;
1081 }
1082
1083 jsObjectClassID.append(*(java_result->return_string));
1084
1085 std::string stringClassName = "Ljava/lang/String;";
1086 args.push_back(stringClassName);
1087
1088 java_result = java_request.getMethodID(jsObjectClassID,
1089 browser_functions.getstringidentifier("<init>"), args);
1090
1091 // the result we want is in result_string (assuming there was no error)
1092 if (java_result->error_occurred) {
1093 PLUGIN_ERROR("Unable to find string constructor for %s\n", className.c_str());
1094 id->append("-1");
1095 return;
1096 }
1097
1098 jsObjectConstructorID.append(*(java_result->return_string));
1099
1100 // We have class id and constructor ID. So we know we can create the
1101 // object.. now create the string that will be provided as the arg
1102 java_result = java_request.newString(stringArg);
1103
1104 if (java_result->error_occurred) {
1105 PLUGIN_ERROR("Unable to create requested object\n");
1106 id->append("-1");
1107 return;
1108 }
1109
1110 // Create the object
1111 args.clear();
1112 std::string arg = std::string();
1113 arg.append(*(java_result->return_string));
1114 args.push_back(arg);
1115 java_result = java_request.newObjectWithConstructor("[System]", jsObjectClassID, jsObjectConstructorID, args);
1116
1117 if (java_result->error_occurred) {
1118 PLUGIN_ERROR("Unable to create requested object\n");
1119 id->append("-1");
1120 return;
1121 }
1122
1123
1124 id->append(*(java_result->return_string));
1125
1126 } else {
1127 // Else already created
1128
1129 std::string classId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getClassID());
1130 std::string instanceId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getInstanceID());
1131
1132 if (instanceId.length() == 0)
1133 id->append(classId.c_str());
1134 else
1135 id->append(instanceId.c_str());
1136 }
1137
1138}
1139
1140JavaResultData*
1141JavaRequestProcessor::callStaticMethod(std::string source, std::string classID,
1142 std::string methodName,
1143 std::vector<std::string> args)
1144{
1145 return call(source, true, classID, methodName, args);
1146}
1147
1148JavaResultData*
1149JavaRequestProcessor::callMethod(std::string source,
1150 std::string objectID, std::string methodName,
1151 std::vector<std::string> args)
1152{
1153 return call(source, false, objectID, methodName, args);
1154}
1155
1156JavaResultData*
1157JavaRequestProcessor::call(std::string source,
1158 bool isStatic, std::string objectID,
1159 std::string methodName,
1160 std::vector<std::string> args)
1161{
1162 std::string message = std::string();
1163 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1164 this->reference = IcedTeaPluginUtilities::getReference();
1165
1166 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
1167
1168 if (isStatic)
1169 message += " CallStaticMethod ";
1170 else
1171 message += " CallMethod ";
1172
1173 message += objectID;
1174 message += " ";
1175 message += methodName;
1176 message += " ";
1177
1178 for (int i=0; i < args.size(); i++)
1179 {
1180 message += args[i];
1181 message += " ";
1182 }
1183
1184 postAndWaitForResponse(message);
1185
1186 IcedTeaPluginUtilities::releaseReference();
1187
1188 return result;
1189}
1190
1191JavaResultData*
1192JavaRequestProcessor::getObjectClass(std::string objectID)
1193{
1194 JavaRequestProcessor* java_request;
1195 std::string message = std::string();
1196
1197 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1198 this->reference = IcedTeaPluginUtilities::getReference();
1199
1200 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1201 message += " GetObjectClass ";
1202 message += objectID;
1203
1204 postAndWaitForResponse(message);
1205
1206 IcedTeaPluginUtilities::releaseReference();
1207
1208 return result;
1209}
1210
1211JavaResultData*
1212JavaRequestProcessor::newObject(std::string source, std::string classID,
1213 std::vector<std::string> args)
1214{
1215 JavaRequestProcessor* java_request;
1216 std::string message = std::string();
1217
1218 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1219 this->reference = IcedTeaPluginUtilities::getReference();
1220
1221 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
1222 message += " NewObject ";
1223 message += classID;
1224 message += " ";
1225
1226 for (int i=0; i < args.size(); i++)
1227 {
1228 message += args[i];
1229 message += " ";
1230 }
1231
1232 postAndWaitForResponse(message);
1233
1234 IcedTeaPluginUtilities::releaseReference();
1235
1236 return result;
1237}
1238
1239JavaResultData*
1240JavaRequestProcessor::newObjectWithConstructor(std::string source, std::string classID,
1241 std::string methodID,
1242 std::vector<std::string> args)
1243{
1244 JavaRequestProcessor* java_request;
1245 std::string message = std::string();
1246
1247 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1248 this->reference = IcedTeaPluginUtilities::getReference();
1249
1250 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
1251 message += " NewObjectWithConstructor ";
1252 message += classID;
1253 message += " ";
1254 message += methodID;
1255 message += " ";
1256
1257 for (int i=0; i < args.size(); i++)
1258 {
1259 message += args[i];
1260 message += " ";
1261 }
1262
1263 postAndWaitForResponse(message);
1264
1265 IcedTeaPluginUtilities::releaseReference();
1266
1267 return result;
1268}
1269
1270JavaResultData*
1271JavaRequestProcessor::newString(std::string str)
1272{
1273 std::string utf_string = std::string();
1274 std::string message = std::string();
1275
1276 IcedTeaPluginUtilities::convertStringToUTF8(&str, &utf_string);
1277
1278 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1279 this->reference = IcedTeaPluginUtilities::getReference();
1280
1281 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1282 message.append(" NewStringUTF ");
1283 message.append(utf_string);
1284
1285 postAndWaitForResponse(message);
1286
1287 IcedTeaPluginUtilities::releaseReference();
1288
1289 return result;
1290}
1291
1292JavaResultData*
1293JavaRequestProcessor::hasPackage(int plugin_instance_id,
1294 std::string package_name)
1295{
1296 JavaResultData* java_result;
1297 JavaRequestProcessor* java_request = new JavaRequestProcessor();
1298 std::string plugin_instance_id_str = std::string();
1299 IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
1300
1301 java_result = java_request->newString(package_name);
1302
1303 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1304 this->reference = IcedTeaPluginUtilities::getReference();
1305
1306 std::string message;
1307 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1308 message += " HasPackage " + plugin_instance_id_str + " " + *java_result->return_string;
1309
1310 postAndWaitForResponse(message);
1311
1312 IcedTeaPluginUtilities::releaseReference();
1313
1314 delete java_request;
1315
1316 return result;
1317}
1318
1319JavaResultData*
1320JavaRequestProcessor::hasMethod(std::string classID, std::string method_name)
1321{
1322 JavaResultData* java_result;
1323 JavaRequestProcessor* java_request = new JavaRequestProcessor();
1324 std::string message = std::string();
1325
1326 java_result = java_request->newString(method_name);
1327
1328 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1329 this->reference = IcedTeaPluginUtilities::getReference();
1330
1331 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1332 message.append(" HasMethod ");
1333 message.append(classID);
1334 message.append(" ");
1335 message.append(java_result->return_string->c_str());
1336
1337 postAndWaitForResponse(message);
1338
1339 IcedTeaPluginUtilities::releaseReference();
1340
1341 delete java_request;
1342
1343 return result;
1344}
1345
1346JavaResultData*
1347JavaRequestProcessor::hasField(std::string classID, std::string method_name)
1348{
1349 JavaResultData* java_result;
1350 JavaRequestProcessor java_request = JavaRequestProcessor();
1351 std::string message = std::string();
1352
1353 java_result = java_request.newString(method_name);
1354
1355 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1356 this->reference = IcedTeaPluginUtilities::getReference();
1357
1358 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1359 message.append(" HasField ");
1360 message.append(classID);
1361 message.append(" ");
1362 message.append(java_result->return_string->c_str());
1363
1364 postAndWaitForResponse(message);
1365
1366 IcedTeaPluginUtilities::releaseReference();
1367
1368 return result;
1369}
1370
1371JavaResultData*
1372JavaRequestProcessor::isInstanceOf(std::string objectID, std::string classID)
1373{
1374 std::string message = std::string();
1375
1376 this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
1377 this->reference = IcedTeaPluginUtilities::getReference();
1378
1379 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
1380 message.append(" IsInstanceOf ");
1381 message.append(objectID);
1382 message.append(" ");
1383 message.append(classID);
1384
1385 postAndWaitForResponse(message);
1386
1387 IcedTeaPluginUtilities::releaseReference();
1388
1389 return result;
1390}
1391
1392JavaResultData*
1393JavaRequestProcessor::getAppletObjectInstance(std::string instanceID)
1394{
1395 std::string message = std::string();
1396 std::string ref_str = std::string();
1397
1398 this->instance = 0;
1399 this->reference = IcedTeaPluginUtilities::getReference();
1400 IcedTeaPluginUtilities::itoa(reference, &ref_str);
1401
1402 message = "instance ";
1403 message += instanceID;
1404 message += " reference ";
1405 message += ref_str;
1406 message += " GetJavaObject";
1407
1408 postAndWaitForResponse(message);
1409
1410 IcedTeaPluginUtilities::releaseReference();
1411
1412 return result;
1413}
1414
Note: See TracBrowser for help on using the repository browser.