diff -r 000000000000 -r dd21522fd290 webengine/widgetengine/src/Preferences.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/widgetengine/src/Preferences.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,484 @@ +/* +* Copyright (c) 2006 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: This class represents the Widget Preferences object +* +*/ + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include "Preferences.h" + + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS +const TInt KMaxIntLength = 10; +const TInt KMaxKeyValueSize = 4096; //4 k + +_LIT( KKeyFormat, "%d.%S" ); +_LIT( KPrefsFile,"prefs.dat" ); + + +// ---------------------------------------------------------------------------- +// WidgetPreferences::WidgetPreferences +// C++ Constructor +// +// +// ---------------------------------------------------------------------------- +WidgetPreferences::WidgetPreferences() :m_widgetid(0), + m_widgetbundleid(0), + m_basepath(0), + m_filepath(0) +{ + m_preferences = new RPtrHashMap(); +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::~WidgetPreferences +// Destructor +// +// +// ---------------------------------------------------------------------------- +WidgetPreferences::~WidgetPreferences() +{ + TRAP_IGNORE( saveL() ); + if (m_preferences) { + m_preferences->ResetAndDestroy(); + m_preferences->Close(); + delete m_preferences; + } + delete m_basepath; + delete m_widgetbundleid; + delete m_filepath; +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::setBasePathL +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::setBasePathL(const TDesC& aValue) +{ + m_basepath = aValue.AllocL(); +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::setWidgetId +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::setWidgetId(TInt aValue) +{ + m_widgetid = aValue; +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::setBundleIdL +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::setWidgetBundleId(const TDesC& aValue) +{ + m_widgetbundleid = aValue.AllocL(); +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::setBundleIdL +// +// +// ---------------------------------------------------------------------------- +TDesC& WidgetPreferences::getWidgetBundleId() +{ + return *m_widgetbundleid; +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::PreferenceL +// Get preference for a key +// +// +// ---------------------------------------------------------------------------- +TInt WidgetPreferences::preferenceL( const TDesC& akey, TPtrC& avalue) +{ + + TInt rSuccess = KErrNotFound; + TInt size = 0; + + if ( !m_basepath || (m_basepath->Length() <= 0) ) + return rSuccess; + + + if ( akey.Length() <= KMaxKeyValueSize ) { + + HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 ); + k->Des().Format( KKeyFormat, m_widgetid, &akey ); + + PrefElement* pref = m_preferences->Find( *k ); + + if ( !pref ) { + CleanupStack::PopAndDestroy( k ); + return rSuccess; + } + + size = pref->valueSize(); + + if ( size > KMaxKeyValueSize ) { + // return contents from temp file whose name is stored + // in the m_value member of m_preferences + RFs fs; + + if ( fs.Connect() == KErrNone ) { + CleanupClosePushL( fs ); + HBufC* filePath = HBufC::NewLC( pref->value().Length() ); + TPtr fName( filePath->Des() ); + fName.Append( pref->value() ); + + RFileReadStream readStream; + + if ( readStream.Open( fs, *filePath, EFileRead ) == KErrNone ) { + CleanupClosePushL( readStream ); + TInt len( readStream.ReadInt32L() ); + if ( len > 0 ) { + HBufC* v = HBufC::NewLC( len ); + TPtr ptrvalue = v->Des(); + readStream.ReadL( ptrvalue, len ); + avalue.Set( *v ); + CleanupStack::Pop( v ); + rSuccess = KErrNone; + } + CleanupStack::PopAndDestroy();//readStream + } + + CleanupStack::PopAndDestroy( 2 ); //filePath,fs + } + } + else if ( size >= 0 ) { + avalue.Set( pref->value() ); + rSuccess = KErrNone; + } + + CleanupStack::PopAndDestroy( k ); + } + + return rSuccess; + +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::SetPreferenceL +// set Preference for a key +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::setPreferenceL( const TDesC& akey, const TDesC& avalue) +{ + if ( !m_basepath || (m_basepath->Length() <= 0) ) + return; + + if ( akey.Length() <= KMaxKeyValueSize ) { + + HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 ); + k->Des().Format( KKeyFormat, m_widgetid, &akey ); + + // if hash has the key and its value + // delete the old value later when the new value was successfully updated + PrefElement* prefExisting = NULL; + prefExisting = m_preferences->Find( *k ); + + if ( avalue.Length() <= KMaxKeyValueSize ) { + PrefElement* pref = new (ELeave) PrefElement; + CleanupStack::PushL( pref ); + pref->setValueL( avalue ); + pref->setValueSize( avalue.Length() ); + m_preferences->InsertL( k, pref ); + CleanupStack::Pop(); //pref + } + else { + // create a temp file and save the value in temp file. + // m_value member of PrefElement contains the temp file name. + RFs fs; + RFile file; + if ( fs.Connect() == KErrNone ) { + CleanupClosePushL( fs ); + + // create and write to file + TFileName tempFileName; + file.Temp( fs, *m_basepath, tempFileName, EFileWrite|EFileShareExclusive ); + CleanupClosePushL( file ); + HBufC* filePath = HBufC::NewLC( tempFileName.Length() ); + TPtr fName( filePath->Des() ); + fName.Append( tempFileName ); + RFileWriteStream writeStream( file ); + CleanupClosePushL( writeStream ); + TRAPD( err, + writeStream.WriteInt32L( avalue.Length() ); + writeStream.WriteL( avalue ); + writeStream.CommitL(); ); + // If an error occured while writing to the file, delete the temp file + // This should be the case when disk is full + if ( err != KErrNone ) + { + CleanupStack::PopAndDestroy( ); //writeStream + file.Close(); + fs.Delete( *filePath ); + User::Leave( err ); + } + + // create new preference element + PrefElement* pref = new ( ELeave ) PrefElement; + CleanupStack::PushL( pref ); + pref->setValueSize( avalue.Length() ); + pref->setValueL( *filePath ); + // update new preference element + m_preferences->InsertL( k, pref ); + + CleanupStack::Pop( pref ); + CleanupStack::PopAndDestroy( ); //writeStream + CleanupStack::PopAndDestroy( 3 ); //filePath,file,fs + } + } + + // now the new value is updated, it's safe to delete the old value + if ( prefExisting ) { + prefExisting->setCleanFileFlag( ETrue ); + delete prefExisting; + } + + CleanupStack::Pop(); // k + } + +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::removePreferenceL +// remove Preference for a key +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::removePreferenceL( const TDesC& akey, const TDesC& avalue) +{ + if ( !m_basepath || (m_basepath->Length() <= 0) ) + return; + + // double check value is NULL + if ( avalue != KNullDesC ) { + return; + } + + if ( akey.Length() <= KMaxKeyValueSize ) { + + HBufC* k = HBufC::NewLC( akey.Length() + KMaxIntLength + 1 ); + k->Des().Format( KKeyFormat, m_widgetid, &akey ); + + // if hash has the key and its value + // delete the old value later when the new value was successfully updated + PrefElement* prefExisting = NULL; + prefExisting = m_preferences->Find( *k ); + + m_preferences->Remove(k); + + // now the new value is updated, it's safe to delete the old value + if ( prefExisting ) { + prefExisting->setCleanFileFlag( ETrue ); + delete prefExisting; + } + + CleanupStack::PopAndDestroy(); // k + } +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::SaveL +// SAve preferences to persistent storage +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::saveL() +{ + if ( !m_basepath || (m_basepath->Length() <= 0) ) + return; + + RFs fs; + + if ( fs.Connect() == KErrNone ) { + + CleanupClosePushL( fs ); + HBufC* filePath = HBufC::NewLC( m_basepath->Length() + KPrefsFile().Length() ); + + TPtr fName( filePath->Des() ); + fName.Append( *m_basepath ); + fName.Append( KPrefsFile ); + + RFileWriteStream writeStream; + TInt fileerror = writeStream.Replace( fs, *filePath, EFileWrite ); + + if ( fileerror != KErrNone ) { + fs.CreatePrivatePath( EDriveC ); + fileerror = writeStream.Create( fs, *filePath, EFileWrite|EFileShareExclusive ); + } + + if ( fileerror == KErrNone ) { + CleanupClosePushL( writeStream ); + writeStream.WriteInt32L( m_preferences->Count() ); + + TPtrHashMapIter it( *m_preferences ); + const TDesC* key; + const PrefElement* pref; + + while ( ( key = it.NextKey() ) != 0 ) { + pref = it.CurrentValue(); + writeStream.WriteInt32L( key->Length() ); + writeStream.WriteL( *key ); + writeStream.WriteInt32L( pref->value().Length() ); + writeStream.WriteL( pref->value() ); + writeStream.WriteInt32L( pref->valueSize() ); + } + + writeStream.CommitL(); + CleanupStack::PopAndDestroy(); //writeStream + } + + CleanupStack::PopAndDestroy( 2 ); //fs,filePath + } + +} + +// ---------------------------------------------------------------------------- +// WidgetPreferences::LoadL +// Load preferences from persistent storage +// +// +// ---------------------------------------------------------------------------- +void WidgetPreferences::loadL() +{ + RFs fs; + if ( !m_basepath || (m_basepath->Length() <= 0) ) + return; + + if ( fs.Connect() == KErrNone ) { + CleanupClosePushL( fs ); + HBufC* filePath = HBufC::NewLC( m_basepath->Length() + KPrefsFile().Length() ); + + TPtr fName( filePath->Des() ); + fName.Append( *m_basepath ); + fName.Append( KPrefsFile ); + + RFileReadStream readStream; + + if ( readStream.Open( fs, *filePath, EFileRead ) == KErrNone ) { + CleanupClosePushL( readStream ); + TInt count( readStream.ReadInt32L() ); + + for( TInt i = 0; i < count; i++ ) { + TInt len = readStream.ReadInt32L(); + + if ( len > 0 ) { + HBufC* key = HBufC::NewLC( len ); + TPtr ptrkey = key->Des(); + readStream.ReadL( ptrkey, len ); + len = readStream.ReadInt32L(); + + if ( len <= KMaxKeyValueSize ) { + HBufC* value = HBufC::NewLC( len ); + TPtr ptrvalue = value->Des(); + readStream.ReadL( ptrvalue, len ); + PrefElement* pref = new ( ELeave ) PrefElement; + CleanupStack::PushL( pref ); + pref->setValueL( ptrvalue ); + TInt size = readStream.ReadInt32L(); + pref->setValueSize( size ); + m_preferences->InsertL( key, pref ); + CleanupStack::Pop(); //pref + CleanupStack::PopAndDestroy(); //value + CleanupStack::Pop(); //key + } + else { + CleanupStack::PopAndDestroy( key ); + } + } + else { + break; + } + } + + CleanupStack::PopAndDestroy(); //readStream + } + + CleanupStack::PopAndDestroy( 2 ); //fs,filePath + } +} + +// ---------------------------------------------------------------------------- +// PrefElement::PrefElement +// C++ constructor +// +// +// ---------------------------------------------------------------------------- +PrefElement::PrefElement() : m_value (0), m_valuesize (0), m_cleanFileFlag (EFalse) +{ +} + + +// ---------------------------------------------------------------------------- +// PrefElement::~PrefElement +// Destructor +// +// +// ---------------------------------------------------------------------------- +PrefElement::~PrefElement() +{ + // When we update the existing key with newer value: + // if the value > 4k, which means a file was created to store the value; + // we need to delete the old file. + // If called from ~Preferences(), we shouldn't do this -- cleanFileFlag is false + if ( m_cleanFileFlag && m_valuesize > KMaxKeyValueSize ) { + HBufC* filePathExisting = HBufC::NewLC( value().Length() ); + TPtr fName( filePathExisting->Des() ); + fName.Append( value() ); + + RFs fs; + if ( fs.Connect() == KErrNone ) { + fs.Delete(*filePathExisting); + fs.Close(); + } + + CleanupStack::PopAndDestroy(); //filePathExisting + } + + delete m_value; +} + + +// ---------------------------------------------------------------------------- +// PrefElement::setValueL +// set value for a preference +// +// +// ---------------------------------------------------------------------------- +void PrefElement::setValueL( const TDesC& value ) +{ + if ( m_value ) { + delete m_value; + } + + m_value = value.AllocL(); +} + +