// Copyright (c) 2008 The Chromium Embedded Framework Authors. // Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "precompiled_libcef.h" #include "variant_impl.h" #include "variant_np_util.h" #include "base/compiler_specific.h" #include "config.h" MSVC_PUSH_WARNING_LEVEL(0); #include "DOMWindow.h" #include "Frame.h" #include "npruntime_priv.h" // for NPN_InitializeVariantWithStringCopy MSVC_POP_WARNING(); #undef LOG #include "base/logging.h" #include "base/string_util.h" #include "webkit/glue/webframe.h" CefVariantImpl::CefVariantImpl() { variant_.type = NPVariantType_Null; webframe_ = NULL; } CefVariantImpl::CefVariantImpl(WebFrame *webframe) { variant_.type = NPVariantType_Null; webframe_ = webframe; } // Note that Set() performs a deep copy, which is necessary to safely // call SetNull() on the value in the destructor. CefVariantImpl::CefVariantImpl(const CefVariantImpl& original) { Lock(); variant_.type = NPVariantType_Null; Set(*original.GetNPVariant()); Unlock(); } // See comment for copy constructor, above. CefVariantImpl& CefVariantImpl::operator=(const CefVariantImpl& original) { if (&original != this) { Lock(); Set(*original.GetNPVariant()); Unlock(); } return *this; } CefVariantImpl::~CefVariantImpl() { SetNull(); } CefVariant::Type CefVariantImpl::GetType() { CefVariant::Type type = TYPE_NULL; Lock(); // determine the data type of the underlying NPVariant value switch (variant_.type) { case NPVariantType_Bool: type = TYPE_BOOL; break; case NPVariantType_Int32: type = TYPE_INT; break; case NPVariantType_Double: type = TYPE_DOUBLE; break; case NPVariantType_String: type = TYPE_STRING; break; case NPVariantType_Object: { // determine the most appropriate array type for the NPVariant object NPVariantType nptype; if(_NPN_ArrayObjectToVectorTypeHint(variant_.value.objectValue, nptype)) { switch(nptype) { case NPVariantType_Bool: type = TYPE_BOOL_ARRAY; break; case NPVariantType_Int32: type = TYPE_INT_ARRAY; break; case NPVariantType_Double: type = TYPE_DOUBLE_ARRAY; break; case NPVariantType_String: type = TYPE_STRING_ARRAY; break; } } } break; } Unlock(); return type; } void CefVariantImpl::SetNull() { Lock(); NPN_ReleaseVariantValue(&variant_); variant_.type = NPVariantType_Null; Unlock(); } void CefVariantImpl::SetBool(bool val) { Lock(); if(variant_.type != NPVariantType_Bool) { SetNull(); variant_.type = NPVariantType_Bool; } variant_.value.boolValue = val; Unlock(); } void CefVariantImpl::SetInt(int val) { Lock(); if(variant_.type != NPVariantType_Int32) { SetNull(); variant_.type = NPVariantType_Int32; } variant_.value.intValue = val; Unlock(); } void CefVariantImpl::SetDouble(double val) { Lock(); if(variant_.type != NPVariantType_Double) { SetNull(); variant_.type = NPVariantType_Double; } variant_.value.doubleValue = val; Unlock(); } void CefVariantImpl::SetString(const std::wstring& val) { Lock(); SetNull(); variant_.type = NPVariantType_String; std::string str = WideToUTF8(val); NPString new_string = {str.c_str(), static_cast(str.size())}; _NPN_InitializeVariantWithStringCopy(&variant_, &new_string); Unlock(); } void CefVariantImpl::SetBoolArray(const std::vector& val) { Lock(); DCHECK(webframe_ != NULL); WebCore::Frame* frame = static_cast(webframe_->GetFrameImplementation()); WebCore::DOMWindow* domwindow = frame->domWindow(); NPObject* npobject = _NPN_BooleanVectorToArrayObject(domwindow, val); DCHECK(npobject != NULL); Set(npobject); Unlock(); } void CefVariantImpl::SetIntArray(const std::vector& val) { Lock(); DCHECK(webframe_ != NULL); WebCore::Frame* frame = static_cast(webframe_->GetFrameImplementation()); WebCore::DOMWindow* domwindow = frame->domWindow(); NPObject* npobject = _NPN_IntVectorToArrayObject(domwindow, val); DCHECK(npobject != NULL); Set(npobject); Unlock(); } void CefVariantImpl::SetDoubleArray(const std::vector& val) { Lock(); DCHECK(webframe_ != NULL); WebCore::Frame* frame = static_cast(webframe_->GetFrameImplementation()); WebCore::DOMWindow* domwindow = frame->domWindow(); NPObject* npobject = _NPN_DoubleVectorToArrayObject(domwindow, val); DCHECK(npobject != NULL); Set(npobject); Unlock(); } void CefVariantImpl::SetStringArray(const std::vector& val) { Lock(); DCHECK(webframe_ != NULL); WebCore::Frame* frame = static_cast(webframe_->GetFrameImplementation()); WebCore::DOMWindow* domwindow = frame->domWindow(); NPObject* npobject = _NPN_WStringVectorToArrayObject(domwindow, val); DCHECK(npobject != NULL); Set(npobject); Unlock(); } bool CefVariantImpl::GetBool() { Lock(); DCHECK(variant_.type == NPVariantType_Bool); bool rv = variant_.value.boolValue; Unlock(); return rv; } int CefVariantImpl::GetInt() { Lock(); DCHECK(variant_.type == NPVariantType_Int32); int rv = variant_.value.intValue; Unlock(); return rv; } double CefVariantImpl::GetDouble() { Lock(); DCHECK(variant_.type == NPVariantType_Double); double rv = variant_.value.doubleValue; Unlock(); return rv; } std::wstring CefVariantImpl::GetString() { Lock(); DCHECK(variant_.type == NPVariantType_String); std::wstring rv = UTF8ToWide( std::string( variant_.value.stringValue.UTF8Characters, variant_.value.stringValue.UTF8Length)); Unlock(); return rv; } bool CefVariantImpl::GetBoolArray(std::vector& val) { Lock(); DCHECK(variant_.type == NPVariantType_Object); bool rv = _NPN_ArrayObjectToBooleanVector(variant_.value.objectValue, val); Unlock(); return rv; } bool CefVariantImpl::GetIntArray(std::vector& val) { Lock(); DCHECK(variant_.type == NPVariantType_Object); bool rv = _NPN_ArrayObjectToIntVector(variant_.value.objectValue, val); Unlock(); return rv; } bool CefVariantImpl::GetDoubleArray(std::vector& val) { Lock(); DCHECK(variant_.type == NPVariantType_Object); bool rv = _NPN_ArrayObjectToDoubleVector(variant_.value.objectValue, val); Unlock(); return rv; } bool CefVariantImpl::GetStringArray(std::vector& val) { Lock(); DCHECK(variant_.type == NPVariantType_Object); bool rv = _NPN_ArrayObjectToWStringVector(variant_.value.objectValue, val); Unlock(); return rv; } void CefVariantImpl::CopyToNPVariant(NPVariant* result) { Lock(); result->type = variant_.type; switch (variant_.type) { case NPVariantType_Bool: result->value.boolValue = variant_.value.boolValue; break; case NPVariantType_Int32: result->value.intValue = variant_.value.intValue; break; case NPVariantType_Double: result->value.doubleValue = variant_.value.doubleValue; break; case NPVariantType_String: _NPN_InitializeVariantWithStringCopy(result, &variant_.value.stringValue); break; case NPVariantType_Null: case NPVariantType_Void: // Nothing to set. break; case NPVariantType_Object: result->type = NPVariantType_Object; result->value.objectValue = NPN_RetainObject(variant_.value.objectValue); break; } Unlock(); } void CefVariantImpl::Set(NPObject* val) { Lock(); SetNull(); variant_.type = NPVariantType_Object; variant_.value.objectValue = NPN_RetainObject(val); Unlock(); } void CefVariantImpl::Set(const NPString& val) { Lock(); SetNull(); variant_.type = NPVariantType_String; _NPN_InitializeVariantWithStringCopy(&variant_, &val); Unlock(); } void CefVariantImpl::Set(const NPVariant& val) { Lock(); SetNull(); switch (val.type) { case NPVariantType_Bool: SetBool(val.value.boolValue); break; case NPVariantType_Int32: SetInt(val.value.intValue); break; case NPVariantType_Double: SetDouble(val.value.doubleValue); break; case NPVariantType_String: Set(val.value.stringValue); break; case NPVariantType_Object: Set(val.value.objectValue); break; } Unlock(); }