--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/harvesterplugins/bookmarks/src/bookmarksplugin.cpp Mon Apr 19 14:40:05 2010 +0300
@@ -0,0 +1,373 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: Bookmarks harvester plugin implementation
+*
+*/
+
+#include "bookmarksplugin.h"
+
+#include <favouritesitemlist.h>
+#include <activefavouritesdbnotifier.h>
+#include <e32base.h>
+#include <uri8.h> //For parsing URL names.
+
+#include "harvesterserverlogger.h"
+#include "common.h"
+#include "csearchdocument.h"
+#include "ccpixindexer.h"
+
+/** The milliseconds delay between harvesting chunks. */
+const TInt KHarvestingDelay = 1000;
+/** Number of bookmarks to process in one active scheduler cycle */
+const TInt KBookmarksPerRunL = 1;
+_LIT(KExcerptDelimiter, " ");
+/** Bookmark list size for dynamic array*/
+const TInt KBookmarkListSize = 100;
+
+// -----------------------------------------------------------------------------
+CBookmarksPlugin* CBookmarksPlugin::NewL()
+ {
+ CBookmarksPlugin* instance = CBookmarksPlugin::NewLC();
+ CleanupStack::Pop(instance);
+ return instance;
+ }
+
+// -----------------------------------------------------------------------------
+CBookmarksPlugin* CBookmarksPlugin::NewLC()
+ {
+ CBookmarksPlugin* instance = new (ELeave) CBookmarksPlugin();
+ CleanupStack::PushL(instance);
+ instance->ConstructL();
+ return instance;
+ }
+
+// -----------------------------------------------------------------------------
+CBookmarksPlugin::CBookmarksPlugin()
+ {
+ //No implementation required.
+ //Necessary things done in ConstructL()
+ }
+
+// -----------------------------------------------------------------------------
+CBookmarksPlugin::~CBookmarksPlugin()
+ {
+ if (iAsynchronizer)
+ iAsynchronizer->CancelCallback();
+ iFavoritesNotifier->Cancel();
+ delete iFavoritesNotifier;
+ delete iAsynchronizer;
+ delete iIndexer;
+ delete iArrUidsCurrentBookmarkList;
+ iFavouritesDb.Close();
+ iFavouritesSession.Close();
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::ConstructL()
+ {
+ iArrUidsCurrentBookmarkList = new(ELeave) CArrayFixFlat<TInt>( KBookmarkListSize );
+ User::LeaveIfError( iFavouritesSession.Connect() );
+ User::LeaveIfError( iFavouritesDb.Open( iFavouritesSession, KBrowserBookmarks ) );
+ iFavoritesNotifier = new ( ELeave ) CActiveFavouritesDbNotifier( iFavouritesDb, *this );
+ iAsynchronizer = CDelayedCallback::NewL( CActive::EPriorityIdle );
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::StartPluginL()
+ {
+ iFavoritesNotifier->Start(); //Start the notifier. Guarenteed to be the first call to Start. So no check for IsActive().
+ // Define this base application class, use default location
+ User::LeaveIfError(iSearchSession.DefineVolume( _L(BOOKMARK_QBASEAPPCLASS), KNullDesC ));
+ // Open database
+ iIndexer = CCPixIndexer::NewL( iSearchSession );
+ iIndexer->OpenDatabaseL( _L(BOOKMARK_QBASEAPPCLASS) );
+ // Start harvester for this plugin
+ iObserver->AddHarvestingQueue(this, iIndexer->GetBaseAppClass() );
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::StartHarvestingL( const TDesC& /*aMedia*/ )
+ {
+ CPIXLOGSTRING("StartHarvestingL: resetting database");
+ iIndexer->ResetL();//reset any indexes if exist already
+ iCurrentIndex = 0; //Initialize to zero as it is started
+ iFavouritesDb.Count( iCurrentCount );
+ CPIXLOGSTRING2("StartHarvestingL::Current count = %d.", iCurrentCount);
+ //Get all the UID list from current database
+ //GetUids() appends items to the list. So, reset it first.
+ //From the documentation of GetUids(): "Existing items remain (new ones appended)"
+ iArrUidsCurrentBookmarkList->Reset();
+ iFavouritesDb.GetUids( *iArrUidsCurrentBookmarkList );
+#ifdef __PERFORMANCE_DATA
+ iStartTime.UniversalTime();
+#endif
+ iAsynchronizer->Start( 0, this, KHarvestingDelay ); //Guarenteed to be the first call to Start. So no checking for IsActive().
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::DelayedCallbackL( TInt /*aCode*/ )
+ {
+ // Harvest items on each call
+
+ // Read the next set of bookmark.
+ for( TInt i = 0; i < KBookmarksPerRunL; i++ )
+ {
+ // Exit the loop if no more bookmarks
+ if (iCurrentIndex >= iCurrentCount)
+ break;
+
+ //Create index item
+ CPIXLOGSTRING3("CBookmarksPlugin::DelayedCallbackL(): Harvesting id=%d, BookmarkUid = %d.", iCurrentIndex, iArrUidsCurrentBookmarkList->At(iCurrentIndex) );
+ //Create new bookmark document and add
+ CreateBookmarksIndexItemL(iArrUidsCurrentBookmarkList->At(iCurrentIndex),ECPixAddAction);
+ iCurrentIndex++;
+ }
+
+ if( iAsynchronizer && (iCurrentIndex < iCurrentCount) )
+ {
+ // Launch the next RunL
+ CPIXLOGSTRING2("CBookmarksPlugin::DelayedCallbackL(): scheduling item count: %d.", iCurrentIndex );
+ iAsynchronizer->Start(0, this, KHarvestingDelay);
+ CPIXLOGSTRING2("CBookmarksPlugin::DelayedCallbackL(): DONE scheduling item count: %d.", iCurrentIndex );
+ }
+ else
+ {
+ // Harvesting was successfully completed
+ Flush(*iIndexer);
+#ifdef __PERFORMANCE_DATA
+ UpdatePerformaceDataL();
+#endif
+ iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), KErrNone);
+ CPIXLOGSTRING("CBookmarksPlugin::DelayedCallbackL(): Harvesting complete");
+ }
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::DelayedError( TInt aCode )
+ {
+ Flush(*iIndexer);
+ iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), aCode);
+ }
+
+// -----------------------------------------------------------------------------
+/**
+ * If input is www2.google.com, this return google.com.
+ * If input is www2.google.com/someting, this returns google.com.
+ *
+ * @param aUrl URL from which to extract domain name.
+ * @param aDomain descriptor pointer in which domain will be returned.
+ *
+ * @note Leaves in case of error with KErrArgument
+ * @example
+ * TPtrC domain;
+ * GetDomainNameLC( myUrl, domain );
+ */
+void GetDomainNameL( const TDesC& aUrl, TPtrC& aDomain )
+ {
+ CPIXLOGSTRING2("CBookmarksPlugin::GetDomainNameL(): URL = %S", &aUrl );
+ //Convert to 8-bit descriptors.
+ HBufC8* url8 = HBufC8::NewLC( aUrl.Length() );
+ url8->Des().Copy( aUrl );
+
+ TUriParser8 uriParser;
+ User::LeaveIfError( uriParser.Parse( *url8 ) );
+
+ //Get the host name
+ //This returns www.google.com if URL is http://www.google.com/something...
+ const TDesC8& host = uriParser.Extract( EUriHost );
+ if( host.Length() == 0 )
+ {
+ aDomain.Set( aUrl );
+ CleanupStack::PopAndDestroy( url8 );
+ return;
+ }
+ TLex8 lex( host );
+ //Check if starts with www.
+ TChar currentChar = 0;
+ int wwwCount = 0;
+ do{
+ if( ( currentChar = lex.Get() ) != 0 ) wwwCount++;
+ }while( currentChar == TChar('w') || currentChar == TChar('W') );
+
+ if( currentChar != 0 )
+ {
+ lex.UnGet();
+ wwwCount--;
+ }
+
+ HBufC* domain16 = NULL;
+ //if www34.google.com, skip anything after www, till '.'
+ if( 3 == wwwCount )
+ {
+ while( lex.Peek() != '.' ) lex.Inc();
+ //Now stopped at .google.com. So remove '.'
+ lex.Inc();
+ //The rest is the domain!
+ const TDesC8& domain = lex.Remainder();
+ if ( domain.Length() == 0 )
+ {
+ User::Leave( KErrArgument );
+ }
+ //Convert to 16-bit descriptors.
+ domain16 = HBufC::NewLC( domain.Length() );
+ domain16->Des().Copy( domain );
+ }
+ else
+ {
+ domain16 = HBufC::NewLC( host.Length() );
+ domain16->Des().Copy( host );
+ }
+ aDomain.Set( *domain16 );
+ CleanupStack::Pop( domain16 );
+ CleanupStack::PopAndDestroy( url8 );
+ CPIXLOGSTRING2("CBookmarksPlugin::GetDomainNameL(): domain = %S", &aDomain );
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::DoIndexingL(CFavouritesItem*& aItem, const TDesC& aDocidStr, TCPixActionType& aActionType)
+ {
+ CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Entering");
+ if(aItem->Type() == CFavouritesItem::EItem ) //Store only Items not folders
+ {
+ CPIXLOGSTRING3("CBookmarksPlugin::DoIndexingL(): url = %S ,name = %S", &(aItem->Url()), &(aItem->Name()));
+ CSearchDocument* index_item = CSearchDocument::NewLC(aDocidStr, _L(BOOKMARKAPPCLASS));
+ index_item->AddFieldL(KMimeTypeField, KMimeTypeBookmark, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);
+ if(aItem->Name() != KNullDesC)
+ index_item->AddFieldL(KBookMarkFieldName,aItem->Name(),CDocumentField::EStoreYes | CDocumentField::EIndexTokenized);
+
+ TPtrC domain;
+ if(aItem->Url() != KNullDesC)
+ {
+ index_item->AddFieldL(KBookMarkUrl, aItem->Url(), CDocumentField::EStoreYes | CDocumentField::EIndexTokenized);
+ GetDomainNameL( aItem->Url(), domain );
+ index_item->AddFieldL(KBookMarkDomain, domain , CDocumentField::EStoreYes | CDocumentField::EIndexTokenized);
+ CPIXLOGSTRING2("CBookmarksPlugin::DoIndexingL(): domain = %S", &domain );
+ }
+ //Add Excerpt as it is must have field. What should be excerpt in bookmarks ?
+ HBufC* excerpt = HBufC::NewLC(aItem->Url().Length() + aItem->Name().Length() + 1);
+ TPtr ptr = excerpt->Des();
+ ptr.Append(aItem->Name());
+ ptr.Append(KExcerptDelimiter);
+ ptr.Append(aItem->Url());
+ index_item->AddExcerptL(*excerpt);
+ CleanupStack::PopAndDestroy(excerpt);
+
+ // Send for indexing
+ TRAPD(err, iIndexer->AddL(*index_item));
+ if (err == KErrNone)
+ {
+ CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Added.");
+ }
+ else
+ {
+ CPIXLOGSTRING2("CBookmarksPlugin::DoIndexingL(): Error %d in adding.", err);
+ }
+ CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Logic complete");
+ CleanupStack::PopAndDestroy( index_item );
+ CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Pop complete complete");
+ }
+ CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Returning");
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::CreateBookmarksIndexItemL(TInt aBookMarkUid, TCPixActionType aActionType)
+ {
+ //@sai: CTC: Will never be null in normal usecase. Needs to be present for UTs.
+ if( !iIndexer )
+ return;
+ CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): aBookMarkUid = %d ", aBookMarkUid );
+ // creating CSearchDocument object with unique ID for this application
+ TBuf<20> docid_str;
+ docid_str.AppendNum(aBookMarkUid);
+ //Add or update actions.
+ CFavouritesItem* item = CFavouritesItem::NewLC();
+ TInt err = iFavouritesDb.Get(aBookMarkUid,*item);
+ CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): DB Get error = %d ", err );
+ //@sai: CTC: did not ever get 'false' for this check. Since this is a private function,
+ // we cannot UT this with an invalid bookmarkUid.
+ if(KErrNone != err)
+ {
+ CleanupStack::PopAndDestroy(item);
+ return;
+ }
+ CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): item->Type() = %d ", item->Type() );
+ DoIndexingL(item, docid_str, aActionType); //add to / update index
+ CleanupStack::PopAndDestroy(item);
+ }
+
+// -----------------------------------------------------------------------------
+void CBookmarksPlugin::HandleFavouritesDbEventL( RDbNotifier::TEvent aEvent )
+ {
+ //Since we cannot efficiently identify updated item, it makes most
+ //sense to simply re-index the bookmarks - their numbers are not
+ //prohibitively large.
+ //@sai:CTC: the DB does not seem to be sending any other event.
+ if( RDbNotifier::ECommit == aEvent )
+ {
+ if( iAsynchronizer->CallbackPending() )
+ {
+ CPIXLOGSTRING("HandleFavouritesDbEventL: Cancelling callback");
+ iAsynchronizer->CancelCallback(); //first cancel any ongoing harvesting.
+ }
+ CPIXLOGSTRING("HandleFavouritesDbEventL: calling StartHarvestingL");
+ StartHarvestingL( KNullDesC );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+#ifdef __PERFORMANCE_DATA
+void CBookmarksPlugin::UpdatePerformaceDataL()
+ {
+ TTime now;
+
+
+ iCompleteTime.UniversalTime();
+ TTimeIntervalMicroSeconds timeDiff = iCompleteTime.MicroSecondsFrom(iStartTime);
+
+ RFs fileSession;
+ RFile perfFile;
+ User::LeaveIfError( fileSession.Connect () );
+
+
+ /* Open file if it exists, otherwise create it and write content in it */
+
+ if(perfFile.Open(fileSession, _L("c:\\data\\BookmarksPerf.txt"), EFileWrite))
+ User::LeaveIfError(perfFile.Create (fileSession, _L("c:\\data\\BookmarksPerf.txt"), EFileWrite));
+
+ HBufC8 *heap = HBufC8::NewL(100);
+ TPtr8 ptr = heap->Des();
+ now.HomeTime();
+ TBuf<50> timeString;
+
+ _LIT(KOwnTimeFormat,"%:0%H%:1%T%:2%S");
+ now.FormatL(timeString,KOwnTimeFormat);
+ ptr.AppendNum(now.DateTime().Day());
+ ptr.Append(_L("/"));
+ ptr.AppendNum(now.DateTime().Month());
+ ptr.Append(_L("/"));
+ ptr.AppendNum(now.DateTime().Year());
+ ptr.Append(_L(":"));
+ ptr.Append(timeString);
+ ptr.Append( _L(":Ani: Time took for Harvesting Bookmarks is : "));
+ ptr.AppendNum(timeDiff.Int64()/1000) ;
+ ptr.Append(_L(" MilliSeonds \n"));
+ TInt myInt = 0;
+ perfFile.Seek(ESeekEnd,myInt);
+ perfFile.Write (ptr);
+ perfFile.Close ();
+ fileSession.Close ();
+ delete heap;
+ }
+#endif
+// End of file