gssettingsuis/Gs/GSFramework/src/GSPluginLoader.cpp
branchRCL_3
changeset 54 7e0eff37aedb
equal deleted inserted replaced
53:8ee96d21d9bf 54:7e0eff37aedb
       
     1 /*
       
     2 * Copyright (c) 2005-2008 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:  GS plugin loader.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include    <gspluginloader.h>
       
    21 #include    <gsplugininterface.h>
       
    22 #include    <gsprivatepluginproviderids.h>
       
    23 #include    "GsLogger.h"
       
    24 #include    "GSBaseDocument.h"
       
    25 #include    "GSPluginWrapper.h"
       
    26 #include    "GSPluginAndViewIdCache.h"
       
    27 #include    <mgswatchdog.h>
       
    28 
       
    29 #include    <aknViewAppUi.h>
       
    30 #include    <AknIconArray.h>
       
    31 #include    <aknlists.h> // CAknSingleLargeStyleListbox
       
    32 #include    <eikclbd.h> // CColumnListBoxData
       
    33 #include    <gulicon.h> // For CGulIcon
       
    34 #include    <utf.h> // CnvUtfConverter
       
    35 #include  	<basched.h>
       
    36 #include    <AknInfoPopupNoteController.h>
       
    37 
       
    38 //Flag for enabling/disablign compare by category feature
       
    39 #undef RD_GS_COMPARE_BY_CATEGORY
       
    40 
       
    41 // ================= MEMBER FUNCTIONS =======================
       
    42 
       
    43 #ifdef _DEBUG
       
    44     #pragma message("-----_DEBUG ACTIVATED IN GS!-----")
       
    45 #endif //_GEBUG
       
    46 
       
    47 #ifdef _GS_PERFORMANCE_TRACES
       
    48     #pragma message("-GS plugin load performance measurements activated-")
       
    49 #endif // _GS_PERFORMANCE_TRACES
       
    50 
       
    51 const TInt KGSCaptionSize = 256;
       
    52 
       
    53 // ----------------------------------------------------------------------------
       
    54 // CGSPluginLoader::NewL
       
    55 //
       
    56 // EPOC two-phased constructor
       
    57 // ----------------------------------------------------------------------------
       
    58 //
       
    59 EXPORT_C CGSPluginLoader* CGSPluginLoader::NewL( CAknViewAppUi* aAppUi )
       
    60     {
       
    61     CGSPluginLoader* self = new( ELeave ) CGSPluginLoader;
       
    62     CleanupStack::PushL( self );
       
    63     self->ConstructL( aAppUi );
       
    64     CleanupStack::Pop( self );
       
    65     return self;
       
    66     }
       
    67 
       
    68 
       
    69 // ----------------------------------------------------------------------------
       
    70 // CGSPluginLoader::CGSPluginLoader
       
    71 //
       
    72 // C++ default constructor can NOT contain any code, that
       
    73 // might leave.
       
    74 //
       
    75 //  Uses low priority for Active Object so that more bandwith is available for 
       
    76 //  the most important pluginloaders. 
       
    77 // ----------------------------------------------------------------------------
       
    78 //
       
    79 CGSPluginLoader::CGSPluginLoader() 
       
    80     : CActive( EPriorityLow ),
       
    81       iRequestedPriority( EPriorityLow )
       
    82     {
       
    83     __GSLOGSTRING( "[GSPlgLoader] CGSPluginLoader()" );
       
    84     }
       
    85 
       
    86 
       
    87 // ----------------------------------------------------------------------------
       
    88 // CGSPluginLoader::ConstructL
       
    89 //
       
    90 // EPOC default constructor can leave.
       
    91 // ----------------------------------------------------------------------------
       
    92 //
       
    93 EXPORT_C void CGSPluginLoader::ConstructL( CAknViewAppUi* aAppUi )
       
    94     {
       
    95     __GSLOGSTRING( "[GSPlgLoader] ConstructL()" );
       
    96     iAppUi = aAppUi;
       
    97     iDocument = static_cast<CGSBaseDocument*>( iAppUi->Document() );
       
    98     iImplInfoArray = iDocument->GetImplInfo();
       
    99 
       
   100     CActiveScheduler* scheluder = CActiveScheduler::Current();
       
   101     __GSLOGSTRING1( "[GSPlgLoader] Current CActiveScheduler:0x%X", scheluder );
       
   102     __GSLOGSTRING1( "[GSPlgLoader] CActiveScheduler stackdepth: %d",
       
   103         scheluder->StackDepth() );
       
   104 
       
   105     CActiveScheduler::Add( this );
       
   106 
       
   107     iWatchDog = iDocument->WatchDog();
       
   108     }
       
   109 
       
   110 
       
   111 // ----------------------------------------------------------------------------
       
   112 // CGSPluginLoader::~CGSPluginLoader
       
   113 //
       
   114 // Destructor
       
   115 // ----------------------------------------------------------------------------
       
   116 //
       
   117 EXPORT_C CGSPluginLoader::~CGSPluginLoader()
       
   118     {
       
   119     __GSLOGSTRING( "[GSPlgLoader] ~CGSPluginLoader()" );
       
   120     AbortAsyncLoad();
       
   121     Cancel();
       
   122 
       
   123     if( iErrorPopup )
       
   124         {
       
   125         iErrorPopup->HideInfoPopupNote();
       
   126         delete iErrorPopup;
       
   127         iErrorPopup = NULL;
       
   128         }
       
   129     //iPluginArray is not owned and therefore not deleted.
       
   130     }
       
   131 
       
   132 
       
   133 // ----------------------------------------------------------------------------
       
   134 // CGSPluginLoader::LoadAsync
       
   135 //
       
   136 //
       
   137 // ----------------------------------------------------------------------------
       
   138 //
       
   139 EXPORT_C void CGSPluginLoader::LoadAsyncL(
       
   140     TUid aInterfaceUid,
       
   141     TUid aParentUid,
       
   142     CArrayPtrFlat<CGSPluginInterface>* aPluginArray )
       
   143     {
       
   144     iPluginArray = aPluginArray;
       
   145     iParentUid = aParentUid;
       
   146 
       
   147     __GSLOGSTRING3(
       
   148         "[GSPlgLoader] LoadAsync(). aInterfaceUid:0x%X aParentUid:0x%X, aPluginArray:0x%X",
       
   149         aInterfaceUid, aParentUid, aPluginArray );
       
   150     // Reset iterator:
       
   151     iImplInfoArrayIterator = 0;
       
   152 
       
   153     __GSLOGSTRING1( "[GSPlgLoader] Implementation info count: %d",
       
   154         iImplInfoArray.Count() );
       
   155 
       
   156     NotifyProgress();
       
   157 
       
   158     //Begin CActive asynchronous loop.
       
   159     CompleteOwnRequest();
       
   160     }
       
   161 
       
   162 
       
   163 // ----------------------------------------------------------------------------
       
   164 // CGSPluginLoader::LoadSyncL
       
   165 //
       
   166 //
       
   167 // ----------------------------------------------------------------------------
       
   168 //
       
   169 CGSPluginInterface& CGSPluginLoader::LoadSyncL( TUid aInterfaceUid,
       
   170                                                 TUid aImplementationUid )
       
   171     {
       
   172     Cancel();
       
   173     CGSPluginInterface* ret = NULL;
       
   174 
       
   175     // Get a list of all implementations, even though we only want one specific.
       
   176     // There appears to be no way to otherwise extract a specific implementation
       
   177     // info object :(
       
   178     // Search for the implementation that matches aImplementationUid
       
   179     const TInt impCount = iImplInfoArray.Count();
       
   180     for( TInt i=0; i<impCount; i++ )
       
   181         {
       
   182         const CImplementationInformation* info = iImplInfoArray[ i ];
       
   183         if  ( info->ImplementationUid() == aImplementationUid )
       
   184             {
       
   185             ret = &CreatePluginInstanceL( *info );
       
   186             break;
       
   187             }
       
   188         }
       
   189 
       
   190     if  ( !ret )
       
   191         {
       
   192         User::Leave( KErrNotFound );
       
   193         }
       
   194     return *ret;
       
   195     }
       
   196 
       
   197 
       
   198 // ----------------------------------------------------------------------------
       
   199 // CGSPluginLoader::AbortAsyncLoad
       
   200 //
       
   201 //
       
   202 // ----------------------------------------------------------------------------
       
   203 //
       
   204 EXPORT_C void CGSPluginLoader::AbortAsyncLoad()
       
   205     {
       
   206     __GSLOGSTRING( "[GSPlgLoader] AbortAsyncLoad()" );
       
   207     Cancel();
       
   208     }
       
   209 
       
   210 
       
   211 // ----------------------------------------------------------------------------
       
   212 // CGSPluginLoader::RunL
       
   213 //
       
   214 //
       
   215 // ----------------------------------------------------------------------------
       
   216 //
       
   217 void CGSPluginLoader::RunL()
       
   218     {
       
   219     iRunLDebugCount++;
       
   220     
       
   221     // This must be done only in RunL or otherwise request might be 
       
   222     // outstanding.
       
   223     if( iRequestedPriority != Priority() )
       
   224         {
       
   225         __GSLOGSTRING3(
       
   226             "[CGSPluginLoader::RunL] 0x%X original priority:%d requested priority:%d", 
       
   227             iParentUid.iUid, 
       
   228             Priority(),
       
   229             iRequestedPriority );
       
   230         
       
   231         SetPriority( iRequestedPriority );
       
   232         }
       
   233     
       
   234     LoadNextPluginL();
       
   235 
       
   236     // Check if there are still more plugins to be loaded:
       
   237     if ( iImplInfoArrayIterator < iImplInfoArray.Count() )
       
   238         {
       
   239         NotifyProgress();
       
   240         // Continue CActive asynchronous loop.
       
   241         CompleteOwnRequest();
       
   242         }
       
   243     else
       
   244         {
       
   245         // All plugins loaded:
       
   246         __GSLOGSTRING( "[GSPlgLoader] Loading plugins finished." );
       
   247         NotifyFinished();
       
   248         }
       
   249     }
       
   250 
       
   251 
       
   252 // ---------------------------------------------------------------------------
       
   253 // CScGenreItemConstructionConductor::CompleteOwnRequest
       
   254 //
       
   255 // Issue request complete notification.
       
   256 // ---------------------------------------------------------------------------
       
   257 void CGSPluginLoader::CompleteOwnRequest()
       
   258     {
       
   259     TRequestStatus* status = &iStatus;
       
   260     User::RequestComplete( status, KErrNone );
       
   261     SetActive();
       
   262     }
       
   263 
       
   264 
       
   265 // ----------------------------------------------------------------------------
       
   266 // CGSPluginLoader::RunError
       
   267 //
       
   268 //
       
   269 // ----------------------------------------------------------------------------
       
   270 //
       
   271 TInt CGSPluginLoader::RunError( TInt aError )
       
   272     {
       
   273     // This method is called when a plugin loading fails.
       
   274     // Always "fake" the return value so that ActiveSchedule
       
   275     // keeps running and later plugins are continued to be loaded.
       
   276     // Check if still plugins to be loaded:
       
   277     if( iImplInfoArrayIterator < iImplInfoArray.Count() )
       
   278         {
       
   279         NotifyProgress();
       
   280 
       
   281         //Continue CActive asynchronous loop.
       
   282         CompleteOwnRequest();
       
   283         }
       
   284     else // All plugins loaded:
       
   285         {
       
   286         NotifyFinished();
       
   287         }
       
   288 
       
   289     if ( aError == KLeaveExit )
       
   290         {
       
   291         return KLeaveExit;
       
   292         }
       
   293 
       
   294     return KErrNone;
       
   295     }
       
   296 
       
   297 
       
   298 // ----------------------------------------------------------------------------
       
   299 // CGSPluginLoader::DoCancel
       
   300 //
       
   301 //
       
   302 // ----------------------------------------------------------------------------
       
   303 //
       
   304 void CGSPluginLoader::DoCancel()
       
   305     {
       
   306 
       
   307     }
       
   308 
       
   309 
       
   310 // ----------------------------------------------------------------------------
       
   311 // CGSPluginLoader::NotifyProgress
       
   312 //
       
   313 //
       
   314 // ----------------------------------------------------------------------------
       
   315 //
       
   316 void CGSPluginLoader::NotifyProgress()
       
   317     {
       
   318     if( iObserver )
       
   319         {
       
   320         iObserver->HandlePluginLoaded( MGSPluginLoadObserver::EGSSuccess);
       
   321         }
       
   322     }
       
   323 
       
   324 
       
   325 // ----------------------------------------------------------------------------
       
   326 // CGSPluginLoader::NotifyFinished
       
   327 //
       
   328 //
       
   329 // ----------------------------------------------------------------------------
       
   330 //
       
   331 void CGSPluginLoader::NotifyFinished()
       
   332     {
       
   333 
       
   334     #ifdef _GS_PLUGINLOADER_FINAL_SORTING_TRACES
       
   335         TRAP_IGNORE( PrintOrderTracesL( iPluginArray ) );
       
   336     #endif // _GS_PLUGINLOADER_FINAL_SORTING_TRACES
       
   337 
       
   338     // I have finished loading: No need to keep me in the expensive scheduler
       
   339     // queue.
       
   340     Deque();
       
   341 
       
   342     if( iObserver )
       
   343         {
       
   344         iObserver->HandlePluginLoaded( MGSPluginLoadObserver::EGSFinished );
       
   345         }
       
   346     
       
   347     __GSLOGSTRING1( "[CGSPluginLoader::NotifyFinished] 0x%X", 
       
   348                     iParentUid.iUid );
       
   349     }
       
   350 
       
   351 
       
   352 // ----------------------------------------------------------------------------
       
   353 // CGSPluginLoader::SetObserver
       
   354 //
       
   355 //
       
   356 // ----------------------------------------------------------------------------
       
   357 //
       
   358 EXPORT_C void CGSPluginLoader::SetObserver(MGSPluginLoadObserver* aObserver)
       
   359     {
       
   360     __GSLOGSTRING1("[GSPlgLoader] Observer set:0x%X", aObserver);
       
   361     iObserver = aObserver;
       
   362     }
       
   363 
       
   364 
       
   365 // ----------------------------------------------------------------------------
       
   366 // CGSPluginLoader::ParseToUid
       
   367 // Parses a UID from descriptor of form '0xNNNNNNNN' where N is hexadecimal.
       
   368 //
       
   369 // ----------------------------------------------------------------------------
       
   370 //
       
   371 TInt CGSPluginLoader::ParseToUid( const TDesC8& aSource, TUid& aTarget )
       
   372     {
       
   373     // Remove "0x" from the descriptor if it exists
       
   374     _LIT8(KHexPrefix, "0x");
       
   375 
       
   376     TPtrC8 pSource( aSource );
       
   377     const TInt prefixPosition = pSource.Find( KHexPrefix );
       
   378     if  ( prefixPosition != KErrNotFound )
       
   379         {
       
   380         pSource.Set( aSource.Mid( prefixPosition + KHexPrefix().Length() ) );
       
   381         }
       
   382 
       
   383     // Parse to integer
       
   384     TLex8 lex( pSource );
       
   385     TUint integer = 0;
       
   386 
       
   387     // Parse using TRadix::EHex as radix:
       
   388     const TInt err = lex.Val( integer, EHex );
       
   389     aTarget.iUid = integer;
       
   390 
       
   391     if( err != KErrNone )
       
   392         {
       
   393         // If parsing parent UID failed, do not load plugin:
       
   394         __GSLOGSTRING1(
       
   395             "[GSPlgLoader] Parsing parent UID failed. Error code:%d",
       
   396             err );
       
   397         }
       
   398     return err;
       
   399     }
       
   400 
       
   401 
       
   402 // ----------------------------------------------------------------------------
       
   403 // CGSPluginLoader::ParseOrderNumber
       
   404 //
       
   405 //
       
   406 // ----------------------------------------------------------------------------
       
   407 //
       
   408 TInt CGSPluginLoader::ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber )
       
   409     {
       
   410     // Parse plugin's order number from opaque_data:
       
   411     TLex8 lex( aSource );
       
   412     const TInt orderErr = lex.Val( aOrderNumber );
       
   413     return orderErr;
       
   414     }
       
   415 
       
   416 
       
   417 // ----------------------------------------------------------------------------
       
   418 // CGSPluginLoader::PrintInfoDebug
       
   419 // Print CImplementationInformation to log. Used for debugging.
       
   420 //
       
   421 // ----------------------------------------------------------------------------
       
   422 //
       
   423 void CGSPluginLoader::PrintInfoDebugL( const CImplementationInformation& aInfo,
       
   424                                       TInt aIterator,
       
   425                                       TInt aPluginCount )
       
   426     {
       
   427 
       
   428 
       
   429     #pragma message("-CGSPluginLoader verbose traces activated-")
       
   430     __GSLOGSTRING2( "[GSPlgLoader::LoadNextPluginL] %d/%d",
       
   431                     aIterator,
       
   432                     aPluginCount);
       
   433 
       
   434     __GSLOGSTRING1( "[GSPlgLoader] --Plugin 0x%X info--", &aInfo);
       
   435     __GSLOGSTRING1( "[GSPlgLoader] DisplayName:%S", &aInfo.DisplayName() );
       
   436     __GSLOGSTRING1( "[GSPlgLoader] ImplementationUid:0x%X",
       
   437                     aInfo.ImplementationUid() );
       
   438 
       
   439     const TInt KMaxEComDataLength = 256;
       
   440 
       
   441     HBufC* dataType = HBufC::New( KMaxEComDataLength );
       
   442     HBufC* opaqueData = HBufC::New( KMaxEComDataLength );
       
   443 
       
   444     dataType->Des().Copy( aInfo.DataType() );
       
   445     opaqueData->Des().Copy( aInfo.OpaqueData() );
       
   446     __GSLOGSTRING1( "[GSPlgLoader] DataType:%S", dataType );
       
   447     __GSLOGSTRING1( "[GSPlgLoader] OpaqueData:%S", opaqueData );
       
   448 
       
   449     delete opaqueData;
       
   450     delete dataType;
       
   451     }
       
   452 
       
   453 
       
   454 // ----------------------------------------------------------------------------
       
   455 // CGSPluginLoader::LoadNextPluginL
       
   456 // Iterate through iImplInfoArray. Load the plugin if it is eligible for
       
   457 // loading. Loaded plugin is added to iPluginArray. Each time a plugin is
       
   458 // loaded, iObserver is notified.
       
   459 //
       
   460 // ----------------------------------------------------------------------------
       
   461 //
       
   462 EXPORT_C void CGSPluginLoader::LoadNextPluginL()
       
   463     {
       
   464     // Iterate through iImplInfoArray. This loop continues between function
       
   465     // calls. Therefore member variable iImplInfoArrayIterator is used as a
       
   466     // counter. Loop will break when match is found and continues on next RunL.
       
   467     for( ; iImplInfoArrayIterator < iImplInfoArray.Count();  )
       
   468         {
       
   469         const CImplementationInformation* info =
       
   470             iImplInfoArray[ iImplInfoArrayIterator ];
       
   471 
       
   472         iImplInfoArrayIterator++;
       
   473 
       
   474         #ifdef _GS_PLUGINLOADER_VERBOSE_TRACES
       
   475             PrintInfoDebugL( *info, iImplInfoArrayIterator, iImplInfoArray.Count() );
       
   476         #endif //_GS_PLUGINLOADER_VERBOSE_TRACES
       
   477 
       
   478         // Parse parent UID from default_data:
       
   479         TUid parentUid;
       
   480         const TInt uidErr = ParseToUid( info->DataType(), parentUid );
       
   481 
       
   482         if( uidErr == KErrNone  && iParentUid == parentUid )
       
   483             {
       
   484             // If this plugin is OK -> load it:
       
   485             __GSLOGSTRING2( "[GSPlgLoader] %S eligible for parent 0x%X",
       
   486                     &info->DisplayName(), iParentUid.iUid );
       
   487             CGSPluginInterface* plugin = NULL;
       
   488             TInt error = KErrCancel;
       
   489         #ifdef GS_ENABLE_WATCH_DOG
       
   490             if( !iWatchDog->IsInBlackList( info->ImplementationUid() ) )
       
   491         #endif
       
   492                 {
       
   493                 // Only panics move quarantined plugins to blacklist. Leaving is
       
   494                 // normal programmatic functionality and therefore does not move
       
   495                 // plugin to blacklist.
       
   496                 #ifdef GS_ENABLE_WATCH_DOG
       
   497                     iWatchDog->QuarantineL( info->ImplementationUid() );
       
   498                 #endif
       
   499 
       
   500                 #ifdef _GS_PERFORMANCE_TRACES
       
   501                     TTime timeStart;
       
   502                     TTime timeEnd;
       
   503                     timeStart.HomeTime();
       
   504                 #endif //_GS_PERFORMANCE_TRACES
       
   505 
       
   506                 // Create plugin. Trap leave for debugging purposes.
       
   507                 TRAP( error, plugin = &CreatePluginInstanceL( *info ); );
       
   508 
       
   509                 #ifdef _GS_PERFORMANCE_TRACES
       
   510                     timeEnd.HomeTime();
       
   511                     TTimeIntervalMicroSeconds funcDuration = timeEnd.MicroSecondsFrom( timeStart );
       
   512                     __GSLOGSTRING2( "[GSPlgLoader::LoadNextPluginL/perf] %Ld    (%S)", funcDuration, &info->DisplayName() );
       
   513                 #endif //_GS_PERFORMANCE_TRACES
       
   514 
       
   515                 #ifdef GS_ENABLE_WATCH_DOG
       
   516                     TRAP_IGNORE( iWatchDog->RemoveFromQuarantineL( info->ImplementationUid() ); );
       
   517                 #endif
       
   518                 }
       
   519             if( error == KErrNone )
       
   520                 {
       
   521                 // Plugin ownership is transfered to iPluginArray
       
   522                 InsertPluginInOrderL( plugin, iPluginArray );
       
   523                 }
       
   524             else if( error == KLeaveExit )
       
   525                 {
       
   526                 __GSLOGSTRING( "[GSPlgLoader::LoadNextPluginL] LEAVE: KLeaveExit!!!" );
       
   527                 // Must pass KLeaveExit through or otherwise Exit-command will
       
   528                 // not be handled.
       
   529                 User::Leave( KLeaveExit );
       
   530                 }
       
   531             else
       
   532                 {
       
   533                 // Error note is displayed even if plugin is not loaded
       
   534                 // -> plugin is in blacklist -> blacklist note displayed.
       
   535                 #ifdef _DEBUG
       
   536                     DisplayErrorPopupL( error, info );
       
   537                 #endif //_DEBUG
       
   538                 }
       
   539             // Wait for next round
       
   540             break;
       
   541             }
       
   542         }
       
   543     }
       
   544 
       
   545 
       
   546 // ----------------------------------------------------------------------------
       
   547 // CGSPluginLoader::DisplayErrorPopupL
       
   548 //
       
   549 // ----------------------------------------------------------------------------
       
   550 //
       
   551 void CGSPluginLoader::DisplayErrorPopupL(
       
   552         TInt aError,
       
   553         const CImplementationInformation* aInfo )
       
   554     {
       
   555 
       
   556     // Log error:
       
   557     __GSLOGSTRING3( "[GSPlgLoader] %S (0x%X) loading failed with error code %d",
       
   558                     &aInfo->DisplayName(),
       
   559                     aInfo->ImplementationUid().iUid,
       
   560                     aError );
       
   561 
       
   562     // Runtime info message used only in _DEBUG builds.
       
   563     // Buffer needs space for about 50 chars for debug text
       
   564     // + 8 chars for hex UID
       
   565     // + DisplayName().Length()
       
   566     // + error code 10 chars...
       
   567     HBufC* buf = HBufC::NewLC( 100 + aInfo->DisplayName().Length() );
       
   568     TPtr ptr = buf->Des();
       
   569 
       
   570     if( aError == KErrCancel )
       
   571         {
       
   572         _LIT( KDbgMsgBlacklisted, "Plugin in blacklist:\n%S (0x%X)" );
       
   573         ptr.Format( KDbgMsgBlacklisted,
       
   574                     &aInfo->DisplayName(),
       
   575                     aInfo->ImplementationUid().iUid );
       
   576         }
       
   577     else
       
   578         {
       
   579         _LIT( KDbgMsg, "Error:\n%S (0x%X)\nloading failed with error code %d" );
       
   580         ptr.Format( KDbgMsg,
       
   581                     &aInfo->DisplayName(),
       
   582                     aInfo->ImplementationUid().iUid,
       
   583                     aError );
       
   584         }
       
   585     if( iErrorPopup )
       
   586         {
       
   587         delete iErrorPopup;
       
   588         iErrorPopup = NULL;
       
   589         }
       
   590     iErrorPopup = CAknInfoPopupNoteController::NewL();
       
   591     iErrorPopup->SetTextL( ptr );
       
   592     CleanupStack::PopAndDestroy( buf );
       
   593     iErrorPopup->ShowInfoPopupNote();
       
   594     }
       
   595 
       
   596 // ----------------------------------------------------------------------------
       
   597 // CGSPluginLoader::CreatePluginInstanceL
       
   598 //
       
   599 //
       
   600 // ----------------------------------------------------------------------------
       
   601 //
       
   602 CGSPluginInterface& CGSPluginLoader::CreatePluginInstanceL(
       
   603     const CImplementationInformation& aImpInfo )
       
   604     {
       
   605     // Create a wrapper for the plugin - this will take
       
   606     // care of cleaning up the plugin dll. This must be on
       
   607     // the cleanup stack above the plugin object itself - since
       
   608     // the cleanup stack will first delete the plugin, then the
       
   609     // plugin wrapper will be called to unload the ECOM plugin
       
   610     // dll itself.
       
   611     CGSPluginWrapper* wrapper = iDocument->NewPluginUnloadWrapperLC();
       
   612 
       
   613     // Now we can load the plugin
       
   614     const TUid implUid = aImpInfo.ImplementationUid();
       
   615 
       
   616     CGSPluginInterface* plugin = CGSPluginInterface::NewL( implUid,
       
   617                                                            iAppUi );// Remove iAppUi
       
   618     CleanupStack::PushL ( plugin );
       
   619 
       
   620     // And now its okay to update the wrapper with the plugin's
       
   621     // ECOM destructor info.
       
   622     wrapper->SetDetails( plugin->iDtor_ID_Key );
       
   623 
       
   624     // If plugin's resource definition had a valid order number,
       
   625     // set it to plugin.
       
   626     //
       
   627     // If parent is GSAppsPlugin, this is where the ordering
       
   628     // could be changed to follow the to-be-implemented resource file
       
   629     // defining the plugin order.
       
   630 
       
   631     // Parse plugin's order number from opaque_data:
       
   632     TInt orderNumber = 0;
       
   633     const TInt orderErr = ParseOrderNumber( aImpInfo.OpaqueData(), orderNumber );
       
   634     if  ( orderErr == KErrNone && orderNumber >= 0 )
       
   635         {
       
   636         plugin->iOrder = orderNumber;
       
   637         }
       
   638 
       
   639     // When a specific view has been activated externally to GS (e.g
       
   640     // whilst GS is not running) we have to load the view's plugin on-demand.
       
   641     // This means that the plugin is essentially free-floating and is not bound
       
   642     // to a parent's CGSParentPlugin::iPluginArray.
       
   643     //
       
   644     // In this situation, even though we have activated a specific view,
       
   645     // the plugin loader(s) continue to operate in the background.
       
   646     //
       
   647     // Eventually, as the loaders progress, a second attempt will occur to
       
   648     // load the same view (that was activated externally).
       
   649     //
       
   650     // In this situation, we discard the recently loaded instance of the plugin
       
   651     // and instead preserve the view that the user is (presumably) already using.
       
   652     //
       
   653     // However, we must ensure that we synchronous the parent's iPluginArray
       
   654     // with the pre-existing view instance.
       
   655     const TUid viewId = plugin->Id();
       
   656     CGSPluginAndViewIdCache& pluginViewIdCache = iDocument->PluginViewIdCache();
       
   657     const TBool isAlreadyLoaded = pluginViewIdCache.IsPluginLoaded( viewId );
       
   658 
       
   659     if  ( !isAlreadyLoaded )
       
   660         {
       
   661         // Cache the view uid & ECOM plugin dll uid to enable us
       
   662         // to more quickly handle external view activation requests
       
   663         // when GS is not already running.
       
   664         pluginViewIdCache.RegisterViewAndImplementationAssociationL( viewId, implUid );
       
   665 
       
   666         // Prepare to register the plugin with the cache.  Pushes a cleanup stack
       
   667         // item in case adding the view should leave.
       
   668         pluginViewIdCache.PrepareToRegisterPluginInstanceLC( viewId );
       
   669 
       
   670         // Add loaded view to appUi. At this point, the GS framework
       
   671         // is no longer responsible for the lifetime of the 'plugin'
       
   672         // object.
       
   673         //
       
   674         // However, to ensure sucessful cleanup of deleted
       
   675         // views, we have separated the ECOM plugin dll (controlled by
       
   676         // plugin->iDtor_ID_Key) to a separate object. This object is
       
   677         // owned by the loader.
       
   678         iAppUi->AddViewL( plugin );
       
   679 
       
   680         // Pop the cleanup item - all is well now.
       
   681         CleanupStack::Pop(); // cleanup item from PrepareToRegisterPluginInstanceLC
       
   682 
       
   683         CleanupStack::Pop( plugin ); // view framework is now responsible for this memory.
       
   684 
       
   685         // Document, when it is destroyed, will handle unloading of ECOM dll.
       
   686         CleanupStack::Pop( wrapper );
       
   687 
       
   688         // Also register that we have loaded an instance of the specified view
       
   689         // from a plugin.
       
   690         pluginViewIdCache.RegisterPluginInstanceL( viewId, *plugin );
       
   691         }
       
   692     else
       
   693         {
       
   694         // Plugin is already loaded, presumably due to external view activation
       
   695         // request.
       
   696         //
       
   697         // Discard "just loaded" instance and use the pre-loaded one instead.
       
   698         CleanupStack::PopAndDestroy( 2, wrapper );
       
   699         plugin = pluginViewIdCache.PluginInstance( viewId );
       
   700         }
       
   701 
       
   702     return *plugin;
       
   703     }
       
   704 
       
   705 // ----------------------------------------------------------------------------
       
   706 // CGSPluginLoader::SortPluginsL
       
   707 //
       
   708 // ----------------------------------------------------------------------------
       
   709 //
       
   710 EXPORT_C void CGSPluginLoader::SortPluginsL(
       
   711         CArrayPtrFlat<CGSPluginInterface>* aPlugins )
       
   712     {
       
   713     RPointerArray<CGSPluginInterface> plugins;
       
   714     TLinearOrder<CGSPluginInterface> order( CGSPluginLoader::Compare );
       
   715 
       
   716     // Insertion will also order
       
   717     for( TInt i = 0; i < aPlugins->Count(); i++ )
       
   718         {
       
   719         plugins.InsertInOrderL( (*aPlugins)[i], order );
       
   720         }
       
   721 
       
   722     // Replace original array content with sorted items
       
   723     aPlugins->Reset();
       
   724     for( TInt i = 0; i < plugins.Count(); i++ )
       
   725         {
       
   726         aPlugins->AppendL( plugins[i] );
       
   727         }
       
   728     }
       
   729 
       
   730 
       
   731 // ----------------------------------------------------------------------------
       
   732 // CGSPluginLoader::Compare
       
   733 //
       
   734 // Compare two plugins.
       
   735 // Precedence:
       
   736 // [1. plugin provider category]
       
   737 // 2. plugin order number
       
   738 // 3. plugin caption
       
   739 // Plugin provider gategory is currently disabled (not supported yet).
       
   740 // ----------------------------------------------------------------------------
       
   741 //
       
   742 TInt CGSPluginLoader::Compare( const CGSPluginInterface& aFirst,
       
   743                                const CGSPluginInterface& aSecond )
       
   744     {
       
   745     TInt comparison = CompareCategory( aFirst, aSecond );
       
   746     if( comparison == KGSComparisonEqual )
       
   747         {
       
   748         comparison = CompareIndex( aFirst, aSecond );
       
   749         if( comparison == KGSComparisonEqual )
       
   750             {
       
   751             comparison = CompareCaption( aFirst, aSecond );
       
   752             }
       
   753         }
       
   754     return comparison;
       
   755     }
       
   756 
       
   757 
       
   758 // ----------------------------------------------------------------------------
       
   759 // CGSPluginLoader::InsertPluginInOrderL
       
   760 //
       
   761 // ----------------------------------------------------------------------------
       
   762 //
       
   763 void CGSPluginLoader::InsertPluginInOrderL(
       
   764     CGSPluginInterface* aPlugin,
       
   765     CArrayPtrFlat<CGSPluginInterface>* aPlugins )
       
   766     {
       
   767     CGSPluginInterface* comparedPlugin;
       
   768     TInt comparison = 0;
       
   769     TBool inserted = EFalse;
       
   770 
       
   771     for( TInt i = 0; i < aPlugins->Count(); i++ )
       
   772         {
       
   773         comparedPlugin = (*aPlugins)[i];
       
   774         // Optimization: do not call time consuming Compare() multiple times!
       
   775         comparison = Compare( *aPlugin, *comparedPlugin );
       
   776         if( comparison < 0 )
       
   777             {
       
   778             aPlugins->InsertL( i, aPlugin );
       
   779             inserted = ETrue;
       
   780             break;
       
   781             }
       
   782         else if( comparison == 0 )
       
   783             {
       
   784             aPlugins->InsertL( i+1, aPlugin );
       
   785             inserted = ETrue;
       
   786             break;
       
   787             }
       
   788         }
       
   789     // Plugin was not before any other plugin - make sure it's appended
       
   790     if( !inserted )
       
   791         {
       
   792         aPlugins->AppendL( aPlugin );
       
   793         }
       
   794 
       
   795     #ifdef _GS_PLUGINLOADER_ITERATION_SORTING_TRACES
       
   796         PrintOrderTracesL( aPlugins );
       
   797     #endif // _GS_PLUGINLOADER_ITERATION_SORTING_TRACES
       
   798 
       
   799     }
       
   800 
       
   801 // ----------------------------------------------------------------------------
       
   802 // CGSPluginLoader::CompareCategory
       
   803 //
       
   804 // ----------------------------------------------------------------------------
       
   805 //
       
   806 void CGSPluginLoader::PrintOrderTracesL(
       
   807         CArrayPtrFlat<CGSPluginInterface>* aPlugins )
       
   808     {
       
   809     __GSLOGSTRING1( "---[CGSPluginLoader] Sorted list for 0x%X---", iParentUid.iUid );
       
   810     HBufC* name = HBufC::New( KGSCaptionSize );
       
   811     CleanupStack::PushL( name );
       
   812 
       
   813     TPtr ptr = name->Des();
       
   814     CGSPluginInterface* plg;
       
   815 
       
   816     for( TInt i = 0; i < aPlugins->Count(); i++ )
       
   817         {
       
   818         plg = (*aPlugins)[i];
       
   819         plg->GetCaptionL( ptr );
       
   820         __GSLOGSTRING4( "[CGSPluginLoader] Sorted list[%d] Category:%d (0x%X) %S",
       
   821                 plg->iOrder,
       
   822                 plg->PluginProviderCategory(),
       
   823                 plg->Id().iUid,
       
   824                 &ptr );
       
   825         }
       
   826     CleanupStack::PopAndDestroy( name );
       
   827 
       
   828     }
       
   829 
       
   830 
       
   831 // ----------------------------------------------------------------------------
       
   832 // CGSPluginLoader::CompareCategory
       
   833 //
       
   834 //
       
   835 // ----------------------------------------------------------------------------
       
   836 //
       
   837 TInt CGSPluginLoader::CompareCategory( const CGSPluginInterface& aFirst,
       
   838                                        const CGSPluginInterface& aSecond )
       
   839     {
       
   840 #ifdef RD_GS_COMPARE_BY_CATEGORY
       
   841     TInt comparison = KGSComparisonBefore;//KGSComparisonEqual;
       
   842 
       
   843     // Compare if a is before b:
       
   844     TInt a = aFirst.PluginProviderCategory();
       
   845     TInt b = aSecond.PluginProviderCategory();
       
   846 
       
   847     // Cannot use less/greater comparison because int values used in here
       
   848     // (KGSPluginProviderInternal) must not be revealed to 3rd parties.
       
   849     if( a != b )
       
   850         {
       
   851         switch ( a )
       
   852             {
       
   853 /*            case KGSPluginProviderInternal:
       
   854                 if( b != KGSPluginProviderInternal )
       
   855                     {
       
   856                     comparison = KGSComparisonAfter;
       
   857                     }
       
   858                 break;*/
       
   859             case CGSPluginInterface::EGSPluginProviderOEM:
       
   860                 if( b == KGSPluginProviderInternal )
       
   861                     {
       
   862                     comparison = KGSComparisonAfter;
       
   863                     }
       
   864                 break;
       
   865             case CGSPluginInterface::EGSPluginProviderOperator:
       
   866                 if( b == KGSPluginProviderInternal ||
       
   867                     b == CGSPluginInterface::EGSPluginProviderOEM )
       
   868                     {
       
   869                     comparison = KGSComparisonAfter;
       
   870                     }
       
   871                 break;
       
   872             case CGSPluginInterface::EGSPluginProvider3rdParty:
       
   873                 if( b == KGSPluginProviderInternal ||
       
   874                     b == CGSPluginInterface::EGSPluginProviderOEM ||
       
   875                     b == CGSPluginInterface::EGSPluginProviderOperator )
       
   876                     {
       
   877                     comparison = KGSComparisonAfter;
       
   878                     }
       
   879                 break;
       
   880             default:
       
   881                 comparison = KGSComparisonBefore;
       
   882                 break;
       
   883             }
       
   884         }
       
   885     else
       
   886         {
       
   887         comparison = KGSComparisonEqual;
       
   888         }
       
   889 
       
   890     return comparison;
       
   891 
       
   892 #else //RD_GS_COMPARE_BY_CATEGORY
       
   893     #pragma message("Comparing by category DISABLED")
       
   894     // Force comparison to equal so category comparison will not matter. If
       
   895     // comparison by gategory is needed, simply remove the line below:
       
   896     return KGSComparisonEqual;
       
   897 #endif //RD_GS_COMPARE_BY_CATEGORY
       
   898     }
       
   899 
       
   900 
       
   901 // ----------------------------------------------------------------------------
       
   902 // CGSPluginLoader::CompareCaption
       
   903 //
       
   904 //
       
   905 // ----------------------------------------------------------------------------
       
   906 //
       
   907 TInt CGSPluginLoader::CompareCaption( const CGSPluginInterface& aFirst,
       
   908                                       const CGSPluginInterface& aSecond )
       
   909     {
       
   910     HBufC* firstCaptionBuf =  HBufC::New( KGSCaptionSize );
       
   911     HBufC* secondCaptionBuf = HBufC::New( KGSCaptionSize );
       
   912     TPtr firstCaption  = firstCaptionBuf->Des();
       
   913     TPtr secondCaption = secondCaptionBuf->Des();
       
   914     TInt comparison = KGSComparisonEqual;
       
   915 
       
   916     TRAPD( err,  aFirst.GetCaptionL( firstCaption ); );
       
   917     TRAPD( err2, aSecond.GetCaptionL( secondCaption ); );
       
   918 
       
   919     if( err == KErrNone && err2 == KErrNone )
       
   920         {
       
   921         // CompareC return value must be converted to KGSComparisonXXX value.
       
   922         TInt result = secondCaption.CompareC( firstCaption );
       
   923         if( result < 0 )
       
   924             {
       
   925             comparison = KGSComparisonAfter;
       
   926             }
       
   927         else if( result > 0 )
       
   928             {
       
   929             comparison = KGSComparisonBefore;
       
   930             }
       
   931         }
       
   932     delete firstCaptionBuf;
       
   933     delete secondCaptionBuf;
       
   934     return comparison;
       
   935     }
       
   936 
       
   937 
       
   938 // ----------------------------------------------------------------------------
       
   939 // CGSPluginLoader::CompareIndex
       
   940 //
       
   941 //
       
   942 // ----------------------------------------------------------------------------
       
   943 //
       
   944 TInt CGSPluginLoader::CompareIndex( const CGSPluginInterface& aFirst,
       
   945                                     const CGSPluginInterface& aSecond )
       
   946     {
       
   947     TInt comparison = KGSComparisonEqual;
       
   948 
       
   949     // The plugin having index is before the one not having one
       
   950 
       
   951     if( aFirst.iOrder  == KGSPluginNotIndexed &&
       
   952         aSecond.iOrder == KGSPluginNotIndexed )
       
   953         {
       
   954         // Neither have index -> equal
       
   955         comparison = KGSComparisonEqual;
       
   956         }
       
   957     else if( aFirst.iOrder == KGSPluginNotIndexed )
       
   958         {
       
   959         // The plugin having index is before the one not having one
       
   960         comparison = KGSComparisonAfter;
       
   961         }
       
   962     else if( aSecond.iOrder == KGSPluginNotIndexed )
       
   963         {
       
   964         // The plugin having index is before the one not having one
       
   965         comparison = KGSComparisonBefore;
       
   966         }
       
   967     else if( aFirst.iOrder < aSecond.iOrder )
       
   968         {
       
   969         // Compare actual index values
       
   970         comparison = KGSComparisonBefore;
       
   971         }
       
   972     else if( aFirst.iOrder > aSecond.iOrder )
       
   973         {
       
   974         // Compare actual index values
       
   975         comparison = KGSComparisonAfter;
       
   976         }
       
   977 
       
   978     return comparison;
       
   979     }
       
   980 
       
   981 
       
   982 
       
   983 EXPORT_C void CGSPluginLoader::RequestPriority( CActive::TPriority aPriority )
       
   984     {
       
   985     iRequestedPriority = aPriority; 
       
   986     }
       
   987 
       
   988 
       
   989 //  End of File