Index: tools/nixysa/nixysa/static_glue/npapi/common.cc |
=================================================================== |
--- tools/nixysa/nixysa/static_glue/npapi/common.cc (revision 0) |
+++ tools/nixysa/nixysa/static_glue/npapi/common.cc (revision 0) |
@@ -0,0 +1,423 @@ |
+// Copyright 2008 Google Inc. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include <assert.h> |
+#include <string.h> |
+ |
+#ifdef OS_WINDOWS |
+#include <windows.h> |
+#define snprintf _snprintf |
+#endif |
+ |
+#ifdef OS_MACOSX |
+#include <Carbon/Carbon.h> |
+#endif |
+ |
+#ifdef OS_LINUX |
+#include <stdio.h> |
+#endif |
+ |
+#include <npapi.h> |
+#include <npruntime.h> |
+#include <string> |
+#include "common.h" |
+#include "npn_api.h" |
+ |
+//------------------------------------------------------------------------------ |
+// UTF8ToString16 |
+//------------------------------------------------------------------------------ |
+bool UTF8ToString16(const char *in, int len, std::wstring *out16) { |
+ assert(in); |
+ assert(len >= 0); |
+ assert(out16); |
+ |
+ if (len == 0) { |
+ *out16 = L""; |
+ return true; |
+ } |
+ |
+#ifdef OS_MACOSX |
+ CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, in, |
+ kCFStringEncodingUTF8); |
+ if (!cfStr) |
+ return false; |
+ CFDataRef cfData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, |
+ cfStr, kCFStringEncodingUTF32, 0); |
+ CFRelease(cfStr); |
+ if (!cfData) |
+ return false; |
+ int out_byte_len = CFDataGetLength(cfData); |
+ out_byte_len -= sizeof(wchar_t); // don't count the 32 bit BOM char at start |
+ int out_len = out_byte_len / sizeof(wchar_t); |
+ wchar_t *tmp = new wchar_t[out_len + 1]; |
+ // start after the BOM, hence sizeof(wchar_t) |
+ CFDataGetBytes(cfData, CFRangeMake(sizeof(wchar_t), out_byte_len), |
+ (UInt8*)tmp); |
+ CFRelease(cfData); |
+ tmp[out_len] = 0; |
+ out16->assign(tmp); |
+ delete[] tmp; |
+#endif |
+ |
+#ifdef OS_WINDOWS |
+ int out_len = MultiByteToWideChar(CP_UTF8, 0, in, len, NULL, 0); |
+ if (out_len <= 0) |
+ return false; |
+ wchar_t *tmp = new wchar_t[out_len + 1]; |
+ out_len = MultiByteToWideChar(CP_UTF8, 0, in, len, tmp, out_len); |
+ if (out_len <= 0) { |
+ delete[] tmp; |
+ return false; |
+ } |
+ tmp[out_len] = 0; |
+ out16->assign(tmp); |
+ delete[] tmp; |
+#endif |
+ |
+#ifdef OS_LINUX |
+ // TODO: this is incorrect. Fix it. |
+ std::string string_in(in, len); |
+ *out16 = std::wstring(string_in.begin(), string_in.end()); |
+#endif |
+ return true; |
+} |
+ |
+//------------------------------------------------------------------------------ |
+// String16ToUTF8 |
+//------------------------------------------------------------------------------ |
+bool String16ToUTF8(const wchar_t *in, int len, std::string *out8) { |
+ assert(in); |
+ assert(len >= 0); |
+ assert(out8); |
+ |
+ if (len == 0) { |
+ *out8 = ""; |
+ return true; |
+ } |
+ |
+#ifdef OS_MACOSX |
+ CFDataRef cfWCharData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)in, |
+ len * sizeof(wchar_t)); |
+ CFStringRef cfStr = CFStringCreateFromExternalRepresentation( |
+ kCFAllocatorDefault, cfWCharData, |
+ kCFStringEncodingUTF32); |
+ CFRelease(cfWCharData); |
+ CFDataRef cfUTF8Data = CFStringCreateExternalRepresentation( |
+ kCFAllocatorDefault, |
+ cfStr, kCFStringEncodingUTF8, 0); |
+ CFRelease(cfStr); |
+ int out_len = CFDataGetLength(cfUTF8Data); |
+ char *tmp = new char[out_len + 1]; |
+ CFDataGetBytes(cfUTF8Data, CFRangeMake(0, out_len), (UInt8*)tmp); |
+ tmp[out_len] = '\0'; |
+ CFRelease(cfUTF8Data); |
+ if (out_len <= 0) { |
+ delete[] tmp; |
+ return false; |
+ } |
+ tmp[out_len] = 0; |
+ out8->assign(tmp); |
+ delete[] tmp; |
+#endif |
+ |
+#ifdef OS_WINDOWS |
+ int out_len = WideCharToMultiByte(CP_UTF8, 0, in, len, NULL, 0, NULL, NULL); |
+ if (out_len <= 0) |
+ return false; |
+ char *tmp = new char[out_len + 1]; |
+ out_len = WideCharToMultiByte(CP_UTF8, 0, in, len, tmp, out_len, |
+ NULL, NULL); |
+ if (out_len <= 0) { |
+ delete[] tmp; |
+ return false; |
+ } |
+ tmp[out_len] = 0; |
+ out8->assign(tmp); |
+ delete[] tmp; |
+#endif |
+ |
+#ifdef OS_LINUX |
+ // TODO: this is incorrect. Fix it. |
+ std::wstring string_in(in, len); |
+ *out8 = std::string(string_in.begin(), string_in.end()); |
+#endif |
+ return true; |
+} |
+ |
+bool String16ToNPVariant(const std::wstring &in, NPVariant *variant) { |
+ std::string out8; |
+ bool r = String16ToUTF8(in.c_str(), in.size(), &out8); |
+ if (!r) { |
+ VOID_TO_NPVARIANT(*variant); |
+ return false; |
+ } |
+ return StringToNPVariant(out8, variant); |
+} |
+ |
+bool StringToNPVariant(const std::string &in, NPVariant *variant) { |
+ size_t length = in.size(); |
+ NPUTF8 *chars = static_cast<NPUTF8 *>(NPN_MemAlloc(length)); |
+ if (!chars) { |
+ VOID_TO_NPVARIANT(*variant); |
+ return false; |
+ } |
+ memcpy(chars, in.c_str(), length); |
+ STRINGN_TO_NPVARIANT(chars, length, *variant); |
+ return true; |
+} |
+ |
+std::string UIntToString(unsigned int value) { |
+ // Biggest unsigned int is 2^32-1 or about 4*10^9 so we need at most 10 |
+ // digits plus the terminal NUL. |
+ char buffer[11] = {0}; |
+ int result = snprintf(buffer, 11, "%u", value); |
+ return std::string(buffer); |
+} |
+ |
+bool GetNPObjectProperty(NPP npp, NPObject *object, const char *name, |
+ NPVariant *output) { |
+ GLUE_PROFILE_START(npp, "NPN_GetStringIdentifier"); |
+ NPIdentifier identifier = NPN_GetStringIdentifier(name); |
+ GLUE_PROFILE_STOP(npp, "NPN_GetStringIdentifier"); |
+ GLUE_PROFILE_START(npp, "NPN_HasProperty"); |
+ bool result = NPN_HasProperty(npp, object, identifier); |
+ GLUE_PROFILE_STOP(npp, "NPN_HasProperty"); |
+ if (!result) return false; |
+ GLUE_PROFILE_START(npp, "NPN_GetProperty"); |
+ result = NPN_GetProperty(npp, object, identifier, output); |
+ GLUE_PROFILE_STOP(npp, "NPN_GetProperty"); |
+ return result; |
+} |
+ |
+ |
+// Helper for privateIntToDecimal below. |
+static void PrivateSwapChars(char *a, char *b) { |
+ char temp = *a; |
+ *a = *b; |
+ *b = temp; |
+} |
+ |
+ |
+// Helper for GetNPArrayProperty below. |
+// Write out an int as a decimal string. |
+static void PrivateIntToDecimal(int int_in, char *string_out) { |
+ bool neg = int_in < 0; |
+ int i = neg ? -int_in : int_in; // Var i = absolute value of int_in. |
+ |
+ // Vast majority of calls are for 1 digit positive integers. |
+ if((!neg) && (i < 10)) { |
+ string_out[0] = '0' + i; |
+ string_out[1] = '\0'; |
+ } else { |
+ // All other values. |
+ char *o = string_out; |
+ |
+ // Write string backwards - each digit starting with the smallest. |
+ do { |
+ *o++ = '0' + (i % 10); |
+ i /= 10; |
+ } while (i); |
+ |
+ // Write minus sign if negative. |
+ if (neg) |
+ *o++ = '-'; |
+ |
+ // Terminate and point o at last char of number. |
+ *o-- = '\0'; |
+ |
+ // Reverse the chars in the backwards string and we're done. |
+ // This swaps each char into place, but leaves the 0 terminator where it is. |
+ // A 2 or 3 digit number would only require one swap, a 4 or 5 digit numnber |
+ // would require 2, etc. |
+ while(string_out < o) |
+ PrivateSwapChars(string_out++, o--); |
+ } |
+} |
+ |
+ |
+bool GetNPArrayProperty(NPP npp, NPObject *object, int index, |
+ NPVariant *output) { |
+ // Some newer versions of Safari crash or fail when accessing array elements |
+ // with an int identifer rather than a string identifier, |
+ // ie Safari wants "2" not 2. |
+ // As all browsers accept the string version, just use that. |
+ char num_str[32]; |
+ PrivateIntToDecimal(index, num_str); |
+ GLUE_PROFILE_START(npp, "NPN_GetStringIdentifier"); |
+ NPIdentifier string_identifier = NPN_GetStringIdentifier(num_str); |
+ GLUE_PROFILE_STOP(npp, "NPN_GetStringIdentifier"); |
+ // Old versions of Safari don't implement NPN_HasProperty, the work-around is |
+ // too slow for big arrays, so don't check for the existence of int properties |
+ // - the user may get unexpected error messages, but what can we do. |
+ if (!IsHasPropertyWorkaround()) { |
+ GLUE_PROFILE_START(npp, "NPN_HasProperty"); |
+ bool result = NPN_HasProperty(npp, object, string_identifier); |
+ GLUE_PROFILE_STOP(npp, "NPN_HasProperty"); |
+ if (!result) return false; |
+ } |
+ GLUE_PROFILE_START(npp, "NPN_GetProperty"); |
+ bool result = NPN_GetProperty(npp, object, string_identifier, output); |
+ GLUE_PROFILE_STOP(npp, "NPN_GetProperty"); |
+ return result; |
+} |
+ |
+NPObject *CreateArray(NPP npp) { |
+ // Evaluate '[]' in JavaScript, which will create a new array. |
+ // We need to retrieve the 'global context' too execute into, that's what |
+ // global_object is. |
+ NPObject *global_object; |
+ GLUE_PROFILE_START(npp, "CreateArray"); |
+ GLUE_PROFILE_START(npp, "getvalue"); |
+ NPN_GetValue(npp, NPNVWindowNPObject, &global_object); |
+ GLUE_PROFILE_STOP(npp, "getvalue"); |
+ NPString string; |
+ string.UTF8Characters = "[]"; |
+ string.UTF8Length = strlen(string.UTF8Characters); |
+ NPVariant result; |
+ GLUE_PROFILE_START(npp, "evaluate"); |
+ bool temp = NPN_Evaluate(npp, global_object, &string, &result); |
+ GLUE_PROFILE_STOP(npp, "evaluate"); |
+ if (!temp) return NULL; |
+ if (NPVARIANT_IS_OBJECT(result)) { |
+ return NPVARIANT_TO_OBJECT(result); |
+ } else { |
+ GLUE_PROFILE_START(npp, "NPN_ReleaseVariantValue"); |
+ NPN_ReleaseVariantValue(&result); |
+ GLUE_PROFILE_STOP(npp, "NPN_ReleaseVariantValue"); |
+ return NULL; |
+ } |
+ GLUE_PROFILE_STOP(npp, "CreateArray"); |
+} |
+ |
+ScopedId::ScopedId(NPIdentifier name) { |
+ text_ = NPN_UTF8FromIdentifier(name); |
+} |
+ |
+ScopedId::~ScopedId() { |
+ NPN_MemFree(text_); |
+} |
+ |
+bool NPCallback::SupportsAsync() { |
+ return IsPluginThreadAsyncCallSupported(); |
+} |
+ |
+NPCallback* NPCallback::Create(NPP npp) { |
+ return static_cast<NPCallback*>(NPN_CreateObject(npp, |
+ const_cast<NPClass*>(&np_class_))); |
+} |
+ |
+void NPCallback::Set(NPObject* function, const NPVariant* args, int num_args) { |
+ // Retain the new function. |
+ if (function) { |
+ NPN_RetainObject(function); |
+ } |
+ |
+ // Release the previous function. |
+ if (function_) { |
+ NPN_ReleaseObject(function_); |
+ } |
+ |
+ function_ = function; |
+ |
+ // Copy new arguments and retain or copy their variants as necessary for the |
+ // type. |
+ std::vector<NPVariant> new_args(num_args); |
+ for (size_t i = 0; i < new_args.size(); ++i) { |
+ new_args[i] = args[i]; |
+ if (NPVARIANT_IS_OBJECT(new_args[i])) { |
+ NPN_RetainObject(NPVARIANT_TO_OBJECT(new_args[i])); |
+ } else if (NPVARIANT_IS_STRING(new_args[i])) { |
+ NPUTF8* dest = static_cast<NPUTF8*>( |
+ NPN_MemAlloc(new_args[i].value.stringValue.UTF8Length)); |
+ memcpy(dest, new_args[i].value.stringValue.UTF8Characters, |
+ new_args[i].value.stringValue.UTF8Length); |
+ new_args[i].value.stringValue.UTF8Characters = dest; |
+ } |
+ } |
+ |
+ // Release previous argument variants. |
+ for (size_t i = 0; i < args_.size(); ++i) { |
+ NPN_ReleaseVariantValue(&args_[i]); |
+ } |
+ |
+ args_.swap(new_args); |
+} |
+ |
+namespace { |
+void DoAsyncCall(void* data) { |
+ NPCallback* call = static_cast<NPCallback*>(data); |
+ NPVariant result; |
+ if (call->Call(&result)) { |
+ NPN_ReleaseVariantValue(&result); |
+ } |
+ |
+ // The call object was retained in NPCallback::Call. This releases it. |
+ NPN_ReleaseObject(call); |
+} |
+} |
+ |
+bool NPCallback::Call(NPVariant* result) { |
+ if (!function_) |
+ return false; |
+ |
+ return NPN_InvokeDefault(npp_, function_, |
+ args_.size() == 0 ? NULL : &args_[0], |
+ args_.size(), |
+ result); |
+} |
+ |
+bool NPCallback::CallAsync() { |
+ if (!function_) |
+ return false; |
+ |
+ if (!SupportsAsync()) |
+ return false; |
+ |
+ // Extend the reference count until async call completes. |
+ NPN_RetainObject(this); |
+ |
+ NPN_PluginThreadAsyncCall(npp_, DoAsyncCall, this); |
+ return true; |
+} |
+ |
+NPCallback::NPCallback(NPP npp) |
+ : npp_(npp), |
+ function_(NULL) { |
+} |
+ |
+NPCallback::~NPCallback() { |
+ Set(NULL, NULL, 0); |
+} |
+ |
+NPObject* NPCallback::Allocate(NPP npp, NPClass* the_class) { |
+ NPCallback* call = new NPCallback(npp); |
+ return call; |
+} |
+ |
+void NPCallback::Deallocate(NPObject* object) { |
+ delete static_cast<NPCallback*>(object); |
+} |
+ |
+void NPCallback::Invalidate(NPObject* object) { |
+ NPCallback* call = static_cast<NPCallback*>(object); |
+ call->function_ = NULL; |
+ call->args_.clear(); |
+} |
+ |
+const NPClass NPCallback::np_class_ = { |
+ NP_CLASS_STRUCT_VERSION, |
+ NPCallback::Allocate, |
+ NPCallback::Deallocate, |
+ NPCallback::Invalidate |
+}; |
Property changes on: tools/nixysa/nixysa/static_glue/npapi/common.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |