browserutilities/recenturlstore/RecentUrlSrc/RecentUrlStore.cpp
changeset 0 dd21522fd290
child 16 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2006 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: 
       
    15 *      Implementation of RecentUrlStore
       
    16 *
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include "RecentUrlStore.h"
       
    24 
       
    25 // EXTERNAL DATA STRUCTURES
       
    26 
       
    27 // EXTERNAL FUNCTION PROTOTYPES
       
    28 
       
    29 // CONSTANTS
       
    30 
       
    31 // MACROS
       
    32 
       
    33 // LOCAL CONSTANTS AND MACROS
       
    34 _LIT(KRecentUrlDBFile, "c:\\private\\%08x\\RecentUrlStore.db");
       
    35 
       
    36 _LIT(KSQLInsertVersion, "INSERT INTO dbversion (dbver) VALUES ('1.0')");
       
    37 
       
    38 /*
       
    39 *    Database columns:
       
    40 *       History - counter used to order the urls latest first
       
    41 *       Url - url of visited page
       
    42 */
       
    43 _LIT(KVersionTableSQL, "CREATE TABLE dbversion(dbver CHAR(10))");
       
    44 _LIT(KRecentUrlTableSQL, "CREATE TABLE recenturl(history COUNTER, domain VARCHAR(50), url VARCHAR(250), title VARCHAR(250))");
       
    45 const TUint KDomainSize = 50;
       
    46 const TUint KUrlSize = 250;
       
    47 const TUint KTitleSize = 250;
       
    48 
       
    49 _LIT(KIndex1SQL, "CREATE INDEX updateidx ON recenturl (history)");
       
    50 
       
    51 _LIT(KSQLInsert, "INSERT INTO recenturl (domain,url,title) VALUES ('%S','%S', '%S')");
       
    52 _LIT(KSQLDelete, "DELETE FROM recenturl WHERE url = '%S'");
       
    53 _LIT(KSQLSelect, "SELECT url,title FROM recenturl WHERE domain LIKE '%S*' OR url LIKE '*://%S*' ORDER BY history desc");
       
    54 _LIT(KSQLSelectAll, "SELECT url,title FROM recenturl ORDER BY history desc");
       
    55 const TUint KUrlCol = 1;
       
    56 const TUint KTitleCol = 2;
       
    57 
       
    58 const TUint KMaxRows = 100;
       
    59 
       
    60 _LIT(KDomainDelim, "."); // domain starts after first '.' and ends after second '.'
       
    61 
       
    62 // MODULE DATA STRUCTURES
       
    63 
       
    64 // LOCAL FUNCTION PROTOTYPES
       
    65 
       
    66 // FORWARD DECLARATIONS
       
    67 
       
    68 // ============================= FUNCTIONS ===============================
       
    69 
       
    70 // -----------------------------------------------------------------------------
       
    71 // CRecentUrlStore::NewLC
       
    72 // Two-phased constructor.
       
    73 // -----------------------------------------------------------------------------
       
    74 EXPORT_C CRecentUrlStore * CRecentUrlStore::NewL ()
       
    75     {
       
    76     CRecentUrlStore* self = new (ELeave) CRecentUrlStore();
       
    77     self->ConstructL();
       
    78     return self;
       
    79 
       
    80     }
       
    81 
       
    82 // -----------------------------------------------------------------------------
       
    83 // CRecentUrlStore::CRecentUrlStore
       
    84 // C++ default constructor can NOT contain any code, that might leave.
       
    85 // -----------------------------------------------------------------------------
       
    86 CRecentUrlStore::CRecentUrlStore():
       
    87 	iFirstTimeOpened(ETrue)
       
    88 	{
       
    89 
       
    90 	}
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CRecentUrlStore::ConstructL
       
    94 // Symbian 2nd phase constructor can leave.
       
    95 // -----------------------------------------------------------------------------
       
    96 void CRecentUrlStore::ConstructL()
       
    97     {
       
    98     
       
    99     // Create the file name from UID
       
   100 	RProcess myProcess;	
       
   101 	TBuf <256>buf;    
       
   102     buf.Format(KRecentUrlDBFile, myProcess.Identity());
       
   103 	iRecentUrlDBFile = buf.AllocL();
       
   104 
       
   105 	User::LeaveIfError(iDbSession.Connect());
       
   106 	
       
   107     }
       
   108     
       
   109 //-----------------------------------------------------------------------------
       
   110 // CRecentUrlStore Destructor
       
   111 //-----------------------------------------------------------------------------
       
   112 CRecentUrlStore::~CRecentUrlStore()
       
   113     {
       
   114 	iDbSession.Close();
       
   115 	delete iRecentUrlDBFile;
       
   116     }
       
   117 
       
   118     
       
   119 //-----------------------------------------------------------------------------
       
   120 // CRecentUrlStore::GetData
       
   121 // params aUrl - Url filter
       
   122 // Returns matching urls.
       
   123 //-----------------------------------------------------------------------------
       
   124 EXPORT_C TInt CRecentUrlStore::GetData (CDesCArray& aUrls, CDesCArray& aTitles, const TDesC& aUrl)
       
   125     {
       
   126     RDbNamedDatabase dataBase;
       
   127     TInt err = OpenDatabase(dataBase);
       
   128     if (err == KErrNone)
       
   129     	{
       
   130     	TRAP(err, GetDataL(dataBase, aUrls, aTitles, aUrl));
       
   131     	dataBase.Close();
       
   132     	}
       
   133     return err;
       
   134     }
       
   135 //-----------------------------------------------------------------------------
       
   136 // CRecentUrlStore::GetData
       
   137 // params aUrl - Url filter
       
   138 // Returns matching urls.
       
   139 //-----------------------------------------------------------------------------
       
   140 void CRecentUrlStore::GetDataL (RDbNamedDatabase& aDataBase, 
       
   141 			CDesCArray& aUrls, CDesCArray& aTitles, const TDesC& aUrl)
       
   142     {
       
   143 	
       
   144     TInt rowCount(0);
       
   145 
       
   146 	// select values from the database filtered by url
       
   147 	if (aUrl.Length())
       
   148 		{
       
   149 		HBufC* domain = aUrl.AllocLC();
       
   150 		domain->Des().LowerCase();
       
   151 		iSQLStatement.Format(KSQLSelect, domain, domain);
       
   152 		CleanupStack::PopAndDestroy();
       
   153 		}
       
   154 	else
       
   155 		{
       
   156 		iSQLStatement.Format(KSQLSelectAll);
       
   157 		}
       
   158 	
       
   159 
       
   160     RDbView view;
       
   161     
       
   162     TInt err = view.Prepare(aDataBase, TDbQuery(iSQLStatement));
       
   163     if (err == KErrNone)
       
   164     	{
       
   165     	err = view.EvaluateAll();
       
   166     	if (err == KErrNone)
       
   167     		{
       
   168     		view.FirstL();
       
   169     		// loop through rows and build the list
       
   170     		while (view.AtRow() && rowCount++ < KMaxRows)
       
   171     			{
       
   172     			view.GetL();
       
   173 				aUrls.AppendL(view.ColDes(KUrlCol));
       
   174 				aTitles.AppendL(view.ColDes(KTitleCol));
       
   175     			view.NextL();
       
   176     			}
       
   177     		/*
       
   178     		* This loop will keep the number of rows in the database at a reasonable size by
       
   179     		* deleting old rows (deletes rows beyond KMaxRows).  Should be at most 1 row deleted.
       
   180     		* Its more efficiant to delete it here than in the SaveData because in this function
       
   181     		* we already have the list and know its size
       
   182     		*/
       
   183     		while (view.AtRow())
       
   184     			{
       
   185     			view.GetL();
       
   186     			iSQLStatement.Format(KSQLDelete, &aUrl);
       
   187 				aDataBase.Execute(iSQLStatement);
       
   188     			view.NextL();
       
   189     			}
       
   190        		}
       
   191     	}
       
   192     view.Close();
       
   193     }
       
   194 
       
   195 //-----------------------------------------------------------------------------
       
   196 // CRecentUrlStore::DeleteData
       
   197 // Deletes a single row from the database.
       
   198 //-----------------------------------------------------------------------------
       
   199 EXPORT_C void CRecentUrlStore::DeleteData (const TDesC& aUrl)
       
   200     {
       
   201     RDbNamedDatabase dataBase;
       
   202     if (OpenDatabase(dataBase) == KErrNone)
       
   203     	{
       
   204 		iSQLStatement.Format(KSQLDelete, &aUrl);
       
   205 		dataBase.Execute(iSQLStatement);
       
   206     	dataBase.Close();
       
   207     	}
       
   208     }
       
   209 
       
   210 //-----------------------------------------------------------------------------
       
   211 // CRecentUrlStore::SaveDataL
       
   212 // Save the url in store.
       
   213 //-----------------------------------------------------------------------------
       
   214 EXPORT_C void CRecentUrlStore::SaveData (const TDesC& aUrl, const TDesC& aTitle)
       
   215 	{
       
   216 	RDbNamedDatabase dataBase;
       
   217 	TInt urlLength (aUrl.Length());
       
   218 	
       
   219 	// shouldn't happen but if it's too long for the data store just skip it!
       
   220 	if (urlLength > KUrlSize)
       
   221 		{
       
   222 		return;
       
   223 		}
       
   224 	
       
   225 	if (OpenDatabase(dataBase) == KErrNone)
       
   226 		{
       
   227 		// find the point where the domain starts and ends
       
   228 		TInt domainLength(urlLength);
       
   229 		TInt domainStart(0);
       
   230 		
       
   231 		TInt startPos = aUrl.Find(KDomainDelim);
       
   232 		if (startPos != KErrNotFound)
       
   233 			{
       
   234 			domainStart = startPos + (KDomainDelim().Length()); // first char after delim
       
   235 			TInt len = aUrl.Right(urlLength - domainStart).Find(KDomainDelim);
       
   236 			if (len > 0) // ignore delim following delim.  we don't want an empty string
       
   237 				{
       
   238 				domainLength = len;
       
   239 				}
       
   240 			else
       
   241 				{
       
   242 				domainLength -= domainStart;
       
   243 				}
       
   244 			}
       
   245 			
       
   246 		// make sure it's not too big for the data store
       
   247 		domainLength = (domainLength > KDomainSize) ? KDomainSize : domainLength;
       
   248 		TInt titleLength = (aTitle.Length() > KTitleSize) ? KTitleSize : aTitle.Length();
       
   249 			
       
   250 		HBufC* domain = aUrl.Mid(domainStart,domainLength).AllocLC();
       
   251 		domain->Des().LowerCase();
       
   252 		HBufC* title = aTitle.Left(titleLength).AllocLC();
       
   253 
       
   254 		// delete and re-insert
       
   255 		iSQLStatement.Format(KSQLDelete, &aUrl);
       
   256 		dataBase.Execute(iSQLStatement);
       
   257 		iSQLStatement.Format(KSQLInsert, domain, &aUrl, title);
       
   258 		CleanupStack::PopAndDestroy(2); // domain, title
       
   259 		
       
   260 		dataBase.Execute(iSQLStatement);
       
   261 		dataBase.Close();
       
   262 		}
       
   263 	}
       
   264 	
       
   265 //-----------------------------------------------------------------------------
       
   266 // CRecentUrlStore::ClearData
       
   267 // Clear the store.
       
   268 //-----------------------------------------------------------------------------
       
   269 EXPORT_C void CRecentUrlStore::ClearData ()
       
   270 	{
       
   271 	// the quickest way to clear the data is to re-create it
       
   272 	TRAP_IGNORE(CreateDatabaseL());
       
   273 	}
       
   274 
       
   275 
       
   276 // private
       
   277 //-----------------------------------------------------------------------------
       
   278 // CRecentUrlStore::DeleteOldRowsL
       
   279 //-----------------------------------------------------------------------------
       
   280 void CRecentUrlStore::DeleteOldRowsL (RDbNamedDatabase& aDataBase)
       
   281     {
       
   282 	
       
   283     TInt rowCount(0);
       
   284 
       
   285 	iSQLStatement.Format(KSQLSelectAll);
       
   286 	
       
   287     RDbView view;
       
   288     
       
   289     TInt err = view.Prepare(aDataBase, TDbQuery(iSQLStatement));
       
   290     if (err == KErrNone)
       
   291     	{
       
   292     	err = view.EvaluateAll();
       
   293     	if (err == KErrNone)
       
   294     		{
       
   295     		view.FirstL();
       
   296     		// loop through rows we want to keep
       
   297     		while (view.AtRow() && rowCount++ < KMaxRows)
       
   298     			{
       
   299     			view.NextL();
       
   300     			}
       
   301     		// delete the rows that are old
       
   302     		while (view.AtRow())
       
   303     			{
       
   304     			view.DeleteL();
       
   305     			view.NextL();
       
   306     			}
       
   307        		}
       
   308     	}
       
   309     view.Close();
       
   310     }
       
   311 
       
   312 //-----------------------------------------------------------------------------
       
   313 // CRecentUrlStore::OpenDatabase
       
   314 // Open the data store.
       
   315 //-----------------------------------------------------------------------------
       
   316 TInt CRecentUrlStore::OpenDatabase(RDbNamedDatabase& aDataBase)
       
   317 	{
       
   318 	TInt error = KErrNone;
       
   319 	// open the database - create if it doesn't exist
       
   320 	error = aDataBase.Open(iDbSession, *iRecentUrlDBFile);
       
   321 	// compact it once during our session
       
   322 	if (error == KErrNone && iFirstTimeOpened)
       
   323 		{
       
   324 		TRAP_IGNORE(DeleteOldRowsL(aDataBase));
       
   325 		aDataBase.Compact();
       
   326 		iFirstTimeOpened = EFalse;
       
   327 		}
       
   328 		
       
   329 	if (error != KErrNone)
       
   330 		{
       
   331 		TRAP(error,CreateDatabaseL());
       
   332 		if (error == KErrNone)
       
   333 			{
       
   334 			error = aDataBase.Open(iDbSession, *iRecentUrlDBFile);
       
   335 			}
       
   336 		}
       
   337 	return error;
       
   338 	}
       
   339 
       
   340 //-----------------------------------------------------------------------------
       
   341 // CRecentUrlStore::CreateDatabaseL
       
   342 // Create the data store.
       
   343 //-----------------------------------------------------------------------------
       
   344 void CRecentUrlStore::CreateDatabaseL()
       
   345 	{
       
   346 	RDbNamedDatabase dataBase;
       
   347 	User::LeaveIfError(dataBase.Replace(iDbSession, *iRecentUrlDBFile));
       
   348 	    	
       
   349 	CleanupClosePushL(dataBase);
       
   350 	User::LeaveIfError(dataBase.Execute(KVersionTableSQL));
       
   351 	User::LeaveIfError(dataBase.Execute(KRecentUrlTableSQL));
       
   352 	User::LeaveIfError(dataBase.Execute(KIndex1SQL));
       
   353 	User::LeaveIfError(dataBase.Execute(KSQLInsertVersion));
       
   354 	CleanupStack::PopAndDestroy();//dataBase	    
       
   355     
       
   356 	}
       
   357 	
       
   358 //  End of File