menucontentsrv/src/menu.cpp
changeset 0 79c6a41cd166
equal deleted inserted replaced
-1:000000000000 0:79c6a41cd166
       
     1 /*
       
     2 * Copyright (c) 2009 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 "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:
       
    15 *
       
    16 */
       
    17 #include "mcsdef.h"
       
    18 
       
    19 #include "mcsmenu.h"
       
    20 #include "menusrvdef.h"
       
    21 #include "menumsg.h"
       
    22 #include "menubuf.h"
       
    23 #include "menuutil.h"
       
    24 #include "menuclientoperation.h"
       
    25 #include "menuhandlereng.h"
       
    26 #include "mcsmenufilter.h"
       
    27 
       
    28 #include <s32strm.h>
       
    29 #include <e32debug.h>
       
    30 
       
    31 // ================= LOCAL FUNCTIONS =======================
       
    32 
       
    33 /**
       
    34 * Start the server executable.
       
    35 * @return Error code.
       
    36 */
       
    37 LOCAL_C TInt StartServer()
       
    38     {
       
    39     TInt err( KErrNone );
       
    40     RProcess server;
       
    41     err = server.Create( KMenuSrvExe, KNullDesC, EOwnerThread );
       
    42     if ( !err )
       
    43         {
       
    44         TRequestStatus status;
       
    45         server.Rendezvous( status );
       
    46         if ( status != KRequestPending )
       
    47             {
       
    48             server.Kill( 0 ); // Abort startup.
       
    49             }
       
    50         else
       
    51             {
       
    52             server.Resume(); // Logon OK - start the server.
       
    53             }
       
    54         User::WaitForRequest( status ); // Wait for start or death.
       
    55         // We can't use the 'exit reason' if the server panicked as this
       
    56         // is the panic 'reason' and may be '0' which cannot be distinguished
       
    57         // from KErrNone.
       
    58         err = (server.ExitType() == EExitPanic) ? KErrGeneral : status.Int();
       
    59         server.Close();
       
    60         }
       
    61     return err;
       
    62     }
       
    63 
       
    64 // ================= MEMBER FUNCTIONS =======================
       
    65 
       
    66 NONSHARABLE_CLASS( RMenu::TData )
       
    67     {
       
    68 public:
       
    69     // Transfer buffer. Size must be big enough to accomodate any object that
       
    70     // will go through it: attribute, TMenuItem
       
    71     TUint16 iBuf[KMenuMaxAttrValueLen];
       
    72     // Handler engine.
       
    73     CMenuHandlerEng* iHandler;
       
    74     };
       
    75 
       
    76 // ================= MEMBER FUNCTIONS =======================
       
    77 
       
    78 // ---------------------------------------------------------
       
    79 // RMenu::Close
       
    80 // ---------------------------------------------------------
       
    81 //
       
    82 EXPORT_C void RMenu::Close()
       
    83     {
       
    84     RSessionBase::Close();
       
    85     if ( iData )
       
    86         {
       
    87         delete iData->iHandler; iData->iHandler = NULL;
       
    88         delete iData; iData = NULL;
       
    89         }
       
    90     }
       
    91 
       
    92 // ---------------------------------------------------------
       
    93 // RMenu::OpenL
       
    94 // ---------------------------------------------------------
       
    95 //
       
    96 EXPORT_C void RMenu::OpenL( const TDesC& aName )
       
    97     {
       
    98     __ASSERT_DEBUG( !iData, User::Invariant() );
       
    99     User::LeaveIfError( ConnectSession() );
       
   100     CleanupClosePushL( *this ); // Atomcic connect + local data + construct.
       
   101     iData = new (ELeave) RMenu::TData();
       
   102     iData->iHandler = NULL;
       
   103     // We have a connected blank session, now construct it.
       
   104     // It would be good to have a CreateSession which leaves us at least one
       
   105     // IpcArg, so the name could be sent to session creation directly.
       
   106     // Since having a fully constructed session needs this extra IPC, the
       
   107     // server side session had to be cluttered with ASSERTS. (Almost all
       
   108     // messages need to check that the session is fully constructed.)
       
   109     //
       
   110     // The reason for this is a design issue (we use the session as an object,
       
   111     // and not just as a communication channel. But normally there is only one
       
   112     // object used, so why complicate things for the client?
       
   113     User::LeaveIfError
       
   114         ( SendReceive( EMenuConstructSession, TIpcArgs( &aName ) ) );
       
   115     CleanupStack::Pop( this );
       
   116     }
       
   117 
       
   118 // ---------------------------------------------------------
       
   119 // RMenu::RootFolderL
       
   120 // ---------------------------------------------------------
       
   121 //
       
   122 EXPORT_C TInt RMenu::RootFolderL()
       
   123     {
       
   124     __ASSERT_DEBUG( iData, User::Invariant() );
       
   125     TPckgBuf<TInt> pckg;
       
   126     User::LeaveIfError( SendReceive( EMenuRootFolder, TIpcArgs( &pckg ) ) );
       
   127     return pckg();
       
   128     }
       
   129 
       
   130 // ---------------------------------------------------------
       
   131 // RMenu::GetItemsL
       
   132 // ---------------------------------------------------------
       
   133 //
       
   134 EXPORT_C void RMenu::GetItemsL(
       
   135         RArray<TMenuItem>& aItemArray,
       
   136         TInt aFolder,
       
   137         const CMenuFilter* aFilter /*=NULL*/,
       
   138         TBool aRecursive /*=EFalse*/ )
       
   139     {
       
   140     __ASSERT_DEBUG( iData, User::Invariant() );
       
   141     if ( aFilter )
       
   142         {
       
   143         // Filtered query, 2+ more IPC.
       
   144         // The buffer is opened empty, used to send the filter
       
   145         // then the result is received into it.
       
   146         RMenuBuf buf;
       
   147         User::LeaveIfError( buf.Open( *this ) );
       
   148         CleanupClosePushL( buf );
       
   149         RWriteStream stream( &buf );
       
   150         aFilter->ExternalizeL( stream );
       
   151         stream.CommitL();
       
   152         TIpcArgs args( aFolder, aRecursive, buf.SubSessionHandle() );
       
   153         User::LeaveIfError( SendReceive( EMenuGetItemsFiltered, args ) );
       
   154         RReadStream rs( &buf );
       
   155         MenuUtil::InternalizeL( aItemArray, rs );
       
   156         CleanupStack::PopAndDestroy( &buf );
       
   157         }
       
   158     else
       
   159         {
       
   160         // Unfiltered query.
       
   161         // The buffer already contains the query result when Open() returns.
       
   162         RMenuBuf buf;
       
   163         TIpcArgs args( aFolder, aRecursive );
       
   164         User::LeaveIfError( buf.Open( *this, EMenuGetItems, args ) );
       
   165         CleanupClosePushL( buf );
       
   166         RReadStream stream( &buf );
       
   167         MenuUtil::InternalizeL( aItemArray, stream );
       
   168         CleanupStack::PopAndDestroy( &buf );
       
   169         }
       
   170     }
       
   171 
       
   172 // ---------------------------------------------------------
       
   173 // RMenu::GetRunningAppsL
       
   174 // ---------------------------------------------------------
       
   175 //
       
   176 EXPORT_C  void RMenu::GetRunningAppsL( RArray<TUid>& aArray )
       
   177 	{
       
   178     RMenuBuf buf;
       
   179     TIpcArgs args( 0 );
       
   180     User::LeaveIfError( buf.Open( *this, EMenuGetRunningApps, args ) );
       
   181     CleanupClosePushL( buf );
       
   182     RReadStream stream( &buf );
       
   183     MenuUtil::InternalizeL( aArray, stream );
       
   184     CleanupStack::PopAndDestroy( &buf );
       
   185 	}
       
   186     
       
   187 
       
   188 // ---------------------------------------------------------
       
   189 // RMenu::RemoveL
       
   190 // ---------------------------------------------------------
       
   191 //
       
   192 EXPORT_C CMenuOperation* RMenu::RemoveL( TInt aId, TRequestStatus& aStatus )
       
   193     {
       
   194     __ASSERT_DEBUG( iData, User::Invariant() );
       
   195     CMenuClientOperation* op = new (ELeave) CMenuClientOperation
       
   196         ( *this, CActive::EPriorityStandard, aStatus );
       
   197     CleanupStack::PushL( op );
       
   198     op->RemoveL( aId );
       
   199     CleanupStack::Pop( op );
       
   200     return op;
       
   201     }
       
   202 
       
   203 // ---------------------------------------------------------
       
   204 // RMenu::MoveToFolderL
       
   205 // ---------------------------------------------------------
       
   206 //
       
   207 EXPORT_C CMenuOperation* RMenu::MoveToFolderL(
       
   208         const RArray<TInt>& aItems,
       
   209         TInt aFolder,
       
   210         TInt aMoveBefore,
       
   211         TRequestStatus& aStatus )
       
   212     {
       
   213     __ASSERT_DEBUG( iData, User::Invariant() );
       
   214     RMenuBuf buf;
       
   215     User::LeaveIfError( buf.Open( *this ) );
       
   216     CleanupClosePushL( buf );
       
   217     RWriteStream stream( &buf );
       
   218     MenuUtil::ExternalizeL( aItems, stream );
       
   219     stream.CommitL();
       
   220     CMenuClientOperation* op = new (ELeave) CMenuClientOperation
       
   221         ( *this, CActive::EPriorityStandard, aStatus );
       
   222     CleanupStack::PushL( op );
       
   223     op->MoveToFolderL( buf, aFolder, aMoveBefore );
       
   224     CleanupStack::Pop( op );
       
   225     CleanupStack::PopAndDestroy( &buf );
       
   226     return op;
       
   227     }
       
   228 
       
   229 // ---------------------------------------------------------
       
   230 // RMenu::ReorderL
       
   231 // ---------------------------------------------------------
       
   232 //
       
   233 EXPORT_C CMenuOperation* RMenu::ReorderL
       
   234 ( TInt aId, TInt aMoveBefore, TRequestStatus& aStatus )
       
   235     {
       
   236     __ASSERT_DEBUG( iData, User::Invariant() );
       
   237     CMenuClientOperation* op = new (ELeave) CMenuClientOperation
       
   238         ( *this, CActive::EPriorityStandard, aStatus );
       
   239     CleanupStack::PushL( op );
       
   240     op->ReorderL( aId, aMoveBefore );
       
   241     CleanupStack::Pop( op );
       
   242     return op;
       
   243     }
       
   244 
       
   245 // ---------------------------------------------------------
       
   246 // RMenu::ResourceMark
       
   247 // ---------------------------------------------------------
       
   248 //
       
   249 EXPORT_C void RMenu::ResourceMark()
       
   250     {
       
   251     SendReceive( EMenuResourceMarkStart );
       
   252     }
       
   253 
       
   254 // ---------------------------------------------------------
       
   255 // RMenu::ResourceCheck
       
   256 // ---------------------------------------------------------
       
   257 //
       
   258 EXPORT_C void RMenu::ResourceCheck()
       
   259     {
       
   260     SendReceive( EMenuResourceMarkEnd );
       
   261     }
       
   262 
       
   263 // ---------------------------------------------------------
       
   264 // RMenu::ResourceCount
       
   265 // ---------------------------------------------------------
       
   266 //
       
   267 EXPORT_C TInt RMenu::ResourceCount()
       
   268     {
       
   269     return SendReceive( EMenuResourceCount );
       
   270     }
       
   271 
       
   272 #ifdef _DEBUG
       
   273 
       
   274 // ---------------------------------------------------------
       
   275 // RMenu::__DbgSetAllocFail
       
   276 // ---------------------------------------------------------
       
   277 //
       
   278 EXPORT_C void RMenu::__DbgSetAllocFail
       
   279 ( RAllocator::TAllocFail aType, TInt aRate )
       
   280     {
       
   281     TInt type = STATIC_CAST( TInt, aType );
       
   282     SendReceive( EMenuSetHeapFailure, TIpcArgs( type, aRate ) );
       
   283     }
       
   284 
       
   285 #else /* not _DEBUG */
       
   286 
       
   287 // ---------------------------------------------------------
       
   288 // RMenu::__DbgSetAllocFail
       
   289 // ---------------------------------------------------------
       
   290 //
       
   291 EXPORT_C void RMenu::__DbgSetAllocFail
       
   292 ( RAllocator::TAllocFail /*aType*/, TInt /*aRate*/ )
       
   293     {
       
   294     }
       
   295 
       
   296 #endif /* def _DEBUG */
       
   297 
       
   298 // ---------------------------------------------------------
       
   299 // RMenu::HandleCommandL
       
   300 // ---------------------------------------------------------
       
   301 //
       
   302 CMenuOperation* RMenu::HandleCommandL(
       
   303         CMenuItem& aItem,
       
   304         const TDesC8& aCommand,
       
   305         const TDesC8& aParams,
       
   306         TRequestStatus& aStatus )
       
   307     {
       
   308     __ASSERT_DEBUG( iData, User::Invariant() );
       
   309     if ( !iData->iHandler )
       
   310         {
       
   311         // Create handler engine on demand - handlers not loaded unless needed.
       
   312         iData->iHandler = CMenuHandlerEng::NewL( *this );
       
   313         }
       
   314     return iData->iHandler->HandleCommandL
       
   315         ( aItem, aCommand, aParams, aStatus );
       
   316     }
       
   317 
       
   318 // ---------------------------------------------------------
       
   319 // RMenu::ConnectSession
       
   320 // ---------------------------------------------------------
       
   321 //
       
   322 TInt RMenu::ConnectSession()
       
   323     {
       
   324     TVersion version( KMenuMajorVersion, KMenuMinorVersion, KMenuBuild );
       
   325     TInt err = CreateSession( KMenuSrvName, version );
       
   326     if ( KErrNotFound == err )
       
   327         {
       
   328         err = StartServer();
       
   329         if ( !err || KErrAlreadyExists == err ) // Deal with race conditions.
       
   330             {
       
   331             err = CreateSession( KMenuSrvName, version );
       
   332             }
       
   333         }
       
   334     return err;
       
   335     }
       
   336 
       
   337 // ---------------------------------------------------------
       
   338 // RMenu::GetAttributeL
       
   339 // ---------------------------------------------------------
       
   340 //
       
   341 HBufC* RMenu::GetAttributeL( TInt aId, const TDesC& aAttrName )
       
   342     {
       
   343     __ASSERT_DEBUG( iData, User::Invariant() );
       
   344     __ASSERT_DEBUG( sizeof( iData->iBuf ) >= 2 * KMenuMaxAttrValueLen, \
       
   345         User::Invariant() ); // Must fit into the transfer buffer.
       
   346     
       
   347     RBuf ptr;
       
   348     ptr.CleanupClosePushL();
       
   349     ptr.CreateL(KMenuMaxAttrValueLen);
       
   350     TPckgBuf<TBool> attrExists( EFalse );
       
   351     TIpcArgs args( aId, &aAttrName, &attrExists, &ptr );
       
   352     User::LeaveIfError( SendReceive( EMenuItemGetAttribute, args ) );
       
   353     
       
   354     if( attrExists() )
       
   355     	{
       
   356     	HBufC* ret = ptr.AllocL();
       
   357     	CleanupStack::PopAndDestroy( &ptr );
       
   358     	return ret;
       
   359     	}
       
   360     else
       
   361     	{
       
   362     	CleanupStack::PopAndDestroy( &ptr );
       
   363     	return NULL;
       
   364     	}
       
   365     }
       
   366     
       
   367 
       
   368 
       
   369 // ---------------------------------------------------------
       
   370 // RMenu::GetAttributeL
       
   371 // ---------------------------------------------------------
       
   372 void RMenu::GetAttributeListL( TInt aId, RArray<TAttributeName>& aList )
       
   373     {
       
   374     __ASSERT_DEBUG( iData, User::Invariant() );
       
   375     __ASSERT_DEBUG( sizeof( iData->iBuf ) >= 2 * KMenuMaxAttrValueLen, \
       
   376         User::Invariant() ); // Must fit into the transfer buffer.
       
   377 
       
   378     RMenuBuf buf;
       
   379     TIpcArgs args( aId );
       
   380     User::LeaveIfError( buf.Open( *this, EMenuItemGetAttributeList, args ) );
       
   381     CleanupClosePushL( buf );
       
   382     RReadStream rs( &buf );
       
   383     
       
   384     TInt len;
       
   385     TAttributeName name;
       
   386     while ( ETrue )
       
   387         {
       
   388 
       
   389         len = rs.ReadInt32L();
       
   390 
       
   391         if ( len == 0 )
       
   392             {
       
   393             break;
       
   394             }
       
   395 
       
   396         rs.ReadL( name, len );
       
   397         aList.AppendL( name );
       
   398         }
       
   399 
       
   400     CleanupStack::PopAndDestroy( &buf );
       
   401     }
       
   402 
       
   403 // ---------------------------------------------------------
       
   404 // RMenu::GetHdrL
       
   405 // ---------------------------------------------------------
       
   406 //
       
   407 const TMenuItem& RMenu::GetHdrL( TInt aId )
       
   408     {
       
   409     __ASSERT_DEBUG( iData, User::Invariant() );
       
   410     __ASSERT_DEBUG( sizeof( iData->iBuf ) >= sizeof( TMenuItem ), \
       
   411         User::Invariant() ); // Header must fit into the transfer buffer.
       
   412     TPckg<TMenuItem> pckg( (TMenuItem&)iData->iBuf );
       
   413     TIpcArgs args( aId, &pckg );
       
   414     User::LeaveIfError( SendReceive( EMenuGetHdr, args ) );
       
   415     return pckg(); // Returned object is in the transfer buffer.
       
   416     }