1
/* IcedTeaPluginUtils.cc
3
Copyright (C) 2009, 2010 Red Hat
5
This file is part of IcedTea.
7
IcedTea is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
12
IcedTea is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with IcedTea; see the file COPYING. If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library. Thus, the terms and
24
conditions of the GNU General Public License cover the whole
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module. An independent module is a module which is not derived from
34
or based on this library. If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so. If you do not wish to do so, delete this
37
exception statement from your version. */
39
#include "IcedTeaNPPlugin.h"
40
#include "IcedTeaScriptablePluginObject.h"
41
#include "IcedTeaPluginUtils.h"
44
* Misc. utility functions used by the plugin
47
/***********************************************
48
* Begin IcedTeaPluginUtilities implementation *
49
************************************************/
51
// Initialize static variables
52
int IcedTeaPluginUtilities::reference = -1;
53
pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER;
54
std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>();
55
std::map<std::string, NPObject*>* IcedTeaPluginUtilities::object_map = new std::map<std::string, NPObject*>();
57
/* Plugin async call queue */
58
static std::vector< PluginThreadCall* >* pendingPluginThreadRequests = new std::vector< PluginThreadCall* >();
61
* Given a context number, constructs a message prefix to send to Java
63
* @param context The context of the request
64
* @return The string prefix (allocated on heap)
68
IcedTeaPluginUtilities::constructMessagePrefix(int context, std::string *result)
70
std::string context_str = std::string();
72
itoa(context, &context_str);
74
result->append("context ");
75
result->append(context_str);
76
result->append(" reference -1");
81
* Given a context number, and reference number, constructs a message prefix to
84
* @param context The context of the request
85
* @param rerefence The reference number of the request
86
* @param result The message
90
IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference, std::string* result)
92
// Until security is implemented, use file:// source for _everything_
94
std::string context_str = std::string();
95
std::string reference_str = std::string();
97
itoa(context, &context_str);
98
itoa(reference, &reference_str);
100
*result += "context ";
101
result->append(context_str);
102
*result += " reference ";
103
result->append(reference_str);
107
* Given a context number, reference number, and source location, constructs
108
* a message prefix to send to Java
110
* @param context The context of the request
111
* @param rerefence The reference number of the request
112
* @param address The address for the script that made the request
113
* @param result The message
117
IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference,
121
std::string context_str = std::string();
122
std::string reference_str = std::string();
124
itoa(context, &context_str);
125
itoa(reference, &reference_str);
127
*result += "context ";
128
result->append(context_str);
129
*result += " reference ";
130
result->append(reference_str);
132
if (address.length() > 0)
135
result->append(address);
140
* Returns a string representation of a void pointer
142
* @param id The pointer
143
* @param result The string representation
147
IcedTeaPluginUtilities::JSIDToString(void* id, std::string* result)
150
char* id_str = (char*) malloc(sizeof(char)*20); // max = long long = 8446744073709551615 == 19 chars
152
if (sizeof(void*) == sizeof(long long))
154
sprintf(id_str, "%llu", id);
158
sprintf(id_str, "%lu", id); // else use long
161
result->append(id_str);
163
PLUGIN_DEBUG("Converting pointer %p to %s\n", id, id_str);
168
* Returns a void pointer from a string representation
170
* @param id_str The string representation
171
* @return The pointer
175
IcedTeaPluginUtilities::stringToJSID(std::string id_str)
178
if (sizeof(void*) == sizeof(long long))
180
PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str.c_str(), strtoull(id_str.c_str(), NULL, 0));
181
ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str.c_str(), NULL, 0));
184
PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str.c_str(), strtoul(id_str.c_str(), NULL, 0));
185
ptr = reinterpret_cast <void*> ((unsigned long) strtoul(id_str.c_str(), NULL, 0));
188
PLUGIN_DEBUG("Casted: %p\n", ptr);
194
* Returns a void pointer from a string representation
196
* @param id_str The pointer to the string representation
197
* @return The pointer
201
IcedTeaPluginUtilities::stringToJSID(std::string* id_str)
204
if (sizeof(void*) == sizeof(long long))
206
PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str->c_str(), strtoull(id_str->c_str(), NULL, 0));
207
ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str->c_str(), NULL, 0));
210
PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str->c_str(), strtoul(id_str->c_str(), NULL, 0));
211
ptr = reinterpret_cast <void*> ((unsigned long) strtoul(id_str->c_str(), NULL, 0));
214
PLUGIN_DEBUG("Casted: %p\n", ptr);
220
* Increments the global reference number and returns it.
222
* This function is thread-safe.
225
IcedTeaPluginUtilities::getReference()
227
pthread_mutex_lock(&reference_mutex);
229
// If we are nearing the max, reset
230
if (reference < -0x7FFFFFFF + 10) {
235
pthread_mutex_unlock(&reference_mutex);
241
* Decrements the global reference number.
243
* This function is thread-safe.
246
IcedTeaPluginUtilities::releaseReference()
248
// do nothing for now
252
* Converts integer to char*
254
* @param i The integer to convert to ascii
255
* @param result The resulting string
258
IcedTeaPluginUtilities::itoa(int i, std::string* result)
260
// largest possible integer is 10 digits long
261
char* int_str = (char*) malloc(sizeof(char)*11);
262
sprintf(int_str, "%d", i);
263
result->append(int_str);
269
* Frees memory from a string* vector
271
* The vector deconstructor will only delete string pointers upon being
272
* called. This function frees the associated string memory as well.
274
* @param v The vector whose strings are to be freed
277
IcedTeaPluginUtilities::freeStringPtrVector(std::vector<std::string*>* v)
281
for (int i=0; i < v->size(); i++) {
291
* Given a string, splits it on the given delimiters.
293
* @param str The string to split
294
* @param The delimiters to split on
295
* @return A string vector containing the aplit components
298
std::vector<std::string*>*
299
IcedTeaPluginUtilities::strSplit(const char* str, const char* delim)
301
std::vector<std::string*>* v = new std::vector<std::string*>();
302
v->reserve(strlen(str)/2);
305
// Tokening is done on a copy
306
copy = (char*) malloc (sizeof(char)*strlen(str) + 1);
310
tok_ptr = strtok (copy, delim);
312
while (tok_ptr != NULL)
314
// Allocation on heap since caller has no way to knowing how much will
315
// be needed. Make sure caller cleans up!
316
std::string* s = new std::string();
319
tok_ptr = strtok (NULL, " ");
326
* Given a unicode byte array, converts it to a UTF8 string
328
* The actual contents in the array may be surrounded by other data.
330
* e.g. with length 5, begin = 3,
331
* unicode_byte_array = "37 28 5 48 45 4c 4c 4f 9e 47":
333
* We'd start at 3 i.e. "48" and go on for 5 i.e. upto and including "4f".
334
* So we convert "48 45 4c 4c 4f" which is "hello"
336
* @param length The length of the string
337
* @param begin Where in the array to begin conversion
338
* @param result_unicode_str The return variable in which the
339
* converted string is placed
343
IcedTeaPluginUtilities::getUTF8String(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::string* result_unicode_str)
345
result_unicode_str->clear();
346
result_unicode_str->reserve(unicode_byte_array->size()/2);
347
for (int i = begin; i < begin+length; i++)
348
result_unicode_str->push_back((char) strtol(unicode_byte_array->at(i)->c_str(), NULL, 16));
350
PLUGIN_DEBUG("Converted UTF-8 string: %s. Length=%d\n", result_unicode_str->c_str(), result_unicode_str->length());
354
* Given a UTF8 string, converts it to a space delimited string of hex characters
356
* The first element in the return array is the length of the string
358
* e.g. "hello" would convert to: "5 48 45 4c 4c 4f"
360
* @param str The string to convert
361
* @param urt_str The result
365
IcedTeaPluginUtilities::convertStringToUTF8(std::string* str, std::string* utf_str)
367
std::ostringstream ostream;
369
std::string length = std::string();
370
itoa(str->length(), &length);
374
// UTF-8 characters are 4-bytes max + space + '\0'
375
char* hex_value = (char*) malloc(sizeof(char)*10);
377
for (int i = 0; i < str->length(); i++)
379
sprintf(hex_value, " %hx", str->at(i));
380
ostream << hex_value;
384
*utf_str = ostream.str();
387
PLUGIN_DEBUG("Converted %s to UTF-8 string %s\n", str->c_str(), utf_str->c_str());
391
* Given a unicode byte array, converts it to a UTF16LE/UCS-2 string
393
* This works in a manner similar to getUTF8String, except that it reads 2
394
* slots for each byte.
396
* @param length The length of the string
397
* @param begin Where in the array to begin conversion
398
* @param result_unicode_str The return variable in which the
399
* converted string is placed
402
IcedTeaPluginUtilities::getUTF16LEString(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::wstring* result_unicode_str)
407
if (plugin_debug) printf("Converted UTF-16LE string: ");
409
result_unicode_str->clear();
410
for (int i = begin; i < begin+length; i+=2)
412
int low = strtol(unicode_byte_array->at(i)->c_str(), NULL, 16);
413
int high = strtol(unicode_byte_array->at(i+1)->c_str(), NULL, 16);
415
c = ((high << 8) | low);
417
if ((c >= 'a' && c <= 'z') ||
418
(c >= 'A' && c <= 'Z') ||
419
(c >= '0' && c <= '9'))
421
if (plugin_debug) printf("%c", c);
424
result_unicode_str->push_back(c);
427
// not routing via debug print macros due to wide-string issues
428
if (plugin_debug) printf(". Length=%d\n", result_unicode_str->length());
432
* Prints the given string vector (if debug is true)
434
* @param prefix The prefix to print before printing the vector contents
435
* @param cv The string vector whose contents are to be printed
438
IcedTeaPluginUtilities::printStringVector(const char* prefix, std::vector<std::string>* str_vector)
441
// This is a CPU intensive function. Run only if debugging
445
std::string* str = new std::string();
447
for (int i=0; i < str_vector->size(); i++)
449
*str += str_vector->at(i);
451
if (i != str_vector->size() - 1)
457
PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
463
IcedTeaPluginUtilities::getSourceFromInstance(NPP instance)
465
// At the moment, src cannot be securely fetched via NPAPI
467
// http://www.mail-archive.com/chromium-dev@googlegroups.com/msg04872.html
469
// Since we use the insecure window.location.href attribute to compute
470
// source, we cannot use it to make security decisions. Therefore,
471
// instance associated source will always return empty
473
//ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
474
//return (data->source) ? data->source : "";
476
return "http://null.null";
480
* Stores a window pointer <-> instance mapping
482
* @param member_ptr The pointer key
483
* @param instance The instance to associate with this pointer
487
IcedTeaPluginUtilities::storeInstanceID(void* member_ptr, NPP instance)
489
PLUGIN_DEBUG("Storing instance %p with key %p\n", instance, member_ptr);
490
instance_map->insert(std::make_pair(member_ptr, instance));
494
* Removes a window pointer <-> instance mapping
496
* @param member_ptr The key to remove
500
IcedTeaPluginUtilities::removeInstanceID(void* member_ptr)
502
PLUGIN_DEBUG("Removing key %p from instance map\n", member_ptr);
503
instance_map->erase(member_ptr);
507
* Removes all mappings to a given instance, and all associated objects
510
IcedTeaPluginUtilities::invalidateInstance(NPP instance)
512
PLUGIN_DEBUG("Invalidating instance %p\n", instance);
514
std::map<void*,NPP>::iterator iterator;
516
for (iterator = instance_map->begin(); iterator != instance_map->end(); )
518
if ((*iterator).second == instance)
520
instance_map->erase(iterator++);
530
* Given the window pointer, returns the instance associated with it
532
* @param member_ptr The pointer key
533
* @return The associated instance
537
IcedTeaPluginUtilities::getInstanceFromMemberPtr(void* member_ptr)
541
PLUGIN_DEBUG("getInstanceFromMemberPtr looking for %p\n", member_ptr);
543
std::map<void*, NPP>::iterator iterator = instance_map->find(member_ptr);
545
if (iterator != instance_map->end())
547
instance = instance_map->find(member_ptr)->second;
548
PLUGIN_DEBUG("getInstanceFromMemberPtr found %p. Instance = %p\n", member_ptr, instance);
555
* Given a java id key ('classid:instanceid'), returns the associated valid NPObject, if any
558
* @return The associated active NPObject, NULL otherwise
562
IcedTeaPluginUtilities::getNPObjectFromJavaKey(std::string key)
565
NPObject* object = NULL;
566
PLUGIN_DEBUG("getNPObjectFromJavaKey looking for %s\n", key.c_str());
568
std::map<std::string, NPObject*>::iterator iterator = object_map->find(key);
570
if (iterator != object_map->end())
572
NPObject* mapped_object = object_map->find(key)->second;
574
if (getInstanceFromMemberPtr(mapped_object) != NULL)
576
object = mapped_object;
577
PLUGIN_DEBUG("getNPObjectFromJavaKey found %s. NPObject = %p\n", key.c_str(), object);
585
* Stores a java id key <-> NPObject mapping
587
* @param key The Java ID Key
588
* @param object The object to map to
592
IcedTeaPluginUtilities::storeObjectMapping(std::string key, NPObject* object)
594
PLUGIN_DEBUG("Storing object %p with key %s\n", object, key.c_str());
595
object_map->insert(std::make_pair(key, object));
599
* Removes a java id key <-> NPObject mapping
601
* @param key The key to remove
605
IcedTeaPluginUtilities::removeObjectMapping(std::string key)
607
PLUGIN_DEBUG("Removing key %s from object map\n", key.c_str());
608
object_map->erase(key);
612
* Similar to printStringVector, but takes a vector of string pointers instead
614
* @param prefix The prefix to print before printing the vector contents
615
* @param cv The string* vector whose contents are to be printed
619
IcedTeaPluginUtilities::printStringPtrVector(const char* prefix, std::vector<std::string*>* str_ptr_vector)
621
// This is a CPU intensive function. Run only if debugging
625
std::string* str = new std::string();
627
for (int i=0; i < str_ptr_vector->size(); i++)
629
*str += *(str_ptr_vector->at(i));
631
if (i != str_ptr_vector->size() - 1)
637
PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
643
IcedTeaPluginUtilities::printNPVariant(NPVariant variant)
645
// This is a CPU intensive function. Run only if debugging
649
if (NPVARIANT_IS_VOID(variant))
651
PLUGIN_DEBUG("VOID %d\n", variant);
653
else if (NPVARIANT_IS_NULL(variant))
655
PLUGIN_DEBUG("NULL\n", variant);
657
else if (NPVARIANT_IS_BOOLEAN(variant))
659
PLUGIN_DEBUG("BOOL: %d\n", NPVARIANT_TO_BOOLEAN(variant));
661
else if (NPVARIANT_IS_INT32(variant))
663
PLUGIN_DEBUG("INT32: %d\n", NPVARIANT_TO_INT32(variant));
665
else if (NPVARIANT_IS_DOUBLE(variant))
667
PLUGIN_DEBUG("DOUBLE: %f\n", NPVARIANT_TO_DOUBLE(variant));
669
else if (NPVARIANT_IS_STRING(variant))
671
#if MOZILLA_VERSION_COLLAPSED < 1090200
672
PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).utf8characters);
674
PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).UTF8Characters);
679
PLUGIN_DEBUG("OBJ: %p\n", NPVARIANT_TO_OBJECT(variant));
684
IcedTeaPluginUtilities::NPVariantToString(NPVariant variant, std::string* result)
686
char* str = (char*) malloc(sizeof(char)*32); // enough for everything except string
688
if (NPVARIANT_IS_VOID(variant))
690
sprintf(str, "%p", variant);
692
else if (NPVARIANT_IS_NULL(variant))
694
sprintf(str, "NULL");
696
else if (NPVARIANT_IS_BOOLEAN(variant))
698
if (NPVARIANT_TO_BOOLEAN(variant))
699
sprintf(str, "true");
701
sprintf(str, "false");
703
else if (NPVARIANT_IS_INT32(variant))
705
sprintf(str, "%d", NPVARIANT_TO_INT32(variant));
707
else if (NPVARIANT_IS_DOUBLE(variant))
709
sprintf(str, "%f", NPVARIANT_TO_DOUBLE(variant));;
711
else if (NPVARIANT_IS_STRING(variant))
714
#if MOZILLA_VERSION_COLLAPSED < 1090200
715
str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).utf8length);
716
sprintf(str, "%s", NPVARIANT_TO_STRING(variant).utf8characters);
718
str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).UTF8Length);
719
sprintf(str, "%s", NPVARIANT_TO_STRING(variant).UTF8Characters);
724
sprintf(str, "[Object %p]", variant);
732
IcedTeaPluginUtilities::javaResultToNPVariant(NPP instance,
733
std::string* java_value,
736
JavaRequestProcessor java_request = JavaRequestProcessor();
737
JavaResultData* java_result;
739
if (java_value->find("literalreturn") == 0)
741
// 'literalreturn ' == 14 to skip
742
std::string value = java_value->substr(14);
744
// VOID/BOOLEAN/NUMBER
748
PLUGIN_DEBUG("Method call returned void\n");
749
VOID_TO_NPVARIANT(*variant);
750
} else if (value == "null")
752
PLUGIN_DEBUG("Method call returned null\n");
753
NULL_TO_NPVARIANT(*variant);
754
}else if (value == "true")
756
PLUGIN_DEBUG("Method call returned a boolean (true)\n");
757
BOOLEAN_TO_NPVARIANT(true, *variant);
758
} else if (value == "false")
760
PLUGIN_DEBUG("Method call returned a boolean (false)\n");
761
BOOLEAN_TO_NPVARIANT(false, *variant);
764
double d = strtod(value.c_str(), NULL);
766
// See if it is convertible to int
767
if (value.find(".") != std::string::npos ||
768
d < -(0x7fffffffL - 1L) ||
771
PLUGIN_DEBUG("Method call returned a double %f\n", d);
772
DOUBLE_TO_NPVARIANT(d, *variant);
775
int32_t i = (int32_t) d;
776
PLUGIN_DEBUG("Method call returned an int %d\n", i);
777
INT32_TO_NPVARIANT(i, *variant);
781
// Else this is a complex java object
783
// To keep code a little bit cleaner, we create variables with proper descriptive names
784
std::string return_obj_instance_id = std::string();
785
std::string return_obj_class_id = std::string();
786
std::string return_obj_class_name = std::string();
787
return_obj_instance_id.append(*java_value);
789
// Find out the class name first, because string is a special case
790
java_result = java_request.getClassName(return_obj_instance_id);
792
if (java_result->error_occurred)
797
return_obj_class_name.append(*(java_result->return_string));
799
if (return_obj_class_name == "java.lang.String")
801
// String is a special case as NPVariant can handle it directly
802
java_result = java_request.getString(return_obj_instance_id);
804
if (java_result->error_occurred)
809
// needs to be on the heap
810
NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
811
strcpy(return_str, java_result->return_string->c_str());
813
PLUGIN_DEBUG("Method call returned a string: \"%s\"\n", return_str);
814
STRINGZ_TO_NPVARIANT(return_str, *variant);
818
// Else this is a regular class. Reference the class object so
819
// we can construct an NPObject with it and the instance
820
java_result = java_request.getClassID(return_obj_instance_id);
822
if (java_result->error_occurred)
827
return_obj_class_id.append(*(java_result->return_string));
831
if (return_obj_class_name.find('[') == 0) // array
832
obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
834
return_obj_class_id, return_obj_instance_id, true);
836
obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
838
return_obj_class_id, return_obj_instance_id, false);
840
OBJECT_TO_NPVARIANT(obj, *variant);
848
IcedTeaPluginUtilities::isObjectJSArray(NPP instance, NPObject* object)
851
NPVariant constructor_v = NPVariant();
852
NPIdentifier constructor_id = browser_functions.getstringidentifier("constructor");
853
browser_functions.getproperty(instance, object, constructor_id, &constructor_v);
854
IcedTeaPluginUtilities::printNPVariant(constructor_v);
856
// void constructor => not an array
857
if (NPVARIANT_IS_VOID(constructor_v))
860
NPObject* constructor = NPVARIANT_TO_OBJECT(constructor_v);
862
NPVariant constructor_str;
863
NPIdentifier toString = browser_functions.getstringidentifier("toString");
864
browser_functions.invoke(instance, constructor, toString, NULL, 0, &constructor_str);
865
IcedTeaPluginUtilities::printNPVariant(constructor_str);
867
std::string constructor_name = std::string();
869
#if MOZILLA_VERSION_COLLAPSED < 1090200
870
constructor_name.append(NPVARIANT_TO_STRING(constructor_str).utf8characters);
872
constructor_name.append(NPVARIANT_TO_STRING(constructor_str).UTF8Characters);
875
PLUGIN_DEBUG("Constructor for NPObject is %s\n", constructor_name.c_str());
877
return constructor_name.find("function Array") == 0;
881
IcedTeaPluginUtilities::decodeURL(const gchar* url, gchar** decoded_url)
884
PLUGIN_DEBUG("GOT URL: %s -- %s\n", url, *decoded_url);
885
int length = strlen(url);
886
for (int i=0; i < length; i++)
888
if (url[i] == '%' && i < length - 2)
890
unsigned char code1 = (unsigned char) url[i+1];
891
unsigned char code2 = (unsigned char) url[i+2];
893
if (!IS_VALID_HEX(&code1) || !IS_VALID_HEX(&code2))
896
// Convert hex value to integer
897
int converted1 = HEX_TO_INT(&code1);
898
int converted2 = HEX_TO_INT(&code2);
900
// bitshift 4 to simulate *16
901
int value = (converted1 << 4) + converted2;
902
char decoded = value;
904
strncat(*decoded_url, &decoded, 1);
909
strncat(*decoded_url, &url[i], 1);
913
PLUGIN_DEBUG("SENDING URL: %s\n", *decoded_url);
918
* Posts a function for execution on the plug-in thread and wait for result.
920
* @param instance The NPP instance
921
* @param func The function to post
922
* @param data Arguments to *func
925
IcedTeaPluginUtilities::callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data)
929
struct timespec curr_t;
930
clock_gettime(CLOCK_REALTIME, &t);
931
t.tv_sec += REQUESTTIMEOUT; // timeout
934
postPluginThreadAsyncCall(instance, func, data);
938
clock_gettime(CLOCK_REALTIME, &curr_t);
939
if (data != NULL && !data->result_ready && (curr_t.tv_sec < t.tv_sec))
951
* Posts a request that needs to be handled in a plugin thread.
953
* @param instance The plugin instance
954
* @param func The function to execute
955
* @param userData The userData for the function to consume/write to
956
* @return if the call was posted successfully
960
IcedTeaPluginUtilities::postPluginThreadAsyncCall(NPP instance, void (*func) (void *), void* data)
964
PluginThreadCall* call = new PluginThreadCall();
965
call->instance = instance;
967
call->userData = data;
969
pthread_mutex_lock(&pluginAsyncCallMutex);
970
pendingPluginThreadRequests->push_back(call);
971
pthread_mutex_unlock(&pluginAsyncCallMutex);
973
browser_functions.pluginthreadasynccall(instance, &processAsyncCallQueue, NULL); // Always returns immediately
975
PLUGIN_DEBUG("Pushed back call evt %p\n", call);
981
PLUGIN_DEBUG("Instance is not active. Call rejected.\n");
986
* Runs through the async call wait queue and executes all calls
988
* @param param Ignored -- required to conform to NPN_PluginThreadAsynCall API
991
processAsyncCallQueue(void* param /* ignored */)
994
PluginThreadCall* call = NULL;
996
pthread_mutex_lock(&pluginAsyncCallMutex);
997
if (pendingPluginThreadRequests->size() > 0)
999
call = pendingPluginThreadRequests->front();
1000
pendingPluginThreadRequests->erase(pendingPluginThreadRequests->begin());
1002
pthread_mutex_unlock(&pluginAsyncCallMutex);
1006
PLUGIN_DEBUG("Processing call evt %p\n", call);
1007
call->func(call->userData);
1008
PLUGIN_DEBUG("Call evt %p processed\n", call);
1018
/******************************************
1019
* Begin JavaMessageSender implementation *
1020
******************************************
1022
* This implementation is very simple and is therefore folded into this file
1023
* rather than a new one.
1027
* Sends to the Java side
1029
* @param message The message to send.
1030
* @param returns whether the message was consumable (always true)
1034
JavaMessageSender::newMessageOnBus(const char* message)
1036
char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
1037
strcpy(msg, message);
1038
plugin_send_message_to_appletviewer(msg);
1043
// Always successful
1047
/***********************************
1048
* Begin MessageBus implementation *
1049
***********************************/
1054
* Initializes the mutexes needed by the other functions.
1056
MessageBus::MessageBus()
1060
ret = pthread_mutex_init(&subscriber_mutex, NULL);
1063
PLUGIN_DEBUG("Error: Unable to initialize subscriber mutex: %d\n", ret);
1065
ret = pthread_mutex_init(&msg_queue_mutex, NULL);
1067
PLUGIN_DEBUG("Error: Unable to initialize message queue mutex: %d\n", ret);
1069
PLUGIN_DEBUG("Mutexs %p and %p initialized\n", &subscriber_mutex, &msg_queue_mutex);
1075
* Destroy the mutexes initialized by the constructor.
1078
MessageBus::~MessageBus()
1080
PLUGIN_DEBUG("MessageBus::~MessageBus\n");
1084
ret = pthread_mutex_destroy(&subscriber_mutex);
1086
PLUGIN_DEBUG("Error: Unable to destroy subscriber mutex: %d\n", ret);
1088
ret = pthread_mutex_destroy(&msg_queue_mutex);
1090
PLUGIN_DEBUG("Error: Unable to destroy message queue mutex: %d\n", ret);
1094
* Adds the given BusSubscriber as a subscriber to self
1096
* @param b The BusSubscriber to subscribe
1099
MessageBus::subscribe(BusSubscriber* b)
1101
// Applets may initialize in parallel. So lock before pushing.
1103
PLUGIN_DEBUG("Subscribing %p to bus %p\n", b, this);
1104
pthread_mutex_lock(&subscriber_mutex);
1105
subscribers.push_back(b);
1106
pthread_mutex_unlock(&subscriber_mutex);
1110
* Removes the given BusSubscriber from the subscriber list
1112
* @param b The BusSubscriber to ubsubscribe
1115
MessageBus::unSubscribe(BusSubscriber* b)
1117
// Applets may initialize in parallel. So lock before pushing.
1119
PLUGIN_DEBUG("Un-subscribing %p from bus %p\n", b, this);
1120
pthread_mutex_lock(&subscriber_mutex);
1121
subscribers.remove(b);
1122
pthread_mutex_unlock(&subscriber_mutex);
1126
* Notifies all subscribers with the given message
1128
* @param message The message to send to the subscribers
1131
MessageBus::post(const char* message)
1133
char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
1134
bool message_consumed = false;
1136
// consumer frees this memory
1137
strcpy(msg, message);
1139
PLUGIN_DEBUG("Trying to lock %p...\n", &msg_queue_mutex);
1140
pthread_mutex_lock(&subscriber_mutex);
1142
PLUGIN_DEBUG("Message %s received on bus. Notifying subscribers.\n", msg);
1144
std::list<BusSubscriber*>::const_iterator i;
1145
for( i = subscribers.begin(); i != subscribers.end() && !message_consumed; ++i ) {
1146
PLUGIN_DEBUG("Notifying subscriber %p of %s\n", *i, msg);
1147
message_consumed = ((BusSubscriber*) *i)->newMessageOnBus(msg);
1150
pthread_mutex_unlock(&subscriber_mutex);
1152
if (!message_consumed)
1153
PLUGIN_DEBUG("Warning: No consumer found for message %s\n", msg);
1155
PLUGIN_DEBUG("%p unlocked...\n", &msg_queue_mutex);