|
1 /* |
|
2 * Copyright (c) 2010 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 "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: Bookmarks harvester plugin implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "bookmarksplugin.h" |
|
19 |
|
20 #include <favouritesitemlist.h> |
|
21 #include <activefavouritesdbnotifier.h> |
|
22 #include <e32base.h> |
|
23 #include <uri8.h> //For parsing URL names. |
|
24 |
|
25 #include "harvesterserverlogger.h" |
|
26 #include "common.h" |
|
27 #include "csearchdocument.h" |
|
28 #include "ccpixindexer.h" |
|
29 |
|
30 /** The milliseconds delay between harvesting chunks. */ |
|
31 const TInt KHarvestingDelay = 1000; |
|
32 /** Number of bookmarks to process in one active scheduler cycle */ |
|
33 const TInt KBookmarksPerRunL = 1; |
|
34 _LIT(KExcerptDelimiter, " "); |
|
35 /** Bookmark list size for dynamic array*/ |
|
36 const TInt KBookmarkListSize = 100; |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 CBookmarksPlugin* CBookmarksPlugin::NewL() |
|
40 { |
|
41 CBookmarksPlugin* instance = CBookmarksPlugin::NewLC(); |
|
42 CleanupStack::Pop(instance); |
|
43 return instance; |
|
44 } |
|
45 |
|
46 // ----------------------------------------------------------------------------- |
|
47 CBookmarksPlugin* CBookmarksPlugin::NewLC() |
|
48 { |
|
49 CBookmarksPlugin* instance = new (ELeave) CBookmarksPlugin(); |
|
50 CleanupStack::PushL(instance); |
|
51 instance->ConstructL(); |
|
52 return instance; |
|
53 } |
|
54 |
|
55 // ----------------------------------------------------------------------------- |
|
56 CBookmarksPlugin::CBookmarksPlugin() |
|
57 { |
|
58 //No implementation required. |
|
59 //Necessary things done in ConstructL() |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 CBookmarksPlugin::~CBookmarksPlugin() |
|
64 { |
|
65 if (iAsynchronizer) |
|
66 iAsynchronizer->CancelCallback(); |
|
67 iFavoritesNotifier->Cancel(); |
|
68 delete iFavoritesNotifier; |
|
69 delete iAsynchronizer; |
|
70 delete iIndexer; |
|
71 delete iArrUidsCurrentBookmarkList; |
|
72 iFavouritesDb.Close(); |
|
73 iFavouritesSession.Close(); |
|
74 } |
|
75 |
|
76 // ----------------------------------------------------------------------------- |
|
77 void CBookmarksPlugin::ConstructL() |
|
78 { |
|
79 iArrUidsCurrentBookmarkList = new(ELeave) CArrayFixFlat<TInt>( KBookmarkListSize ); |
|
80 User::LeaveIfError( iFavouritesSession.Connect() ); |
|
81 User::LeaveIfError( iFavouritesDb.Open( iFavouritesSession, KBrowserBookmarks ) ); |
|
82 iFavoritesNotifier = new ( ELeave ) CActiveFavouritesDbNotifier( iFavouritesDb, *this ); |
|
83 iAsynchronizer = CDelayedCallback::NewL( CActive::EPriorityIdle ); |
|
84 } |
|
85 |
|
86 // ----------------------------------------------------------------------------- |
|
87 void CBookmarksPlugin::StartPluginL() |
|
88 { |
|
89 iFavoritesNotifier->Start(); //Start the notifier. Guarenteed to be the first call to Start. So no check for IsActive(). |
|
90 // Define this base application class, use default location |
|
91 User::LeaveIfError(iSearchSession.DefineVolume( _L(BOOKMARK_QBASEAPPCLASS), KNullDesC )); |
|
92 // Open database |
|
93 iIndexer = CCPixIndexer::NewL( iSearchSession ); |
|
94 iIndexer->OpenDatabaseL( _L(BOOKMARK_QBASEAPPCLASS) ); |
|
95 // Start harvester for this plugin |
|
96 iObserver->AddHarvestingQueue(this, iIndexer->GetBaseAppClass() ); |
|
97 } |
|
98 |
|
99 // ----------------------------------------------------------------------------- |
|
100 void CBookmarksPlugin::StartHarvestingL( const TDesC& /*aMedia*/ ) |
|
101 { |
|
102 CPIXLOGSTRING("StartHarvestingL: resetting database"); |
|
103 iIndexer->ResetL();//reset any indexes if exist already |
|
104 iCurrentIndex = 0; //Initialize to zero as it is started |
|
105 iFavouritesDb.Count( iCurrentCount ); |
|
106 CPIXLOGSTRING2("StartHarvestingL::Current count = %d.", iCurrentCount); |
|
107 //Get all the UID list from current database |
|
108 //GetUids() appends items to the list. So, reset it first. |
|
109 //From the documentation of GetUids(): "Existing items remain (new ones appended)" |
|
110 iArrUidsCurrentBookmarkList->Reset(); |
|
111 iFavouritesDb.GetUids( *iArrUidsCurrentBookmarkList ); |
|
112 #ifdef __PERFORMANCE_DATA |
|
113 iStartTime.UniversalTime(); |
|
114 #endif |
|
115 iAsynchronizer->Start( 0, this, KHarvestingDelay ); //Guarenteed to be the first call to Start. So no checking for IsActive(). |
|
116 } |
|
117 |
|
118 // ----------------------------------------------------------------------------- |
|
119 void CBookmarksPlugin::DelayedCallbackL( TInt /*aCode*/ ) |
|
120 { |
|
121 // Harvest items on each call |
|
122 |
|
123 // Read the next set of bookmark. |
|
124 for( TInt i = 0; i < KBookmarksPerRunL; i++ ) |
|
125 { |
|
126 // Exit the loop if no more bookmarks |
|
127 if (iCurrentIndex >= iCurrentCount) |
|
128 break; |
|
129 |
|
130 //Create index item |
|
131 CPIXLOGSTRING3("CBookmarksPlugin::DelayedCallbackL(): Harvesting id=%d, BookmarkUid = %d.", iCurrentIndex, iArrUidsCurrentBookmarkList->At(iCurrentIndex) ); |
|
132 //Create new bookmark document and add |
|
133 CreateBookmarksIndexItemL(iArrUidsCurrentBookmarkList->At(iCurrentIndex),ECPixAddAction); |
|
134 iCurrentIndex++; |
|
135 } |
|
136 |
|
137 if( iAsynchronizer && (iCurrentIndex < iCurrentCount) ) |
|
138 { |
|
139 // Launch the next RunL |
|
140 CPIXLOGSTRING2("CBookmarksPlugin::DelayedCallbackL(): scheduling item count: %d.", iCurrentIndex ); |
|
141 iAsynchronizer->Start(0, this, KHarvestingDelay); |
|
142 CPIXLOGSTRING2("CBookmarksPlugin::DelayedCallbackL(): DONE scheduling item count: %d.", iCurrentIndex ); |
|
143 } |
|
144 else |
|
145 { |
|
146 // Harvesting was successfully completed |
|
147 Flush(*iIndexer); |
|
148 #ifdef __PERFORMANCE_DATA |
|
149 UpdatePerformaceDataL(); |
|
150 #endif |
|
151 iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), KErrNone); |
|
152 CPIXLOGSTRING("CBookmarksPlugin::DelayedCallbackL(): Harvesting complete"); |
|
153 } |
|
154 } |
|
155 |
|
156 // ----------------------------------------------------------------------------- |
|
157 void CBookmarksPlugin::DelayedError( TInt aCode ) |
|
158 { |
|
159 Flush(*iIndexer); |
|
160 iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), aCode); |
|
161 } |
|
162 |
|
163 // ----------------------------------------------------------------------------- |
|
164 /** |
|
165 * If input is www2.google.com, this return google.com. |
|
166 * If input is www2.google.com/someting, this returns google.com. |
|
167 * |
|
168 * @param aUrl URL from which to extract domain name. |
|
169 * @param aDomain descriptor pointer in which domain will be returned. |
|
170 * |
|
171 * @note Leaves in case of error with KErrArgument |
|
172 * @example |
|
173 * TPtrC domain; |
|
174 * GetDomainNameLC( myUrl, domain ); |
|
175 */ |
|
176 void GetDomainNameL( const TDesC& aUrl, TPtrC& aDomain ) |
|
177 { |
|
178 CPIXLOGSTRING2("CBookmarksPlugin::GetDomainNameL(): URL = %S", &aUrl ); |
|
179 //Convert to 8-bit descriptors. |
|
180 HBufC8* url8 = HBufC8::NewLC( aUrl.Length() ); |
|
181 url8->Des().Copy( aUrl ); |
|
182 |
|
183 TUriParser8 uriParser; |
|
184 User::LeaveIfError( uriParser.Parse( *url8 ) ); |
|
185 |
|
186 //Get the host name |
|
187 //This returns www.google.com if URL is http://www.google.com/something... |
|
188 const TDesC8& host = uriParser.Extract( EUriHost ); |
|
189 if( host.Length() == 0 ) |
|
190 { |
|
191 aDomain.Set( aUrl ); |
|
192 CleanupStack::PopAndDestroy( url8 ); |
|
193 return; |
|
194 } |
|
195 TLex8 lex( host ); |
|
196 //Check if starts with www. |
|
197 TChar currentChar = 0; |
|
198 int wwwCount = 0; |
|
199 do{ |
|
200 if( ( currentChar = lex.Get() ) != 0 ) wwwCount++; |
|
201 }while( currentChar == TChar('w') || currentChar == TChar('W') ); |
|
202 |
|
203 if( currentChar != 0 ) |
|
204 { |
|
205 lex.UnGet(); |
|
206 wwwCount--; |
|
207 } |
|
208 |
|
209 HBufC* domain16 = NULL; |
|
210 //if www34.google.com, skip anything after www, till '.' |
|
211 if( 3 == wwwCount ) |
|
212 { |
|
213 while( lex.Peek() != '.' ) lex.Inc(); |
|
214 //Now stopped at .google.com. So remove '.' |
|
215 lex.Inc(); |
|
216 //The rest is the domain! |
|
217 const TDesC8& domain = lex.Remainder(); |
|
218 if ( domain.Length() == 0 ) |
|
219 { |
|
220 User::Leave( KErrArgument ); |
|
221 } |
|
222 //Convert to 16-bit descriptors. |
|
223 domain16 = HBufC::NewLC( domain.Length() ); |
|
224 domain16->Des().Copy( domain ); |
|
225 } |
|
226 else |
|
227 { |
|
228 domain16 = HBufC::NewLC( host.Length() ); |
|
229 domain16->Des().Copy( host ); |
|
230 } |
|
231 aDomain.Set( *domain16 ); |
|
232 CleanupStack::Pop( domain16 ); |
|
233 CleanupStack::PopAndDestroy( url8 ); |
|
234 CPIXLOGSTRING2("CBookmarksPlugin::GetDomainNameL(): domain = %S", &aDomain ); |
|
235 } |
|
236 |
|
237 // ----------------------------------------------------------------------------- |
|
238 void CBookmarksPlugin::DoIndexingL(CFavouritesItem*& aItem, const TDesC& aDocidStr, TCPixActionType& aActionType) |
|
239 { |
|
240 CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Entering"); |
|
241 if(aItem->Type() == CFavouritesItem::EItem ) //Store only Items not folders |
|
242 { |
|
243 CPIXLOGSTRING3("CBookmarksPlugin::DoIndexingL(): url = %S ,name = %S", &(aItem->Url()), &(aItem->Name())); |
|
244 CSearchDocument* index_item = CSearchDocument::NewLC(aDocidStr, _L(BOOKMARKAPPCLASS)); |
|
245 index_item->AddFieldL(KMimeTypeField, KMimeTypeBookmark, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized); |
|
246 if(aItem->Name() != KNullDesC) |
|
247 index_item->AddFieldL(KBookMarkFieldName,aItem->Name(),CDocumentField::EStoreYes | CDocumentField::EIndexTokenized); |
|
248 |
|
249 TPtrC domain; |
|
250 if(aItem->Url() != KNullDesC) |
|
251 { |
|
252 index_item->AddFieldL(KBookMarkUrl, aItem->Url(), CDocumentField::EStoreYes | CDocumentField::EIndexTokenized); |
|
253 GetDomainNameL( aItem->Url(), domain ); |
|
254 index_item->AddFieldL(KBookMarkDomain, domain , CDocumentField::EStoreYes | CDocumentField::EIndexTokenized); |
|
255 CPIXLOGSTRING2("CBookmarksPlugin::DoIndexingL(): domain = %S", &domain ); |
|
256 } |
|
257 //Add Excerpt as it is must have field. What should be excerpt in bookmarks ? |
|
258 HBufC* excerpt = HBufC::NewLC(aItem->Url().Length() + aItem->Name().Length() + 1); |
|
259 TPtr ptr = excerpt->Des(); |
|
260 ptr.Append(aItem->Name()); |
|
261 ptr.Append(KExcerptDelimiter); |
|
262 ptr.Append(aItem->Url()); |
|
263 index_item->AddExcerptL(*excerpt); |
|
264 CleanupStack::PopAndDestroy(excerpt); |
|
265 |
|
266 // Send for indexing |
|
267 TRAPD(err, iIndexer->AddL(*index_item)); |
|
268 if (err == KErrNone) |
|
269 { |
|
270 CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Added."); |
|
271 } |
|
272 else |
|
273 { |
|
274 CPIXLOGSTRING2("CBookmarksPlugin::DoIndexingL(): Error %d in adding.", err); |
|
275 } |
|
276 CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Logic complete"); |
|
277 CleanupStack::PopAndDestroy( index_item ); |
|
278 CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Pop complete complete"); |
|
279 } |
|
280 CPIXLOGSTRING("CBookmarksPlugin::DoIndexingL(): Returning"); |
|
281 } |
|
282 |
|
283 // ----------------------------------------------------------------------------- |
|
284 void CBookmarksPlugin::CreateBookmarksIndexItemL(TInt aBookMarkUid, TCPixActionType aActionType) |
|
285 { |
|
286 //@sai: CTC: Will never be null in normal usecase. Needs to be present for UTs. |
|
287 if( !iIndexer ) |
|
288 return; |
|
289 CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): aBookMarkUid = %d ", aBookMarkUid ); |
|
290 // creating CSearchDocument object with unique ID for this application |
|
291 TBuf<20> docid_str; |
|
292 docid_str.AppendNum(aBookMarkUid); |
|
293 //Add or update actions. |
|
294 CFavouritesItem* item = CFavouritesItem::NewLC(); |
|
295 TInt err = iFavouritesDb.Get(aBookMarkUid,*item); |
|
296 CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): DB Get error = %d ", err ); |
|
297 //@sai: CTC: did not ever get 'false' for this check. Since this is a private function, |
|
298 // we cannot UT this with an invalid bookmarkUid. |
|
299 if(KErrNone != err) |
|
300 { |
|
301 CleanupStack::PopAndDestroy(item); |
|
302 return; |
|
303 } |
|
304 CPIXLOGSTRING2("CBookmarksPlugin::CreateBookmarkIndexItemL(): item->Type() = %d ", item->Type() ); |
|
305 DoIndexingL(item, docid_str, aActionType); //add to / update index |
|
306 CleanupStack::PopAndDestroy(item); |
|
307 } |
|
308 |
|
309 // ----------------------------------------------------------------------------- |
|
310 void CBookmarksPlugin::HandleFavouritesDbEventL( RDbNotifier::TEvent aEvent ) |
|
311 { |
|
312 //Since we cannot efficiently identify updated item, it makes most |
|
313 //sense to simply re-index the bookmarks - their numbers are not |
|
314 //prohibitively large. |
|
315 //@sai:CTC: the DB does not seem to be sending any other event. |
|
316 if( RDbNotifier::ECommit == aEvent ) |
|
317 { |
|
318 if( iAsynchronizer->CallbackPending() ) |
|
319 { |
|
320 CPIXLOGSTRING("HandleFavouritesDbEventL: Cancelling callback"); |
|
321 iAsynchronizer->CancelCallback(); //first cancel any ongoing harvesting. |
|
322 } |
|
323 CPIXLOGSTRING("HandleFavouritesDbEventL: calling StartHarvestingL"); |
|
324 StartHarvestingL( KNullDesC ); |
|
325 } |
|
326 } |
|
327 |
|
328 // ----------------------------------------------------------------------------- |
|
329 #ifdef __PERFORMANCE_DATA |
|
330 void CBookmarksPlugin::UpdatePerformaceDataL() |
|
331 { |
|
332 TTime now; |
|
333 |
|
334 |
|
335 iCompleteTime.UniversalTime(); |
|
336 TTimeIntervalMicroSeconds timeDiff = iCompleteTime.MicroSecondsFrom(iStartTime); |
|
337 |
|
338 RFs fileSession; |
|
339 RFile perfFile; |
|
340 User::LeaveIfError( fileSession.Connect () ); |
|
341 |
|
342 |
|
343 /* Open file if it exists, otherwise create it and write content in it */ |
|
344 |
|
345 if(perfFile.Open(fileSession, _L("c:\\data\\BookmarksPerf.txt"), EFileWrite)) |
|
346 User::LeaveIfError(perfFile.Create (fileSession, _L("c:\\data\\BookmarksPerf.txt"), EFileWrite)); |
|
347 |
|
348 HBufC8 *heap = HBufC8::NewL(100); |
|
349 TPtr8 ptr = heap->Des(); |
|
350 now.HomeTime(); |
|
351 TBuf<50> timeString; |
|
352 |
|
353 _LIT(KOwnTimeFormat,"%:0%H%:1%T%:2%S"); |
|
354 now.FormatL(timeString,KOwnTimeFormat); |
|
355 ptr.AppendNum(now.DateTime().Day()); |
|
356 ptr.Append(_L("/")); |
|
357 ptr.AppendNum(now.DateTime().Month()); |
|
358 ptr.Append(_L("/")); |
|
359 ptr.AppendNum(now.DateTime().Year()); |
|
360 ptr.Append(_L(":")); |
|
361 ptr.Append(timeString); |
|
362 ptr.Append( _L(":Ani: Time took for Harvesting Bookmarks is : ")); |
|
363 ptr.AppendNum(timeDiff.Int64()/1000) ; |
|
364 ptr.Append(_L(" MilliSeonds \n")); |
|
365 TInt myInt = 0; |
|
366 perfFile.Seek(ESeekEnd,myInt); |
|
367 perfFile.Write (ptr); |
|
368 perfFile.Close (); |
|
369 fileSession.Close (); |
|
370 delete heap; |
|
371 } |
|
372 #endif |
|
373 // End of file |