⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 webhistory.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2005, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1.  Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer.  * 2.  Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution.  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of *     its contributors may be used to endorse or promote products derived *     from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#import "WebHistoryInternal.h"#import "WebHistoryItemInternal.h"#import "WebKitLogging.h"#import "WebNSURLExtras.h"#import "WebTypesInternal.h"#import <WebCore/HistoryItem.h>#import <WebCore/PageGroup.h>using namespace WebCore;typedef int64_t WebHistoryDateKey;typedef HashMap<WebHistoryDateKey, RetainPtr<NSMutableArray> > DateToEntriesMap;NSString *WebHistoryItemsAddedNotification = @"WebHistoryItemsAddedNotification";NSString *WebHistoryItemsRemovedNotification = @"WebHistoryItemsRemovedNotification";NSString *WebHistoryAllItemsRemovedNotification = @"WebHistoryAllItemsRemovedNotification";NSString *WebHistoryLoadedNotification = @"WebHistoryLoadedNotification";NSString *WebHistoryItemsDiscardedWhileLoadingNotification = @"WebHistoryItemsDiscardedWhileLoadingNotification";NSString *WebHistorySavedNotification = @"WebHistorySavedNotification";NSString *WebHistoryItemsKey = @"WebHistoryItems";static WebHistory *_sharedHistory = nil;NSString *FileVersionKey = @"WebHistoryFileVersion";NSString *DatesArrayKey = @"WebHistoryDates";#define currentFileVersion 1@interface WebHistoryPrivate : NSObject {@private    NSMutableDictionary *_entriesByURL;    DateToEntriesMap* _entriesByDate;    NSMutableArray *_orderedLastVisitedDays;    BOOL itemLimitSet;    int itemLimit;    BOOL ageInDaysLimitSet;    int ageInDaysLimit;}- (WebHistoryItem *)visitedURL:(NSURL *)url withTitle:(NSString *)title;- (BOOL)addItem:(WebHistoryItem *)entry discardDuplicate:(BOOL)discardDuplicate;- (void)addItems:(NSArray *)newEntries;- (BOOL)removeItem:(WebHistoryItem *)entry;- (BOOL)removeItems:(NSArray *)entries;- (BOOL)removeAllItems;- (NSArray *)orderedLastVisitedDays;- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)calendarDate;- (BOOL)containsURL:(NSURL *)URL;- (WebHistoryItem *)itemForURL:(NSURL *)URL;- (WebHistoryItem *)itemForURLString:(NSString *)URLString;- (NSArray *)allItems;- (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error;- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error;- (NSCalendarDate *)ageLimitDate;- (void)setHistoryItemLimit:(int)limit;- (int)historyItemLimit;- (void)setHistoryAgeInDaysLimit:(int)limit;- (int)historyAgeInDaysLimit;- (void)addVisitedLinksToPageGroup:(PageGroup&)group;@end@implementation WebHistoryPrivate#pragma mark OBJECT FRAMEWORK+ (void)initialize{    [[NSUserDefaults standardUserDefaults] registerDefaults:        [NSDictionary dictionaryWithObjectsAndKeys:            @"1000", @"WebKitHistoryItemLimit",            @"7", @"WebKitHistoryAgeInDaysLimit",            nil]];    }- (id)init{    if (![super init])        return nil;        _entriesByURL = [[NSMutableDictionary alloc] init];    _entriesByDate = new DateToEntriesMap;    return self;}- (void)dealloc{    [_entriesByURL release];    [_orderedLastVisitedDays release];    delete _entriesByDate;    [super dealloc];}- (void)finalize{    delete _entriesByDate;    [super finalize];}#pragma mark MODIFYING CONTENTSstatic WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval){    CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();    CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(interval, timeZone);    date.hour = 0;    date.minute = 0;    date.second = 0;    NSTimeInterval result = CFGregorianDateGetAbsoluteTime(date, timeZone);    CFRelease(timeZone);    // Converting from double to int64_t is safe here as NSDate's useful range    // is -2**48 .. 2**47 which will safely fit in an int64_t.    return (WebHistoryDateKey)result;}// Returns whether the day is already in the list of days,// and fills in *key with the key used to access its location- (BOOL)findKey:(WebHistoryDateKey*)key forDay:(NSTimeInterval)date{    ASSERT_ARG(key, key != nil);    *key = timeIntervalForBeginningOfDay(date);    return _entriesByDate->contains(*key);}- (void)insertItem:(WebHistoryItem *)entry forDateKey:(WebHistoryDateKey)dateKey{    ASSERT_ARG(entry, entry != nil);    ASSERT(_entriesByDate->contains(dateKey));    NSMutableArray *entriesForDate = _entriesByDate->get(dateKey).get();    NSTimeInterval entryDate = [entry lastVisitedTimeInterval];    unsigned count = [entriesForDate count];    // The entries for each day are stored in a sorted array with the most recent entry first    // Check for the common cases of the entry being newer than all existing entries or the first entry of the day    if (!count || [[entriesForDate objectAtIndex:0] lastVisitedTimeInterval] < entryDate) {        [entriesForDate insertObject:entry atIndex:0];        return;    }    // .. or older than all existing entries    if (count > 0 && [[entriesForDate objectAtIndex:count - 1] lastVisitedTimeInterval] >= entryDate) {        [entriesForDate insertObject:entry atIndex:count];        return;    }    unsigned low = 0;    unsigned high = count;    while (low < high) {        unsigned mid = low + (high - low) / 2;        if ([[entriesForDate objectAtIndex:mid] lastVisitedTimeInterval] >= entryDate)            low = mid + 1;        else            high = mid;    }    // low is now the index of the first entry that is older than entryDate    [entriesForDate insertObject:entry atIndex:low];}- (BOOL)removeItemFromDateCaches:(WebHistoryItem *)entry{    WebHistoryDateKey dateKey;    BOOL foundDate = [self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]];     if (!foundDate)        return NO;    DateToEntriesMap::iterator it = _entriesByDate->find(dateKey);    NSMutableArray *entriesForDate = it->second.get();    [entriesForDate removeObjectIdenticalTo:entry];        // remove this date entirely if there are no other entries on it    if ([entriesForDate count] == 0) {        _entriesByDate->remove(it);        // Clear _orderedLastVisitedDays so it will be regenerated when next requested.        [_orderedLastVisitedDays release];        _orderedLastVisitedDays = nil;    }        return YES;}- (BOOL)removeItemForURLString:(NSString *)URLString{    WebHistoryItem *entry = [_entriesByURL objectForKey:URLString];    if (!entry)        return NO;    [_entriesByURL removeObjectForKey:URLString];    #if ASSERT_DISABLED    [self removeItemFromDateCaches:entry];#else    BOOL itemWasInDateCaches = [self removeItemFromDateCaches:entry];    ASSERT(itemWasInDateCaches);#endif    if (![_entriesByURL count])        PageGroup::removeAllVisitedLinks();    return YES;}- (void)addItemToDateCaches:(WebHistoryItem *)entry{    WebHistoryDateKey dateKey;    if ([self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]])        // other entries already exist for this date        [self insertItem:entry forDateKey:dateKey];    else {        // no other entries exist for this date        NSMutableArray *entries = [[NSMutableArray alloc] initWithObjects:&entry count:1];        _entriesByDate->set(dateKey, entries);        [entries release];        // Clear _orderedLastVisitedDays so it will be regenerated when next requested.        [_orderedLastVisitedDays release];        _orderedLastVisitedDays = nil;    }}- (WebHistoryItem *)visitedURL:(NSURL *)url withTitle:(NSString *)title{    ASSERT(url);    ASSERT(title);        NSString *URLString = [url _web_originalDataAsString];    WebHistoryItem *entry = [_entriesByURL objectForKey:URLString];    if (entry) {        LOG(History, "Updating global history entry %@", entry);        // Remove the item from date caches before changing its last visited date.  Otherwise we might get duplicate entries        // as seen in <rdar://problem/6570573>.        BOOL itemWasInDateCaches = [self removeItemFromDateCaches:entry];        ASSERT_UNUSED(itemWasInDateCaches, itemWasInDateCaches);        [entry _visitedWithTitle:title];    } else {        LOG(History, "Adding new global history entry for %@", url);        entry = [[WebHistoryItem alloc] initWithURLString:URLString title:title lastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate]];        [entry _recordInitialVisit];        [_entriesByURL setObject:entry forKey:URLString];        [entry release];    }        [self addItemToDateCaches:entry];    return entry;}- (BOOL)addItem:(WebHistoryItem *)entry discardDuplicate:(BOOL)discardDuplicate{    ASSERT_ARG(entry, entry);    ASSERT_ARG(entry, [entry lastVisitedTimeInterval] != 0);    NSString *URLString = [entry URLString];    WebHistoryItem *oldEntry = [_entriesByURL objectForKey:URLString];    if (oldEntry) {        if (discardDuplicate)            return NO;        // The last reference to oldEntry might be this dictionary, so we hold onto a reference        // until we're done with oldEntry.        [oldEntry retain];        [self removeItemForURLString:URLString];        // If we already have an item with this URL, we need to merge info that drives the        // URL autocomplete heuristics from that item into the new one.        [entry _mergeAutoCompleteHints:oldEntry];        [oldEntry release];    }    [self addItemToDateCaches:entry];    [_entriesByURL setObject:entry forKey:URLString];        return YES;}- (BOOL)removeItem:(WebHistoryItem *)entry{    NSString *URLString = [entry URLString];    // If this exact object isn't stored, then make no change.    // FIXME: Is this the right behavior if this entry isn't present, but another entry for the same URL is?    // Maybe need to change the API to make something like removeEntryForURLString public instead.    WebHistoryItem *matchingEntry = [_entriesByURL objectForKey:URLString];    if (matchingEntry != entry)        return NO;    [self removeItemForURLString:URLString];    return YES;}- (BOOL)removeItems:(NSArray *)entries{    NSUInteger count = [entries count];    if (!count)        return NO;    for (NSUInteger index = 0; index < count; ++index)        [self removeItem:[entries objectAtIndex:index]];        return YES;}- (BOOL)removeAllItems{    if (_entriesByDate->isEmpty())        return NO;    _entriesByDate->clear();    [_entriesByURL removeAllObjects];    // Clear _orderedLastVisitedDays so it will be regenerated when next requested.    [_orderedLastVisitedDays release];    _orderedLastVisitedDays = nil;    PageGroup::removeAllVisitedLinks();    return YES;}- (void)addItems:(NSArray *)newEntries{    // There is no guarantee that the incoming entries are in any particular    // order, but if this is called with a set of entries that were created by    // iterating through the results of orderedLastVisitedDays and orderedItemsLastVisitedOnDayy    // then they will be ordered chronologically from newest to oldest. We can make adding them    // faster (fewer compares) by inserting them from oldest to newest.    NSEnumerator *enumerator = [newEntries reverseObjectEnumerator];    while (WebHistoryItem *entry = [enumerator nextObject])        [self addItem:entry discardDuplicate:NO];}#pragma mark DATE-BASED RETRIEVAL- (NSArray *)orderedLastVisitedDays{    if (!_orderedLastVisitedDays) {        Vector<int> daysAsTimeIntervals;        daysAsTimeIntervals.reserveCapacity(_entriesByDate->size());        DateToEntriesMap::const_iterator end = _entriesByDate->end();        for (DateToEntriesMap::const_iterator it = _entriesByDate->begin(); it != end; ++it)            daysAsTimeIntervals.append(it->first);        std::sort(daysAsTimeIntervals.begin(), daysAsTimeIntervals.end());        size_t count = daysAsTimeIntervals.size();        _orderedLastVisitedDays = [[NSMutableArray alloc] initWithCapacity:count];        for (int i = count - 1; i >= 0; i--) {            NSTimeInterval interval = daysAsTimeIntervals[i];            NSCalendarDate *date = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:interval];            [_orderedLastVisitedDays addObject:date];            [date release];        }    }    return _orderedLastVisitedDays;}- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)date{    WebHistoryDateKey dateKey;    if (![self findKey:&dateKey forDay:[date timeIntervalSinceReferenceDate]])        return nil;    return _entriesByDate->get(dateKey).get();}#pragma mark URL MATCHING- (WebHistoryItem *)itemForURLString:(NSString *)URLString{    return [_entriesByURL objectForKey:URLString];}- (BOOL)containsURL:(NSURL *)URL{    return [self itemForURLString:[URL _web_originalDataAsString]] != nil;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -