Mercurial > hg > release > icedtea-web-1.8
changeset 573:172a5691e70d
Refactor IcedTeaPluginUtilities::javaResultToNPVariant into multiple functions
author | Adam Domurad <adomurad@redhat.com> |
---|---|
date | Fri, 30 Nov 2012 13:08:45 -0500 |
parents | 0a968aa027ea |
children | eedc15145aa6 |
files | ChangeLog plugin/icedteanp/IcedTeaPluginUtils.cc plugin/icedteanp/IcedTeaPluginUtils.h tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc |
diffstat | 4 files changed, 180 insertions(+), 100 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Fri Nov 30 12:38:03 2012 -0500 +++ b/ChangeLog Fri Nov 30 13:08:45 2012 -0500 @@ -1,3 +1,14 @@ +2012-11-30 Adam Domurad <adomurad@redhat.com> + + Breaks up IcedTeaPluginUtilities::javaResultToNPVariant into multiple, + more manageable parts. + * plugin/icedteanp/IcedTeaPluginUtils.cc: Make three helper functions + for the different cases. Two new helper functions for converting from + std::string to NPString and NPVariant. + * plugin/icedteanp/IcedTeaPluginUtils.h: Two new helper functions. + * tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc: Tests for the new + NPString and NPVariant from std::string functions. + 2012-11-30 Adam Domurad <adomurad@redhat.com> Added a simple mechanism for mocking functions in the browser function
--- a/plugin/icedteanp/IcedTeaPluginUtils.cc Fri Nov 30 12:38:03 2012 -0500 +++ b/plugin/icedteanp/IcedTeaPluginUtils.cc Fri Nov 30 13:08:45 2012 -0500 @@ -715,116 +715,124 @@ } } +/** + * Convert either a void, boolean, or a number + */ +static void +javaPrimitiveResultToNPVariant(const std::string& value, NPVariant* variant) +{ + if (value == "void") + { + PLUGIN_DEBUG("Method call returned void\n"); + VOID_TO_NPVARIANT(*variant); + } else if (value == "null") + { + PLUGIN_DEBUG("Method call returned null\n"); + NULL_TO_NPVARIANT(*variant); + } else if (value == "true") + { + PLUGIN_DEBUG("Method call returned a boolean (true)\n"); + BOOLEAN_TO_NPVARIANT(true, *variant); + } else if (value == "false") + { + PLUGIN_DEBUG("Method call returned a boolean (false)\n"); + BOOLEAN_TO_NPVARIANT(false, *variant); + } else + { + double d = strtod(value.c_str(), NULL); + + // See if it is convertible to int + if (value.find(".") != std::string::npos || d < -(0x7fffffffL - 1L) || d > 0x7fffffffL) + { + PLUGIN_DEBUG("Method call returned a double %f\n", d); + DOUBLE_TO_NPVARIANT(d, *variant); + } else + { + int32_t i = (int32_t) d; + PLUGIN_DEBUG("Method call returned an int %d\n", i); + INT32_TO_NPVARIANT(i, *variant); + } + } +} + +static bool +javaStringResultToNPVariant(const std::string& jobject_id, NPVariant* variant) +{ + JavaRequestProcessor jrequest_processor; + JavaResultData* jstring_result = jrequest_processor.getString(jobject_id); + + if (jstring_result->error_occurred) + { + return false; + } + + std::string str = *jstring_result->return_string; + + PLUGIN_DEBUG( "Method call returned a string:\"%s\"\n", str.c_str()); + + *variant = IcedTeaPluginUtilities::NPVariantStringCopy(str); + + return true; +} + +static bool +javaObjectResultToNPVariant(NPP instance, const std::string& jobject_id, NPVariant* variant) +{ + // Reference the class object so we can construct an NPObject with it and the instance + + JavaRequestProcessor jrequest_processor; + JavaResultData* jclass_result = jrequest_processor.getClassID(jobject_id); + + if (jclass_result->error_occurred) + { + return false; + } + + std::string jclass_id = *jclass_result->return_string; + + NPObject* obj; + if (jclass_id.at(0) == '[') // array + { + obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, jclass_id, + jobject_id, true); + } else + { + obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, jclass_id, + jobject_id, false); + } + + OBJECT_TO_NPVARIANT(obj, *variant); + + return true; +} + bool IcedTeaPluginUtilities::javaResultToNPVariant(NPP instance, - std::string* java_value, - NPVariant* variant) + std::string* java_value, NPVariant* variant) { - JavaRequestProcessor java_request = JavaRequestProcessor(); - JavaResultData* java_result; - - if (java_value->find("literalreturn") == 0) + int literal_n = sizeof("literalreturn"); // Accounts for one space char + if (strncmp("literalreturn ", java_value->c_str(), literal_n) == 0) { - // 'literalreturn ' == 14 to skip - std::string value = java_value->substr(14); - - // VOID/BOOLEAN/NUMBER + javaPrimitiveResultToNPVariant(java_value->substr(literal_n), variant); + } else + { + std::string jobject_id = *java_value; - if (value == "void") - { - PLUGIN_DEBUG("Method call returned void\n"); - VOID_TO_NPVARIANT(*variant); - } else if (value == "null") - { - PLUGIN_DEBUG("Method call returned null\n"); - NULL_TO_NPVARIANT(*variant); - }else if (value == "true") - { - PLUGIN_DEBUG("Method call returned a boolean (true)\n"); - BOOLEAN_TO_NPVARIANT(true, *variant); - } else if (value == "false") - { - PLUGIN_DEBUG("Method call returned a boolean (false)\n"); - BOOLEAN_TO_NPVARIANT(false, *variant); - } else - { - double d = strtod(value.c_str(), NULL); + JavaRequestProcessor jrequest_processor; + JavaResultData* jclassname_result = jrequest_processor.getClassName(jobject_id); - // See if it is convertible to int - if (value.find(".") != std::string::npos || - d < -(0x7fffffffL - 1L) || - d > 0x7fffffffL) - { - PLUGIN_DEBUG("Method call returned a double %f\n", d); - DOUBLE_TO_NPVARIANT(d, *variant); - } else - { - int32_t i = (int32_t) d; - PLUGIN_DEBUG("Method call returned an int %d\n", i); - INT32_TO_NPVARIANT(i, *variant); - } - } - } else { - // Else this is a complex java object - - // To keep code a little bit cleaner, we create variables with proper descriptive names - std::string return_obj_instance_id = std::string(); - std::string return_obj_class_id = std::string(); - std::string return_obj_class_name = std::string(); - return_obj_instance_id.append(*java_value); - - // Find out the class name first, because string is a special case - java_result = java_request.getClassName(return_obj_instance_id); - - if (java_result->error_occurred) + if (jclassname_result->error_occurred) { return false; } - return_obj_class_name.append(*(java_result->return_string)); - - if (return_obj_class_name == "java.lang.String") + // Special-case for NPString if string + if (*jclassname_result->return_string == "java.lang.String") { - // String is a special case as NPVariant can handle it directly - java_result = java_request.getString(return_obj_instance_id); - - if (java_result->error_occurred) - { - return false; - } - - // needs to be on the heap - NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1); - strcpy(return_str, java_result->return_string->c_str()); - - PLUGIN_DEBUG("Method call returned a string: \"%s\"\n", return_str); - STRINGZ_TO_NPVARIANT(return_str, *variant); - - } else { - - // Else this is a regular class. Reference the class object so - // we can construct an NPObject with it and the instance - java_result = java_request.getClassID(return_obj_instance_id); - - if (java_result->error_occurred) - { - return false; - } - - return_obj_class_id.append(*(java_result->return_string)); - - NPObject* obj; - - if (return_obj_class_name.find('[') == 0) // array - obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object( - instance, - return_obj_class_id, return_obj_instance_id, true); - else - obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object( - instance, - return_obj_class_id, return_obj_instance_id, false); - - OBJECT_TO_NPVARIANT(obj, *variant); + return javaStringResultToNPVariant(jobject_id, variant); + } else // Else this needs a java object wrapper + { + return javaObjectResultToNPVariant(instance, jobject_id, variant); } } @@ -916,6 +924,25 @@ * @param func The function to post * @param data Arguments to *func */ +NPString IcedTeaPluginUtilities::NPStringCopy(const std::string& result) { + char* utf8 = (char*)browser_functions.memalloc(result.size() + 1); + strncpy(utf8, result.c_str(), result.size() + 1); + + NPString npstr = {utf8, result.size()}; + return npstr; +} + +NPVariant IcedTeaPluginUtilities::NPVariantStringCopy(const std::string& result) { + NPString npstr = NPStringCopy(result); + NPVariant npvar; +#if MOZILLA_VERSION_COLLAPSED < 1090200 + STRINGN_TO_NPVARIANT(npstr.utf8characters, npstr.utf8length, npvar); +#else + STRINGN_TO_NPVARIANT(npstr.UTF8Characters, npstr.UTF8Length, npvar); +#endif + return npvar; +} + void IcedTeaPluginUtilities::callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data) {
--- a/plugin/icedteanp/IcedTeaPluginUtils.h Fri Nov 30 12:38:03 2012 -0500 +++ b/plugin/icedteanp/IcedTeaPluginUtils.h Fri Nov 30 13:08:45 2012 -0500 @@ -211,6 +211,12 @@ /* Copies a variant data type into a C++ string */ static std::string NPVariantAsString(NPVariant variant); + /* This must be freed with browserfunctions.memfree */ + static NPString NPStringCopy(const std::string& result); + + /* This must be freed with browserfunctions.releasevariantvalue */ + static NPVariant NPVariantStringCopy(const std::string& result); + /* Frees the given vector and the strings that its contents point to */ static void freeStringPtrVector(std::vector<std::string*>* v); @@ -242,7 +248,7 @@ static void printNPVariant(NPVariant variant); - static void NPVariantToString(NPVariant variant, std::string* result); + static void NPVariantToString(NPVariant variant, std::string* result); static bool javaResultToNPVariant(NPP instance, std::string* java_result,
--- a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc Fri Nov 30 12:38:03 2012 -0500 +++ b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc Fri Nov 30 13:08:45 2012 -0500 @@ -37,7 +37,11 @@ #include <UnitTest++.h> #include <npapi.h> + +#include "browser_mock.h" + #include "IcedTeaPluginUtils.h" +#include "IcedTeaNPPlugin.h" TEST(NPVariantAsString) { NPVariant var; @@ -45,4 +49,36 @@ std::string cppstr = IcedTeaPluginUtilities::NPVariantAsString(var); CHECK(cppstr == "test"); + } + +TEST(NPStringCopy) { + std::string cppstr = "test"; + NPString npstr = IcedTeaPluginUtilities::NPStringCopy(cppstr); + + CHECK_EQUAL(4, npstr.UTF8Length); + CHECK_EQUAL("test", npstr.UTF8Characters); + + // NPAPI states that browser allocation function should be used for NPString/NPVariant + CHECK_EQUAL(1, browsermock_unfreed_allocations()); + + browser_functions.memfree((void*) npstr.UTF8Characters); + + CHECK_EQUAL(0, browsermock_unfreed_allocations()); +} + +TEST(NPVariantStringCopy) { + std::string cppstr = "test"; + NPVariant npvar = IcedTeaPluginUtilities::NPVariantStringCopy(cppstr); + + CHECK_EQUAL(NPVariantType_String, npvar.type); + + CHECK_EQUAL(4, npvar.value.stringValue.UTF8Length); + CHECK_EQUAL("test", npvar.value.stringValue.UTF8Characters); + + CHECK_EQUAL(1, browsermock_unfreed_allocations()); + + browser_functions.memfree((void*) npvar.value.stringValue.UTF8Characters); + + CHECK_EQUAL(0, browsermock_unfreed_allocations()); +}