18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2005, 2008, 2009 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * its contributors may be used to endorse or promote products derived 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * from this software without specific prior written permission. 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebHistoryInternal.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebHistoryItemInternal.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebKitLogging.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebNSURLExtras.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebTypesInternal.h" 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#import <WebCore/HistoryItem.h> 360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import <WebCore/HistoryPropertyList.h> 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/PageGroup.h> 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore; 400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochusing namespace std; 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef int64_t WebHistoryDateKey; 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef HashMap<WebHistoryDateKey, RetainPtr<NSMutableArray> > DateToEntriesMap; 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryItemsAddedNotification = @"WebHistoryItemsAddedNotification"; 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryItemsRemovedNotification = @"WebHistoryItemsRemovedNotification"; 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryAllItemsRemovedNotification = @"WebHistoryAllItemsRemovedNotification"; 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryLoadedNotification = @"WebHistoryLoadedNotification"; 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryItemsDiscardedWhileLoadingNotification = @"WebHistoryItemsDiscardedWhileLoadingNotification"; 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistorySavedNotification = @"WebHistorySavedNotification"; 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebHistoryItemsKey = @"WebHistoryItems"; 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic WebHistory *_sharedHistory = nil; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *FileVersionKey = @"WebHistoryFileVersion"; 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *DatesArrayKey = @"WebHistoryDates"; 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define currentFileVersion 1 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass WebHistoryWriter : public HistoryPropertyListWriter { 610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic: 620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch WebHistoryWriter(DateToEntriesMap*); 630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate: 650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch virtual void writeHistoryItems(BinaryPropertyListObjectStream&); 660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch DateToEntriesMap* m_entriesByDate; 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Vector<int> m_dateKeys; 690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}; 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@interface WebHistoryPrivate : NSObject { 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@private 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableDictionary *_entriesByURL; 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DateToEntriesMap* _entriesByDate; 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *_orderedLastVisitedDays; 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL itemLimitSet; 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int itemLimit; 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL ageInDaysLimitSet; 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int ageInDaysLimit; 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (WebHistoryItem *)visitedURL:(NSURL *)url withTitle:(NSString *)title increaseVisitCount:(BOOL)increaseVisitCount; 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (BOOL)addItem:(WebHistoryItem *)entry discardDuplicate:(BOOL)discardDuplicate; 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addItems:(NSArray *)newEntries; 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItem:(WebHistoryItem *)entry; 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItems:(NSArray *)entries; 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeAllItems; 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedLastVisitedDays; 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)calendarDate; 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)containsURL:(NSURL *)URL; 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)itemForURL:(NSURL *)URL; 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)itemForURLString:(NSString *)URLString; 95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (NSArray *)allItems; 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error; 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error; 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSCalendarDate *)ageLimitDate; 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryItemLimit:(int)limit; 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyItemLimit; 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryAgeInDaysLimit:(int)limit; 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyAgeInDaysLimit; 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addVisitedLinksToPageGroup:(PageGroup&)group; 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebHistoryPrivate 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 113cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: OBJECT FRAMEWORK 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)initialize 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [[NSUserDefaults standardUserDefaults] registerDefaults: 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [NSDictionary dictionaryWithObjectsAndKeys: 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project @"1000", @"WebKitHistoryItemLimit", 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project @"7", @"WebKitHistoryAgeInDaysLimit", 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nil]]; 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (id)init 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![super init]) 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return nil; 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _entriesByURL = [[NSMutableDictionary alloc] init]; 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _entriesByDate = new DateToEntriesMap; 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)dealloc 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_entriesByURL release]; 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_orderedLastVisitedDays release]; 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete _entriesByDate; 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [super dealloc]; 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)finalize 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete _entriesByDate; 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [super finalize]; 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 149cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: MODIFYING CONTENTS 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void getDayBoundaries(NSTimeInterval interval, NSTimeInterval& beginningOfDay, NSTimeInterval& beginningOfNextDay) 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFTimeZoneRef timeZone = CFTimeZoneCopyDefault(); 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(interval, timeZone); 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project date.hour = 0; 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project date.minute = 0; 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project date.second = 0; 158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block beginningOfDay = CFGregorianDateGetAbsoluteTime(date, timeZone); 159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block date.day += 1; 160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block beginningOfNextDay = CFGregorianDateGetAbsoluteTime(date, timeZone); 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFRelease(timeZone); 162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic inline NSTimeInterval beginningOfDay(NSTimeInterval date) 165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static NSTimeInterval cachedBeginningOfDay = NAN; 167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static NSTimeInterval cachedBeginningOfNextDay; 168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!(date >= cachedBeginningOfDay && date < cachedBeginningOfNextDay)) 169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block getDayBoundaries(date, cachedBeginningOfDay, cachedBeginningOfNextDay); 170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return cachedBeginningOfDay; 171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic inline WebHistoryDateKey dateKey(NSTimeInterval date) 174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Converting from double (NSTimeInterval) to int64_t (WebHistoryDateKey) is 176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // safe here because all sensible dates are in the range -2**48 .. 2**47 which 177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // safely fits in an int64_t. 178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return beginningOfDay(date); 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns whether the day is already in the list of days, 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// and fills in *key with the key used to access its location 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)findKey:(WebHistoryDateKey*)key forDay:(NSTimeInterval)date 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT_ARG(key, key); 186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *key = dateKey(date); 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return _entriesByDate->contains(*key); 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)insertItem:(WebHistoryItem *)entry forDateKey:(WebHistoryDateKey)dateKey 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT_ARG(entry, entry != nil); 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(_entriesByDate->contains(dateKey)); 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *entriesForDate = _entriesByDate->get(dateKey).get(); 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSTimeInterval entryDate = [entry lastVisitedTimeInterval]; 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned count = [entriesForDate count]; 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The entries for each day are stored in a sorted array with the most recent entry first 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check for the common cases of the entry being newer than all existing entries or the first entry of the day 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!count || [[entriesForDate objectAtIndex:0] lastVisitedTimeInterval] < entryDate) { 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entriesForDate insertObject:entry atIndex:0]; 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // .. or older than all existing entries 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count > 0 && [[entriesForDate objectAtIndex:count - 1] lastVisitedTimeInterval] >= entryDate) { 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entriesForDate insertObject:entry atIndex:count]; 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned low = 0; 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned high = count; 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (low < high) { 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned mid = low + (high - low) / 2; 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([[entriesForDate objectAtIndex:mid] lastVisitedTimeInterval] >= entryDate) 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project low = mid + 1; 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project high = mid; 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // low is now the index of the first entry that is older than entryDate 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entriesForDate insertObject:entry atIndex:low]; 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItemFromDateCaches:(WebHistoryItem *)entry 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryDateKey dateKey; 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL foundDate = [self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]]; 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!foundDate) 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DateToEntriesMap::iterator it = _entriesByDate->find(dateKey); 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *entriesForDate = it->second.get(); 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entriesForDate removeObjectIdenticalTo:entry]; 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remove this date entirely if there are no other entries on it 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([entriesForDate count] == 0) { 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _entriesByDate->remove(it); 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Clear _orderedLastVisitedDays so it will be regenerated when next requested. 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_orderedLastVisitedDays release]; 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _orderedLastVisitedDays = nil; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItemForURLString:(NSString *)URLString 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryItem *entry = [_entriesByURL objectForKey:URLString]; 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!entry) 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_entriesByURL removeObjectForKey:URLString]; 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ASSERT_DISABLED 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self removeItemFromDateCaches:entry]; 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL itemWasInDateCaches = [self removeItemFromDateCaches:entry]; 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(itemWasInDateCaches); 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![_entriesByURL count]) 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PageGroup::removeAllVisitedLinks(); 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addItemToDateCaches:(WebHistoryItem *)entry 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryDateKey dateKey; 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]]) 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // other entries already exist for this date 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self insertItem:entry forDateKey:dateKey]; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // no other entries exist for this date 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *entries = [[NSMutableArray alloc] initWithObjects:&entry count:1]; 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _entriesByDate->set(dateKey, entries); 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entries release]; 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Clear _orderedLastVisitedDays so it will be regenerated when next requested. 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_orderedLastVisitedDays release]; 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _orderedLastVisitedDays = nil; 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (WebHistoryItem *)visitedURL:(NSURL *)url withTitle:(NSString *)title increaseVisitCount:(BOOL)increaseVisitCount 288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(url); 290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(title); 291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project NSString *URLString = [url _web_originalDataAsString]; 293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project WebHistoryItem *entry = [_entriesByURL objectForKey:URLString]; 294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (entry) { 296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project LOG(History, "Updating global history entry %@", entry); 297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Remove the item from date caches before changing its last visited date. Otherwise we might get duplicate entries 298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // as seen in <rdar://problem/6570573>. 299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project BOOL itemWasInDateCaches = [self removeItemFromDateCaches:entry]; 300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT_UNUSED(itemWasInDateCaches, itemWasInDateCaches); 301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch [entry _visitedWithTitle:title increaseVisitCount:increaseVisitCount]; 303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project LOG(History, "Adding new global history entry for %@", url); 305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project entry = [[WebHistoryItem alloc] initWithURLString:URLString title:title lastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate]]; 306635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [entry _recordInitialVisit]; 307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [_entriesByURL setObject:entry forKey:URLString]; 308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [entry release]; 309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [self addItemToDateCaches:entry]; 312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return entry; 314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (BOOL)addItem:(WebHistoryItem *)entry discardDuplicate:(BOOL)discardDuplicate 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT_ARG(entry, entry); 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT_ARG(entry, [entry lastVisitedTimeInterval] != 0); 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *URLString = [entry URLString]; 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryItem *oldEntry = [_entriesByURL objectForKey:URLString]; 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (oldEntry) { 325635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (discardDuplicate) 326635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return NO; 327635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The last reference to oldEntry might be this dictionary, so we hold onto a reference 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // until we're done with oldEntry. 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [oldEntry retain]; 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self removeItemForURLString:URLString]; 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we already have an item with this URL, we need to merge info that drives the 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // URL autocomplete heuristics from that item into the new one. 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [entry _mergeAutoCompleteHints:oldEntry]; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [oldEntry release]; 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self addItemToDateCaches:entry]; 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_entriesByURL setObject:entry forKey:URLString]; 341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return YES; 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItem:(WebHistoryItem *)entry 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *URLString = [entry URLString]; 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If this exact object isn't stored, then make no change. 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Is this the right behavior if this entry isn't present, but another entry for the same URL is? 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Maybe need to change the API to make something like removeEntryForURLString public instead. 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryItem *matchingEntry = [_entriesByURL objectForKey:URLString]; 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (matchingEntry != entry) 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self removeItemForURLString:URLString]; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeItems:(NSArray *)entries 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSUInteger count = [entries count]; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!count) 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (NSUInteger index = 0; index < count; ++index) 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self removeItem:[entries objectAtIndex:index]]; 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)removeAllItems 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (_entriesByDate->isEmpty()) 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _entriesByDate->clear(); 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_entriesByURL removeAllObjects]; 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Clear _orderedLastVisitedDays so it will be regenerated when next requested. 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_orderedLastVisitedDays release]; 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _orderedLastVisitedDays = nil; 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PageGroup::removeAllVisitedLinks(); 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addItems:(NSArray *)newEntries 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There is no guarantee that the incoming entries are in any particular 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // order, but if this is called with a set of entries that were created by 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // iterating through the results of orderedLastVisitedDays and orderedItemsLastVisitedOnDayy 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // then they will be ordered chronologically from newest to oldest. We can make adding them 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // faster (fewer compares) by inserting them from oldest to newest. 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSEnumerator *enumerator = [newEntries reverseObjectEnumerator]; 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (WebHistoryItem *entry = [enumerator nextObject]) 399635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [self addItem:entry discardDuplicate:NO]; 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 402cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: DATE-BASED RETRIEVAL 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedLastVisitedDays 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!_orderedLastVisitedDays) { 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<int> daysAsTimeIntervals; 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project daysAsTimeIntervals.reserveCapacity(_entriesByDate->size()); 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DateToEntriesMap::const_iterator end = _entriesByDate->end(); 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (DateToEntriesMap::const_iterator it = _entriesByDate->begin(); it != end; ++it) 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project daysAsTimeIntervals.append(it->first); 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch sort(daysAsTimeIntervals.begin(), daysAsTimeIntervals.end()); 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t count = daysAsTimeIntervals.size(); 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _orderedLastVisitedDays = [[NSMutableArray alloc] initWithCapacity:count]; 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSTimeInterval interval = daysAsTimeIntervals[i]; 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSCalendarDate *date = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:interval]; 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_orderedLastVisitedDays addObject:date]; 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [date release]; 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return _orderedLastVisitedDays; 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)date 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryDateKey dateKey; 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![self findKey:&dateKey forDay:[date timeIntervalSinceReferenceDate]]) 4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return nil; 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return _entriesByDate->get(dateKey).get(); 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 434cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: URL MATCHING 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)itemForURLString:(NSString *)URLString 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_entriesByURL objectForKey:URLString]; 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)containsURL:(NSURL *)URL 4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [self itemForURLString:[URL _web_originalDataAsString]] != nil; 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)itemForURL:(NSURL *)URL 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [self itemForURLString:[URL _web_originalDataAsString]]; 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 451635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (NSArray *)allItems 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 453635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return [_entriesByURL allValues]; 454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 456cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: ARCHIVING/UNARCHIVING 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryAgeInDaysLimit:(int)limit 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ageInDaysLimitSet = YES; 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ageInDaysLimit = limit; 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyAgeInDaysLimit 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ageInDaysLimitSet) 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ageInDaysLimit; 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitHistoryAgeInDaysLimit"]; 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryItemLimit:(int)limit 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project itemLimitSet = YES; 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project itemLimit = limit; 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyItemLimit 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (itemLimitSet) 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return itemLimit; 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitHistoryItemLimit"]; 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Return a date that marks the age limit for history entries saved to or 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// loaded from disk. Any entry older than this item should be rejected. 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSCalendarDate *)ageLimitDate 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [[NSCalendarDate calendarDate] dateByAddingYears:0 months:0 days:-[self historyAgeInDaysLimit] 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project hours:0 minutes:0 seconds:0]; 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)loadHistoryGutsFromURL:(NSURL *)URL savedItemsCount:(int *)numberOfItemsLoaded collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *numberOfItemsLoaded = 0; 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSDictionary *dictionary = nil; 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Optimize loading from local file, which is faster than using the general URL loading mechanism 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([URL isFileURL]) { 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dictionary = [NSDictionary dictionaryWithContentsOfFile:[URL path]]; 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!dictionary) { 5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([[NSFileManager defaultManager] fileExistsAtPath:[URL path]]) 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("unable to read history from file %@; perhaps contents are corrupted", [URL path]); 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // else file doesn't exist, which is normal the first time 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:URL] returningResponse:nil error:error]; 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (data && [data length] > 0) { 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project dictionary = [NSPropertyListSerialization propertyListFromData:data 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mutabilityOption:NSPropertyListImmutable 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project format:nil 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project errorDescription:nil]; 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We used to support NSArrays here, but that was before Safari 1.0 shipped. We will no longer support 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // that ancient format, so anything that isn't an NSDictionary is bogus. 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![dictionary isKindOfClass:[NSDictionary class]]) 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSNumber *fileVersionObject = [dictionary objectForKey:FileVersionKey]; 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fileVersion; 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // we don't trust data obtained from elsewhere, so double-check 5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!fileVersionObject || ![fileVersionObject isKindOfClass:[NSNumber class]]) { 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("history file version can't be determined, therefore not loading"); 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fileVersion = [fileVersionObject intValue]; 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (fileVersion > currentFileVersion) { 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("history file version is %d, newer than newest known version %d, therefore not loading", fileVersion, currentFileVersion); 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSArray *array = [dictionary objectForKey:DatesArrayKey]; 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int itemCountLimit = [self historyItemLimit]; 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSTimeInterval ageLimitDate = [[self ageLimitDate] timeIntervalSinceReferenceDate]; 5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSEnumerator *enumerator = [array objectEnumerator]; 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL ageLimitPassed = NO; 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project BOOL itemLimitPassed = NO; 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(*numberOfItemsLoaded == 0); 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSDictionary *itemAsDictionary; 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while ((itemAsDictionary = [enumerator nextObject]) != nil) { 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebHistoryItem *item = [[WebHistoryItem alloc] initFromDictionaryRepresentation:itemAsDictionary]; 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // item without URL is useless; data on disk must have been bad; ignore 5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([item URLString]) { 5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Test against date limit. Since the items are ordered newest to oldest, we can stop comparing 5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // once we've found the first item that's too old. 5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!ageLimitPassed && [item lastVisitedTimeInterval] <= ageLimitDate) 5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ageLimitPassed = YES; 5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ageLimitPassed || itemLimitPassed) 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [discardedItems addObject:item]; 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 560635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if ([self addItem:item discardDuplicate:YES]) 561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ++(*numberOfItemsLoaded); 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (*numberOfItemsLoaded == itemCountLimit) 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project itemLimitPassed = YES; 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Draining the autorelease pool every 50 iterations was found by experimentation to be optimal 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (*numberOfItemsLoaded % 50 == 0) { 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [pool drain]; 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pool = [[NSAutoreleasePool alloc] init]; 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [item release]; 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [pool drain]; 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project double start = CFAbsoluteTimeGetCurrent(); 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int numberOfItems; 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![self loadHistoryGutsFromURL:URL savedItemsCount:&numberOfItems collectDiscardedItemsInto:discardedItems error:error]) 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project double duration = CFAbsoluteTimeGetCurrent() - start; 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG(Timing, "loading %d history entries from %@ took %f seconds", numberOfItems, URL, duration); 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (NSData *)data 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (_entriesByDate->isEmpty()) { 6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch static NSData *emptyHistoryData = (NSData *)CFDataCreate(0, 0, 0); 6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return emptyHistoryData; 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Ignores the date and item count limits; these are respected when loading instead of when saving, so 6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // that clients can learn of discarded items by listening to WebHistoryItemsDiscardedWhileLoadingNotification. 6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch WebHistoryWriter writer(_entriesByDate); 6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch writer.writePropertyList(); 6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return [[(NSData *)writer.releaseData().get() retain] autorelease]; 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error 6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project double start = CFAbsoluteTimeGetCurrent(); 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch BOOL result = [[self data] writeToURL:URL options:0 error:error]; 6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED 6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project double duration = CFAbsoluteTimeGetCurrent() - start; 6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch LOG(Timing, "saving history to %@ took %f seconds", URL, duration); 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return result; 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addVisitedLinksToPageGroup:(PageGroup&)group 6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSEnumerator *enumerator = [_entriesByURL keyEnumerator]; 6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (NSString *url = [enumerator nextObject]) { 6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t length = [url length]; 6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url)); 6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (characters) 6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project group.addVisitedLink(characters, length); 6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar, 512> buffer(length); 6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [url getCharacters:buffer.data()]; 6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project group.addVisitedLink(buffer.data(), length); 6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebHistory 6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (WebHistory *)optionalSharedHistory 6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return _sharedHistory; 6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)setOptionalSharedHistory:(WebHistory *)history 6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (_sharedHistory == history) 6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Need to think about multiple instances of WebHistory per application 6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // and correct synchronization of history file between applications. 6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_sharedHistory release]; 6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _sharedHistory = [history retain]; 6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PageGroup::setShouldTrackVisitedLinks(history); 6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PageGroup::removeAllVisitedLinks(); 6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (id)init 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project self = [super init]; 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!self) 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return nil; 6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project _historyPrivate = [[WebHistoryPrivate alloc] init]; 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)dealloc 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_historyPrivate release]; 6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [super dealloc]; 6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 679cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: MODIFYING CONTENTS 6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_sendNotification:(NSString *)name entries:(NSArray *)entries 6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:entries, WebHistoryItemsKey, nil]; 6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [[NSNotificationCenter defaultCenter] 6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project postNotificationName:name object:self userInfo:userInfo]; 6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)removeItems:(NSArray *)entries 6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([_historyPrivate removeItems:entries]) { 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self _sendNotification:WebHistoryItemsRemovedNotification 6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project entries:entries]; 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)removeAllItems 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 698635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project NSArray *entries = [_historyPrivate allItems]; 699635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if ([_historyPrivate removeAllItems]) 700635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [self _sendNotification:WebHistoryAllItemsRemovedNotification entries:entries]; 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)addItems:(NSArray *)newEntries 7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_historyPrivate addItems:newEntries]; 7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self _sendNotification:WebHistoryItemsAddedNotification 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project entries:newEntries]; 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 710cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: DATE-BASED RETRIEVAL 7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedLastVisitedDays 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate orderedLastVisitedDays]; 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)date 7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate orderedItemsLastVisitedOnDay:date]; 7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 722cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: URL MATCHING 7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)containsURL:(NSURL *)URL 7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate containsURL:URL]; 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)itemForURL:(NSURL *)URL 7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate itemForURL:URL]; 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 734cad810f21b803229eb11403f9209855525a25d57Steve Block// MARK: SAVING TO DISK 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)loadFromURL:(NSURL *)URL error:(NSError **)error 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *discardedItems = [[NSMutableArray alloc] init]; 7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![_historyPrivate loadFromURL:URL collectDiscardedItemsInto:discardedItems error:error]) { 7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [discardedItems release]; 7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [[NSNotificationCenter defaultCenter] 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project postNotificationName:WebHistoryLoadedNotification 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project object:self]; 7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([discardedItems count]) 7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self _sendNotification:WebHistoryItemsDiscardedWhileLoadingNotification entries:discardedItems]; 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [discardedItems release]; 7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![_historyPrivate saveToURL:URL error:error]) 7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [[NSNotificationCenter defaultCenter] 7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project postNotificationName:WebHistorySavedNotification 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project object:self]; 7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryItemLimit:(int)limit 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_historyPrivate setHistoryItemLimit:limit]; 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyItemLimit 7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate historyItemLimit]; 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setHistoryAgeInDaysLimit:(int)limit 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_historyPrivate setHistoryAgeInDaysLimit:limit]; 7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (int)historyAgeInDaysLimit 7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate historyAgeInDaysLimit]; 7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebHistory (WebPrivate) 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (WebHistoryItem *)_itemForURLString:(NSString *)URLString 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [_historyPrivate itemForURLString:URLString]; 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 794635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (NSArray *)allItems 795635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 796635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return [_historyPrivate allItems]; 797635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 798635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 7990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (NSData *)_data 8000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 8010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return [_historyPrivate data]; 8020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 8030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 804cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block+ (void)_setVisitedLinkTrackingEnabled:(BOOL)visitedLinkTrackingEnabled 805cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 806cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block PageGroup::setShouldTrackVisitedLinks(visitedLinkTrackingEnabled); 807cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 808cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 809cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block+ (void)_removeAllVisitedLinks 810cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 811cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block PageGroup::removeAllVisitedLinks(); 812cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 813cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebHistory (WebInternal) 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch- (void)_visitedURL:(NSURL *)url withTitle:(NSString *)title method:(NSString *)method wasFailure:(BOOL)wasFailure increaseVisitCount:(BOOL)increaseVisitCount 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch WebHistoryItem *entry = [_historyPrivate visitedURL:url withTitle:title increaseVisitCount:increaseVisitCount]; 821635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 822635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HistoryItem* item = core(entry); 823635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project item->setLastVisitWasFailure(wasFailure); 824635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 825635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if ([method length]) 826563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark item->setLastVisitWasHTTPNonGet([method caseInsensitiveCompare:@"GET"] && (![[url scheme] caseInsensitiveCompare:@"http"] || ![[url scheme] caseInsensitiveCompare:@"https"])); 827635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 8280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch item->setRedirectURLs(0); 829635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 830635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project NSArray *entries = [[NSArray alloc] initWithObjects:entry, nil]; 831635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [self _sendNotification:WebHistoryItemsAddedNotification entries:entries]; 832635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project [entries release]; 833635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 834635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_addVisitedLinksToPageGroup:(WebCore::PageGroup&)group 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [_historyPrivate addVisitedLinksToPageGroup:group]; 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochWebHistoryWriter::WebHistoryWriter(DateToEntriesMap* entriesByDate) 8430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_entriesByDate(entriesByDate) 8440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 8450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_dateKeys.reserveCapacity(m_entriesByDate->size()); 8460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch DateToEntriesMap::const_iterator end = m_entriesByDate->end(); 8470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (DateToEntriesMap::const_iterator it = m_entriesByDate->begin(); it != end; ++it) 8480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_dateKeys.append(it->first); 8490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch sort(m_dateKeys.begin(), m_dateKeys.end()); 8500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 8510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid WebHistoryWriter::writeHistoryItems(BinaryPropertyListObjectStream& stream) 8530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 8540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (int dateIndex = m_dateKeys.size() - 1; dateIndex >= 0; dateIndex--) { 8550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NSArray *entries = m_entriesByDate->get(m_dateKeys[dateIndex]).get(); 8560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NSUInteger entryCount = [entries count]; 8570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (NSUInteger entryIndex = 0; entryIndex < entryCount; ++entryIndex) 8580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch writeHistoryItem(stream, core([entries objectAtIndex:entryIndex])); 8590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 8600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 861