webengine/device/src/DeviceLiwBinding.cpp
changeset 0 dd21522fd290
child 16 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of Liw Device binding
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <config.h>
       
    20 #include <value.h>
       
    21 #include <interpreter.h>
       
    22 #include <date_object.h>
       
    23 #include <operations.h>
       
    24 #include <liwServiceHandler.h>
       
    25 #include <RTSecManager.h>
       
    26 #include <RTSecMgrUtility.h>
       
    27 #include <RTSecMgrScriptSession.h>
       
    28 #include <RTSecMgrCommonDef.h>
       
    29 #include <WidgetRegistryClient.h>
       
    30 #include <PropertyNameArray.h>
       
    31 #include <internal.h>
       
    32 #include <liwvariant.h>
       
    33 #include <liwbufferextension.h>
       
    34 
       
    35 #include "DeviceLiwBinding.h"
       
    36 #include "DeviceLiwPeer.h"
       
    37 #include "DeviceBinding.h"
       
    38 #include "ServiceObject.h"
       
    39 #include "ServiceEventHandler.h"
       
    40 #include "DeviceLiwInterface.h"
       
    41 #include "DeviceLiwMap.h"
       
    42 #include "DeviceLiwIterable.h"
       
    43 #include "DeviceLiwResult.h"
       
    44 
       
    45 using namespace KJS;
       
    46 using namespace LIW;
       
    47 
       
    48 // CONSTANTS
       
    49 #define SAPISECURITYPROMPTNEEDED 0x0001
       
    50 #define SAPIPROMPTLESS           0x0002
       
    51 #define SAPIACCESSDENIED         0x0003
       
    52 
       
    53 // TBD: This needs to be substituted with LIW const in LIW header
       
    54 const TInt KMaxKeySize = 255;
       
    55 _LIT8( KWildChar, "*" );
       
    56 
       
    57 const TInt KTimeBufSize = 255;
       
    58 _LIT( KLocaleDateTime, "%E,%D%N%Y  %1 %2, %3%-B %:0%J%:1%T%:2%S%+B" );
       
    59 
       
    60 // JS time epoch 1st January 1970 (needed to offset from Symbian epoch)
       
    61 _LIT(KJsEpoch, "19700000:000000.000000");
       
    62 
       
    63 
       
    64 // ============================ MEMBER FUNCTIONS ===============================
       
    65 
       
    66 // ----------------------------------------------------------------------------
       
    67 // CDeviceLiwBinding::NewL
       
    68 // NewL
       
    69 //
       
    70 // ----------------------------------------------------------------------------
       
    71 //
       
    72 CDeviceLiwBinding* CDeviceLiwBinding::NewL()
       
    73     {
       
    74     CDeviceLiwBinding* bind = new (ELeave) CDeviceLiwBinding();
       
    75     CleanupStack::PushL(bind);
       
    76     bind->ConstructL();
       
    77     CleanupStack::Pop(bind);
       
    78     return bind;
       
    79     }
       
    80 
       
    81 // ----------------------------------------------------------------------------
       
    82 // CDeviceLiwBinding::ConstructL
       
    83 // ConstructL sencond phace construction.
       
    84 //
       
    85 // ----------------------------------------------------------------------------
       
    86 //
       
    87 void CDeviceLiwBinding::ConstructL()
       
    88     {
       
    89         m_critArr = new (ELeave) RCriteriaArray();
       
    90         m_serviceHandler = CLiwServiceHandler::NewL();
       
    91 
       
    92         RWidgetRegistryClientSession widgetregistry;
       
    93         TInt ret = widgetregistry.Connect();
       
    94         if ( ret != KErrNone && ret != KErrAlreadyExists )
       
    95             {
       
    96             User::Leave( ret );
       
    97             }
       
    98         else
       
    99             {
       
   100             CleanupClosePushL( widgetregistry );
       
   101             }
       
   102         TInt aPolicyId = widgetregistry.SecurityPolicyId();
       
   103         if ( aPolicyId < 0 )
       
   104             {
       
   105             User::Leave( aPolicyId );
       
   106             }
       
   107         User::LeaveIfError(widgetregistry.Disconnect());
       
   108         CleanupStack::PopAndDestroy(); //widgetregistry
       
   109 
       
   110         // we need to keep main session allive, to keep sub session
       
   111         m_secMgr = CRTSecManager::NewL();
       
   112         
       
   113         CTrustInfo* trust = CTrustInfo::NewLC();
       
   114 
       
   115         // TODO: in future, to support blanket permission,
       
   116         // this function should be called at installation time.
       
   117         // TInt32 exId = secMgr->RegisterScript( aPolicyId, *trust );
       
   118         // m_scriptSession = secMgr->GetScriptSession( aPolicyId, exId );
       
   119 
       
   120         // check for script session validity.
       
   121         m_scriptSession = m_secMgr->GetScriptSessionL( aPolicyId, *trust );
       
   122         if ( !m_scriptSession )
       
   123             {
       
   124             User::Leave( KErrGeneral );
       
   125             }
       
   126         CleanupStack::PopAndDestroy( trust );
       
   127     }
       
   128 
       
   129 
       
   130 // ----------------------------------------------------------------------------
       
   131 // CDeviceLiwBinding::~CDeviceLiwBinding
       
   132 // Default destructor
       
   133 //
       
   134 // ----------------------------------------------------------------------------
       
   135 //
       
   136 CDeviceLiwBinding::~CDeviceLiwBinding()
       
   137     {
       
   138     m_critArr->ResetAndDestroy();
       
   139     m_serviceHandler->DetachL(*m_critArr);
       
   140     m_critArr->ResetAndDestroy();
       
   141     delete m_critArr;
       
   142     delete m_serviceHandler;
       
   143     delete m_scriptSession;
       
   144     delete m_secMgr; 
       
   145     }
       
   146 
       
   147 
       
   148 // ----------------------------------------------------------------------------
       
   149 // CDeviceLiwBinding::LoadServiceProvider
       
   150 // Load service provider
       
   151 //
       
   152 // ----------------------------------------------------------------------------
       
   153 //
       
   154 TInt CDeviceLiwBinding::LoadServiceProvider( ExecState* exec, const List& args )
       
   155     {
       
   156     TInt error = KErrNone;
       
   157     CLiwCriteriaItem* item;
       
   158     HBufC8* svcName = NULL;
       
   159     HBufC8* interfaceName = NULL;
       
   160     int argcount = args.size();
       
   161 
       
   162     if ( argcount > 0 && args[0]->type() == StringType &&
       
   163         args[0]->toString( exec ).size() > 0 )
       
   164         {
       
   165             TRAP( error,
       
   166             {
       
   167             // Get service name
       
   168             svcName = KJS::GetAsciiBufferL( args[0]->toString( exec ) );
       
   169             CleanupStack::PushL( svcName );
       
   170 
       
   171             // Get optional supported interface
       
   172             if ( argcount > 1 && args[1]->type() == StringType &&
       
   173                 args[1]->toString( exec ).size() > 0 )
       
   174                 {
       
   175                 interfaceName = KJS::GetAsciiBufferL( args[1]->toString( exec ) );
       
   176                 CleanupStack::PushL( interfaceName );
       
   177                 }
       
   178 
       
   179             if ( interfaceName && interfaceName->Length() > 0 )
       
   180                 {
       
   181                 item = CLiwCriteriaItem::NewLC( 1, *interfaceName, *svcName );
       
   182                 }
       
   183             else
       
   184                 {
       
   185                 item = CLiwCriteriaItem::NewLC( 1, KNullDesC8(), *svcName );
       
   186                 }
       
   187 
       
   188             item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
       
   189             RCriteriaArray crit_arr;
       
   190             crit_arr.AppendL( item );
       
   191             
       
   192             CleanupStack::Pop(item); // item
       
   193 
       
   194             // "Attach" runtime to service
       
   195             if ( m_scriptSession && m_serviceHandler )
       
   196                 {
       
   197                 TInt load_err;
       
   198                 RWidgetRegistryClientSession widgetregistry;
       
   199                 TInt ret = widgetregistry.Connect();
       
   200                 if ( ret != KErrNone && ret != KErrAlreadyExists )
       
   201                     {
       
   202                     User::Leave( ret );
       
   203                     }
       
   204                 else
       
   205                    {
       
   206                    CleanupClosePushL( widgetregistry );
       
   207                    }
       
   208 
       
   209                 switch ( widgetregistry.WidgetSapiAccessState(m_Uid))
       
   210                     {
       
   211                     case SAPISECURITYPROMPTNEEDED :
       
   212                         load_err = m_serviceHandler->AttachL( crit_arr, *m_scriptSession );
       
   213                         break;
       
   214                     case SAPIPROMPTLESS :
       
   215                         load_err = m_serviceHandler->AttachL( crit_arr );
       
   216                         break;
       
   217                     case SAPIACCESSDENIED : 
       
   218                         load_err = KLiwSecurityAccessCheckFailed;
       
   219                         break;
       
   220                     default :
       
   221                         load_err = KLiwSecurityAccessCheckFailed;
       
   222                         break;
       
   223                     }
       
   224                 
       
   225                 User::LeaveIfError(widgetregistry.Disconnect());
       
   226                 CleanupStack::PopAndDestroy(); //widgetregistry
       
   227                 // hard coded for now since the definition of TLiwLoadStatus is not exposed to common dir yet
       
   228                 if ( load_err == KLiwServiceLoadSuccess || load_err == KLiwServiceAlreadyLoaded )
       
   229                     {
       
   230                     error = KErrNone; // normalize the error
       
   231                     m_critArr->AppendL( item );
       
   232                     }
       
   233                 else 
       
   234                     {
       
   235                     error = load_err; // pass on the TLiwLoadStatus
       
   236                     delete item;
       
   237                     }
       
   238                 }
       
   239 
       
   240             if ( interfaceName )
       
   241                 {
       
   242                 CleanupStack::PopAndDestroy( interfaceName );
       
   243                 }
       
   244 
       
   245             CleanupStack::PopAndDestroy( svcName );
       
   246             });
       
   247         }
       
   248     else
       
   249         {
       
   250         error = KErrArgument;
       
   251         }
       
   252 
       
   253     return error;
       
   254     }
       
   255 
       
   256 // ---------------------------------------------------------------------------
       
   257 // Convert Unload service provider
       
   258 // return JSValue - javascript list
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CDeviceLiwBinding::UnloadServiceProvider(const TDesC8& aServiceName,const TDesC8& aInterfaceName)
       
   262     {
       
   263     TRAP_IGNORE(
       
   264         CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC( 1, aInterfaceName, aServiceName );
       
   265         item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
       
   266         RCriteriaArray critArray;
       
   267         critArray.AppendL( item );
       
   268         m_serviceHandler->DetachL( critArray );
       
   269         CleanupStack::Pop(item);
       
   270         critArray.ResetAndDestroy();
       
   271         for (int i = 0; i < m_critArr->Count(); i++)
       
   272             {
       
   273             if ( (*m_critArr)[i]->ServiceCmdStr() == aInterfaceName &&
       
   274                  (*m_critArr)[i]->ContentType() == aServiceName)
       
   275                 m_critArr->Remove(i);
       
   276             }
       
   277         )
       
   278     }
       
   279 
       
   280 // ----------------------------------------------------------------------------
       
   281 // CDeviceLiwBinding::ServiceObjectPeer
       
   282 // Factory method to create a peer with service name
       
   283 //
       
   284 //
       
   285 // ----------------------------------------------------------------------------
       
   286 //
       
   287 MDevicePeer* CDeviceLiwBinding::ServiceObjectPeer(
       
   288     ExecState *exec,
       
   289     const List& args )
       
   290     {
       
   291     DeviceLiwPeer* peer = NULL;
       
   292 
       
   293     TRAPD( error,
       
   294         {
       
   295         peer = new ( ELeave ) DeviceLiwPeer(
       
   296             exec->lexicalInterpreter()->globalExec(), this, 0 );
       
   297         CleanupStack::PushL( peer );
       
   298         peer->SetServiceNameL( exec, args );
       
   299         CleanupStack::Pop(peer);
       
   300         });
       
   301 
       
   302     if ( error != KErrNone )
       
   303         {
       
   304         return 0;
       
   305         }
       
   306 
       
   307     return static_cast<MDevicePeer*>( peer );
       
   308     }
       
   309 
       
   310 // ----------------------------------------------------------------------------
       
   311 // CDeviceLiwBinding::ListProviders
       
   312 // Call/Invoke the LIW function to list the providers
       
   313 //
       
   314 //
       
   315 // ----------------------------------------------------------------------------
       
   316 //
       
   317 JSValue* CDeviceLiwBinding::ListProviders(
       
   318     ExecState* exec,
       
   319     const List& args )
       
   320     {
       
   321     CLiwCriteriaItem* item = NULL;
       
   322     HBufC8* cmdName = NULL;
       
   323     HBufC8* contentName = NULL;
       
   324     int argcount = args.size();
       
   325 
       
   326     // Get content name
       
   327     if ( argcount > 0 && args[0]->type() == StringType &&
       
   328         args[0]->toString( exec ).size() > 0 )
       
   329         {
       
   330         contentName = KJS::GetAsciiBufferL( args[0]->toString( exec ) );
       
   331         CleanupStack::PushL( contentName );
       
   332         }
       
   333 
       
   334     if ( argcount > 1 && args[1]->type() == StringType &&
       
   335         args[1]->toString( exec ).size() > 0 )
       
   336         {
       
   337         // Get cmd name
       
   338         cmdName = KJS::GetAsciiBufferL( args[1]->toString( exec ) );
       
   339         CleanupStack::PushL( cmdName );
       
   340         }
       
   341 
       
   342     if ( cmdName && cmdName->Length() > 0 )
       
   343         {
       
   344         if ( contentName && contentName->Length() > 0 )
       
   345             {
       
   346             item = CLiwCriteriaItem::NewLC( 1, *cmdName, *contentName );
       
   347             }
       
   348         else
       
   349             {
       
   350             item = CLiwCriteriaItem::NewLC( 1, *cmdName, KWildChar() );
       
   351             }
       
   352         }
       
   353     else
       
   354         {
       
   355         if ( contentName && contentName->Length() > 0 )
       
   356             {
       
   357             item = CLiwCriteriaItem::NewLC( 1, KWildChar(), *contentName );
       
   358             }
       
   359         else
       
   360             {
       
   361             item = CLiwCriteriaItem::NewLC( 1, KWildChar(), KWildChar() );
       
   362             }
       
   363         }
       
   364 
       
   365     RCriteriaArray critArray, providerList;
       
   366     item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
       
   367     critArray.AppendL( item );
       
   368     m_serviceHandler->QueryImplementationL( critArray, providerList );
       
   369     CleanupStack::Pop();//item
       
   370 
       
   371     if ( contentName )
       
   372         {
       
   373         CleanupStack::PopAndDestroy();//contentName
       
   374         }
       
   375 
       
   376     if ( cmdName )
       
   377         {
       
   378         CleanupStack::PopAndDestroy();//cmdName
       
   379         }
       
   380 
       
   381     if ( providerList.Count() > 0 )
       
   382         {
       
   383         // convert to js value
       
   384         List jsList;
       
   385         jsList.append( jsNumber( providerList.Count() ) );
       
   386         JSObject * rval = exec->lexicalInterpreter()->builtinArray()->construct(
       
   387                                                             exec, jsList );
       
   388 
       
   389         for ( TInt i = 0; i < providerList.Count(); i++ )
       
   390             {
       
   391             List jsPair;
       
   392             jsPair.append( jsNumber( 2 ) );
       
   393             JSObject * pairVal = exec->lexicalInterpreter()->builtinArray()->construct(
       
   394                                                             exec, jsPair );
       
   395 
       
   396             HBufC* buf1 = HBufC::NewLC( providerList[i]->ServiceCmdStr().Length() + 1 ); // +1 for zero terminate
       
   397             buf1->Des().Copy( providerList[i]->ServiceCmdStr() );
       
   398             buf1->Des().ZeroTerminate();
       
   399             pairVal->put( exec, Identifier::from(0), jsString( UString( (UChar*) buf1->Des().Ptr(), buf1->Des().Length() ) ) );
       
   400 
       
   401             HBufC* buf2 = HBufC::NewLC( providerList[i]->ContentType().Length() + 1 ); // +1 for zero terminate
       
   402             buf2->Des().Copy( providerList[i]->ContentType() );
       
   403             buf2->Des().ZeroTerminate();
       
   404             pairVal->put( exec, Identifier::from(1),
       
   405             jsString( UString( (UChar*) buf2->Des().Ptr(), buf2->Des().Length() ) ) );
       
   406 
       
   407             rval->put( exec, Identifier::from(i), pairVal );
       
   408             CleanupStack::PopAndDestroy(2);//buf1,buf2
       
   409             }
       
   410 
       
   411         critArray.ResetAndDestroy();
       
   412         providerList.ResetAndDestroy();
       
   413 
       
   414         return( rval );
       
   415         }
       
   416 
       
   417     critArray.ResetAndDestroy();
       
   418     providerList.ResetAndDestroy();
       
   419     return jsUndefined();
       
   420     }
       
   421 
       
   422 // ----------------------------------------------------------------------------
       
   423 // CDeviceLiwBinding::InvokeOpInternal
       
   424 // Call/Invoke the SAPI function
       
   425 //
       
   426 //
       
   427 // ----------------------------------------------------------------------------
       
   428 //
       
   429 JSValue* CDeviceLiwBinding::InvokeOpInternal(
       
   430     ExecState* exec,
       
   431     const Identifier& propertyName,
       
   432     const List& args,
       
   433     MDevicePeer* peer )
       
   434     {
       
   435     TUint cmdOption = 0;
       
   436     JSValue* rval = jsUndefined();
       
   437     int argcount = args.size();
       
   438     DeviceLiwPeer* callBack = NULL;
       
   439 
       
   440     if ( argcount > 1 )
       
   441         {
       
   442         cmdOption = KLiwOptASyncronous;
       
   443         if( args[1]->isObject() )
       
   444             {
       
   445             callBack = static_cast<DeviceLiwPeer*>( peer );
       
   446             }
       
   447         }
       
   448     if (propertyName == "Cancel")
       
   449         {
       
   450         cmdOption = KLiwOptCancel;
       
   451         }
       
   452     // Must have at least an operation name
       
   453     if ( propertyName.ustring().size() > 0 )
       
   454         {
       
   455         // Operation on a service interface object
       
   456         if ( peer && static_cast<DeviceLiwPeer*>( peer )->Interface() )
       
   457             {
       
   458             TRAPD( error,
       
   459                 {
       
   460                 CLiwGenericParamList* inps = CLiwGenericParamList::NewL(); // We manage this memory
       
   461                 CleanupStack::PushL( inps );
       
   462                 CLiwGenericParamList* outps = CLiwGenericParamList::NewL(); // And this
       
   463                 CleanupStack::PushL( outps );
       
   464 
       
   465                 // Collect args from first parameter. Note that args are
       
   466                 // passed as an associative array.
       
   467                 if ( argcount >= 1 )
       
   468                     {
       
   469                     JsList2LiwGenericParamListL( exec, args[0], *inps );
       
   470                     }
       
   471 
       
   472                 // Get the operation name
       
   473                 HBufC8* oper = KJS::GetAsciiBufferL( propertyName.ustring() );
       
   474                 CleanupStack::PushL( oper );
       
   475 
       
   476                 // Call the interface operation
       
   477 
       
   478                 TTrapHandler* ____t = User::MarkCleanupStack();
       
   479                 static_cast<DeviceLiwPeer*>( peer )->Interface()->ExecuteCmdL(
       
   480                                             *oper, *inps, *outps, cmdOption,
       
   481                                             callBack );
       
   482                 User::UnMarkCleanupStack(____t);
       
   483                 inps->Reset();
       
   484                 rval = LiwGenericParamList2JsArray( exec, outps );
       
   485                 outps->Reset();
       
   486                 CleanupStack::PopAndDestroy( oper ); // map
       
   487                 CleanupStack::Pop();// outps
       
   488                 CleanupStack::PopAndDestroy(  );// inps
       
   489                });
       
   490 
       
   491             if ( error != KErrNone )
       
   492                 {
       
   493                 return throwError(exec, GeneralError);
       
   494                 }
       
   495             }
       
   496         }
       
   497 
       
   498     return rval;
       
   499     }
       
   500 
       
   501 
       
   502 // ----------------------------------------------------------------------------
       
   503 // CDeviceLiwBinding::InvokeOp
       
   504 // Call/Invoke the SAPI function
       
   505 //
       
   506 //
       
   507 // ----------------------------------------------------------------------------
       
   508 //
       
   509 JSValue* CDeviceLiwBinding::InvokeOp(
       
   510     ExecState* exec,
       
   511     const Identifier& propertyName,
       
   512     const List& args,
       
   513     MDevicePeer* peer )
       
   514     {
       
   515     return InvokeOpInternal( exec, propertyName, args, peer );
       
   516     }
       
   517 
       
   518 
       
   519 // ----------------------------------------------------------------------------
       
   520 // CDeviceLiwBinding::CreateInterface
       
   521 // Create SAPI interface
       
   522 //
       
   523 //
       
   524 // ----------------------------------------------------------------------------
       
   525 //
       
   526 JSValue* CDeviceLiwBinding::CreateInterface(
       
   527     ExecState* exec, HBufC8* serviceName, const Identifier& interfaceName )
       
   528     {
       
   529     JSValue* rval = jsUndefined();
       
   530     TInt error = KErrNone;
       
   531 
       
   532     if ( m_serviceHandler && serviceName->Length() > 0 && interfaceName.ustring().size() > 0 )
       
   533         {
       
   534         // Since this is called from JS context, set up our own trap harness
       
   535         TRAP( error,
       
   536             {
       
   537             CLiwGenericParamList& inps = m_serviceHandler->InParamListL(); // LIW manages this memory
       
   538             CleanupStack::PushL( &inps );
       
   539             CLiwGenericParamList& outps = m_serviceHandler->OutParamListL(); // LIW manages this memory
       
   540             CleanupStack::PushL( &outps );
       
   541 
       
   542             HBufC8* ifaceName = KJS::GetAsciiBufferL( interfaceName.ustring() );
       
   543             CleanupStack::PushL( ifaceName );
       
   544 
       
   545             const HBufC8* hsvc = serviceName;
       
   546 
       
   547             // Create LIW params
       
   548             CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC( 1, *ifaceName,
       
   549                                         TPtrC8( hsvc->Ptr(), hsvc->Size() ) );
       
   550 
       
   551             item->SetServiceClass( TUid::Uid( KLiwClassBase ) );
       
   552 
       
   553             // Call the service command operation
       
   554             m_serviceHandler->ExecuteServiceCmdL(
       
   555                 *item, inps, outps, NULL );
       
   556 
       
   557             // Convert results into JS array
       
   558             rval = LiwGenericParamList2JsArray( exec, &outps );
       
   559             CleanupStack::PopAndDestroy( 2 ); //item, ifaceName
       
   560             CleanupStack::Pop( 2 );//inps, outps
       
   561         });
       
   562 
       
   563         if ( error != KErrNone)
       
   564             {
       
   565             return throwError(exec, GeneralError);
       
   566             }
       
   567         }
       
   568 
       
   569     return rval;
       
   570     }
       
   571 
       
   572 
       
   573 //TBD: replace this with a generic object type discovery method
       
   574 
       
   575 // ----------------------------------------------------------------------------
       
   576 // CDeviceLiwBinding::IsAList
       
   577 // Check if javascript list
       
   578 //
       
   579 //
       
   580 // ----------------------------------------------------------------------------
       
   581 //
       
   582 TBool CDeviceLiwBinding::IsAList( ExecState* exec, JSValue* aValue )
       
   583     {
       
   584     if(!aValue->isObject())
       
   585         return EFalse;
       
   586     PropertyNameArray propertyNames;
       
   587     aValue->toObject( exec )->getPropertyNames( exec, propertyNames );
       
   588     unsigned size = static_cast<unsigned>(propertyNames.size());
       
   589 
       
   590     for (unsigned i = 0; i < size; i++)
       
   591     {
       
   592         bool rval;
       
   593         propertyNames[i].toArrayIndex( &rval );
       
   594         if ( rval )
       
   595             {
       
   596             return ETrue;
       
   597             }
       
   598     }
       
   599 
       
   600     return EFalse;
       
   601     }
       
   602 
       
   603 
       
   604 // ----------------------------------------------------------------------------
       
   605 // CDeviceLiwBinding::JsVal2LiwVariant
       
   606 // Convert from javascript value to LiwVariant
       
   607 //
       
   608 //
       
   609 // ----------------------------------------------------------------------------
       
   610 //
       
   611 TBool CDeviceLiwBinding::JsVal2LiwVariant(
       
   612     ExecState* exec,
       
   613     JSValue* aValue,
       
   614     TLiwVariant& variant )
       
   615     {
       
   616     TBool ret = ETrue;
       
   617     TInt error = KErrNone;
       
   618 
       
   619     switch ( aValue->type() )
       
   620         {
       
   621         case StringType:
       
   622             {
       
   623             // Pass as TPtrC and let SAPI do the conversion to 8 bit if needed.
       
   624             TRAP( error,
       
   625                 {
       
   626                 variant.SetL( TLiwVariant(
       
   627                     TPtrC16( ( unsigned short* ) aValue->toString( exec ).data(),
       
   628                     aValue->toString( exec ).size() ) ) );
       
   629                 });
       
   630             break;
       
   631             }
       
   632         case NumberType:
       
   633             {
       
   634             if (isNaN(aValue->getNumber()) || isInf(aValue->getNumber()))
       
   635             {
       
   636                 ret = EFalse;
       
   637                 break;
       
   638             }
       
   639             TInt32 intVal = aValue->toInt32( exec );
       
   640             double doubleVal = aValue->toNumber( exec );
       
   641             if ( intVal != doubleVal )
       
   642             {
       
   643                 variant.Set( (TReal)doubleVal );
       
   644             }
       
   645             else
       
   646             {
       
   647                 // this is not fully correct due to the limitation of js number
       
   648                 variant.Set( intVal );
       
   649             }
       
   650             break;
       
   651             }
       
   652         case ObjectType:
       
   653             {
       
   654             JSObject* anObj = aValue->toObject( exec );
       
   655 
       
   656             // Handle date
       
   657             if(anObj->className().find(UString("Date"),0) == 0)
       
   658                 {
       
   659                 double d = aValue->toNumber( exec );  // get UTC milli seconds
       
   660                 if( isNaN(d) || isInf(d) )
       
   661                 {
       
   662                     ret = EFalse;
       
   663                     break;
       
   664                 }
       
   665 
       
   666                 //Get the JS time in integer seconds
       
   667                 const TInt64 dateVal = d;
       
   668 
       
   669                 // Set JS epoch offset from Symbian epoch
       
   670                 TTime sTime(KJsEpoch);
       
   671                 TTimeIntervalMicroSeconds dateMicroSecs(dateVal*1000);  // convert to UTC micro seconds
       
   672                 sTime += dateMicroSecs;
       
   673 
       
   674                 // uncomment following to debug time
       
   675                 //TBuf<100> date;
       
   676                 //sTime.FormatL(date,KLocaleDateTime);
       
   677 
       
   678                 // Set the LIW Variant time
       
   679                 variant.Set( sTime );
       
   680 
       
   681                 break;
       
   682             }
       
   683             // Boolean object
       
   684             else if(anObj->className().find(UString("Boolean"),0) == 0)
       
   685                 {
       
   686                 TBool val = aValue->toNumber( exec );
       
   687                 variant.Set( val );
       
   688                 break;
       
   689                 }
       
   690             // Number object
       
   691             else if(anObj->className().find(UString("Number"),0) == 0)
       
   692                 {
       
   693                 double d = aValue->toNumber( exec );
       
   694                 if (isNaN(d) || isInf(d))
       
   695                     {
       
   696                     ret = EFalse;
       
   697                     break;
       
   698                     }
       
   699                 TInt32 intVal = aValue->toInt32( exec );
       
   700                 if ( intVal != d )
       
   701                     {
       
   702                     variant.Set( (TReal)d );
       
   703                     }
       
   704                 else
       
   705                     {
       
   706                     // this is not fully correct due to the limitation of js number
       
   707                     variant.Set( intVal );
       
   708                     }
       
   709                 break;
       
   710                 }
       
   711             // String object
       
   712             else if(anObj->className().find(UString("String"),0) == 0)
       
   713                 {
       
   714                 // Pass as TPtrC and let SAPI do the conversion to 8 bit if needed.
       
   715                 TRAP( error,
       
   716                     {
       
   717                     variant.SetL( TLiwVariant(
       
   718                         TPtrC16( ( unsigned short* ) aValue->toString( exec ).data(),
       
   719                         aValue->toString( exec ).size() ) ) );
       
   720                     });
       
   721                 break;
       
   722                 }
       
   723             PropertyNameArray prop_names;
       
   724             aValue->toObject( exec )->getPropertyNames( exec, prop_names );
       
   725             unsigned size = static_cast<unsigned>(prop_names.size());
       
   726 
       
   727             // handle array
       
   728             if ( IsAList( exec, aValue ) )
       
   729                 {
       
   730                 CLiwList* liwList = NULL;
       
   731 
       
   732                 TRAP( error, { liwList = CLiwDefaultList::NewL(); } );
       
   733                 if ( error != KErrNone )
       
   734                     {
       
   735                     break;
       
   736                     }
       
   737                 CleanupStack::PushL( liwList );
       
   738 
       
   739                 for (unsigned i = 0; i < size; i++)
       
   740                     {
       
   741                     bool rval;
       
   742                     prop_names[i].toArrayIndex( &rval );
       
   743 
       
   744                     if ( rval )
       
   745                         {
       
   746                         TLiwVariant vv;
       
   747                         JSValue* v = aValue->toObject( exec )->get(exec, prop_names[i]);
       
   748 
       
   749                         if ( JsVal2LiwVariant( exec, v, vv ) )
       
   750                             {
       
   751                             TRAP( error, { liwList->AppendL( vv ); } );  // makes a copy
       
   752                             vv.Reset();
       
   753 
       
   754                             if ( error != KErrNone )
       
   755                                 {
       
   756                                 break; //from while
       
   757                                 }
       
   758                             }
       
   759                         }
       
   760                     }//end of while
       
   761 
       
   762                 if ( error == KErrNone )
       
   763                     {
       
   764                     if( liwList->Count() ) // do not set variant if list is empty
       
   765                         {
       
   766                         TRAP( error, { variant.SetL( liwList ); } );
       
   767                         }
       
   768                     }
       
   769 
       
   770                 CleanupStack::Pop( liwList );
       
   771                 liwList->DecRef();
       
   772                 }
       
   773             // handle other objects
       
   774             else
       
   775                 { // Map
       
   776                 TRAP( error,
       
   777                     {
       
   778                     CLiwMap* liwMap = CLiwDefaultMap::NewL();
       
   779                     CleanupClosePushL( *liwMap );
       
   780 
       
   781                     for (unsigned i = 0; i < size; i++)
       
   782                         {
       
   783                         HBufC8* keyName = KJS::GetAsciiBufferL(
       
   784                                         prop_names[i].ustring() );
       
   785                         CleanupStack::PushL( keyName );
       
   786 
       
   787                         TLiwVariant vv;
       
   788                         JSValue* v = aValue->toObject( exec )->get(exec, prop_names[i]);
       
   789 
       
   790                         if (!keyName || !keyName->Length() )
       
   791                             continue;
       
   792 
       
   793                         if ( !JsVal2LiwVariant( exec, v, vv )  )
       
   794                             {
       
   795                             // error converting js value to liw variant, throw debugging error
       
   796                             UString err_txt( "Invalid value:[" );
       
   797                             err_txt.append( v->toString(exec) );
       
   798                             err_txt.append( "] for key:[" );
       
   799                             err_txt.append( (const char *)keyName->Des().PtrZ() );
       
   800                             err_txt.append( "].\0" );
       
   801                             throwError( exec, GeneralError, err_txt );
       
   802                             }
       
   803                             else if ( !vv.IsEmpty() )
       
   804                             {
       
   805                             liwMap->InsertL( *keyName, vv );//makes a copy
       
   806                             vv.Reset();
       
   807                             }
       
   808 
       
   809                         CleanupStack::PopAndDestroy( keyName );
       
   810                         }
       
   811 
       
   812                     if( liwMap->Count() ) //do notset variant if map is empty
       
   813                         {
       
   814                         variant.SetL( liwMap );
       
   815                         }
       
   816                     CleanupStack::PopAndDestroy(); // this will call liwMap->close
       
   817                     });
       
   818                 }
       
   819             break;
       
   820             }
       
   821         case BooleanType:
       
   822             {
       
   823             TBool val = aValue->toNumber( exec );
       
   824             variant.Set( val );
       
   825             break;
       
   826             }
       
   827         case NullType:
       
   828         case UnspecifiedType:
       
   829         case UndefinedType:
       
   830         default:
       
   831             ret = EFalse;
       
   832             break;
       
   833         }
       
   834 
       
   835     if ( error != KErrNone )
       
   836         {
       
   837         ret = EFalse;
       
   838         }
       
   839 
       
   840     return ret;
       
   841     }
       
   842 
       
   843 
       
   844 // ----------------------------------------------------------------------------
       
   845 // CDeviceLiwBinding::DeviceLiwVariant2JsVal
       
   846 // Convert from LiwVariant to javascript value of the same type
       
   847 //
       
   848 //
       
   849 // ----------------------------------------------------------------------------
       
   850 //
       
   851 JSValue* CDeviceLiwBinding::LiwVariant2JsVal(
       
   852     ExecState* exec,
       
   853     const TLiwVariant& variant )
       
   854     {
       
   855     switch ( variant.TypeId() )
       
   856         {
       
   857         case EVariantTypeTInt32:
       
   858             {
       
   859             return jsNumber( variant.AsTInt32() );
       
   860             }
       
   861         case EVariantTypeDesC:
       
   862             {
       
   863             return jsString( UString(
       
   864                 (UChar*) variant.AsDes().Ptr(), variant.AsDes().Length() ) );
       
   865             }
       
   866         case EVariantTypeDesC8:// this is something wrong
       
   867             {
       
   868             JSValue* rval = jsUndefined();
       
   869             TRAPD( error,
       
   870                 {
       
   871                 HBufC* buf = HBufC::NewLC( variant.AsData().Length() + 1 ); // +1 for zero terminate
       
   872                 TPtr bufDes = buf->Des();
       
   873                 bufDes.Copy( variant.AsData() );
       
   874                 bufDes.ZeroTerminate();
       
   875                 rval = jsString( UString( (UChar*) bufDes.Ptr(), bufDes.Length() ) );
       
   876                 CleanupStack::PopAndDestroy();//buf
       
   877                 });
       
   878                 return rval;
       
   879             }
       
   880         case EVariantTypeList:
       
   881             {
       
   882             TLiwVariant v;
       
   883             List jsList;
       
   884             jsList.append( jsNumber( variant.AsList()->Count() ) );
       
   885             JSObject * rval = exec->lexicalInterpreter()->builtinArray()->construct(
       
   886                 exec, jsList );
       
   887 
       
   888             for ( TInt i = 0; i < variant.AsList()->Count(); i++ )
       
   889                 {
       
   890                 TRAPD( error, { variant.AsList()->AtL( i, v ); } );
       
   891                 rval->put(
       
   892                     exec, Identifier::from(i), LiwVariant2JsVal( exec, v ) );
       
   893                 }
       
   894             v.Reset();
       
   895             return rval;
       
   896             }
       
   897         case EVariantTypeMap:
       
   898             {
       
   899             TLiwVariant v;
       
   900             List jsList;
       
   901             jsList.append( jsNumber( variant.AsMap()->Count() ) );
       
   902             JSObject * rval = new DeviceLiwMap(exec->lexicalInterpreter()->builtinArray()->construct(
       
   903                 exec, jsList ), variant.AsMap(), this);
       
   904 
       
   905             for ( TInt i = 0; i < variant.AsMap()->Count(); i++ )
       
   906                 {
       
   907                 TBuf8<KMaxKeySize> name;
       
   908                 TRAPD( error,
       
   909                     {
       
   910                     if ( variant.AsMap()->AtL( i, name ) )
       
   911                         {
       
   912                         variant.AsMap()->FindL( name, v );
       
   913                         rval->put( exec,
       
   914                                 Identifier( ( const char* ) name.PtrZ() ),
       
   915                                 LiwVariant2JsVal( exec, v ) );
       
   916                         }
       
   917                     });
       
   918                 // No error processing
       
   919                 }
       
   920             v.Reset();
       
   921             return rval;
       
   922             }
       
   923         case EVariantTypeInterface:
       
   924             {
       
   925             // new DeviceLiwPeer() might fail, in which case the service JSObject * peer will be null
       
   926             DeviceLiwPeer* peer = new DeviceLiwPeer(
       
   927                                 exec->lexicalInterpreter()->globalExec(),
       
   928                                 this, variant.AsInterface() );
       
   929             if ( !peer )
       
   930                 {
       
   931                 return jsUndefined();
       
   932                 }
       
   933 
       
   934             JSObject* impl = new DeviceLiwInterface( exec, this, peer );
       
   935             return impl;
       
   936             }
       
   937         case EVariantTypeIterable:
       
   938             {
       
   939             return new DeviceLiwIterable(exec, this, variant.AsIterable());
       
   940             }
       
   941         case EVariantTypeTReal:
       
   942             {
       
   943             TReal realValue;
       
   944             variant.Get( realValue );
       
   945             return jsNumber( realValue );
       
   946             }
       
   947         case EVariantTypeTBool:
       
   948             {
       
   949             TBool boolValue;
       
   950             variant.Get( boolValue );
       
   951             return jsBoolean( boolValue );
       
   952             }
       
   953             //Note that unmarshaling to String here is not symetrical with marshaling from Date
       
   954             //but JS application can easily construct a Date if it wants one
       
   955         case EVariantTypeTTime:
       
   956             {
       
   957             TTime UTCTime;
       
   958             TBuf<KTimeBufSize> buf;
       
   959             variant.Get( UTCTime );
       
   960 
       
   961             TTime utcNow;
       
   962             utcNow.UniversalTime();
       
   963             TTime localNow;
       
   964             localNow.HomeTime();
       
   965             // convert UTC time to local time
       
   966             TTimeIntervalMicroSeconds diff = localNow.MicroSecondsFrom(utcNow);
       
   967             TTime localTime = UTCTime + diff;
       
   968             // format the time to output string
       
   969             localTime.FormatL( buf, KLocaleDateTime );
       
   970             const UChar *p = (const UChar*)buf.Ptr();
       
   971             return jsString( UString( p, buf.Length() ) );
       
   972             }
       
   973         case EVariantTypeBuffer: // this is something i don't what to do
       
   974             {
       
   975             return jsUndefined();
       
   976                 /*
       
   977             CLiwBuffer* buf = variant.AsBuffer();
       
   978             switch (buf->TypeID())
       
   979                 {
       
   980                 case KLiwBufferFile:
       
   981                     {
       
   982                     RFile file = ((CLiwFileBuffer*)buf)->AsFile();
       
   983                     TFileName fileName;
       
   984                     file.FullName(fileName);
       
   985                     return jsString( UString((UChar*) fileName.Ptr(), fileName.Length() ) );
       
   986                     }
       
   987                 case KLiwBufferBitmap:
       
   988                     {
       
   989                     return jsUndefined();
       
   990                     }
       
   991                 default:
       
   992                     return jsUndefined();
       
   993                 }*/
       
   994             }
       
   995         case EVariantTypeTUid:
       
   996         case EVariantTypeFileHandle:
       
   997         default:
       
   998             return jsUndefined();
       
   999         }
       
  1000     }
       
  1001 
       
  1002 
       
  1003 // ----------------------------------------------------------------------------
       
  1004 // CDeviceLiwBinding::JsList2LiwGenericParamListL
       
  1005 // Convert javascript array (list) to LiwGenericParamList
       
  1006 //
       
  1007 //
       
  1008 // ----------------------------------------------------------------------------
       
  1009 //
       
  1010 void CDeviceLiwBinding::JsList2LiwGenericParamListL(
       
  1011     ExecState* exec,
       
  1012     JSValue* aValue,
       
  1013     CLiwGenericParamList& aLiwList )
       
  1014     {
       
  1015     if (!aValue->isObject())
       
  1016         return;
       
  1017     PropertyNameArray propertyNames;
       
  1018     aValue->toObject( exec )->getPropertyNames( exec, propertyNames );
       
  1019     int size = static_cast<unsigned>(propertyNames.size());
       
  1020 
       
  1021     for (unsigned i = 0; i < size; i++)
       
  1022         {
       
  1023         HBufC8* name = KJS::GetAsciiBufferL(propertyNames[i].ustring() );
       
  1024         if ( !name->Length() )
       
  1025             break;
       
  1026         CleanupStack::PushL( name );
       
  1027         JSValue* v = aValue->toObject( exec )->get( exec, propertyNames[i] );;
       
  1028         TLiwVariant vv;
       
  1029 
       
  1030         if (  !JsVal2LiwVariant( exec, v, vv ) ) // error occurred
       
  1031             {
       
  1032             throwError(exec, GeneralError);
       
  1033             }
       
  1034         else if ( !vv.IsEmpty() )
       
  1035             {
       
  1036             aLiwList.AppendL( TLiwGenericParam( *name, vv ) );
       
  1037             vv.Reset();
       
  1038             }
       
  1039 
       
  1040         CleanupStack::PopAndDestroy(); //name
       
  1041         }
       
  1042     }
       
  1043 
       
  1044 
       
  1045 // ----------------------------------------------------------------------------
       
  1046 // CDeviceLiwBinding::LiwGenericParamList2JsArray
       
  1047 // Convert LiwGenericParamList to javascript array (list)
       
  1048 //
       
  1049 //
       
  1050 // ----------------------------------------------------------------------------
       
  1051 //
       
  1052 JSValue* CDeviceLiwBinding::LiwGenericParamList2JsArray(
       
  1053     ExecState* exec,
       
  1054     CLiwGenericParamList* aLiwList )
       
  1055     {
       
  1056     // the output param list should not be empty, if it is, return an undefined js obj.
       
  1057     if ( aLiwList->Count() == 0 )
       
  1058         return jsUndefined();
       
  1059 
       
  1060     List jsList;
       
  1061 
       
  1062     jsList.append( jsNumber( aLiwList->Count() ) );
       
  1063 
       
  1064     JSObject * rval = new DeviceLiwResult(exec->lexicalInterpreter()->builtinArray()->construct(
       
  1065                 exec, jsList ));
       
  1066 
       
  1067     for ( TInt i = 0; i < aLiwList->Count(); i++ )
       
  1068         {
       
  1069         TBuf8<KMaxKeySize> name( (*aLiwList)[i].Name() );
       
  1070         rval->put( exec, Identifier( (const char*) name.PtrZ() ),
       
  1071             LiwVariant2JsVal( exec, (*aLiwList)[i].Value() ) );  //??? should call AtL?
       
  1072         }
       
  1073 
       
  1074     return rval;
       
  1075     }
       
  1076 
       
  1077 // ----------------------------------------------------------------------------
       
  1078 // CDeviceLiwBinding::SetUid
       
  1079 // Sets the widget uid
       
  1080 //
       
  1081 //
       
  1082 // ----------------------------------------------------------------------------
       
  1083 //
       
  1084 void CDeviceLiwBinding::SetUid( const TUint& aValue)
       
  1085     {
       
  1086     m_Uid.iUid = aValue;
       
  1087     }
       
  1088 
       
  1089 // ----------------------------------------------------------------------------
       
  1090 // KJS::GetAsciiBufferL
       
  1091 // Convert the Unicode string to plain ASCII chars chopping of any higher bytes
       
  1092 //
       
  1093 //
       
  1094 // ----------------------------------------------------------------------------
       
  1095 //
       
  1096 HBufC8* KJS::GetAsciiBufferL( const UString& aBuf )
       
  1097     {
       
  1098     int length = aBuf.size();
       
  1099     HBufC8* buf = HBufC8::NewL( length + 1 ); // +1 for zero terminate
       
  1100     TPtr8 bufDes8 = buf->Des();
       
  1101     const UChar* p = aBuf.data();
       
  1102     const UChar *limit = p + length;
       
  1103 
       
  1104     while ( p != limit )
       
  1105         {
       
  1106         TChar c = p->uc;
       
  1107         bufDes8.Append( c );
       
  1108         ++p;
       
  1109         }
       
  1110 
       
  1111     bufDes8.ZeroTerminate();
       
  1112     return buf;
       
  1113     }
       
  1114 
       
  1115 //END OF FILE