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

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

icedtea-web: Adapt 1.5.1 changes to OS/2.

File size: 31.8 KB
Line 
1/* IcedTeaPluginRequestProcessor.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#include <typeinfo>
40
41#include "IcedTeaScriptablePluginObject.h"
42#include "IcedTeaNPPlugin.h"
43#include "IcedTeaPluginRequestProcessor.h"
44
45/*
46 * This class processes requests made by Java. The requests include pointer
47 * information, script execution and variable get/set
48 */
49
50/**
51 * PluginRequestProcessor constructor.
52 *
53 * Initializes various complex data structures used by the class.
54 */
55
56PluginRequestProcessor::PluginRequestProcessor()
57{
58 this->message_queue = new std::vector< std::vector<std::string*>* >();
59
60 internal_req_ref_counter = 0;
61
62 pthread_mutex_init(&this->message_queue_mutex, NULL);
63 pthread_mutex_init(&this->syn_write_mutex, NULL);
64 pthread_cond_init(&this->cond_message_available, NULL);
65}
66
67/**
68 * PluginRequestProcessor destructor.
69 *
70 * Frees memory used by complex objects.
71 */
72
73PluginRequestProcessor::~PluginRequestProcessor()
74{
75 PLUGIN_DEBUG("PluginRequestProcessor::~PluginRequestProcessor\n");
76
77 if (message_queue)
78 delete message_queue;
79
80 pthread_mutex_destroy(&message_queue_mutex);
81 pthread_mutex_destroy(&syn_write_mutex);
82 pthread_cond_destroy(&cond_message_available);
83}
84
85/**
86 * Processes plugin (C++ side) requests from the Java side, and internally.
87 *
88 * @param message The message request to process
89 * @return boolean indicating whether the message is serviceable by this object
90 */
91
92bool
93PluginRequestProcessor::newMessageOnBus(const char* message)
94{
95 PLUGIN_DEBUG("PluginRequestProcessor processing %s\n", message);
96
97 std::string* type;
98 std::string* command;
99 int counter = 0;
100
101 std::vector<std::string*>* message_parts = IcedTeaPluginUtilities::strSplit(message, " ");
102
103 std::vector<std::string*>::iterator the_iterator;
104 the_iterator = message_parts->begin();
105
106 IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::newMessageOnBus:", message_parts);
107
108 type = message_parts->at(0);
109 command = message_parts->at(4);
110
111 if (!type->find("instance"))
112 {
113 if (!command->find("GetWindow"))
114 {
115 // Window can be queried from the main thread only. And this call
116 // returns immediately, so we do it in the same thread.
117 this->sendWindow(message_parts);
118 return true;
119 } else if (!command->find("Finalize"))
120 {
121 // Object can be finalized from the main thread only. And this
122 // call returns immediately, so we do it in the same thread.
123 this->finalize(message_parts);
124 return true;
125 } else if (!command->find("GetMember") ||
126 !command->find("SetMember") ||
127 !command->find("ToString") ||
128 !command->find("Call") ||
129 !command->find("GetSlot") ||
130 !command->find("SetSlot") ||
131 !command->find("Eval") ||
132 !command->find("LoadURL"))
133 {
134
135 // Update queue synchronously
136 pthread_mutex_lock(&message_queue_mutex);
137 message_queue->push_back(message_parts);
138 pthread_cond_signal(&cond_message_available);
139 pthread_mutex_unlock(&message_queue_mutex);
140
141
142 return true;
143 }
144
145 }
146
147 IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
148
149 // If we got here, it means we couldn't process the message. Let the caller know.
150 return false;
151}
152
153/**
154 * Sends the window pointer to the Java side.
155 *
156 * @param message_parts The request message.
157 */
158
159void
160PluginRequestProcessor::sendWindow(std::vector<std::string*>* message_parts)
161{
162 std::string* type;
163 std::string* command;
164 int reference;
165 std::string response = std::string();
166 std::string window_ptr_str = std::string();
167 NPVariant* variant = new NPVariant();
168 static NPObject* window_ptr;
169 int id;
170
171 type = message_parts->at(0);
172 id = atoi(message_parts->at(1)->c_str());
173 reference = atoi(message_parts->at(3)->c_str());
174 command = message_parts->at(4);
175
176 NPP instance;
177 get_instance_from_id(id, instance);
178
179 browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr);
180 PLUGIN_DEBUG("ID=%d, Instance=%p, WindowPTR = %p\n", id, instance, window_ptr);
181
182 OBJECT_TO_NPVARIANT(window_ptr, *variant);
183 browser_functions.retainobject(window_ptr);
184 IcedTeaPluginUtilities::JSIDToString(variant, &window_ptr_str);
185
186 // We need the context 0 for backwards compatibility with the Java side
187 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
188 response += " JavaScriptGetWindow ";
189 response += window_ptr_str;
190
191 plugin_to_java_bus->post(response.c_str());
192
193 // store the instance pointer for future reference
194 IcedTeaPluginUtilities::storeInstanceID(variant, instance);
195}
196
197/**
198 * Evaluates the given script
199 *
200 * @param message_parts The request message.
201 */
202
203void
204PluginRequestProcessor::eval(std::vector<std::string*>* message_parts)
205{
206 JavaRequestProcessor request_processor = JavaRequestProcessor();
207 JavaResultData* java_result;
208
209 NPVariant* window_ptr;
210 NPP instance;
211 std::string script;
212 NPVariant result;
213 int reference;
214 std::string response = std::string();
215 std::string return_type = std::string();
216 int id;
217
218 reference = atoi(message_parts->at(3)->c_str());
219 window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(message_parts->at(5));
220 instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
221
222 // If instance is invalid, do not proceed further
223 if (!instance)
224 return;
225
226 java_result = request_processor.getString(*(message_parts->at(6)));
227 CHECK_JAVA_RESULT(java_result);
228 script.append(*(java_result->return_string));
229
230 AsyncCallThreadData thread_data = AsyncCallThreadData();
231 thread_data.result_ready = false;
232 thread_data.parameters = std::vector<void*>();
233 thread_data.result = std::string();
234
235 thread_data.parameters.push_back(instance);
236 thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr));
237 thread_data.parameters.push_back(&script);
238
239 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_eval, &thread_data);
240
241 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
242 response += " JavaScriptEval ";
243 response += thread_data.result;
244
245 plugin_to_java_bus->post(response.c_str());
246}
247
248/**
249 * Calls the given javascript script
250 *
251 * @param message_parts The request message.
252 */
253
254void
255PluginRequestProcessor::call(std::vector<std::string*>* message_parts)
256{
257 NPP instance;
258 std::string* window_ptr_str;
259 NPVariant* window_ptr;
260 int reference;
261 std::string window_function_name;
262 std::vector<NPVariant> args = std::vector<NPVariant>();
263 std::vector<std::string> arg_ids = std::vector<std::string>();
264 int arg_count;
265 std::string response = std::string();
266 JavaRequestProcessor java_request = JavaRequestProcessor();
267 JavaResultData* java_result;
268 NPVariant* result_variant;
269 std::string result_variant_jniid = std::string();
270 NPVariant* args_array = NULL;
271 AsyncCallThreadData thread_data = AsyncCallThreadData();
272
273 reference = atoi(message_parts->at(3)->c_str());
274
275 // window
276 window_ptr_str = message_parts->at(5);
277 window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(window_ptr_str);
278
279 // instance
280 instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
281
282 // If instance is invalid, do not proceed further
283 if (!instance)
284 goto cleanup;
285
286 // function name
287 java_result = java_request.getString(*(message_parts->at(6)));
288 CHECK_JAVA_RESULT(java_result);
289 window_function_name.append(*(java_result->return_string));
290
291 // arguments
292 for (int i=7; i < message_parts->size(); i++)
293 {
294 arg_ids.push_back(*(message_parts->at(i)));
295 }
296
297 // determine arguments
298 for (int i=0; i < arg_ids.size(); i++)
299 {
300 NPVariant* variant = new NPVariant();
301 java_result = java_request.getValue(arg_ids[i]);
302 CHECK_JAVA_RESULT(java_result);
303
304 IcedTeaPluginUtilities::javaResultToNPVariant(instance, java_result->return_string, variant);
305
306 args.push_back(*variant);
307 }
308
309 arg_count = args.size();
310 args_array = (NPVariant*) malloc(sizeof(NPVariant)*args.size());
311 for (int i=0; i < args.size(); i++)
312 args_array[i] = args[i];
313
314 thread_data.result_ready = false;
315 thread_data.parameters = std::vector<void*>();
316 thread_data.result = std::string();
317
318 thread_data.parameters.push_back(instance);
319 thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr));
320 thread_data.parameters.push_back(&window_function_name);
321 thread_data.parameters.push_back(&arg_count);
322 thread_data.parameters.push_back(args_array);
323
324 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_call, &thread_data);
325
326 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
327 response += " JavaScriptCall ";
328 response += thread_data.result;
329
330 plugin_to_java_bus->post(response.c_str());
331
332 cleanup:
333 free(args_array);
334}
335
336/**
337 * Sends the string value of the requested variable
338 *
339 * @param message_parts The request message.
340 */
341void
342PluginRequestProcessor::sendString(std::vector<std::string*>* message_parts)
343{
344 std::string variant_ptr;
345 NPVariant* variant;
346 JavaRequestProcessor java_request = JavaRequestProcessor();
347 JavaResultData* java_result;
348 int reference;
349 std::string response = std::string();
350
351 reference = atoi(message_parts->at(3)->c_str());
352 variant_ptr = *(message_parts->at(5));
353
354 variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr);
355 AsyncCallThreadData thread_data = AsyncCallThreadData();
356 thread_data.result_ready = false;
357 thread_data.parameters = std::vector<void*>();
358 thread_data.result = std::string();
359
360 NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(variant);
361
362 // If instance is invalid, do not proceed further
363 if (!instance)
364 return;
365
366 thread_data.parameters.push_back(instance);
367 thread_data.parameters.push_back(variant);
368
369 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_getString, &thread_data);
370
371 // We need the context 0 for backwards compatibility with the Java side
372 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
373 response += " JavaScriptToString ";
374 response += thread_data.result;
375
376 plugin_to_java_bus->post(response.c_str());
377}
378
379/**
380 * Sets variable to given value
381 *
382 * @param message_parts The request message.
383 */
384
385void
386PluginRequestProcessor::setMember(std::vector<std::string*>* message_parts)
387{
388 std::string propertyNameID;
389 std::string value = std::string();
390 std::string response = std::string();
391 int reference;
392
393 NPP instance;
394 NPVariant* member;
395 std::string property_id = std::string();
396 bool int_identifier;
397
398 JavaRequestProcessor java_request = JavaRequestProcessor();
399 JavaResultData* java_result;
400
401 IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::_setMember - ", message_parts);
402
403 reference = atoi(message_parts->at(3)->c_str());
404
405 member = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(*(message_parts->at(5))));
406 propertyNameID = *(message_parts->at(6));
407
408 if (*(message_parts->at(7)) == "literalreturn" || *(message_parts->at(7)) == "jsobject" )
409 {
410 value.append(*(message_parts->at(7)));
411 value.append(" ");
412 value.append(*(message_parts->at(8)));
413 } else
414 {
415 value.append(*(message_parts->at(7)));
416 }
417
418 instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(member);
419
420 // If instance is invalid, do not proceed further
421 if (!instance)
422 return;
423
424 if (*(message_parts->at(4)) == "SetSlot")
425 {
426 property_id.append(*(message_parts->at(6)));
427 int_identifier = true;
428 } else
429 {
430 java_result = java_request.getString(propertyNameID);
431
432 // the result we want is in result_string (assuming there was no error)
433 if (java_result->error_occurred)
434 {
435 PLUGIN_ERROR("Unable to get member name for setMember. Error occurred: %s\n", java_result->error_msg->c_str());
436 //goto cleanup;
437 }
438
439 property_id.append(*(java_result->return_string));
440 int_identifier = false;
441 }
442
443 AsyncCallThreadData thread_data = AsyncCallThreadData();
444 thread_data.result_ready = false;
445 thread_data.parameters = std::vector<void*>();
446 thread_data.result = std::string();
447
448 thread_data.parameters.push_back(instance);
449 thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*member));
450 thread_data.parameters.push_back(&property_id);
451 thread_data.parameters.push_back(&value);
452 thread_data.parameters.push_back(&int_identifier);
453
454 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_setMember, &thread_data);
455
456 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
457 response.append(" JavaScriptSetMember ");
458 plugin_to_java_bus->post(response.c_str());
459}
460
461/**
462 * Sends request member pointer to the Java side.
463 *
464 * This is a static function, called in another thread. Since certain data
465 * can only be requested from the main thread in Mozilla, this function
466 * does whatever it can separately, and then makes an internal request that
467 * causes _getMember to do the rest of the work.
468 *
469 * @param message_parts The request message
470 */
471
472void
473PluginRequestProcessor::sendMember(std::vector<std::string*>* message_parts)
474{
475 // member initialization
476 std::vector<std::string> args;
477 JavaRequestProcessor java_request = JavaRequestProcessor();
478 JavaResultData* java_result;
479 NPVariant* parent_ptr;
480 NPVariant* member_ptr;
481
482 //int reference;
483 std::string member_id = std::string();
484 std::string response = std::string();
485 std::string result_id = std::string();
486
487 NPIdentifier member_identifier;
488
489 int method_id;
490 int instance_id;
491 int reference;
492 bool int_identifier;
493
494 // debug printout of parent thread data
495 IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::getMember:", message_parts);
496
497 reference = atoi(message_parts->at(3)->c_str());
498
499 // store info in local variables for easy access
500 instance_id = atoi(message_parts->at(1)->c_str());
501 parent_ptr = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(message_parts->at(5)));
502 member_id.append(*(message_parts->at(6)));
503
504 /** Request data from Java if necessary **/
505 if (*(message_parts->at(4)) == "GetSlot")
506 {
507 int_identifier=true;
508 } else
509 {
510 // make a new request for getString, to get the name of the identifier
511 java_result = java_request.getString(member_id);
512
513 // the result we want is in result_string (assuming there was no error)
514 if (java_result->error_occurred)
515 {
516 PLUGIN_ERROR("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg->c_str());
517 //goto cleanup;
518 }
519
520 member_id.assign(*(java_result->return_string));
521 int_identifier=false;
522 }
523
524 AsyncCallThreadData thread_data = AsyncCallThreadData();
525 thread_data.result_ready = false;
526 thread_data.parameters = std::vector<void*>();
527 thread_data.result = std::string();
528
529 NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(parent_ptr);
530
531 // If instance is invalid, do not proceed further
532 if (!instance)
533 return;
534
535 thread_data.parameters.push_back(instance);
536 thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*parent_ptr));
537 thread_data.parameters.push_back(&member_id);
538 thread_data.parameters.push_back(&int_identifier);
539
540 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_getMember, &thread_data);
541
542 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
543 if (*(message_parts->at(4)) == "GetSlot")
544 {
545 response.append(" JavaScriptGetSlot ");
546 } else {
547 response.append(" JavaScriptGetMember ");
548 }
549 response.append(thread_data.result);
550 plugin_to_java_bus->post(response.c_str());
551}
552
553/**
554 * Decrements reference count to given object
555 *
556 * @param message_parts The request message.
557 */
558
559void
560PluginRequestProcessor::finalize(std::vector<std::string*>* message_parts)
561{
562 std::string* type;
563 std::string* command;
564 int reference;
565 std::string response = std::string();
566 std::string* variant_ptr_str;
567 NPVariant* variant_ptr;
568 NPObject* window_ptr;
569 int id;
570
571 type = message_parts->at(0);
572 id = atoi(message_parts->at(1)->c_str());
573 reference = atoi(message_parts->at(3)->c_str());
574 variant_ptr_str = message_parts->at(5);
575
576 NPP instance;
577 get_instance_from_id(id, instance);
578
579 variant_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr_str);
580 window_ptr = NPVARIANT_TO_OBJECT(*variant_ptr);
581 browser_functions.releaseobject(window_ptr);
582
583 // remove reference
584 IcedTeaPluginUtilities::removeInstanceID(variant_ptr);
585
586 // clear memory
587 free(variant_ptr);
588
589 // We need the context 0 for backwards compatibility with the Java side
590 IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
591 response += " JavaScriptFinalize";
592
593 plugin_to_java_bus->post(response.c_str());
594}
595
596/**
597 * Fetches the URL and loads it into the given target
598 *
599 * @param message_parts The request message.
600 */
601void
602PluginRequestProcessor::loadURL(std::vector<std::string*>* message_parts)
603{
604
605 int id = atoi(message_parts->at(1)->c_str());
606
607 AsyncCallThreadData thread_data = AsyncCallThreadData();
608 thread_data.result_ready = false;
609 thread_data.parameters = std::vector<void*>();
610 thread_data.result = std::string();
611
612 NPP instance;
613 get_instance_from_id(id, instance);
614
615 // If instance is invalid, do not proceed further
616 if (!instance)
617 return;
618
619 thread_data.parameters.push_back(instance);
620 thread_data.parameters.push_back(message_parts->at(5)); // push url
621 thread_data.parameters.push_back(message_parts->at(6)); // push target
622
623 thread_data.result_ready = false;
624 IcedTeaPluginUtilities::callAndWaitForResult(instance, &_loadURL, &thread_data);
625}
626
627static void
628queue_cleanup(void* data)
629{
630 PLUGIN_DEBUG("Queue processing stopped.\n");
631}
632
633static void
634queue_wait_cleanup(void* data)
635{
636 pthread_mutex_unlock((pthread_mutex_t*) data);
637}
638
639void*
640queue_processor(void* data)
641{
642#ifdef __OS2__
643 QueueProcessorData *queue_processor_data = (QueueProcessorData *) data;
644 PluginRequestProcessor* processor = queue_processor_data->processor;
645 processor->queueProcessorThread(queue_processor_data);
646#else
647 PluginRequestProcessor* processor = (PluginRequestProcessor*) data;
648 processor->queueProcessorThread();
649#endif
650 return NULL;
651}
652
653void
654#ifdef __OS2__
655PluginRequestProcessor::queueProcessorThread(QueueProcessorData *queue_processor_data)
656#else
657PluginRequestProcessor::queueProcessorThread()
658#endif
659{
660 std::vector<std::string*>* message_parts = NULL;
661 std::string command;
662
663 PLUGIN_DEBUG("Queue processor initialized. Queue = %p\n", message_queue);
664
665#ifdef __OS2__
666 queue_processor_data->stopRequested = false;
667#else
668 pthread_cleanup_push(queue_cleanup, NULL);
669#endif
670
671 while (true)
672 {
673 pthread_mutex_lock(&message_queue_mutex);
674 if (message_queue->size() > 0)
675 {
676 message_parts = message_queue->front();
677 message_queue->erase(message_queue->begin());
678 }
679 pthread_mutex_unlock(&message_queue_mutex);
680
681 if (message_parts)
682 {
683 command = *(message_parts->at(4));
684
685 if (command == "GetMember")
686 {
687 sendMember(message_parts);
688 } else if (command == "ToString")
689 {
690 sendString(message_parts);
691 } else if (command == "SetMember")
692 {
693 // write methods are synchronized
694 pthread_mutex_lock(&syn_write_mutex);
695 setMember(message_parts);
696 pthread_mutex_unlock(&syn_write_mutex);
697 } else if (command == "Call")
698 {
699 // write methods are synchronized
700 pthread_mutex_lock(&syn_write_mutex);
701 call(message_parts);
702 pthread_mutex_unlock(&syn_write_mutex);
703 } else if (command == "Eval")
704 {
705 // write methods are synchronized
706 pthread_mutex_lock(&syn_write_mutex);
707 eval(message_parts);
708 pthread_mutex_unlock(&syn_write_mutex);
709 } else if (command == "GetSlot")
710 {
711 // write methods are synchronized
712 pthread_mutex_lock(&syn_write_mutex);
713 sendMember(message_parts);
714 pthread_mutex_unlock(&syn_write_mutex);
715 } else if (command == "SetSlot")
716 {
717 // write methods are synchronized
718 pthread_mutex_lock(&syn_write_mutex);
719 setMember(message_parts);
720 pthread_mutex_unlock(&syn_write_mutex);
721 } else if (command == "LoadURL") // For instance X url <url> <target>
722 {
723 // write methods are synchronized
724 pthread_mutex_lock(&syn_write_mutex);
725 loadURL(message_parts);
726 pthread_mutex_unlock(&syn_write_mutex);
727 } else
728 {
729 // Nothing matched
730 IcedTeaPluginUtilities::printStringPtrVector("Error: Unable to process message: ", message_parts);
731 }
732
733 // Free memory for message_parts
734 IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
735
736 } else
737 {
738 pthread_mutex_lock(&message_queue_mutex);
739 if (message_queue->size() == 0)
740 {
741#ifndef __OS2__
742 pthread_cleanup_push(queue_wait_cleanup, &message_queue_mutex);
743#endif
744 pthread_cond_wait(&cond_message_available, &message_queue_mutex);
745#ifndef __OS2__
746 pthread_cleanup_pop(0);
747#endif
748 }
749 pthread_mutex_unlock(&message_queue_mutex);
750 }
751
752 message_parts = NULL;
753
754#ifdef __OS2__
755 if (queue_processor_data->stopRequested)
756 break;
757#else
758 pthread_testcancel();
759#endif
760 }
761
762#ifdef __OS2__
763 queue_cleanup(NULL);
764 queue_wait_cleanup(&message_queue_mutex);
765#else
766 pthread_cleanup_pop(1);
767#endif
768}
769
770/******************************************
771 * Functions delegated to the main thread *
772 ******************************************/
773
774void
775_setMember(void* data)
776{
777 std::string* value;
778
779 NPP instance;
780 NPVariant value_variant = NPVariant();
781 NPObject* member;
782 NPIdentifier property_identifier;
783
784
785 std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
786 instance = (NPP) parameters.at(0);
787 member = (NPObject*) parameters.at(1);
788 std::string* property_id = (std::string*) parameters.at(2);
789 value = (std::string*) parameters.at(3);
790 bool* int_identifier = (bool*) parameters.at(4);
791
792 if(*int_identifier==true)
793 property_identifier = browser_functions.getintidentifier(atoi(property_id->c_str()));
794 else
795 property_identifier = browser_functions.getstringidentifier(property_id->c_str());
796
797 PLUGIN_DEBUG("Setting %s on instance %p, object %p to value %s\n", IcedTeaPluginUtilities::NPIdentifierAsString(property_identifier).c_str(), instance, member, value->c_str());
798
799 IcedTeaPluginUtilities::javaResultToNPVariant(instance, value, &value_variant);
800
801 ((AsyncCallThreadData*) data)->call_successful = browser_functions.setproperty(instance, member, property_identifier, &value_variant);
802
803 ((AsyncCallThreadData*) data)->result_ready = true;
804}
805
806void
807_getMember(void* data)
808{
809 NPObject* parent_ptr;
810 NPVariant* member_ptr = new NPVariant();
811 std::string member_ptr_str = std::string();
812 NPP instance;
813
814 std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
815
816 instance = (NPP) parameters.at(0);
817
818 parent_ptr = (NPObject*) parameters.at(1);
819 std::string* member_id = (std::string*) parameters.at(2);
820 NPIdentifier member_identifier;
821
822 bool* int_identifier = (bool*) parameters.at(3);
823
824 if(*int_identifier==true)
825 member_identifier = browser_functions.getintidentifier(atoi(member_id->c_str()));
826 else
827 member_identifier = browser_functions.getstringidentifier(member_id->c_str());
828
829 // Get the NPVariant corresponding to this member
830 PLUGIN_DEBUG("Looking for %p %p %p (%s)\n", instance, parent_ptr, member_identifier, IcedTeaPluginUtilities::NPIdentifierAsString(member_identifier).c_str());
831
832 if (!browser_functions.hasproperty(instance, parent_ptr, member_identifier))
833 {
834 PLUGIN_ERROR("%s not found!\n", IcedTeaPluginUtilities::NPIdentifierAsString(member_identifier).c_str());
835 }
836 ((AsyncCallThreadData*) data)->call_successful = browser_functions.getproperty(instance, parent_ptr, member_identifier, member_ptr);
837
838 IcedTeaPluginUtilities::printNPVariant(*member_ptr);
839
840 if (((AsyncCallThreadData*) data)->call_successful)
841 {
842 createJavaObjectFromVariant(instance, *member_ptr, &member_ptr_str);
843 ((AsyncCallThreadData*) data)->result.append(member_ptr_str);
844 } else
845 {
846 ((AsyncCallThreadData*) data)->result.append("null");
847 }
848 ((AsyncCallThreadData*) data)->result_ready = true;
849
850 // store member -> instance link
851 IcedTeaPluginUtilities::storeInstanceID(member_ptr, instance);
852
853 PLUGIN_DEBUG("_getMember returning.\n");
854}
855
856void
857_eval(void* data)
858{
859 NPP instance;
860 NPObject* window_ptr;
861 std::string* script_str;
862 NPIdentifier script_identifier;
863 NPString script = NPString();
864 NPVariant* eval_variant = new NPVariant();
865 std::string eval_variant_str = std::string();
866
867 PLUGIN_DEBUG("_eval called\n");
868
869 std::vector<void*>* call_data = (std::vector<void*>*) data;
870
871 instance = (NPP) call_data->at(0);
872 window_ptr = (NPObject*) call_data->at(1);
873 script_str = (std::string*) call_data->at(2);
874
875 script.UTF8Characters = script_str->c_str();
876 script.UTF8Length = script_str->size();
877
878 PLUGIN_DEBUG("Evaluating: %s\n", script_str->c_str());
879
880 ((AsyncCallThreadData*) data)->call_successful = browser_functions.evaluate(instance, window_ptr, &script, eval_variant);
881 IcedTeaPluginUtilities::printNPVariant(*eval_variant);
882
883 if (((AsyncCallThreadData*) data)->call_successful)
884 {
885 if (eval_variant)
886 {
887 createJavaObjectFromVariant(instance, *eval_variant, &eval_variant_str);
888 } else
889 {
890 eval_variant_str = "0";
891 }
892 } else
893 {
894 eval_variant_str = "0";
895 }
896
897 ((AsyncCallThreadData*) data)->result.append(eval_variant_str);
898 ((AsyncCallThreadData*) data)->result_ready = true;
899
900 PLUGIN_DEBUG("_eval returning\n");
901}
902
903
904void
905_call(void* data)
906{
907 NPP instance;
908 NPObject* window_ptr;
909 std::string* function_name;
910 NPIdentifier function;
911 int* arg_count;
912 NPVariant* args;
913 NPVariant* call_result = new NPVariant();
914 std::string call_result_ptr_str = std::string();
915
916 PLUGIN_DEBUG("_call called\n");
917
918 std::vector<void*>* call_data = (std::vector<void*>*) data;
919
920 instance = (NPP) call_data->at(0);
921 window_ptr = (NPObject*) call_data->at(1);
922 function_name = (std::string*) call_data->at(2);
923
924 function = browser_functions.getstringidentifier(function_name->c_str());
925 arg_count = (int*) call_data->at(3);
926 args = (NPVariant*) call_data->at(4);
927
928 for (int i=0; i < *arg_count; i++) {
929 IcedTeaPluginUtilities::printNPVariant(args[i]);
930 }
931
932 PLUGIN_DEBUG("_calling\n");
933 ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, window_ptr, function, args, *arg_count, call_result);
934 PLUGIN_DEBUG("_called\n");
935
936 IcedTeaPluginUtilities::printNPVariant(*call_result);
937
938 if (((AsyncCallThreadData*) data)->call_successful)
939 {
940
941 if (call_result)
942 {
943 createJavaObjectFromVariant(instance, *call_result, &call_result_ptr_str);
944 } else
945 {
946 call_result_ptr_str = "0";
947 }
948 } else
949 {
950 call_result_ptr_str = "0";
951 }
952
953 ((AsyncCallThreadData*) data)->result.append(call_result_ptr_str);
954 ((AsyncCallThreadData*) data)->result_ready = true;
955
956 PLUGIN_DEBUG("_call returning\n");
957}
958
959void
960_getString(void* data)
961{
962 NPP instance;
963 NPObject* object;
964 NPIdentifier toString = browser_functions.getstringidentifier("toString");
965 NPVariant tostring_result;
966 std::string result = std::string();
967
968 std::vector<void*>* call_data = (std::vector<void*>*) data;
969 instance = (NPP) call_data->at(0);
970 NPVariant* variant = (NPVariant*) call_data->at(1);
971
972 PLUGIN_DEBUG("_getString called with %p and %p\n", instance, variant);
973
974 if (NPVARIANT_IS_OBJECT(*variant))
975 {
976 ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, NPVARIANT_TO_OBJECT(*variant), toString, NULL, 0, &tostring_result);
977 }
978 else
979 {
980 IcedTeaPluginUtilities::NPVariantToString(*variant, &result);
981 tostring_result = NPVariant();
982 STRINGZ_TO_NPVARIANT(result.c_str(), tostring_result);
983 ((AsyncCallThreadData*) data)->call_successful = true;
984 }
985
986 PLUGIN_DEBUG("ToString result: ");
987 IcedTeaPluginUtilities::printNPVariant(tostring_result);
988
989 if (((AsyncCallThreadData*) data)->call_successful)
990 {
991 createJavaObjectFromVariant(instance, tostring_result, &(((AsyncCallThreadData*) data)->result));
992 } else
993 {
994 ((AsyncCallThreadData*) data)->result.append("null");
995 }
996 ((AsyncCallThreadData*) data)->result_ready = true;
997
998 PLUGIN_DEBUG("_getString returning\n");
999}
1000
1001void
1002_loadURL(void* data) {
1003
1004 PLUGIN_DEBUG("_loadURL called\n");
1005
1006 NPP instance;
1007 std::string* url;
1008 std::string* target;
1009
1010 std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
1011
1012 instance = (NPP) parameters.at(0);
1013 url = (std::string*) parameters.at(1);
1014 target = (std::string*) parameters.at(2);
1015
1016 PLUGIN_DEBUG("Launching %s in %s\n", url->c_str(), target->c_str());
1017
1018 // Each decode can expand to 4 chars at the most
1019 gchar* decoded_url = (gchar*) calloc(strlen(url->c_str())*4 + 1, sizeof(gchar));
1020 IcedTeaPluginUtilities::decodeURL(url->c_str(), &decoded_url);
1021
1022 ((AsyncCallThreadData*) data)->call_successful =
1023 (*browser_functions.geturl) (instance, decoded_url, target->c_str());
1024
1025 ((AsyncCallThreadData*) data)->result_ready = true;
1026
1027 free(decoded_url);
1028 decoded_url = NULL;
1029
1030 PLUGIN_DEBUG("_loadURL returning %d\n", ((AsyncCallThreadData*) data)->call_successful);
1031}
Note: See TracBrowser for help on using the repository browser.