uifw/AknGlobalUI/NotifierWrapper/src/AknNotifierWrapper.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2004-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 "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:  Notifier server app wrapper implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    19 #include <uiklaf/private/pluginuid.hrh>
       
    20 #include <uikon/eiknotifyalert.h>
       
    21 #endif
       
    22 #include <apgtask.h>
       
    23 #include <apgcli.h>
       
    24 #include <apacmdln.h>
       
    25 #include <coemain.h>
       
    26 #include <uikon/eiksrvui.h>
       
    27 #include "AknNotifierWrapper.h"
       
    28 #include "AknNotifierControllerUtilities.h"
       
    29 #include <AknNotifierControllerPlugin.h>
       
    30 #include <AknCapServerDefs.h>
       
    31 
       
    32 const TInt KPreLoadEnabledButNotDoneYet(2);
       
    33 
       
    34 //-------------------------------------------
       
    35 // CAknNotifierMessageObserver
       
    36 //-------------------------------------------    
       
    37  
       
    38 CAknNotifierMessageObserver::CAknNotifierMessageObserver(TUid aNotifierUid, 
       
    39     MAknNotifierWrapper* aOwner, 
       
    40     const RMessagePtr2& aClientMessage, 
       
    41     TInt aReplySlot)
       
    42 :CActive(CActive::EPriorityStandard), 
       
    43     iNotifierUid(aNotifierUid), 
       
    44     iReplySlot(aReplySlot), 
       
    45     iOwner(aOwner)
       
    46     {
       
    47     iMessage = aClientMessage;
       
    48     CActiveScheduler::Add(this);       
       
    49     }
       
    50  
       
    51  
       
    52 EXPORT_C CAknNotifierMessageObserver* CAknNotifierMessageObserver::NewServerRequestL(
       
    53     TUid aNotifierUid, 
       
    54     MAknNotifierWrapper* aOwner, 
       
    55     const RMessagePtr2& aClientMessage, 
       
    56     TInt aReplySlot)
       
    57     {
       
    58     CAknNotifierMessageObserver* me = 
       
    59         new (ELeave) CAknNotifierMessageObserver(aNotifierUid,aOwner,aClientMessage,aReplySlot);
       
    60     
       
    61     // a bit awkward I admit...
       
    62     if (!aClientMessage.IsNull())
       
    63         {
       
    64         CleanupStack::PushL(me);
       
    65         me->iReplyBuf = HBufC8::NewL(aClientMessage.GetDesLength(aReplySlot));
       
    66         // we need ptr which keeps its address during async operation
       
    67         me->iReplyDesc = new (ELeave) TPtr8(me->iReplyBuf->Des());
       
    68         CleanupStack::Pop();
       
    69 
       
    70         // just in case: if notifier implementation wants to transmit data via replybuf for 
       
    71         // some reason
       
    72         aClientMessage.Read(aReplySlot,*(me->iReplyDesc));  
       
    73         }
       
    74         
       
    75     return me;    
       
    76     }
       
    77  
       
    78  
       
    79 CAknNotifierMessageObserver::~CAknNotifierMessageObserver()
       
    80     {
       
    81     delete iReplyDesc;
       
    82     delete iReplyBuf;
       
    83     delete iInputBuf;
       
    84     __ASSERT_DEBUG(!IsActive(), User::Invariant() );
       
    85     }
       
    86   
       
    87 void CAknNotifierMessageObserver::DoCancel()
       
    88     {
       
    89     if (iOwner)
       
    90         {
       
    91         iOwner->AsyncMessageCompleted( this );
       
    92         }
       
    93 
       
    94     if (!iMessage.IsNull())
       
    95         {
       
    96         iMessage.Complete(KErrCancel);
       
    97         }
       
    98 
       
    99     User::WaitForRequest(iStatus);
       
   100     delete this;
       
   101     }
       
   102  
       
   103 void CAknNotifierMessageObserver::RunL()
       
   104     {
       
   105     if (iOwner)
       
   106         {// offer message from app-server for wrapper to clone
       
   107         iOwner->AsyncMessageCompleted( this );
       
   108         }
       
   109 
       
   110     // if Owner did not complete the message, do default reply 
       
   111     if (!iMessage.IsNull())
       
   112         {
       
   113         TInt err = iMessage.Write(iReplySlot,iReplyBuf->Des());
       
   114         iMessage.Complete(err?err:iStatus.Int());
       
   115         }
       
   116     delete this;
       
   117     }
       
   118 
       
   119 //-------------------------------------------
       
   120 // MAknNotifierWrapper
       
   121 //-------------------------------------------  
       
   122 
       
   123 // Default implementation to avoid SC break.
       
   124 EXPORT_C void MAknNotifierWrapper::UpdateNotifierL( 
       
   125     TUid /*aNotifierUid*/,
       
   126     const TDesC8& /*aBuffer*/,
       
   127     TInt /*aReplySlot*/, 
       
   128     const RMessagePtr2& /*aMessage*/ )
       
   129     {
       
   130     User::Leave( KErrNotSupported );
       
   131     }
       
   132  
       
   133 //-------------------------------------------
       
   134 // CAknNotifierWrapperLight
       
   135 //-------------------------------------------    
       
   136 EXPORT_C CAknNotifierWrapperLight::~CAknNotifierWrapperLight()
       
   137     {
       
   138     }
       
   139  
       
   140 EXPORT_C CAknNotifierWrapperLight::CAknNotifierWrapperLight(
       
   141     MAknNotifierWrapper& aSessionOwningNotifier, 
       
   142     TUid aNotifierUid, 
       
   143     TUid aChannel, 
       
   144     TInt aPriority )
       
   145 :iOwner(aSessionOwningNotifier)
       
   146     {
       
   147     iInfo.iUid = aNotifierUid;
       
   148     iInfo.iChannel = aChannel;
       
   149     iInfo.iPriority = aPriority;   
       
   150     }
       
   151     
       
   152 
       
   153 EXPORT_C TPtrC8 CAknNotifierWrapperLight::UpdateL(const TDesC8& aBuffer)
       
   154     {
       
   155     return iOwner.UpdateNotifierL( iInfo.iUid, aBuffer );
       
   156     }
       
   157     
       
   158 EXPORT_C void CAknNotifierWrapperLight::UpdateL(const TDesC8& aBuffer, TInt aReplySlot, 
       
   159     const RMessagePtr2& aMessage)
       
   160     {
       
   161     iOwner.UpdateNotifierL( iInfo.iUid, aBuffer, aReplySlot, aMessage );
       
   162     }
       
   163 
       
   164 EXPORT_C void CAknNotifierWrapperLight::Cancel()
       
   165     {
       
   166     iOwner.CancelNotifier(iInfo.iUid);
       
   167     }
       
   168         
       
   169 EXPORT_C void CAknNotifierWrapperLight::StartL(const TDesC8& aBuffer, TInt aReplySlot, 
       
   170     const RMessagePtr2& aMessage)
       
   171     {
       
   172     iOwner.StartNotifierL(iInfo.iUid, aBuffer, aReplySlot, aMessage);
       
   173     }
       
   174     
       
   175 EXPORT_C TPtrC8 CAknNotifierWrapperLight::StartL(const TDesC8& aBuffer)
       
   176     {
       
   177     return iOwner.StartNotifierL(iInfo.iUid, aBuffer);
       
   178     }
       
   179         
       
   180 EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapperLight::Info() const
       
   181     {
       
   182     return iInfo;    
       
   183     }
       
   184         
       
   185 EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapperLight::RegisterL()
       
   186     {
       
   187     return iInfo;    
       
   188     }
       
   189   
       
   190 EXPORT_C void CAknNotifierWrapperLight::Release()
       
   191     {
       
   192     Cancel();
       
   193     delete this;
       
   194     }
       
   195 
       
   196 EXPORT_C TInt CAknNotifierWrapperLight::NotifierCapabilites()
       
   197     {
       
   198     return MEikSrvNotifierBase2::NotifierCapabilites();
       
   199     }
       
   200     
       
   201 //-------------------------------------------
       
   202 // CAknNotifierWrapper
       
   203 //-------------------------------------------    
       
   204 
       
   205 EXPORT_C CAknNotifierWrapper::CAknNotifierWrapper(TUid aNotifierUid, TUid aChannel, TInt aPriority)
       
   206     :CAknNotifierWrapperLight(*this, aNotifierUid, aChannel, aPriority)
       
   207     {
       
   208     iClient.SetServerAppUid(AppServerUid());
       
   209     }
       
   210     
       
   211 CAknNotifierWrapper::CAknNotifierWrapper(TUid aNotifierUid, TUid aChannel, TInt aPriority, 
       
   212     TUid aAppServerUid)
       
   213 :CAknNotifierWrapperLight(*this, aNotifierUid, aChannel, aPriority), iAppServerUid(aAppServerUid)
       
   214     {
       
   215     iClient.SetServerAppUid(iAppServerUid);
       
   216     }
       
   217      
       
   218 
       
   219 EXPORT_C CAknNotifierWrapper::~CAknNotifierWrapper()
       
   220     {
       
   221     CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
       
   222     if (appUi && appUi->NotifierController())
       
   223         {
       
   224         appUi->NotifierController()->RegisterNotifierControllerPlugin(this, ETrue);
       
   225         }
       
   226     
       
   227     delete iReplyBuffer;
       
   228     
       
   229     // Make sure that there are no pending messages
       
   230     __ASSERT_DEBUG(iMessageQueue.Count()==0, User::Invariant());
       
   231     
       
   232     iClient.Close();
       
   233     }
       
   234 
       
   235 // We use CEikServAppUi idle queue to launch application servers (applications will be started after 
       
   236 // eiksrv-construction has been completed )
       
   237 EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapper::RegisterL()
       
   238     {
       
   239     CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
       
   240     if (appUi)
       
   241         {
       
   242         if (AppServerUid()!=KAknCapServerUid) // aknCapServer is handled elsewhere
       
   243             {
       
   244             appUi->StartNewServerApplicationL(AppServerUid());
       
   245             }
       
   246         
       
   247         appUi->NotifierController()->RegisterNotifierControllerPlugin(this, EFalse);
       
   248         }
       
   249     return CAknNotifierWrapperLight::RegisterL();    
       
   250     }
       
   251 
       
   252  
       
   253 EXPORT_C TPtrC8 CAknNotifierWrapper::UpdateNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)
       
   254     {
       
   255     User::LeaveIfError(iClient.SendSync(EUpdateNotifier, aNotifierUid, aBuffer, 
       
   256         SynchronousReplyBuf(), KNullDesC));
       
   257         
       
   258     return TPtrC8(SynchronousReplyBuf()); 
       
   259     }
       
   260 
       
   261 EXPORT_C void CAknNotifierWrapper::UpdateNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
       
   262     TInt aReplySlot, const RMessagePtr2& aMessage)
       
   263     {    
       
   264     CAknNotifierMessageObserver* entry = 
       
   265         CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
       
   266         
       
   267     if (entry)
       
   268         {
       
   269         iClient.SendAsync(EUpdateNotifierAndGetResponse, aNotifierUid,*entry->iInputBuf, entry, 
       
   270             KNullDesC);
       
   271         }        
       
   272     }
       
   273     
       
   274 void CAknNotifierWrapper::CompleteOutstandingRequests( TUid aNotifierUid, TInt aReason )
       
   275     {
       
   276     for ( TInt i = 0; i < iMessageQueue.Count(); i++ )
       
   277         {
       
   278         if (iMessageQueue[i]->iNotifierUid == aNotifierUid)
       
   279             {
       
   280             // This leaves listener to active state, it will be destroyed when a message in
       
   281             // Notifier server application is completed. 
       
   282             // Effectively this means that plugin can't send any data inside message which is 
       
   283             // being cancelled.
       
   284             if (!iMessageQueue[i]->iMessage.IsNull())
       
   285                 {
       
   286                 iMessageQueue[i]->iMessage.Complete(aReason);               
       
   287                 }
       
   288             }
       
   289         }
       
   290     }
       
   291     
       
   292 EXPORT_C void CAknNotifierWrapper::CancelNotifier( TUid aNotifierUid )
       
   293     {
       
   294     iClient.SendSync(ECancelNotifier, aNotifierUid, KNullDesC8, SynchronousReplyBuf(), KNullDesC);
       
   295     CompleteOutstandingRequests( aNotifierUid, KErrCancel);
       
   296     }
       
   297 
       
   298 
       
   299 CAknNotifierMessageObserver* CAknNotifierWrapper::CreateNewQueueEntryL(TUid aNotifierUid, 
       
   300     const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
       
   301     {
       
   302     CAknNotifierMessageObserver* entry = 0;
       
   303     if (!aMessage.IsNull())
       
   304         {
       
   305         entry = CAknNotifierMessageObserver::NewServerRequestL(aNotifierUid, this, aMessage, 
       
   306             aReplySlot);
       
   307             
       
   308         CleanupStack::PushL(entry);
       
   309         entry->iInputBuf = aBuffer.AllocL();
       
   310         CleanupStack::Pop();
       
   311         TInt err = iMessageQueue.Append(entry);  
       
   312         if (err)
       
   313             { // completes client message with err;
       
   314             TRequestStatus* ptr = &entry->iStatus;
       
   315             User::RequestComplete(ptr, err);
       
   316             entry = 0;
       
   317             }
       
   318         }
       
   319     return entry;
       
   320     }
       
   321 
       
   322 EXPORT_C void CAknNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
       
   323     TInt aReplySlot, const RMessagePtr2& aMessage)
       
   324     {    
       
   325     CAknNotifierMessageObserver* entry = 
       
   326         CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
       
   327         
       
   328     if (entry)
       
   329         {
       
   330         iClient.SendAsync(
       
   331             EStartNotifierAndGetResponse, 
       
   332             aNotifierUid, 
       
   333             *entry->iInputBuf, 
       
   334             entry, 
       
   335             KNullDesC);        
       
   336         }        
       
   337     }
       
   338 
       
   339 EXPORT_C TPtrC8 CAknNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)
       
   340     {
       
   341     User::LeaveIfError(iClient.SendSync(EStartNotifier, aNotifierUid, aBuffer, 
       
   342         SynchronousReplyBuf(), KNullDesC));      
       
   343         
       
   344     return TPtrC8(SynchronousReplyBuf());     
       
   345     }
       
   346 
       
   347 // Just remove completed entry from queue, default completion (ie. just copying message from 
       
   348 // app server) is currently enough for us. 
       
   349 EXPORT_C void CAknNotifierWrapper::AsyncMessageCompleted( CAknNotifierMessageObserver* aEntry )
       
   350     {
       
   351     TInt status = aEntry->iStatus.Int();
       
   352 
       
   353     TInt index = iMessageQueue.Find(aEntry);
       
   354     if (index != KErrNotFound)
       
   355         {
       
   356         iMessageQueue.Remove(index);    
       
   357         }     
       
   358 
       
   359     if ( status == KErrServerTerminated && AppServerUid() != KCommonNotifierAppSrvUid)
       
   360         { // Just try to restart (connect on next request), not interested if success or fail
       
   361           //
       
   362           // We could clone the original message here and resend it to server
       
   363           // if information was really vital for system
       
   364         Client().Close();    
       
   365         Client().SetHandle(0);
       
   366         
       
   367         TRAP_IGNORE(((CEikServAppUi*)CCoeEnv::Static()->AppUi())->StartNewServerApplicationL(
       
   368             AppServerUid()));    
       
   369         }
       
   370     }
       
   371 
       
   372 EXPORT_C CAknNotifierWrapper* CAknNotifierWrapper::NewL( 
       
   373     TUid aNotifierUid, 
       
   374     TUid aChannel, 
       
   375     TInt aPriority, 
       
   376     TUid aAppServerUid, 
       
   377     TUint aReplyBufSize)
       
   378     {
       
   379     CAknNotifierWrapper* me = 
       
   380         new (ELeave) CAknNotifierWrapper(aNotifierUid, aChannel, aPriority, aAppServerUid);
       
   381         
       
   382     CleanupStack::PushL(me);
       
   383     me->ConstructL(aReplyBufSize);
       
   384     CleanupStack::Pop();
       
   385     return me;
       
   386     }
       
   387     
       
   388 EXPORT_C void CAknNotifierWrapper::DoNotifierControllerCommand(TInt aCommand)
       
   389     {
       
   390     iClient.SendAsync(aCommand);
       
   391     }
       
   392                                     
       
   393 void CAknNotifierWrapper::ConstructL(TUint aReplyBufSize)
       
   394     {
       
   395     iReplyBuffer = HBufC8::NewL(aReplyBufSize);
       
   396     }
       
   397 
       
   398 RAknNotifierAppServClient::RAknNotifierAppServClient()
       
   399     :iAppServerUid(KNullUid), iOwnerUsingMonitor(0)
       
   400     {       
       
   401     }   
       
   402  
       
   403 void RAknNotifierAppServClient::SetServerAppUid(TUid aAppServerUid)
       
   404     {
       
   405     iAppServerUid = aAppServerUid;   
       
   406     }
       
   407  
       
   408 TInt RAknNotifierAppServClient::StartServer()
       
   409     {
       
   410     TRAPD(ret, StartServerL())        
       
   411     return ret;
       
   412     }
       
   413  
       
   414 void RAknNotifierAppServClient::StartServerL()
       
   415     {
       
   416     if (Handle() != 0)
       
   417         {
       
   418         return;
       
   419         }
       
   420             
       
   421     if (iAppServerUid == KNullUid)
       
   422         {
       
   423         User::Leave(KErrGeneral);
       
   424         }
       
   425 
       
   426     _LIT(KServerNameFormat, "%08x_%08x_AppServer");
       
   427     TFullName serverName;
       
   428     serverName.Format(KServerNameFormat, KUikonUidPluginInterfaceNotifiers, iAppServerUid);
       
   429     TFindServer find(serverName);
       
   430     TFullName fullName;
       
   431     if (find.Next(fullName) == KErrNone)
       
   432         {
       
   433         ConnectExistingByNameL(serverName); 
       
   434         if (iOwnerUsingMonitor)
       
   435             {
       
   436             iOwnerUsingMonitor->AppServerConnectedL();
       
   437             }
       
   438         return;
       
   439         }
       
   440 
       
   441     User::Leave(KErrNotReady);
       
   442     }
       
   443     
       
   444 TUid RAknNotifierAppServClient::ServiceUid() const
       
   445     {
       
   446     return KAknNotifierServiceUid;
       
   447     }
       
   448     
       
   449 TInt RAknNotifierAppServClient::SendSync(TNotifierMessage aFunction, TUid aNotifierUid, 
       
   450     const TDesC8& aBuffer, TPtr8 aReply, const TDesC& aLibraryName)
       
   451     {
       
   452     // just an optimisation
       
   453     if (aFunction == ECancelNotifier && !Handle())
       
   454         {
       
   455         return KErrNone;
       
   456         }
       
   457     
       
   458     TInt err = StartServer();
       
   459     return err ? err : SendReceive(aFunction, TIpcArgs((TInt)aNotifierUid.iUid, &aBuffer, &aReply, 
       
   460         &aLibraryName));
       
   461     }
       
   462  
       
   463 void RAknNotifierAppServClient::SendAsync(TNotifierMessage aFunction, TUid aNotifierUid, 
       
   464     const TDesC8& aBuffer, CAknNotifierMessageObserver* aQueueEntry, const TDesC& aLibraryName)
       
   465     {
       
   466     TInt err = StartServer();
       
   467 
       
   468     aQueueEntry->Start();  
       
   469     if (err)
       
   470         {
       
   471         TRequestStatus* sptr= &aQueueEntry->iStatus;
       
   472         User::RequestComplete(sptr, err);
       
   473         return;
       
   474         }
       
   475     // we implicitely trust that aLibraryName will exist when data is extracted at other end...    
       
   476     SendReceive(
       
   477         aFunction, 
       
   478         TIpcArgs((TInt)aNotifierUid.iUid, &aBuffer, aQueueEntry->iReplyDesc, &aLibraryName), 
       
   479         aQueueEntry->iStatus);
       
   480     }
       
   481 
       
   482 TInt RAknNotifierAppServClient::SendAsync(TInt aNotifierControllerCommand)
       
   483     {
       
   484     if (Handle()!=0)
       
   485         {
       
   486         return Send(KDoNotifierControllerCommand, TIpcArgs(aNotifierControllerCommand));
       
   487         }
       
   488         
       
   489     // omit error as there is no need to forward commands to server apps which are not running yet.
       
   490     return KErrNone; 
       
   491     }
       
   492 
       
   493 EXPORT_C CAknCommonNotifierWrapper* CAknCommonNotifierWrapper::NewL( 
       
   494     TUid aNotifierUid, 
       
   495     TUid aChannel, 
       
   496     TInt aPriority, 
       
   497     const TDesC& aLibraryName, 
       
   498     TUint aReplyBufSize,
       
   499     TBool aPreLoad)
       
   500     {
       
   501     CAknCommonNotifierWrapper* me = 
       
   502         new (ELeave) CAknCommonNotifierWrapper(aNotifierUid, aChannel, aPriority, aPreLoad);
       
   503         
       
   504     CleanupStack::PushL(me);
       
   505     me->ConstructL(aLibraryName, aReplyBufSize);
       
   506     CleanupStack::Pop();   
       
   507     return me;
       
   508     }
       
   509 
       
   510 void CAknCommonNotifierWrapper::ConstructL(const TDesC& aLibraryName, TUint aReplyBufSize)
       
   511     {
       
   512     SetSynchReplybuf(HBufC8::NewL(aReplyBufSize));
       
   513     iLibraryName = aLibraryName.AllocL();
       
   514     Client().SetOwnerUsingMonitor(this);
       
   515     }
       
   516 
       
   517 CAknCommonNotifierWrapper::CAknCommonNotifierWrapper( 
       
   518     TUid aNotifierUid, 
       
   519     TUid aChannel, 
       
   520     TInt aPriority,
       
   521     TBool aPreLoad)
       
   522 :CAknNotifierWrapper(aNotifierUid, aChannel, aPriority), iPreLoad(aPreLoad)
       
   523     {
       
   524     Client().SetServerAppUid(AppServerUid());
       
   525     if (aPreLoad)
       
   526         {
       
   527         iPreLoad = KPreLoadEnabledButNotDoneYet;
       
   528         }
       
   529     }
       
   530 
       
   531 EXPORT_C void CAknCommonNotifierWrapper::SetCustomSecurityHandler(
       
   532     MAknNotifierCustomSecurityCheck* aHandler)
       
   533     {
       
   534     iCustomSecurityCheck = aHandler;
       
   535     }
       
   536 
       
   537 CAknCommonNotifierWrapper::~CAknCommonNotifierWrapper()
       
   538     {
       
   539     delete iMonitor;
       
   540     delete iIdle;
       
   541     if (iCustomSecurityCheck)
       
   542         {
       
   543         iCustomSecurityCheck->Release();
       
   544         }
       
   545     delete iLibraryName;
       
   546     iPendingArray.Close();
       
   547     }
       
   548 
       
   549 void CAknCommonNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
       
   550     TInt aReplySlot, const RMessagePtr2& aMessage)
       
   551     {
       
   552     if (iPreLoad == KPreLoadEnabledButNotDoneYet) // only preload libs to support message queue
       
   553         {
       
   554         iPendingArray.AppendL(TPendingMsg(aNotifierUid, aMessage));
       
   555         return;
       
   556         }
       
   557 
       
   558     if (iCustomSecurityCheck)
       
   559         {
       
   560         iCustomSecurityCheck->CustomSecurityCheckL(aMessage);
       
   561         }
       
   562     
       
   563     CAknNotifierMessageObserver* entry = 
       
   564         CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
       
   565         
       
   566     if (entry)
       
   567         {
       
   568         Client().SendAsync(
       
   569             EStartNotifierAndGetResponse, 
       
   570             aNotifierUid,
       
   571             *entry->iInputBuf,
       
   572             entry, 
       
   573             *iLibraryName);        
       
   574         }        
       
   575     }
       
   576 
       
   577 TPtrC8 CAknCommonNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)          
       
   578     {
       
   579     if (iPreLoad == KPreLoadEnabledButNotDoneYet) 
       
   580         {              
       
   581         // In case of synchronous commands (start / update) we cannot delay sending messages,
       
   582         // only way to recover is to return error. Update cannot occur before one successfull 
       
   583         // start so it does need changes.
       
   584         User::Leave(KErrNotReady); 
       
   585         }
       
   586 
       
   587     User::LeaveIfError(Client().SendSync(EStartNotifier, aNotifierUid, aBuffer, 
       
   588         SynchronousReplyBuf(), *iLibraryName));      
       
   589     
       
   590     return TPtrC8(SynchronousReplyBuf());     
       
   591     }
       
   592 
       
   593 TBool CallBackLoad(TAny* aThis)
       
   594     {
       
   595     return ((CAknCommonNotifierWrapper*)aThis)->PreLoadLibrary();
       
   596     }
       
   597  
       
   598 EXPORT_C void CAknCommonNotifierWrapper::PreLoadLibraryL()
       
   599     {
       
   600     iPreLoad = ETrue; // restore original, real boolean value once callback from server arrives
       
   601     if (!iIdle)
       
   602         {
       
   603         iIdle = CIdle::NewL(CActive::EPriorityIdle);
       
   604         iIdle->Start(TCallBack(CallBackLoad, this));
       
   605         }
       
   606     }
       
   607 
       
   608 // On succes this method will cause unbalanced reference count in app server -> library will not be 
       
   609 // unloaded unless server terminates.
       
   610 TBool CAknCommonNotifierWrapper::PreLoadLibrary()
       
   611     {
       
   612     TInt err = Client().SendSync(
       
   613         (TNotifierMessage)EAknNfySrvLoadLibrary, 
       
   614         KNullUid, 
       
   615         KNullDesC8, 
       
   616         SynchronousReplyBuf(), 
       
   617         *iLibraryName);
       
   618         
       
   619     if (err == KErrNotReady)
       
   620         {
       
   621         return ETrue;
       
   622         }
       
   623     else
       
   624         {
       
   625         delete iIdle;
       
   626         iIdle = 0;  
       
   627         return EFalse;  
       
   628         }
       
   629     }
       
   630     
       
   631 MEikSrvNotifierBase2::TNotifierInfo CAknCommonNotifierWrapper::RegisterL()
       
   632     {
       
   633     if (iPreLoad)
       
   634         {
       
   635         CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
       
   636         if (appUi)
       
   637             {
       
   638             appUi->NotifierController()->RegisterPreloadPluginL(this);
       
   639             }
       
   640         }
       
   641     return CAknNotifierWrapper::RegisterL();
       
   642     }
       
   643 
       
   644 
       
   645 void CAknCommonNotifierWrapper::HandleServerAppExit(TInt)
       
   646     {
       
   647     delete iMonitor;
       
   648     iMonitor = 0;
       
   649     Client().Close();    
       
   650     Client().SetHandle(0);
       
   651     if (iPreLoad)
       
   652         {
       
   653         iPreLoad = KPreLoadEnabledButNotDoneYet;
       
   654         }
       
   655     }
       
   656 
       
   657 void CAknCommonNotifierWrapper::CancelNotifier( TUid aNotifierUid )
       
   658     {
       
   659     // if there are pending requests, there cannot be actual connection to server yet
       
   660     if (iPendingArray.Count())
       
   661         {
       
   662         for (TInt i = iPendingArray.Count()-1; i >= 0; i--)
       
   663             {
       
   664             if (iPendingArray[i].iUid == aNotifierUid.iUid)
       
   665                 {
       
   666                 iPendingArray.Remove(i);
       
   667                 }
       
   668             }
       
   669         }
       
   670     else
       
   671         {
       
   672         CAknNotifierWrapper::CancelNotifier( aNotifierUid );
       
   673         }        
       
   674     }
       
   675 
       
   676 void TryProcessPendingEntryL(CAknCommonNotifierWrapper::TPendingMsg& aPendingEntry, 
       
   677     CAknCommonNotifierWrapper* aThis)
       
   678     {
       
   679     HBufC8* buf = HBufC8::NewLC(aPendingEntry.iMessage.GetDesLengthL(1));
       
   680     TPtr8 ptr = buf->Des();
       
   681     aPendingEntry.iMessage.ReadL(1, ptr );
       
   682     aThis->StartNotifierL(TUid::Uid(aPendingEntry.iUid), *buf, 2, aPendingEntry.iMessage );
       
   683     CleanupStack::PopAndDestroy();            
       
   684     }
       
   685 
       
   686 void CAknCommonNotifierWrapper::AppServerConnectedL()
       
   687     {
       
   688     if (!iMonitor)
       
   689         {
       
   690         iMonitor = CApaServerAppExitMonitor::NewL(Client(), *this, CActive::EPriorityStandard);   
       
   691         }
       
   692         
       
   693     for (TInt i = 0; i < iPendingArray.Count(); i++)
       
   694         { // common app servers have no problem with asynch message slots
       
   695         // anyway, we don't allow pending messages to abort StartServerL so trap needed 
       
   696         TRAP_IGNORE(TryProcessPendingEntryL(iPendingArray[i], this));
       
   697         }
       
   698         
       
   699     iPendingArray.Reset();    
       
   700     }
       
   701 
       
   702 // End of file