--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/device/src/DeviceLiwBinding.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1115 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of Liw Device binding
+*
+*/
+
+
+#include <config.h>
+#include <value.h>
+#include <interpreter.h>
+#include <date_object.h>
+#include <operations.h>
+#include <liwServiceHandler.h>
+#include <RTSecManager.h>
+#include <RTSecMgrUtility.h>
+#include <RTSecMgrScriptSession.h>
+#include <RTSecMgrCommonDef.h>
+#include <WidgetRegistryClient.h>
+#include <PropertyNameArray.h>
+#include <internal.h>
+#include <liwvariant.h>
+#include <liwbufferextension.h>
+
+#include "DeviceLiwBinding.h"
+#include "DeviceLiwPeer.h"
+#include "DeviceBinding.h"
+#include "ServiceObject.h"
+#include "ServiceEventHandler.h"
+#include "DeviceLiwInterface.h"
+#include "DeviceLiwMap.h"
+#include "DeviceLiwIterable.h"
+#include "DeviceLiwResult.h"
+
+using namespace KJS;
+using namespace LIW;
+
+// CONSTANTS
+#define SAPISECURITYPROMPTNEEDED 0x0001
+#define SAPIPROMPTLESS 0x0002
+#define SAPIACCESSDENIED 0x0003
+
+// TBD: This needs to be substituted with LIW const in LIW header
+const TInt KMaxKeySize = 255;
+_LIT8( KWildChar, "*" );
+
+const TInt KTimeBufSize = 255;
+_LIT( KLocaleDateTime, "%E,%D%N%Y %1 %2, %3%-B %:0%J%:1%T%:2%S%+B" );
+
+// JS time epoch 1st January 1970 (needed to offset from Symbian epoch)
+_LIT(KJsEpoch, "19700000:000000.000000");
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::NewL
+// NewL
+//
+// ----------------------------------------------------------------------------
+//
+CDeviceLiwBinding* CDeviceLiwBinding::NewL()
+ {
+ CDeviceLiwBinding* bind = new (ELeave) CDeviceLiwBinding();
+ CleanupStack::PushL(bind);
+ bind->ConstructL();
+ CleanupStack::Pop(bind);
+ return bind;
+ }
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::ConstructL
+// ConstructL sencond phace construction.
+//
+// ----------------------------------------------------------------------------
+//
+void CDeviceLiwBinding::ConstructL()
+ {
+ m_critArr = new (ELeave) RCriteriaArray();
+ m_serviceHandler = CLiwServiceHandler::NewL();
+
+ RWidgetRegistryClientSession widgetregistry;
+ TInt ret = widgetregistry.Connect();
+ if ( ret != KErrNone && ret != KErrAlreadyExists )
+ {
+ User::Leave( ret );
+ }
+ else
+ {
+ CleanupClosePushL( widgetregistry );
+ }
+ TInt aPolicyId = widgetregistry.SecurityPolicyId();
+ if ( aPolicyId < 0 )
+ {
+ User::Leave( aPolicyId );
+ }
+ User::LeaveIfError(widgetregistry.Disconnect());
+ CleanupStack::PopAndDestroy(); //widgetregistry
+
+ // we need to keep main session allive, to keep sub session
+ m_secMgr = CRTSecManager::NewL();
+
+ CTrustInfo* trust = CTrustInfo::NewLC();
+
+ // TODO: in future, to support blanket permission,
+ // this function should be called at installation time.
+ // TInt32 exId = secMgr->RegisterScript( aPolicyId, *trust );
+ // m_scriptSession = secMgr->GetScriptSession( aPolicyId, exId );
+
+ // check for script session validity.
+ m_scriptSession = m_secMgr->GetScriptSessionL( aPolicyId, *trust );
+ if ( !m_scriptSession )
+ {
+ User::Leave( KErrGeneral );
+ }
+ CleanupStack::PopAndDestroy( trust );
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::~CDeviceLiwBinding
+// Default destructor
+//
+// ----------------------------------------------------------------------------
+//
+CDeviceLiwBinding::~CDeviceLiwBinding()
+ {
+ m_critArr->ResetAndDestroy();
+ m_serviceHandler->DetachL(*m_critArr);
+ m_critArr->ResetAndDestroy();
+ delete m_critArr;
+ delete m_serviceHandler;
+ delete m_scriptSession;
+ delete m_secMgr;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::LoadServiceProvider
+// Load service provider
+//
+// ----------------------------------------------------------------------------
+//
+TInt CDeviceLiwBinding::LoadServiceProvider( ExecState* exec, const List& args )
+ {
+ TInt error = KErrNone;
+ CLiwCriteriaItem* item;
+ HBufC8* svcName = NULL;
+ HBufC8* interfaceName = NULL;
+ int argcount = args.size();
+
+ if ( argcount > 0 && args[0]->type() == StringType &&
+ args[0]->toString( exec ).size() > 0 )
+ {
+ TRAP( error,
+ {
+ // Get service name
+ svcName = KJS::GetAsciiBufferL( args[0]->toString( exec ) );
+ CleanupStack::PushL( svcName );
+
+ // Get optional supported interface
+ if ( argcount > 1 && args[1]->type() == StringType &&
+ args[1]->toString( exec ).size() > 0 )
+ {
+ interfaceName = KJS::GetAsciiBufferL( args[1]->toString( exec ) );
+ CleanupStack::PushL( interfaceName );
+ }
+
+ if ( interfaceName && interfaceName->Length() > 0 )
+ {
+ item = CLiwCriteriaItem::NewLC( 1, *interfaceName, *svcName );
+ }
+ else
+ {
+ item = CLiwCriteriaItem::NewLC( 1, KNullDesC8(), *svcName );
+ }
+
+ item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
+ RCriteriaArray crit_arr;
+ crit_arr.AppendL( item );
+
+ CleanupStack::Pop(item); // item
+
+ // "Attach" runtime to service
+ if ( m_scriptSession && m_serviceHandler )
+ {
+ TInt load_err;
+ RWidgetRegistryClientSession widgetregistry;
+ TInt ret = widgetregistry.Connect();
+ if ( ret != KErrNone && ret != KErrAlreadyExists )
+ {
+ User::Leave( ret );
+ }
+ else
+ {
+ CleanupClosePushL( widgetregistry );
+ }
+
+ switch ( widgetregistry.WidgetSapiAccessState(m_Uid))
+ {
+ case SAPISECURITYPROMPTNEEDED :
+ load_err = m_serviceHandler->AttachL( crit_arr, *m_scriptSession );
+ break;
+ case SAPIPROMPTLESS :
+ load_err = m_serviceHandler->AttachL( crit_arr );
+ break;
+ case SAPIACCESSDENIED :
+ load_err = KLiwSecurityAccessCheckFailed;
+ break;
+ default :
+ load_err = KLiwSecurityAccessCheckFailed;
+ break;
+ }
+
+ User::LeaveIfError(widgetregistry.Disconnect());
+ CleanupStack::PopAndDestroy(); //widgetregistry
+ // hard coded for now since the definition of TLiwLoadStatus is not exposed to common dir yet
+ if ( load_err == KLiwServiceLoadSuccess || load_err == KLiwServiceAlreadyLoaded )
+ {
+ error = KErrNone; // normalize the error
+ m_critArr->AppendL( item );
+ }
+ else
+ {
+ error = load_err; // pass on the TLiwLoadStatus
+ delete item;
+ }
+ }
+
+ if ( interfaceName )
+ {
+ CleanupStack::PopAndDestroy( interfaceName );
+ }
+
+ CleanupStack::PopAndDestroy( svcName );
+ });
+ }
+ else
+ {
+ error = KErrArgument;
+ }
+
+ return error;
+ }
+
+// ---------------------------------------------------------------------------
+// Convert Unload service provider
+// return JSValue - javascript list
+// ---------------------------------------------------------------------------
+//
+void CDeviceLiwBinding::UnloadServiceProvider(const TDesC8& aServiceName,const TDesC8& aInterfaceName)
+ {
+ TRAP_IGNORE(
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC( 1, aInterfaceName, aServiceName );
+ item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
+ RCriteriaArray critArray;
+ critArray.AppendL( item );
+ m_serviceHandler->DetachL( critArray );
+ CleanupStack::Pop(item);
+ critArray.ResetAndDestroy();
+ for (int i = 0; i < m_critArr->Count(); i++)
+ {
+ if ( (*m_critArr)[i]->ServiceCmdStr() == aInterfaceName &&
+ (*m_critArr)[i]->ContentType() == aServiceName)
+ m_critArr->Remove(i);
+ }
+ )
+ }
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::ServiceObjectPeer
+// Factory method to create a peer with service name
+//
+//
+// ----------------------------------------------------------------------------
+//
+MDevicePeer* CDeviceLiwBinding::ServiceObjectPeer(
+ ExecState *exec,
+ const List& args )
+ {
+ DeviceLiwPeer* peer = NULL;
+
+ TRAPD( error,
+ {
+ peer = new ( ELeave ) DeviceLiwPeer(
+ exec->lexicalInterpreter()->globalExec(), this, 0 );
+ CleanupStack::PushL( peer );
+ peer->SetServiceNameL( exec, args );
+ CleanupStack::Pop(peer);
+ });
+
+ if ( error != KErrNone )
+ {
+ return 0;
+ }
+
+ return static_cast<MDevicePeer*>( peer );
+ }
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::ListProviders
+// Call/Invoke the LIW function to list the providers
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::ListProviders(
+ ExecState* exec,
+ const List& args )
+ {
+ CLiwCriteriaItem* item = NULL;
+ HBufC8* cmdName = NULL;
+ HBufC8* contentName = NULL;
+ int argcount = args.size();
+
+ // Get content name
+ if ( argcount > 0 && args[0]->type() == StringType &&
+ args[0]->toString( exec ).size() > 0 )
+ {
+ contentName = KJS::GetAsciiBufferL( args[0]->toString( exec ) );
+ CleanupStack::PushL( contentName );
+ }
+
+ if ( argcount > 1 && args[1]->type() == StringType &&
+ args[1]->toString( exec ).size() > 0 )
+ {
+ // Get cmd name
+ cmdName = KJS::GetAsciiBufferL( args[1]->toString( exec ) );
+ CleanupStack::PushL( cmdName );
+ }
+
+ if ( cmdName && cmdName->Length() > 0 )
+ {
+ if ( contentName && contentName->Length() > 0 )
+ {
+ item = CLiwCriteriaItem::NewLC( 1, *cmdName, *contentName );
+ }
+ else
+ {
+ item = CLiwCriteriaItem::NewLC( 1, *cmdName, KWildChar() );
+ }
+ }
+ else
+ {
+ if ( contentName && contentName->Length() > 0 )
+ {
+ item = CLiwCriteriaItem::NewLC( 1, KWildChar(), *contentName );
+ }
+ else
+ {
+ item = CLiwCriteriaItem::NewLC( 1, KWildChar(), KWildChar() );
+ }
+ }
+
+ RCriteriaArray critArray, providerList;
+ item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
+ critArray.AppendL( item );
+ m_serviceHandler->QueryImplementationL( critArray, providerList );
+ CleanupStack::Pop();//item
+
+ if ( contentName )
+ {
+ CleanupStack::PopAndDestroy();//contentName
+ }
+
+ if ( cmdName )
+ {
+ CleanupStack::PopAndDestroy();//cmdName
+ }
+
+ if ( providerList.Count() > 0 )
+ {
+ // convert to js value
+ List jsList;
+ jsList.append( jsNumber( providerList.Count() ) );
+ JSObject * rval = exec->lexicalInterpreter()->builtinArray()->construct(
+ exec, jsList );
+
+ for ( TInt i = 0; i < providerList.Count(); i++ )
+ {
+ List jsPair;
+ jsPair.append( jsNumber( 2 ) );
+ JSObject * pairVal = exec->lexicalInterpreter()->builtinArray()->construct(
+ exec, jsPair );
+
+ HBufC* buf1 = HBufC::NewLC( providerList[i]->ServiceCmdStr().Length() + 1 ); // +1 for zero terminate
+ buf1->Des().Copy( providerList[i]->ServiceCmdStr() );
+ buf1->Des().ZeroTerminate();
+ pairVal->put( exec, Identifier::from(0), jsString( UString( (UChar*) buf1->Des().Ptr(), buf1->Des().Length() ) ) );
+
+ HBufC* buf2 = HBufC::NewLC( providerList[i]->ContentType().Length() + 1 ); // +1 for zero terminate
+ buf2->Des().Copy( providerList[i]->ContentType() );
+ buf2->Des().ZeroTerminate();
+ pairVal->put( exec, Identifier::from(1),
+ jsString( UString( (UChar*) buf2->Des().Ptr(), buf2->Des().Length() ) ) );
+
+ rval->put( exec, Identifier::from(i), pairVal );
+ CleanupStack::PopAndDestroy(2);//buf1,buf2
+ }
+
+ critArray.ResetAndDestroy();
+ providerList.ResetAndDestroy();
+
+ return( rval );
+ }
+
+ critArray.ResetAndDestroy();
+ providerList.ResetAndDestroy();
+ return jsUndefined();
+ }
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::InvokeOpInternal
+// Call/Invoke the SAPI function
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::InvokeOpInternal(
+ ExecState* exec,
+ const Identifier& propertyName,
+ const List& args,
+ MDevicePeer* peer )
+ {
+ TUint cmdOption = 0;
+ JSValue* rval = jsUndefined();
+ int argcount = args.size();
+ DeviceLiwPeer* callBack = NULL;
+
+ if ( argcount > 1 )
+ {
+ cmdOption = KLiwOptASyncronous;
+ if( args[1]->isObject() )
+ {
+ callBack = static_cast<DeviceLiwPeer*>( peer );
+ }
+ }
+ if (propertyName == "Cancel")
+ {
+ cmdOption = KLiwOptCancel;
+ }
+ // Must have at least an operation name
+ if ( propertyName.ustring().size() > 0 )
+ {
+ // Operation on a service interface object
+ if ( peer && static_cast<DeviceLiwPeer*>( peer )->Interface() )
+ {
+ TRAPD( error,
+ {
+ CLiwGenericParamList* inps = CLiwGenericParamList::NewL(); // We manage this memory
+ CleanupStack::PushL( inps );
+ CLiwGenericParamList* outps = CLiwGenericParamList::NewL(); // And this
+ CleanupStack::PushL( outps );
+
+ // Collect args from first parameter. Note that args are
+ // passed as an associative array.
+ if ( argcount >= 1 )
+ {
+ JsList2LiwGenericParamListL( exec, args[0], *inps );
+ }
+
+ // Get the operation name
+ HBufC8* oper = KJS::GetAsciiBufferL( propertyName.ustring() );
+ CleanupStack::PushL( oper );
+
+ // Call the interface operation
+
+ TTrapHandler* ____t = User::MarkCleanupStack();
+ static_cast<DeviceLiwPeer*>( peer )->Interface()->ExecuteCmdL(
+ *oper, *inps, *outps, cmdOption,
+ callBack );
+ User::UnMarkCleanupStack(____t);
+ inps->Reset();
+ rval = LiwGenericParamList2JsArray( exec, outps );
+ outps->Reset();
+ CleanupStack::PopAndDestroy( oper ); // map
+ CleanupStack::Pop();// outps
+ CleanupStack::PopAndDestroy( );// inps
+ });
+
+ if ( error != KErrNone )
+ {
+ return throwError(exec, GeneralError);
+ }
+ }
+ }
+
+ return rval;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::InvokeOp
+// Call/Invoke the SAPI function
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::InvokeOp(
+ ExecState* exec,
+ const Identifier& propertyName,
+ const List& args,
+ MDevicePeer* peer )
+ {
+ return InvokeOpInternal( exec, propertyName, args, peer );
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::CreateInterface
+// Create SAPI interface
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::CreateInterface(
+ ExecState* exec, HBufC8* serviceName, const Identifier& interfaceName )
+ {
+ JSValue* rval = jsUndefined();
+ TInt error = KErrNone;
+
+ if ( m_serviceHandler && serviceName->Length() > 0 && interfaceName.ustring().size() > 0 )
+ {
+ // Since this is called from JS context, set up our own trap harness
+ TRAP( error,
+ {
+ CLiwGenericParamList& inps = m_serviceHandler->InParamListL(); // LIW manages this memory
+ CleanupStack::PushL( &inps );
+ CLiwGenericParamList& outps = m_serviceHandler->OutParamListL(); // LIW manages this memory
+ CleanupStack::PushL( &outps );
+
+ HBufC8* ifaceName = KJS::GetAsciiBufferL( interfaceName.ustring() );
+ CleanupStack::PushL( ifaceName );
+
+ const HBufC8* hsvc = serviceName;
+
+ // Create LIW params
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC( 1, *ifaceName,
+ TPtrC8( hsvc->Ptr(), hsvc->Size() ) );
+
+ item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
+
+ // Call the service command operation
+ m_serviceHandler->ExecuteServiceCmdL(
+ *item, inps, outps, NULL );
+
+ // Convert results into JS array
+ rval = LiwGenericParamList2JsArray( exec, &outps );
+ CleanupStack::PopAndDestroy( 2 ); //item, ifaceName
+ CleanupStack::Pop( 2 );//inps, outps
+ });
+
+ if ( error != KErrNone)
+ {
+ return throwError(exec, GeneralError);
+ }
+ }
+
+ return rval;
+ }
+
+
+//TBD: replace this with a generic object type discovery method
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::IsAList
+// Check if javascript list
+//
+//
+// ----------------------------------------------------------------------------
+//
+TBool CDeviceLiwBinding::IsAList( ExecState* exec, JSValue* aValue )
+ {
+ if(!aValue->isObject())
+ return EFalse;
+ PropertyNameArray propertyNames;
+ aValue->toObject( exec )->getPropertyNames( exec, propertyNames );
+ unsigned size = static_cast<unsigned>(propertyNames.size());
+
+ for (unsigned i = 0; i < size; i++)
+ {
+ bool rval;
+ propertyNames[i].toArrayIndex( &rval );
+ if ( rval )
+ {
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::JsVal2LiwVariant
+// Convert from javascript value to LiwVariant
+//
+//
+// ----------------------------------------------------------------------------
+//
+TBool CDeviceLiwBinding::JsVal2LiwVariant(
+ ExecState* exec,
+ JSValue* aValue,
+ TLiwVariant& variant )
+ {
+ TBool ret = ETrue;
+ TInt error = KErrNone;
+
+ switch ( aValue->type() )
+ {
+ case StringType:
+ {
+ // Pass as TPtrC and let SAPI do the conversion to 8 bit if needed.
+ TRAP( error,
+ {
+ variant.SetL( TLiwVariant(
+ TPtrC16( ( unsigned short* ) aValue->toString( exec ).data(),
+ aValue->toString( exec ).size() ) ) );
+ });
+ break;
+ }
+ case NumberType:
+ {
+ if (isNaN(aValue->getNumber()) || isInf(aValue->getNumber()))
+ {
+ ret = EFalse;
+ break;
+ }
+ TInt32 intVal = aValue->toInt32( exec );
+ double doubleVal = aValue->toNumber( exec );
+ if ( intVal != doubleVal )
+ {
+ variant.Set( (TReal)doubleVal );
+ }
+ else
+ {
+ // this is not fully correct due to the limitation of js number
+ variant.Set( intVal );
+ }
+ break;
+ }
+ case ObjectType:
+ {
+ JSObject* anObj = aValue->toObject( exec );
+
+ // Handle date
+ if(anObj->className().find(UString("Date"),0) == 0)
+ {
+ double d = aValue->toNumber( exec ); // get UTC milli seconds
+ if( isNaN(d) || isInf(d) )
+ {
+ ret = EFalse;
+ break;
+ }
+
+ //Get the JS time in integer seconds
+ const TInt64 dateVal = d;
+
+ // Set JS epoch offset from Symbian epoch
+ TTime sTime(KJsEpoch);
+ TTimeIntervalMicroSeconds dateMicroSecs(dateVal*1000); // convert to UTC micro seconds
+ sTime += dateMicroSecs;
+
+ // uncomment following to debug time
+ //TBuf<100> date;
+ //sTime.FormatL(date,KLocaleDateTime);
+
+ // Set the LIW Variant time
+ variant.Set( sTime );
+
+ break;
+ }
+ // Boolean object
+ else if(anObj->className().find(UString("Boolean"),0) == 0)
+ {
+ TBool val = aValue->toNumber( exec );
+ variant.Set( val );
+ break;
+ }
+ // Number object
+ else if(anObj->className().find(UString("Number"),0) == 0)
+ {
+ double d = aValue->toNumber( exec );
+ if (isNaN(d) || isInf(d))
+ {
+ ret = EFalse;
+ break;
+ }
+ TInt32 intVal = aValue->toInt32( exec );
+ if ( intVal != d )
+ {
+ variant.Set( (TReal)d );
+ }
+ else
+ {
+ // this is not fully correct due to the limitation of js number
+ variant.Set( intVal );
+ }
+ break;
+ }
+ // String object
+ else if(anObj->className().find(UString("String"),0) == 0)
+ {
+ // Pass as TPtrC and let SAPI do the conversion to 8 bit if needed.
+ TRAP( error,
+ {
+ variant.SetL( TLiwVariant(
+ TPtrC16( ( unsigned short* ) aValue->toString( exec ).data(),
+ aValue->toString( exec ).size() ) ) );
+ });
+ break;
+ }
+ PropertyNameArray prop_names;
+ aValue->toObject( exec )->getPropertyNames( exec, prop_names );
+ unsigned size = static_cast<unsigned>(prop_names.size());
+
+ // handle array
+ if ( IsAList( exec, aValue ) )
+ {
+ CLiwList* liwList = NULL;
+
+ TRAP( error, { liwList = CLiwDefaultList::NewL(); } );
+ if ( error != KErrNone )
+ {
+ break;
+ }
+ CleanupStack::PushL( liwList );
+
+ for (unsigned i = 0; i < size; i++)
+ {
+ bool rval;
+ prop_names[i].toArrayIndex( &rval );
+
+ if ( rval )
+ {
+ TLiwVariant vv;
+ JSValue* v = aValue->toObject( exec )->get(exec, prop_names[i]);
+
+ if ( JsVal2LiwVariant( exec, v, vv ) )
+ {
+ TRAP( error, { liwList->AppendL( vv ); } ); // makes a copy
+ vv.Reset();
+
+ if ( error != KErrNone )
+ {
+ break; //from while
+ }
+ }
+ }
+ }//end of while
+
+ if ( error == KErrNone )
+ {
+ if( liwList->Count() ) // do not set variant if list is empty
+ {
+ TRAP( error, { variant.SetL( liwList ); } );
+ }
+ }
+
+ CleanupStack::Pop( liwList );
+ liwList->DecRef();
+ }
+ // handle other objects
+ else
+ { // Map
+ TRAP( error,
+ {
+ CLiwMap* liwMap = CLiwDefaultMap::NewL();
+ CleanupClosePushL( *liwMap );
+
+ for (unsigned i = 0; i < size; i++)
+ {
+ HBufC8* keyName = KJS::GetAsciiBufferL(
+ prop_names[i].ustring() );
+ CleanupStack::PushL( keyName );
+
+ TLiwVariant vv;
+ JSValue* v = aValue->toObject( exec )->get(exec, prop_names[i]);
+
+ if (!keyName || !keyName->Length() )
+ continue;
+
+ if ( !JsVal2LiwVariant( exec, v, vv ) )
+ {
+ // error converting js value to liw variant, throw debugging error
+ UString err_txt( "Invalid value:[" );
+ err_txt.append( v->toString(exec) );
+ err_txt.append( "] for key:[" );
+ err_txt.append( (const char *)keyName->Des().PtrZ() );
+ err_txt.append( "].\0" );
+ throwError( exec, GeneralError, err_txt );
+ }
+ else if ( !vv.IsEmpty() )
+ {
+ liwMap->InsertL( *keyName, vv );//makes a copy
+ vv.Reset();
+ }
+
+ CleanupStack::PopAndDestroy( keyName );
+ }
+
+ if( liwMap->Count() ) //do notset variant if map is empty
+ {
+ variant.SetL( liwMap );
+ }
+ CleanupStack::PopAndDestroy(); // this will call liwMap->close
+ });
+ }
+ break;
+ }
+ case BooleanType:
+ {
+ TBool val = aValue->toNumber( exec );
+ variant.Set( val );
+ break;
+ }
+ case NullType:
+ case UnspecifiedType:
+ case UndefinedType:
+ default:
+ ret = EFalse;
+ break;
+ }
+
+ if ( error != KErrNone )
+ {
+ ret = EFalse;
+ }
+
+ return ret;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::DeviceLiwVariant2JsVal
+// Convert from LiwVariant to javascript value of the same type
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::LiwVariant2JsVal(
+ ExecState* exec,
+ const TLiwVariant& variant )
+ {
+ switch ( variant.TypeId() )
+ {
+ case EVariantTypeTInt32:
+ {
+ return jsNumber( variant.AsTInt32() );
+ }
+ case EVariantTypeDesC:
+ {
+ return jsString( UString(
+ (UChar*) variant.AsDes().Ptr(), variant.AsDes().Length() ) );
+ }
+ case EVariantTypeDesC8:// this is something wrong
+ {
+ JSValue* rval = jsUndefined();
+ TRAPD( error,
+ {
+ HBufC* buf = HBufC::NewLC( variant.AsData().Length() + 1 ); // +1 for zero terminate
+ TPtr bufDes = buf->Des();
+ bufDes.Copy( variant.AsData() );
+ bufDes.ZeroTerminate();
+ rval = jsString( UString( (UChar*) bufDes.Ptr(), bufDes.Length() ) );
+ CleanupStack::PopAndDestroy();//buf
+ });
+ return rval;
+ }
+ case EVariantTypeList:
+ {
+ TLiwVariant v;
+ List jsList;
+ jsList.append( jsNumber( variant.AsList()->Count() ) );
+ JSObject * rval = exec->lexicalInterpreter()->builtinArray()->construct(
+ exec, jsList );
+
+ for ( TInt i = 0; i < variant.AsList()->Count(); i++ )
+ {
+ TRAPD( error, { variant.AsList()->AtL( i, v ); } );
+ rval->put(
+ exec, Identifier::from(i), LiwVariant2JsVal( exec, v ) );
+ }
+ v.Reset();
+ return rval;
+ }
+ case EVariantTypeMap:
+ {
+ TLiwVariant v;
+ List jsList;
+ jsList.append( jsNumber( variant.AsMap()->Count() ) );
+ JSObject * rval = new DeviceLiwMap(exec->lexicalInterpreter()->builtinArray()->construct(
+ exec, jsList ), variant.AsMap(), this);
+
+ for ( TInt i = 0; i < variant.AsMap()->Count(); i++ )
+ {
+ TBuf8<KMaxKeySize> name;
+ TRAPD( error,
+ {
+ if ( variant.AsMap()->AtL( i, name ) )
+ {
+ variant.AsMap()->FindL( name, v );
+ rval->put( exec,
+ Identifier( ( const char* ) name.PtrZ() ),
+ LiwVariant2JsVal( exec, v ) );
+ }
+ });
+ // No error processing
+ }
+ v.Reset();
+ return rval;
+ }
+ case EVariantTypeInterface:
+ {
+ // new DeviceLiwPeer() might fail, in which case the service JSObject * peer will be null
+ DeviceLiwPeer* peer = new DeviceLiwPeer(
+ exec->lexicalInterpreter()->globalExec(),
+ this, variant.AsInterface() );
+ if ( !peer )
+ {
+ return jsUndefined();
+ }
+
+ JSObject* impl = new DeviceLiwInterface( exec, this, peer );
+ return impl;
+ }
+ case EVariantTypeIterable:
+ {
+ return new DeviceLiwIterable(exec, this, variant.AsIterable());
+ }
+ case EVariantTypeTReal:
+ {
+ TReal realValue;
+ variant.Get( realValue );
+ return jsNumber( realValue );
+ }
+ case EVariantTypeTBool:
+ {
+ TBool boolValue;
+ variant.Get( boolValue );
+ return jsBoolean( boolValue );
+ }
+ //Note that unmarshaling to String here is not symetrical with marshaling from Date
+ //but JS application can easily construct a Date if it wants one
+ case EVariantTypeTTime:
+ {
+ TTime UTCTime;
+ TBuf<KTimeBufSize> buf;
+ variant.Get( UTCTime );
+
+ TTime utcNow;
+ utcNow.UniversalTime();
+ TTime localNow;
+ localNow.HomeTime();
+ // convert UTC time to local time
+ TTimeIntervalMicroSeconds diff = localNow.MicroSecondsFrom(utcNow);
+ TTime localTime = UTCTime + diff;
+ // format the time to output string
+ localTime.FormatL( buf, KLocaleDateTime );
+ const UChar *p = (const UChar*)buf.Ptr();
+ return jsString( UString( p, buf.Length() ) );
+ }
+ case EVariantTypeBuffer: // this is something i don't what to do
+ {
+ return jsUndefined();
+ /*
+ CLiwBuffer* buf = variant.AsBuffer();
+ switch (buf->TypeID())
+ {
+ case KLiwBufferFile:
+ {
+ RFile file = ((CLiwFileBuffer*)buf)->AsFile();
+ TFileName fileName;
+ file.FullName(fileName);
+ return jsString( UString((UChar*) fileName.Ptr(), fileName.Length() ) );
+ }
+ case KLiwBufferBitmap:
+ {
+ return jsUndefined();
+ }
+ default:
+ return jsUndefined();
+ }*/
+ }
+ case EVariantTypeTUid:
+ case EVariantTypeFileHandle:
+ default:
+ return jsUndefined();
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::JsList2LiwGenericParamListL
+// Convert javascript array (list) to LiwGenericParamList
+//
+//
+// ----------------------------------------------------------------------------
+//
+void CDeviceLiwBinding::JsList2LiwGenericParamListL(
+ ExecState* exec,
+ JSValue* aValue,
+ CLiwGenericParamList& aLiwList )
+ {
+ if (!aValue->isObject())
+ return;
+ PropertyNameArray propertyNames;
+ aValue->toObject( exec )->getPropertyNames( exec, propertyNames );
+ int size = static_cast<unsigned>(propertyNames.size());
+
+ for (unsigned i = 0; i < size; i++)
+ {
+ HBufC8* name = KJS::GetAsciiBufferL(propertyNames[i].ustring() );
+ if ( !name->Length() )
+ break;
+ CleanupStack::PushL( name );
+ JSValue* v = aValue->toObject( exec )->get( exec, propertyNames[i] );;
+ TLiwVariant vv;
+
+ if ( !JsVal2LiwVariant( exec, v, vv ) ) // error occurred
+ {
+ throwError(exec, GeneralError);
+ }
+ else if ( !vv.IsEmpty() )
+ {
+ aLiwList.AppendL( TLiwGenericParam( *name, vv ) );
+ vv.Reset();
+ }
+
+ CleanupStack::PopAndDestroy(); //name
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::LiwGenericParamList2JsArray
+// Convert LiwGenericParamList to javascript array (list)
+//
+//
+// ----------------------------------------------------------------------------
+//
+JSValue* CDeviceLiwBinding::LiwGenericParamList2JsArray(
+ ExecState* exec,
+ CLiwGenericParamList* aLiwList )
+ {
+ // the output param list should not be empty, if it is, return an undefined js obj.
+ if ( aLiwList->Count() == 0 )
+ return jsUndefined();
+
+ List jsList;
+
+ jsList.append( jsNumber( aLiwList->Count() ) );
+
+ JSObject * rval = new DeviceLiwResult(exec->lexicalInterpreter()->builtinArray()->construct(
+ exec, jsList ));
+
+ for ( TInt i = 0; i < aLiwList->Count(); i++ )
+ {
+ TBuf8<KMaxKeySize> name( (*aLiwList)[i].Name() );
+ rval->put( exec, Identifier( (const char*) name.PtrZ() ),
+ LiwVariant2JsVal( exec, (*aLiwList)[i].Value() ) ); //??? should call AtL?
+ }
+
+ return rval;
+ }
+
+// ----------------------------------------------------------------------------
+// CDeviceLiwBinding::SetUid
+// Sets the widget uid
+//
+//
+// ----------------------------------------------------------------------------
+//
+void CDeviceLiwBinding::SetUid( const TUint& aValue)
+ {
+ m_Uid.iUid = aValue;
+ }
+
+// ----------------------------------------------------------------------------
+// KJS::GetAsciiBufferL
+// Convert the Unicode string to plain ASCII chars chopping of any higher bytes
+//
+//
+// ----------------------------------------------------------------------------
+//
+HBufC8* KJS::GetAsciiBufferL( const UString& aBuf )
+ {
+ int length = aBuf.size();
+ HBufC8* buf = HBufC8::NewL( length + 1 ); // +1 for zero terminate
+ TPtr8 bufDes8 = buf->Des();
+ const UChar* p = aBuf.data();
+ const UChar *limit = p + length;
+
+ while ( p != limit )
+ {
+ TChar c = p->uc;
+ bufDes8.Append( c );
+ ++p;
+ }
+
+ bufDes8.ZeroTerminate();
+ return buf;
+ }
+
+//END OF FILE