diff -r 7333d7932ef7 -r 8b7f4e561641 installationservices/swi/source/daemon/daemonbehaviour.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/installationservices/swi/source/daemon/daemonbehaviour.cpp Wed Sep 01 12:22:02 2010 +0100 @@ -0,0 +1,435 @@ +/* +* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "daemonbehaviour.h" +#include "swispubsubdefs.h" +#include "recsisx.h" +#include "sisregistrywritablesession.h" +#include "sisregistryentry.h" +#include "filesisdataprovider.h" +#include "swi/sisparser.h" +#include "swi/siscontents.h" +#include "swi/siscontroller.h" +#include "sisinfo.h" +#include "cleanuputils.h" +#include "sisregistrypackage.h" +#include "log.h" + +void ScanDirectoryL(TInt aDrive); + +using namespace Swi; + +CDaemonBehaviour* CDaemonBehaviour::NewL() + { + CDaemonBehaviour* self = NewLC(); + CleanupStack::Pop(self); + return self; + } + +CDaemonBehaviour* CDaemonBehaviour::NewLC() + { + CDaemonBehaviour* self = new (ELeave) CDaemonBehaviour; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +void CDaemonBehaviour::ConstructL() + { + User::LeaveIfError(iFs.Connect()); + User::LeaveIfError(iFs.ShareProtected()); + User::LeaveIfError(iApaSession.Connect()); + iSisInstaller = CSisInstaller::NewL(this); + TRAP_IGNORE(iSwiDaemonPlugin = CSwiDaemonPlugin::NewL()); + } + +CDaemonBehaviour::~CDaemonBehaviour() + { + if(iSwiDaemonPlugin) + { + delete iSwiDaemonPlugin; + REComSession::FinalClose(); + } + delete iSisInstaller; + iFs.Close(); + iApaSession.Close(); + } + + // from MDaemonBehaviour +TBool CDaemonBehaviour::StartupL() + { + // Return state of Startup + return ETrue; + } + +void CDaemonBehaviour::MediaChangeL(TInt aDrive, TChangeType aChangeType) + { + DEBUG_PRINTF3(_L8("SWI Daemon - Media change detected. Drive: %d, Change Type: %d."), + aDrive, aChangeType); + + RSisRegistryWritableSession registrySession; + + User::LeaveIfError(registrySession.Connect()); + CleanupClosePushL(registrySession); + + if (aChangeType==EMediaInserted) + { + // notify IAR + registrySession.AddDriveL(aDrive); + + // Scan directory on the card and run pre-installed through SWIS + // nb. will leave if no SIS files to install. + ProcessPreinstalledFilesL(aDrive); + } + else if (aChangeType==EMediaRemoved) + { + // Cancel all requests for install + iSisInstaller->Reset(); + + // Notify plugin + if(iSwiDaemonPlugin) + { + iSwiDaemonPlugin->MediaRemoved(aDrive); + } + +#ifndef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK + // notify IAR + registrySession.RemoveDriveL(aDrive); +#endif + } + CleanupStack::PopAndDestroy(®istrySession); + } + +void CDaemonBehaviour::ProcessPreinstalledFilesL(TInt aDrive) + { + _LIT(KDaemonPrivatePath,":\\private\\10202dce\\"); + + iSisInstaller->Reset(); + ProcessPreinstalledFilesL(aDrive, KDaemonPrivatePath); + iStartNotified = EFalse; + iDrive = aDrive; + iSisInstaller->StartInstallingL(); + } + +void CDaemonBehaviour::ProcessPreinstalledFilesL(TInt aDrive, const TDesC& aDirectory) + { + TPath preInstalledPath; + TChar drive; + RFs::DriveToChar(aDrive, drive); + preInstalledPath.Append(drive); + preInstalledPath.Append(aDirectory); + + CDir* dir = NULL; + TInt err = iFs.GetDir(preInstalledPath, KEntryAttNormal, ESortByName, dir); + if (err != KErrNone && err != KErrPathNotFound) + { + User::Leave(err); + } + if(dir) + { + // dir will only exist if GetDir succeeded + CleanupStack::PushL(dir); + for(TInt i = 0; i < dir->Count(); i++) + { + const TEntry &entry = (*dir)[i]; + if(!entry.IsDir()) + { + TFileName fileName(preInstalledPath); + fileName.Append(entry.iName); + iSisInstaller->AddFileToInstallL(fileName); + } + } + CleanupStack::PopAndDestroy(dir); + } + } + + +// From MDaemonInstallBehaviour + +MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifyAppCacheListL() + { + MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifyAppCacheList; + + // What is really desired is notification that the Application Architecture cached List + // is valid, but as this cannot be done simply. + // Is is simulated by a call to two member functions. + + TApaAppInfo appInfo; + User::LeaveIfError(iApaSession.GetAllApps()); + TInt err(iApaSession.GetNextApp(appInfo)); // Call member function that can report an EAppListInvalid + + if (err == RApaLsSession::EAppListInvalid) + { + returnState = MDaemonInstallBehaviour::EStateVerifyAppCacheList; + } + else if (err == KErrNone) // cached list of apps is ready + { + returnState = MDaemonInstallBehaviour::EStateVerifySwisProperty; + } + else + { + User::Leave(err); + } + return returnState; + } + +MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifySwisPropertyL() + { + MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifySwisProperty; + TInt swisState; + TInt err(RProperty::Get(KUidSystemCategory,KUidSoftwareInstallKey,swisState)); + + if (err == KErrNotFound) + { + returnState = (MDaemonInstallBehaviour::EStateInstall); + } + else if (err == KErrNone) + { + if (swisState == ESwisNone) + { + // SWIS is idle + returnState = (MDaemonInstallBehaviour::EStateInstall); + } + else + { + // SWIS is performing an operation + returnState = (MDaemonInstallBehaviour::EStateVerifySwisIdle); + } + } + else + { + User::Leave(err); + } + return returnState; + } + +MDaemonInstallBehaviour::TSisInstallState CDaemonBehaviour::VerifySwisIdleL() + { + MDaemonInstallBehaviour::TSisInstallState returnState = MDaemonInstallBehaviour::EStateVerifySwisIdle; + TInt swisState; + + // Obtain the state of the software installer + User::LeaveIfError(RProperty::Get(KUidSystemCategory,KUidSoftwareInstallKey,swisState)); + + if (swisState == ESwisNone) // Swis is idle + { + returnState = (MDaemonInstallBehaviour::EStateInstall); + } + else // Software installer is currently installing/uinstalling + { + returnState = (MDaemonInstallBehaviour::EStateVerifySwisIdle); + } + return returnState; + } + +void CDaemonBehaviour::ReadSymbianHeaderL(RFile& aFile, TUid& aUid1, TUid& aUid2, TUid& aUid3) + { + + TInt uidLen = sizeof(TInt32); + + TPckg uid1(aUid1.iUid); + User::LeaveIfError(aFile.Read(uid1, uidLen)); + if (uid1.Length() != uidLen) + { + User::Leave(KErrUnderflow); + } + + TPckg uid2(aUid2.iUid); + User::LeaveIfError(aFile.Read(uid2, uidLen)); + if (uid1.Length() != uidLen) + { + User::Leave(KErrUnderflow); + } + + TPckg uid3(aUid3.iUid); + User::LeaveIfError(aFile.Read(uid3, uidLen)); + if (uid1.Length() != uidLen) + { + User::Leave(KErrUnderflow); + } + + } + +void CDaemonBehaviour::DoInstallRequestL(const TDesC& aFileName) + { + DEBUG_PRINTF2(_L("SWI Daemon - Processing presinstalled SIS file '%S'"), + &aFileName); + + TUid appUid; + TDataType dataType; + + User::LeaveIfError(iFs.ShareProtected()); + + // have to pass the file using the file handle + // otherwise SisHelper won't be able to read the + // daemon private directory + RFile file; + User::LeaveIfError(file.Open(iFs, aFileName, EFileRead | EFileStream | EFileShareReadersOnly)); + CleanupClosePushL(file); + User::LeaveIfError(iApaSession.AppForDocument(file,appUid,dataType)); + + // Start installing the file only if it is a sisx file + if (dataType.Des8() == KDataTypeSisx) + { + + // Check if this is already installed, by extracting the package UID and + // asking the registry. + + TUid uid1, uid2, uid3; + ReadSymbianHeaderL(file, uid1, uid2, uid3); + + + // UID 3 will be the package UID, query the registry about it. + RSisRegistrySession session; + User::LeaveIfError(session.Connect()); + CleanupClosePushL(session); + + // temporary work around while we decide what IsInstalled should be policed by. + + RSisRegistryEntry entry; + TInt entryOpenResult = entry.Open(session, uid3); + CleanupClosePushL(entry); + + // Get the types and other details from the stub + CFileSisDataProvider* fileProvider = CFileSisDataProvider::NewLC(iFs, aFileName, EFileRead | EFileShareReadersOnly); + TInt64 pos( 0 ); + fileProvider->Seek( ESeekStart, pos ); + Swi::Sis::CContents* content = Swi::Sis::Parser::ContentsL(*fileProvider); + CleanupStack::PushL( content ); + HBufC8* controllerdata = content->ReadControllerL(); + CleanupStack::PushL( controllerdata ); + TPtrProvider provider(controllerdata->Des()); + Sis::CController *siscontroller = Swi::Sis::CController::NewLC(provider); + + switch(siscontroller->Info().InstallType()) + { + /* For SA/PA, If UID is found in registry, Don't install otherwise Install */ + case EInstInstallation: + case EInstPreInstalledApp: + { + if(entryOpenResult != KErrNone) + { + DoInstallL(file,appUid); + } + + break; + } + /* + For PP/SP, If patch name is found already in registry, Don't install + otherwise Install + */ + case EInstPreInstalledPatch: + case EInstAugmentation: + { + TBool shouldInstall = ETrue; + const RPointerArray& names = siscontroller->Info().Names(); + RPointerArray augmentations; + + // If Base package is not available then don't do anything and break the case. + if (entryOpenResult != KErrNone) + { + break; + } + + //Get the Augmentation and Install if augmentation doesn't match + CleanupResetAndDestroy >::PushL(augmentations); + entry.AugmentationsL(augmentations); + for (TInt i = 0; i < augmentations.Count(); ++i) + { + for (TInt j =0; j < names.Count(); ++j) + { + if ((uid3 == augmentations[i]->Uid()) && + (augmentations[i]->Name() == names[j]->Data())) + { + shouldInstall=EFalse; + break; + } + } + } + + if(shouldInstall) + { + DoInstallL(file,appUid); + } + + CleanupStack::PopAndDestroy(&augmentations); + break; + } + + default: + /* + If SA/PA/SP/PP is not the case we can't handle because + PU has never been supported for SwiDaemon according to FS. + */ + ASSERT(EFalse); + + } + + CleanupStack::PopAndDestroy(6, &session); + + } // End of SISX file condition + + CleanupStack::PopAndDestroy(&file); // close + } + +void CDaemonBehaviour::DoNotifyMediaProcessingComplete() + { + if(iSwiDaemonPlugin && iStartNotified) + { + iSwiDaemonPlugin->MediaProcessingComplete(); + } + } + +void CDaemonBehaviour::DoInstallL(RFile &file, const TUid &appUid) + { + + // Rewind file + TInt pos = 0; + file.Seek(ESeekStart, pos); + + if(iSwiDaemonPlugin) + { + DEBUG_PRINTF(_L8("SWI Daemon - Using external plugin to process install")); + + if(!iStartNotified) + { + iSwiDaemonPlugin->MediaProcessingStart(iDrive); + iStartNotified = ETrue; + } + iSwiDaemonPlugin->RequestInstall(file); + } + + else + { + DEBUG_PRINTF(_L8("SWI Daemon - Using internal logic to process install")); + + TThreadId threadId; + User::LeaveIfError(iApaSession.StartDocument(file,appUid,threadId)); + + RThread thread; + User::LeaveIfError(thread.Open(threadId)); + CleanupClosePushL(thread); + + // Wait for the installer to terminate before launching another install. + + TRequestStatus status; + thread.Logon(status); + User::WaitForRequest(status); + CleanupStack::PopAndDestroy(&thread); + } + }