webengine/widgetengine/src/Preferences.cpp
changeset 0 dd21522fd290
child 13 10e98eab6f85
--- /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 <e32std.h>
+#include <S32FILE.H>
+#include <f32file.h>
+#include <uri16.h>
+#include <e32hashtab.h>
+#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<TDesC,PrefElement>();    
+}
+
+// ----------------------------------------------------------------------------
+// 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<TDesC,PrefElement> 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();
+}
+
+