webengine/widgetinstaller/Src/WidgetInstaller.cpp
changeset 0 dd21522fd290
child 16 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2006, 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 the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This file contains the header file of the CMidletUI class.
       
    15 *
       
    16 *                This class implements the ECom SWInstUIPluginAPI interface
       
    17 *                for midlet installation.
       
    18 *
       
    19 *
       
    20 */
       
    21 
       
    22 #include <f32file.h>
       
    23 #include <bautils.h>
       
    24 #include <e32cmn.h>
       
    25 
       
    26 #include "WidgetInstaller.h"
       
    27 #include "WidgetConfigHandler.h" // info.plist parser
       
    28 #include "WidgetRegistrationManager.h" // interface to "shell"
       
    29 #include "IconConverter.h"
       
    30 
       
    31 // CONSTANTS
       
    32 _LIT( KInfoPList,"Info.plist" );
       
    33 _LIT( KIconFile, "Icon.png" );
       
    34 _LIT( KMBMExt, ".mbm");
       
    35 _LIT( KLprojExt, ".lproj" );
       
    36 _LIT( KInfoPlistStrings, "InfoPlist.strings" );
       
    37 
       
    38 // TODO MW has a hard dependency to APP domain. Not very good...
       
    39 // TODO Hard-coded UID.
       
    40 _LIT( KWidgetAppDir, "\\private\\10282822\\" );
       
    41 _LIT( KBackSlash, "\\" );
       
    42 // todo: other keystring.dat for preference
       
    43 _LIT(KWidgetPref, "prefs.dat");
       
    44 
       
    45 
       
    46 // =========================== MEMBER FUNCTIONS ===============================
       
    47 
       
    48 
       
    49 // ============================================================================
       
    50 // CWidgetInstaller::NewL()
       
    51 // two-phase constructor
       
    52 //
       
    53 // @since 3.1
       
    54 // @return pointer to CWidgetInstaller
       
    55 // ============================================================================
       
    56 //
       
    57 EXPORT_C CWidgetInstaller* CWidgetInstaller::NewL()
       
    58     {
       
    59     CWidgetInstaller* self
       
    60         = new (ELeave) CWidgetInstaller();
       
    61     CleanupStack::PushL( self );
       
    62     self->ConstructL();
       
    63     CleanupStack::Pop( self );
       
    64     return self;
       
    65     }
       
    66 
       
    67 // ============================================================================
       
    68 // CWidgetInstaller::CWidgetInstaller()
       
    69 // C++ constructor
       
    70 //
       
    71 // @since 3.1
       
    72 // ============================================================================
       
    73 //
       
    74 CWidgetInstaller::CWidgetInstaller()
       
    75     : iPropertyValues( EWidgetPropertyIdCount )
       
    76     {
       
    77     }
       
    78 
       
    79 // ============================================================================
       
    80 // CWidgetInstaller::ConstructL()
       
    81 // Symbian second phase constructor
       
    82 //
       
    83 // @since 3.1
       
    84 // ============================================================================
       
    85 //
       
    86 void CWidgetInstaller::ConstructL()
       
    87     {
       
    88     User::LeaveIfError( iRfs.Connect() );
       
    89     User::LeaveIfError( iRfs.ShareProtected() );
       
    90     iFileMgr = CFileMan::NewL( iRfs );
       
    91 
       
    92     iAppManager = CWidgetRegistrationManager::NewL( iRfs );
       
    93     iWidgetConfigHandler = CWidgetConfigHandler::NewL();
       
    94 
       
    95     // delay registry connect because registry is a client and that
       
    96     // produces a circular dependency
       
    97     iServerConnected = EFalse;
       
    98 
       
    99     // empty values
       
   100     for ( TInt i( 0 ); i < EWidgetPropertyIdCount; ++i )
       
   101         {
       
   102         CWidgetPropertyValue* value = CWidgetPropertyValue::NewL();
       
   103         User::LeaveIfError( iPropertyValues.Insert( value, i ) );
       
   104         }
       
   105     *(iPropertyValues[EWidgetPropertyListVersion]) = WIDGETPROPERTYLISTVERSION;
       
   106 
       
   107 #ifdef _DEBUG
       
   108     _LIT(KDir, "WidgetBUR");
       
   109     _LIT(KFile, "WidgetBURInstaller.log");
       
   110     TInt err( 0 );
       
   111 
       
   112     err = iFileLogger.Connect();
       
   113     if ( err == KErrNone )
       
   114         {
       
   115         iFileLogger.CreateLog( KDir(), KFile(), EFileLoggingModeOverwrite );
       
   116         iCanLog = ETrue;
       
   117         }
       
   118 #endif
       
   119     }
       
   120 
       
   121 // ============================================================================
       
   122 // CWidgetInstaller::~CWidgetInstaller()
       
   123 // destructor
       
   124 //
       
   125 // @since 3.1
       
   126 // ============================================================================
       
   127 //
       
   128 CWidgetInstaller::~CWidgetInstaller()
       
   129     {
       
   130     TInt i = 0;
       
   131     for ( ; i < EWidgetPropertyIdCount; ++i )
       
   132         {
       
   133         delete iPropertyValues[i];
       
   134         }
       
   135     iPropertyValues.Close();
       
   136 
       
   137     delete iFileMgr;
       
   138     iRfs.Close();
       
   139 
       
   140     delete iWidgetConfigHandler;
       
   141     delete iAppManager;
       
   142 
       
   143     if ( iServerConnected )
       
   144         {
       
   145         iRegistry.Disconnect();
       
   146         }
       
   147 #ifdef _DEBUG
       
   148     iFileLogger.Close();
       
   149 #endif
       
   150     }
       
   151 
       
   152 // ============================================================================
       
   153 // CWidgetInstaller::InstallL()
       
   154 // NORMAL INSTALL STEPS:
       
   155 // 2. get metadata file (e.g. Info.plist) and parse it
       
   156 // 3. if needed, replace identically named existing widget)
       
   157 // 4. do free space check
       
   158 // 5. if replacing existing widget then move currently installed files
       
   159 //    to backup for possible restore on install error
       
   160 //
       
   161 // @since 3.1
       
   162 // ============================================================================
       
   163 //
       
   164 EXPORT_C void CWidgetInstaller::InstallL(
       
   165     TDesC& aRestoreDir )
       
   166     {
       
   167     if ( EFalse == iServerConnected )
       
   168         {
       
   169         User::LeaveIfError( iRegistry.Connect() );
       
   170         iServerConnected = ETrue;
       
   171         }
       
   172 
       
   173     // The bool will be flase until doing something that
       
   174     // needs to be cleaned up on error/cancel.
       
   175     iOverwriting = EFalse;
       
   176 
       
   177     TRAPD( error,
       
   178         {
       
   179         // do initial bundle processing (parse and validate, total size,
       
   180         // check if replacing existing widget with same bundle ID, etc.)
       
   181         //
       
   182         // this step doesn't do anything that would need to be undone
       
   183         TBool replaceExisting = PreprocessWidgetBundleL( aRestoreDir );
       
   184         SetDriveAndCheckSpaceL();
       
   185 
       
   186         if ( replaceExisting )
       
   187             {
       
   188             BackupL(); // nothing need be undone if backup leaves
       
   189             }
       
   190         }
       
   191         ); // TRAPD
       
   192     if ( error == KErrNone )
       
   193         {
       
   194         ProcessRestoreDirL( aRestoreDir );
       
   195         }
       
   196     else if ( error == KErrAlreadyExists )
       
   197         {
       
   198         // max number of uid reached, to avoid SBE undo previous widget restore, don't leave with error
       
   199         return;
       
   200         }
       
   201     else
       
   202         {
       
   203         User::Leave( error );
       
   204         }
       
   205     }
       
   206 
       
   207 // ============================================================================
       
   208 // CWidgetInstaller::SearchWidgetRootL
       
   209 //
       
   210 // @since 3.2
       
   211 // ============================================================================
       
   212 //
       
   213 TInt CWidgetInstaller::SearchWidgetRootL( const TDesC& aDir, TFileName& aFoundName )
       
   214     {
       
   215     CDir* entryList = NULL;
       
   216     TBool found = EFalse;
       
   217     RFile rFile;
       
   218 
       
   219     // aDir = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\"
       
   220     TInt err = iRfs.GetDir( aDir, KEntryAttMatchMask, EDirsFirst, entryList );
       
   221     if ( err == KErrNone )
       
   222         {
       
   223         CleanupStack::PushL(entryList);
       
   224 
       
   225         // check for directory entries
       
   226         TInt cnt = entryList->Count();
       
   227         for (TInt i=0; i<cnt; i++)
       
   228             {
       
   229             const TEntry& fileEntry = (*entryList)[i];
       
   230             TFileName tempFile( aDir );
       
   231             tempFile.Append( fileEntry.iName );
       
   232             tempFile.Append( KBackSlash );
       
   233             TInt64 dirSize = GetDirSizeL( tempFile );
       
   234             if ( 0 == dirSize )
       
   235                 continue;
       
   236             tempFile.Append( KInfoPList );
       
   237             TInt error = rFile.Open( iRfs, tempFile, EFileRead );
       
   238             CleanupClosePushL( rFile );
       
   239             CleanupStack::PopAndDestroy();  // rFile
       
   240             if ( KErrNone == error )
       
   241                 {
       
   242                 aFoundName.Copy( fileEntry.iName );
       
   243                 found = ETrue;
       
   244                 break;
       
   245                 }
       
   246             }  // end of for
       
   247 
       
   248             CleanupStack::PopAndDestroy();  // entryList
       
   249         }  // end of if  iRfs
       
   250 
       
   251     return found;
       
   252     }
       
   253 
       
   254 // ============================================================================
       
   255 // CWidgetInstaller::PreprocessWidgetBundleL()
       
   256 // Handles parsing and creating widget
       
   257 // Widget data are still in "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\
       
   258 //
       
   259 // @since 3.2
       
   260 // ============================================================================
       
   261 //
       
   262 TBool CWidgetInstaller::PreprocessWidgetBundleL( TDesC& aRestoreDir )
       
   263     {
       
   264     TBool found = EFalse;
       
   265     RFile rFile;
       
   266     
       
   267     // Reset the PropertyValues array, so as to erase the previous widget values, 
       
   268     // otherwise widget installation can fail due to the check for duplicate keys 
       
   269     // in ParseValidateBundleMetadataL(). Starting from the second element in the 
       
   270     // array, since the first element (EWidgetPropertyListVersion) is already
       
   271     // initialized to WIDGETPROPERTYLISTVERSION.
       
   272     for (TInt i=1; i<EWidgetPropertyIdCount; i++)
       
   273         {
       
   274         iPropertyValues[i]->Reset();
       
   275         }
       
   276 
       
   277     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   278     // find the top-level directory under which to get metadata
       
   279     // aRestoreDir = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID"
       
   280     // tempFile = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\"
       
   281     // iBundleRootName = "WeatherBug.wdgt"
       
   282     TFileName tempFile( aRestoreDir );
       
   283     tempFile.Append( KBackSlash );
       
   284     // searching for a directory which contains info.plist (under tempFile), 
       
   285     // rather than return the first directory found.
       
   286     TInt foundRoot = SearchWidgetRootL( tempFile, iBundleRootName );
       
   287     if( !foundRoot )
       
   288         {
       
   289         User::Leave( KErrNotSupported );
       
   290         }
       
   291 
       
   292     // root dir in widget bundle (not install root) of WidgetBackupRestore
       
   293     // e.g. bundleRoot = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\WeatherBug.wdgt\"
       
   294     TFileName bundleRoot( tempFile );
       
   295     bundleRoot.Append( iBundleRootName );
       
   296     bundleRoot.Append( KBackSlash );
       
   297 
       
   298     TInt64 bundleRootSize = GetDirSizeL( bundleRoot );
       
   299     if ( 0 == bundleRootSize )
       
   300         {
       
   301          User::Leave( KErrNotSupported );
       
   302         }
       
   303     *(iPropertyValues[EFileSize]) = bundleRootSize;
       
   304 
       
   305     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   306     // metadata file: "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\WeatherBug.wdgt\Info.plist"
       
   307     tempFile.Copy( bundleRoot );
       
   308     tempFile.Append( KInfoPList );
       
   309     TInt err = rFile.Open( iRfs, tempFile, EFileRead );
       
   310     if ( KErrNone != err )
       
   311         {
       
   312         // missing metadata file
       
   313         User::Leave( KErrNotSupported );
       
   314         }
       
   315     CleanupClosePushL( rFile );
       
   316 
       
   317     TInt size = 0;
       
   318     rFile.Size( size );
       
   319     HBufC8* buffer = HBufC8::NewLC( size );
       
   320     TPtr8 bufferPtr( buffer->Des() );
       
   321     User::LeaveIfError( rFile.Read( bufferPtr ) );
       
   322 
       
   323     // METADATA PARSE
       
   324     iWidgetConfigHandler->ParseValidateBundleMetadataL(
       
   325         bufferPtr, iPropertyValues, iRfs );
       
   326 
       
   327     CleanupStack::PopAndDestroy( 2, &rFile ); // rFile, buffer
       
   328 
       
   329     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   330     // EXISTING WIDGET?
       
   331     if( iRegistry.WidgetExistsL( *(iPropertyValues[EBundleIdentifier]) ) )
       
   332         {
       
   333         // replacement for currently installed widget
       
   334         *(iPropertyValues[EUid]) = iRegistry.GetWidgetUidL(
       
   335             *(iPropertyValues[EBundleIdentifier]));
       
   336         found = ETrue;
       
   337         // get original install dir from registry in case user
       
   338         // decides to "overrite" to another memory location
       
   339         // e.g. iOriginalDir = "\private\[WidgetUIUid]\bundleID\"
       
   340         iRegistry.GetWidgetPath( TUid::Uid( *(iPropertyValues[EUid]) ),
       
   341                                  iOriginalDir );
       
   342         }
       
   343     else
       
   344         {
       
   345         // new widget, get an unused UID for this widget
       
   346         TDriveUnit phoneMemDriveUnit( EDriveC );
       
   347         const TDesC& drive = phoneMemDriveUnit.Name();
       
   348         *(iPropertyValues[EUid]) = iRegistry.GetAvailableUidL(drive[0]).iUid;
       
   349         }
       
   350 
       
   351     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   352     // see if main.html exists
       
   353     // main.html file: "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\WeatherBug.wdgt\YahooTraffic.html"
       
   354     tempFile.Copy( bundleRoot );
       
   355     tempFile.Append( *(iPropertyValues[EMainHTML]) );
       
   356     if( !BaflUtils::FileExists( iRfs, tempFile ) )
       
   357         {
       
   358         User::Leave( KErrCorrupt );
       
   359         }
       
   360 
       
   361     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   362     // infoLoc file: "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\WeatherBug.wdgt\en.lproj\InfoPlist.strings"
       
   363     TBuf<32> lproj;
       
   364     iRegistry.GetLprojName( lproj ); // e.g. "en", "fr", "zh_Hans" ...
       
   365     TFileName infoLocFile( bundleRoot );
       
   366     infoLocFile.Append( lproj );
       
   367     infoLocFile.Append( KLprojExt );
       
   368     infoLocFile.Append( KBackSlash );
       
   369     infoLocFile.Append( KInfoPlistStrings );
       
   370 
       
   371     err = rFile.Open( iRfs, infoLocFile, EFileRead );
       
   372 
       
   373     CleanupClosePushL( rFile );
       
   374     if ( err == KErrNone )
       
   375         {
       
   376         TInt size = 0;
       
   377         rFile.Size( size );
       
   378         HBufC8* buffer = HBufC8::NewLC( size );
       
   379         TPtr8 bufferPtr( buffer->Des() );
       
   380         err = rFile.Read( bufferPtr );
       
   381         User::LeaveIfError( err );
       
   382 
       
   383         // parse the l10n file and localize the bundle display name
       
   384         iWidgetConfigHandler->ParseInfoLocL(
       
   385             bufferPtr, iRfs, *(iPropertyValues[EBundleDisplayName]) );
       
   386         CleanupStack::PopAndDestroy( buffer ); // buffer
       
   387         }
       
   388     CleanupStack::PopAndDestroy( &rFile ); // rFile
       
   389 
       
   390     return found;
       
   391     }
       
   392 
       
   393 void CWidgetInstaller::ProcessRestoreDirL( TDesC& aRestoreDir )
       
   394     {
       
   395     TInt err = KErrNone;
       
   396     HBufC* newDir( HBufC::NewLC( KMaxFileName ) );
       
   397     HBufC* tmpDir( HBufC::NewLC( KMaxFileName ) );
       
   398     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   399     // widgetAppDir = "\private\[WidgetUIUid]\"
       
   400     // If the path is missing create it.
       
   401     if ( !BaflUtils::FolderExists( iRfs, KWidgetAppDir ) )
       
   402         {
       
   403         User::LeaveIfError( iRfs.MkDir( KWidgetAppDir ) );
       
   404         }
       
   405 
       
   406     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   407     // newDir = "\private\[WidgetUIUid]\bundleID\"    
       
   408     *newDir = *(iPropertyValues[EBasePath]);
       
   409     // oldDir = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID"
       
   410     *tmpDir =  aRestoreDir;
       
   411     // oldDir = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\"
       
   412     tmpDir->Des().Append( KBackSlash );
       
   413 
       
   414     TInt renameError = iRfs.Rename( *tmpDir, *newDir );
       
   415     if (renameError)
       
   416         {
       
   417         // copy if different drive or KErrAlreadyExists
       
   418         CFileMan* fileManager = CFileMan::NewL( iRfs );
       
   419         CleanupStack::PushL( fileManager );
       
   420         User::LeaveIfError( fileManager->Copy( *tmpDir, *newDir, CFileMan::ERecurse ) );
       
   421         User::LeaveIfError( fileManager->Attribs(*newDir, KEntryAttNormal, KEntryAttReadOnly,
       
   422                             TTime(0), CFileMan::ERecurse) );
       
   423         CleanupStack::PopAndDestroy( fileManager );  // fileMananger
       
   424         }
       
   425 
       
   426     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   427     // e.g. bundleRootWithDrive = "C:\private\[WidgetUIUid]\bundleID\WeatherBug.wdgt\"
       
   428     // e.g. iBundleRootName = "WeatherBug.wdgt"
       
   429     TFileName bundleRootWithDrive( *newDir );
       
   430     bundleRootWithDrive.Append( iBundleRootName );
       
   431     bundleRootWithDrive.Append( KBackSlash );
       
   432 
       
   433     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   434     // update MainHTML info
       
   435     TFileName mainHtml( bundleRootWithDrive );
       
   436     mainHtml.Append( *(iPropertyValues[EMainHTML]) );
       
   437     *(iPropertyValues[EMainHTML]) = mainHtml;
       
   438 
       
   439     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   440     // parse the Icon.png file
       
   441     // e.g. iconPath = "C:\private\[WidgetUIUid]\bundleID\WeatherBug.wdgt\"
       
   442     TFileName iconPath( bundleRootWithDrive );
       
   443     TFileName iconFile( iconPath );
       
   444     iconFile.Append( KIconFile );
       
   445     if ( BaflUtils::FileExists( iRfs, iconFile ) )
       
   446         {
       
   447         *(iPropertyValues[EIconPath]) = iconPath;
       
   448 
       
   449         // scan the bundleRootWithDrive directory
       
   450         TFileName oldMbmIconTemp( KNullDesC );
       
   451         TBool mbmIconFound = SearchByExtL( bundleRootWithDrive, EDirsLast | EDescending, KMBMExt, oldMbmIconTemp );
       
   452         // skip converting to .mbm file, simply rename oldUid.mbm to newUid.mbm
       
   453         // where oldUid comes from backup widget,
       
   454         // newUid comes from widget registration or reuse of existing widget uid
       
   455         if( mbmIconFound )
       
   456             {
       
   457             TUid uid = TUid::Uid( *(iPropertyValues[EUid]) );
       
   458             // e.g. newMbmIcon = "C:\private\[WidgetUIUid]\bundleID\WeatherBug.wdgt\[newUid].mbm"
       
   459             TFileName newMbmIcon( iconPath );
       
   460             newMbmIcon.Append( uid.Name() );
       
   461             newMbmIcon.Append( KMBMExt() );
       
   462 
       
   463             // e.g. oldMbmIcon = "C:\private\[WidgetUIUid]\bundleID\WeatherBug.wdgt\[oldUid].mbm"
       
   464             TFileName oldMbmIcon( iconPath );
       
   465             oldMbmIcon.Append( oldMbmIconTemp );
       
   466             err = iRfs.Rename( oldMbmIcon, newMbmIcon );
       
   467             // it's ok that oldMbm and newMbm share the same uid
       
   468             if( err != KErrNone && err != KErrAlreadyExists )
       
   469                 {
       
   470                 User::Leave( err );
       
   471                 }
       
   472             }
       
   473          else
       
   474             {
       
   475             // This case is specific to the WidgetPreInstaller.
       
   476             // Once the mbm file can be generated by the script this won't be needed.
       
   477             // Create the mbm file from the icon file
       
   478             TUid uid = TUid::Uid( *(iPropertyValues[EUid]) );
       
   479             ConvertIconL(uid, iconPath);
       
   480             }
       
   481         }
       
   482 
       
   483     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   484     // delete "\private\[WidgetUIUid]\bundleID\prefs.dat"
       
   485     TFileName   widgetPref( *newDir );
       
   486     widgetPref.Append(KWidgetPref);
       
   487     err = iRfs.Delete( widgetPref );
       
   488     // it's ok not to have pref.dat
       
   489     if( err != KErrNone && err != KErrNotFound )
       
   490         {
       
   491         User::Leave( err );
       
   492         }
       
   493 
       
   494     CleanupStack::PopAndDestroy( 2, newDir );    
       
   495     //////////////////////////////////////////////////////////////////////////////////////////////////
       
   496     FinishInstallL( KErrNone );
       
   497     }
       
   498 
       
   499 // ============================================================================
       
   500 // CWidgetInstaller::FinishInstallL()
       
   501 //
       
   502 // @since 3.1
       
   503 // ============================================================================
       
   504 //
       
   505 EXPORT_C void CWidgetInstaller::FinishInstallL( TInt aErr )
       
   506     {
       
   507 #ifdef _DEBUG
       
   508     _LIT(KText, "FinishInstallL, aErr = %d, iOverwriting=%d");
       
   509 
       
   510     if ( iCanLog )
       
   511         {
       
   512         iFileLogger.WriteFormat( KText, aErr, iOverwriting );
       
   513         }
       
   514 #endif
       
   515     if ( EFalse == iServerConnected )
       
   516         {
       
   517         User::LeaveIfError( iRegistry.Connect() );
       
   518         iServerConnected = ETrue;
       
   519         }
       
   520 
       
   521     if ( !aErr )
       
   522        {
       
   523         if ( iOverwriting )
       
   524             {
       
   525             TUid uid = TUid::Uid( *(iPropertyValues[EUid]) );
       
   526             iRegistry.DeRegisterWidgetL( uid );
       
   527             iAppManager->DeregisterWidgetL( uid );
       
   528             }
       
   529         iRegistry.RegisterWidgetL( iPropertyValues );
       
   530         iAppManager->RegisterWidgetL( *(iPropertyValues[EMainHTML]),
       
   531                                         *(iPropertyValues[EBundleDisplayName]),
       
   532                                         *(iPropertyValues[EIconPath]),
       
   533                                         *(iPropertyValues[EDriveName]),
       
   534                                         TUid::Uid( *(iPropertyValues[EUid]) ) );
       
   535 
       
   536         if ( iOverwriting )
       
   537             {
       
   538             // delete backup
       
   539             TInt err = iFileMgr->RmDir( iBackupDir );
       
   540             }
       
   541        }
       
   542     else
       
   543         {
       
   544         if ( iOverwriting )
       
   545             {
       
   546             // delete what was being installed, and restore previous
       
   547             iFileMgr->RmDir( *(iPropertyValues[EBasePath]) );
       
   548             RestoreL();
       
   549             }
       
   550         }
       
   551 
       
   552     iOverwriting = EFalse;
       
   553     }
       
   554 
       
   555     /**
       
   556      * @since 5.0
       
   557      */
       
   558 EXPORT_C void CWidgetInstaller::RegisterWidgetL( const TDesC& aMainHTML,
       
   559                                                  const TDesC& aBundleDisplayName,
       
   560                                                  const TDesC& aIconPath,
       
   561                                                  const TDesC& aDriveName,
       
   562                                                  const TUid& aUid )
       
   563     {
       
   564     iAppManager->RegisterWidgetL( aMainHTML, aBundleDisplayName,
       
   565                                   aIconPath, aDriveName, aUid );
       
   566     }
       
   567 
       
   568 /**
       
   569  * @since 5.0
       
   570  */
       
   571 EXPORT_C void CWidgetInstaller::DeregisterWidgetL( const TUid& aUid )
       
   572     {
       
   573     iAppManager->DeregisterWidgetL( aUid );
       
   574     }
       
   575 
       
   576 // ============================================================================
       
   577 // CWidgetInstaller::RunError()
       
   578 // It is called by WidgetActiveCallback when InstallL leaves.
       
   579 //
       
   580 // @since 3.2
       
   581 // ============================================================================
       
   582 //
       
   583 EXPORT_C TInt CWidgetInstaller::RunError( TInt aError )
       
   584     {
       
   585     TRAP_IGNORE( FinishInstallL( aError ) );
       
   586 
       
   587     return KErrNone; // indicates error was handled
       
   588     }
       
   589 
       
   590 // ============================================================================
       
   591 // CWidgetInstaller::SetDriveAndCheckSpaceL()
       
   592 //
       
   593 // @since 3.2
       
   594 // ============================================================================
       
   595 //
       
   596 TBool CWidgetInstaller::SetDriveAndCheckSpaceL()
       
   597     {
       
   598     TDriveUnit phoneMemDriveUnit( EDriveC );
       
   599     TInt64 driveSpace( 0 );
       
   600 
       
   601     TInt error = DriveInfo( (TInt)phoneMemDriveUnit, driveSpace );
       
   602     if ( *(iPropertyValues[EFileSize]) > driveSpace )
       
   603         {
       
   604         User::Leave( KErrNoMemory );
       
   605         }
       
   606 
       
   607     UpdateWidgetBasePathL( phoneMemDriveUnit );
       
   608     *(iPropertyValues[EDriveName]) = phoneMemDriveUnit.Name();
       
   609 
       
   610     return ETrue;
       
   611     }
       
   612 
       
   613 // ============================================================================
       
   614 // CWidgetInstaller::UpdateWidgetBasePathL()
       
   615 //
       
   616 // @since 3.1
       
   617 // ============================================================================
       
   618 //
       
   619 void CWidgetInstaller::UpdateWidgetBasePathL( TDriveUnit& aDrive )
       
   620     {
       
   621     const TDesC& bundleId = *(iPropertyValues[EBundleIdentifier]);
       
   622     HBufC* basePath = HBufC::NewL(
       
   623         aDrive.Name().Length() + KWidgetAppDir().Length()
       
   624         + bundleId.Length() + 1 );
       
   625     basePath->Des().Append( aDrive.Name() );
       
   626     basePath->Des().Append( KWidgetAppDir );
       
   627     basePath->Des().Append( *(iPropertyValues[EBundleIdentifier]) );
       
   628     basePath->Des().Append( KBackSlash );
       
   629 
       
   630     *(iPropertyValues[EBasePath]) = *basePath;
       
   631     delete basePath;
       
   632     }
       
   633 
       
   634 // ============================================================================
       
   635 // CWidgetInstaller::BackupL()
       
   636 // When overwriting an installed widget, backup so can restore on error.
       
   637 //
       
   638 // @since 3.1
       
   639 // ============================================================================
       
   640 //
       
   641 void CWidgetInstaller::BackupL()
       
   642     {
       
   643 #ifdef _DEBUG
       
   644     _LIT(KText1, "inside BackupL, iOriginalDir=%S, iBackupDir=%S");
       
   645 
       
   646     if ( iCanLog )
       
   647         {
       
   648         iFileLogger.WriteFormat( KText1, &iOriginalDir, &iBackupDir );
       
   649         }
       
   650 #endif
       
   651     // if backup leaves, there is nothing caller needs to do to clean up
       
   652 
       
   653     // move to backup (by renaming) the existing install dir for the widget
       
   654 
       
   655     // first create a "unique" backup dir on the original dir drive
       
   656     // (same drive required since can't "rename" across drives)
       
   657     TParse p;
       
   658     p.Set( iOriginalDir, NULL, NULL );
       
   659     TFileName path;
       
   660     path.Copy( p.Drive() );
       
   661     path.Append( KWidgetAppDir );
       
   662     // NOT A GOOD WAY TO CREATE A UNIQUE DIRECTORY First we create a
       
   663     // unique file and then delete it and then create a directory with
       
   664     // same name.
       
   665     RFile file;
       
   666     CleanupClosePushL( file );
       
   667     User::LeaveIfError( file.Temp( iRfs, path, iBackupDir, EFileWrite ) );
       
   668     CleanupStack::PopAndDestroy(); // file
       
   669     // delete the temp file and...
       
   670     iFileMgr->Delete( iBackupDir );
       
   671     // ...convert to dir name
       
   672     iBackupDir.Append( KBackSlash );
       
   673 
       
   674     // make the backup
       
   675     User::LeaveIfError( iFileMgr->Rename( iOriginalDir, iBackupDir ) );
       
   676     // overwriting boolean is only true when backup is successful
       
   677     iOverwriting = ETrue;
       
   678     }
       
   679 
       
   680 // ============================================================================
       
   681 // CWidgetInstaller::RestoreL()
       
   682 //
       
   683 // @since 3.1
       
   684 // ============================================================================
       
   685 //
       
   686 void CWidgetInstaller::RestoreL()
       
   687     {
       
   688     // move (by renaming) the backup copy to the install dir for the widget
       
   689 
       
   690     // to assure a clean destination, try deleting install dir first
       
   691     (void)iFileMgr->RmDir( iOriginalDir );
       
   692 
       
   693     User::LeaveIfError( iFileMgr->Rename( iBackupDir, iOriginalDir ) );
       
   694 
       
   695     // restore complete
       
   696     iOverwriting = EFalse;
       
   697     }
       
   698 
       
   699 // ============================================================================
       
   700 // CWidgetInstaller::DriveInfo
       
   701 // Indicates if the given drive is available and ready to use.
       
   702 // (other items were commented in a header).
       
   703 //
       
   704 // @since 3.2
       
   705 // ============================================================================
       
   706 //
       
   707 TInt CWidgetInstaller::DriveInfo( TInt aDrive, TInt64& aDiskSpace )
       
   708     {
       
   709     TInt error = KErrNone;
       
   710     TVolumeInfo volumeInfo;
       
   711 
       
   712     error = iRfs.Volume( volumeInfo, aDrive );
       
   713     if( !error )
       
   714         {
       
   715         aDiskSpace = volumeInfo.iFree;
       
   716         }
       
   717 
       
   718     return error;
       
   719     }
       
   720 
       
   721 // ============================================================================
       
   722 // CWidgetInstaller::SearchByExtL
       
   723 //
       
   724 // @since 3.2
       
   725 // ============================================================================
       
   726 //
       
   727 TInt CWidgetInstaller::SearchByExtL( const TDesC& aDir, TUint aSortKey, const TDesC& aExt, TFileName& aFoundName )
       
   728     {
       
   729     CDir* entryList = NULL;
       
   730     TBool found = EFalse;
       
   731 
       
   732     // aDir = "\private\[WidgetBackupRestoreUid]\WidgetBURTemp\bundleID\"
       
   733     TInt err = iRfs.GetDir( aDir, KEntryAttMatchMask, aSortKey, entryList );
       
   734     if ( err == KErrNone )
       
   735         {
       
   736         CleanupStack::PushL(entryList);
       
   737 
       
   738         // check for directory entries
       
   739         TInt extLen = aExt.Length();
       
   740         TInt cnt = entryList->Count();
       
   741         for (TInt i=0; i<cnt; i++)
       
   742             {
       
   743             const TEntry& fileEntry = (*entryList)[i];
       
   744             // when looking for root folder, we don't pass aExt in this function; the first directory will be chosen
       
   745             if ( ( aExt.Length() == 0 ) ||
       
   746                  ( fileEntry.iName.Right( extLen ).Compare( aExt ) == 0 ) )
       
   747                 {
       
   748                 aFoundName.Copy( fileEntry.iName );
       
   749                 found = ETrue;
       
   750                 break;
       
   751                 }
       
   752             }  // end of for
       
   753 
       
   754             CleanupStack::PopAndDestroy();  // entryList
       
   755         }  // end of if  iRfs
       
   756 
       
   757     return found;
       
   758     }
       
   759 
       
   760 // ============================================================================
       
   761 // CWidgetInstaller::GetDirSizeL
       
   762 //
       
   763 // @since 3.2
       
   764 // ============================================================================
       
   765 //
       
   766 TInt CWidgetInstaller::GetDirSizeL( const TDesC& aDir )
       
   767     {
       
   768     CDirScan* scanner = CDirScan::NewLC( iRfs );
       
   769     scanner->SetScanDataL( aDir, KEntryAttMatchMask, EDirsLast );
       
   770 
       
   771     TInt64 dirSize = 0;
       
   772     CDir* results = NULL;
       
   773     scanner->NextL( results );
       
   774     while( results )
       
   775         {
       
   776         CleanupStack::PushL( results );
       
   777 
       
   778         // Prescan to get the dir file size.
       
   779         TInt64 fileSize = 0;
       
   780         const TInt count = results->Count();
       
   781         TInt i = 0;
       
   782         for( i=0; i<count; i++ )
       
   783             {
       
   784             const TEntry& entry = (*results)[ i ];
       
   785             if  ( !entry.IsDir() )
       
   786                 {
       
   787                 fileSize += entry.iSize;
       
   788                 }
       
   789             else
       
   790                 {
       
   791                 // sort by EDirLast
       
   792                 break;
       
   793                 }
       
   794             }
       
   795 
       
   796         dirSize += fileSize;
       
   797         const TPtrC path( scanner->FullPath() );
       
   798         CleanupStack::PopAndDestroy( results );
       
   799 
       
   800         scanner->NextL( results );
       
   801         }
       
   802 
       
   803     CleanupStack::PopAndDestroy();  // scanner
       
   804 
       
   805     return dirSize;
       
   806     }
       
   807 
       
   808 // ============================================================================
       
   809 // CWidgetUIOperationsWatcher::ConvertIconL()
       
   810 // Convert icon.png into mbm format for widget
       
   811 //
       
   812 // @since 5.0
       
   813 // ============================================================================
       
   814 //
       
   815 void CWidgetInstaller::ConvertIconL(
       
   816     TUid& aUid,
       
   817     const TDesC& aIconPath )
       
   818     {
       
   819     TFileName pngIcon;
       
   820     pngIcon.Copy( aIconPath );
       
   821 
       
   822     if ( pngIcon.Length() )
       
   823         {
       
   824         pngIcon.Append( KIconFile );
       
   825         TFileName mbmIcon;
       
   826         mbmIcon.Copy( aIconPath );
       
   827         mbmIcon.Append( aUid.Name() );
       
   828         mbmIcon.Append( KMBMExt() );
       
   829 
       
   830         CIconConverter* iconConverter = CIconConverter::NewL( this, iRfs );
       
   831         CleanupStack::PushL(iconConverter);
       
   832 
       
   833         iconConverter->StartToDecodeL( pngIcon, mbmIcon );
       
   834         CActiveScheduler::Start(); // wait until the converter process finishes
       
   835         CleanupStack::PopAndDestroy(); // iconConverter
       
   836         }
       
   837     }
       
   838 
       
   839 // ============================================================================
       
   840 // CWidgetInstaller::NotifyCompletionL()
       
   841 // Icon conversion calls this when it is complete.
       
   842 //
       
   843 // @since 5.0
       
   844 // ============================================================================
       
   845 //
       
   846 void CWidgetInstaller::NotifyCompletionL( TInt /*aErr*/ )
       
   847     {
       
   848     CActiveScheduler::Stop();
       
   849     }
       
   850 
       
   851 
       
   852 // ============================================================================
       
   853 // CWidgetInstaller::WidgetPropertiesFromInstalledWidgetL()
       
   854 // Generates the widget property values from an already installed widget.
       
   855 //
       
   856 // @since 5.0
       
   857 // ============================================================================
       
   858 //
       
   859 EXPORT_C RPointerArray<CWidgetPropertyValue>*
       
   860 CWidgetInstaller::WidgetPropertiesFromInstalledWidgetL(
       
   861     RFs &aFs,
       
   862     const TDesC& aWidgetPath, /* should end with backslash */
       
   863     const TDesC& aLproj,
       
   864     TUid aUid )
       
   865     {
       
   866     // output, ownership will be handed back to caller
       
   867     RPointerArray<CWidgetPropertyValue>* propertyValues = new (ELeave)
       
   868         RPointerArray<CWidgetPropertyValue>(
       
   869             EWidgetPropertyIdCount );
       
   870     CleanupClosePushL( *propertyValues );
       
   871 
       
   872     TInt i = 0;
       
   873     // empty values
       
   874     for ( ; i < EWidgetPropertyIdCount; ++i )
       
   875         {
       
   876         CWidgetPropertyValue* value = CWidgetPropertyValue::NewL();
       
   877         User::LeaveIfError( propertyValues->Insert( value, i ) );
       
   878         }
       
   879     *(*propertyValues)[EWidgetPropertyListVersion] = WIDGETPROPERTYLISTVERSION;
       
   880     // UID
       
   881     *(*propertyValues)[EUid] = aUid.iUid;
       
   882     // size
       
   883     TInt64 bundleRootSize = GetDirSizeL( aWidgetPath );
       
   884     if ( 0 == bundleRootSize )
       
   885         {
       
   886          User::Leave( KErrNotSupported );
       
   887         }
       
   888     *(*propertyValues)[EFileSize] = bundleRootSize;
       
   889     // Info.plist
       
   890     TFileName manifest ( aWidgetPath );
       
   891     manifest.Append( KInfoPList );
       
   892     RFile rFile;
       
   893     User::LeaveIfError( rFile.Open( aFs, manifest, EFileRead ) );
       
   894     CleanupClosePushL( rFile );
       
   895     TInt size = 0;
       
   896     rFile.Size( size );
       
   897     HBufC8* buffer = HBufC8::NewLC( size );
       
   898     TPtr8 bufferPtr( buffer->Des() );
       
   899     User::LeaveIfError( rFile.Read( bufferPtr ) );
       
   900     iWidgetConfigHandler->ParseValidateBundleMetadataL(
       
   901         bufferPtr, *propertyValues, aFs );
       
   902 
       
   903     CleanupStack::PopAndDestroy(  ) ; // buffer
       
   904     CleanupStack::Pop();
       
   905     rFile.Close();
       
   906     // update base path from metadata
       
   907     *(*propertyValues)[EBasePath] = aWidgetPath;
       
   908     // update drive name
       
   909     *(*propertyValues)[EDriveName] = aWidgetPath.Left( 2 );
       
   910     // update main HTML
       
   911     TFileName mainHtml( aWidgetPath );
       
   912     mainHtml.Append( *(*propertyValues)[EMainHTML] );
       
   913     *(*propertyValues)[EMainHTML] = mainHtml;
       
   914     // update icon path, depends on Icon.png and mbm versions existing
       
   915     TFileName iconFile( aWidgetPath );
       
   916     iconFile.Append( KIconFile );
       
   917     if ( BaflUtils::FileExists( aFs, iconFile ) )
       
   918         {
       
   919         // scan the directory for mbm extension file with processed icon images
       
   920         TFileName mbmFilename;
       
   921         TBool mbmFound = SearchByExtL( aWidgetPath,
       
   922                                        EDirsLast | EDescending,
       
   923                                        KMBMExt,
       
   924                                        mbmFilename );
       
   925         if ( mbmFound )
       
   926             {
       
   927             // rename mbm file using supplied UID
       
   928             // [A-Z]:\private\[WidgetUIUid]\[bundleID]\[zip-root]\[UID].mbm"
       
   929             TFileName oldMbmFilename( aWidgetPath );
       
   930             oldMbmFilename.Append( mbmFilename );
       
   931             TFileName newMbmFilename( aWidgetPath );
       
   932             newMbmFilename.Append( aUid.Name() );
       
   933             newMbmFilename.Append( KMBMExt() );
       
   934 
       
   935             TInt error = iRfs.Rename( oldMbmFilename, newMbmFilename );
       
   936             // it's ok that oldMbm and newMbm share the same uid
       
   937             if( error != KErrNone && error != KErrAlreadyExists )
       
   938                 {
       
   939                 User::Leave( error );
       
   940                 }
       
   941             *(*propertyValues)[EIconPath] = aWidgetPath;
       
   942             }
       
   943         }
       
   944 
       
   945     // localization of display name
       
   946     TFileName infoLocFile( aWidgetPath );
       
   947     infoLocFile.Append( aLproj );
       
   948     infoLocFile.Append( KLprojExt );
       
   949     infoLocFile.Append( KBackSlash );
       
   950     infoLocFile.Append( KInfoPlistStrings );
       
   951     TInt error = rFile.Open( aFs, infoLocFile, EFileRead );
       
   952     CleanupClosePushL( rFile );
       
   953     if ( error == KErrNone )
       
   954         {
       
   955         TInt size = 0;
       
   956         rFile.Size( size );
       
   957         HBufC8* buffer = HBufC8::NewLC( size );
       
   958         TPtr8 bufferPtr( buffer->Des() );
       
   959         error = rFile.Read( bufferPtr );
       
   960         User::LeaveIfError( error );
       
   961         // parse the l10n file and localize the bundle display name
       
   962         iWidgetConfigHandler->ParseInfoLocL(
       
   963             bufferPtr, aFs, *(*propertyValues)[EBundleDisplayName] );
       
   964         CleanupStack::PopAndDestroy(  ); // buffer
       
   965         }
       
   966 
       
   967 
       
   968     CleanupStack::Pop( 2 ); // rfile, propertyValues
       
   969     rFile.Close();
       
   970     return propertyValues;
       
   971     }
       
   972 
       
   973 EXPORT_C TInt CWidgetInstaller::RenameIconFile(
       
   974     RFs &aFs,
       
   975     RPointerArray<CWidgetPropertyValue>* aEntry )
       
   976     {
       
   977     // update icon path, depends on Icon.png and mbm versions existing
       
   978     const TDesC& mainHtml = *(*aEntry)[EMainHTML];
       
   979     TInt mainHtmlPathEnd = mainHtml.LocateReverse( TChar( '\\' ) );
       
   980     if ( KErrNotFound == mainHtmlPathEnd )
       
   981         {
       
   982         return KErrNotFound;
       
   983         }
       
   984     TFileName mainPath(  mainHtml.Left( mainHtmlPathEnd + 1 ) );
       
   985     TFileName iconFile( mainPath );
       
   986     iconFile.Append( KIconFile );
       
   987     if ( BaflUtils::FileExists( aFs, iconFile ) )
       
   988         {
       
   989         // scan the directory for mbm extension file with processed icon images
       
   990         TFileName mbmFilename;
       
   991         TBool mbmFound = SearchByExtL( mainPath,
       
   992                                        EDirsLast | EDescending,
       
   993                                        KMBMExt,
       
   994                                        mbmFilename );
       
   995         if ( mbmFound )
       
   996             {
       
   997             // rename mbm file using supplied UID
       
   998             // [A-Z]:\private\[WidgetUIUid]\[bundleID]\[zip-root]\[UID].mbm"
       
   999             TFileName oldMbmFilename( mainPath );
       
  1000             oldMbmFilename.Append( mbmFilename );
       
  1001             TFileName newMbmFilename( mainPath );
       
  1002             TInt uid = *(*aEntry)[EUid];
       
  1003             newMbmFilename.Append( TUid::Uid(uid).Name() );
       
  1004             newMbmFilename.Append( KMBMExt() );
       
  1005 
       
  1006             // it's ok that oldMbm and newMbm share the same uid
       
  1007             TInt error = iRfs.Rename( oldMbmFilename, newMbmFilename );
       
  1008             if( error != KErrNone && error != KErrAlreadyExists )
       
  1009                 {
       
  1010                 return error;
       
  1011                 }
       
  1012             *(*aEntry)[EIconPath] = mainPath;
       
  1013             }
       
  1014         }
       
  1015     return KErrNone;
       
  1016     }
       
  1017 
       
  1018 //  End of File