📄 webhistoryitem.cpp
字号:
/* * Copyright (C) 2006, 2007, 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. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR * 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. */#include "config.h"#include "WebKitDLL.h"#include "WebHistoryItem.h"#include "COMEnumVariant.h"#include "COMPtr.h"#include "MarshallingHelpers.h"#include "WebKit.h"#pragma warning(push, 0)#include <WebCore/BString.h>#include <WebCore/CString.h>#include <WebCore/HistoryItem.h>#include <WebCore/KURL.h>#pragma warning(pop)#include <wtf/RetainPtr.h>using namespace WebCore;// WebHistoryItem ----------------------------------------------------------------static HashMap<HistoryItem*, WebHistoryItem*>& historyItemWrappers(){ static HashMap<HistoryItem*, WebHistoryItem*> staticHistoryItemWrappers; return staticHistoryItemWrappers;}WebHistoryItem::WebHistoryItem(PassRefPtr<HistoryItem> historyItem): m_refCount(0), m_historyItem(historyItem){ ASSERT(!historyItemWrappers().contains(m_historyItem.get())); historyItemWrappers().set(m_historyItem.get(), this); gClassCount++; gClassNameCount.add("WebHistoryItem");}WebHistoryItem::~WebHistoryItem(){ ASSERT(historyItemWrappers().contains(m_historyItem.get())); historyItemWrappers().remove(m_historyItem.get()); gClassCount--; gClassNameCount.remove("WebHistoryItem");}WebHistoryItem* WebHistoryItem::createInstance(){ WebHistoryItem* instance = new WebHistoryItem(HistoryItem::create()); instance->AddRef(); return instance;}WebHistoryItem* WebHistoryItem::createInstance(PassRefPtr<HistoryItem> historyItem){ WebHistoryItem* instance; instance = historyItemWrappers().get(historyItem.get()); if (!instance) instance = new WebHistoryItem(historyItem); instance->AddRef(); return instance;}// IWebHistoryItemPrivate -----------------------------------------------------static CFStringRef urlKey = CFSTR("");static CFStringRef lastVisitedDateKey = CFSTR("lastVisitedDate");static CFStringRef titleKey = CFSTR("title");static CFStringRef visitCountKey = CFSTR("visitCount");static CFStringRef lastVisitWasFailureKey = CFSTR("lastVisitWasFailure");static CFStringRef lastVisitWasHTTPNonGetKey = CFSTR("lastVisitWasHTTPNonGet");static CFStringRef redirectURLsKey = CFSTR("redirectURLs");static CFStringRef dailyVisitCountKey = CFSTR("D"); // short key to save spacestatic CFStringRef weeklyVisitCountKey = CFSTR("W"); // short key to save spaceHRESULT STDMETHODCALLTYPE WebHistoryItem::initFromDictionaryRepresentation(void* dictionary){ CFDictionaryRef dictionaryRef = (CFDictionaryRef) dictionary; CFStringRef urlStringRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, urlKey); if (urlStringRef && CFGetTypeID(urlStringRef) != CFStringGetTypeID()) return E_FAIL; CFStringRef lastVisitedRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, lastVisitedDateKey); if (!lastVisitedRef || CFGetTypeID(lastVisitedRef) != CFStringGetTypeID()) return E_FAIL; CFAbsoluteTime lastVisitedTime = CFStringGetDoubleValue(lastVisitedRef); CFStringRef titleRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, titleKey); if (titleRef && CFGetTypeID(titleRef) != CFStringGetTypeID()) return E_FAIL; CFNumberRef visitCountRef = (CFNumberRef) CFDictionaryGetValue(dictionaryRef, visitCountKey); if (!visitCountRef || CFGetTypeID(visitCountRef) != CFNumberGetTypeID()) return E_FAIL; int visitedCount = 0; if (!CFNumberGetValue(visitCountRef, kCFNumberIntType, &visitedCount)) return E_FAIL; // Can't trust data on disk, and we've had at least one report of this (<rdar://6572300>). if (visitedCount < 0) { LOG_ERROR("visit count for history item \"%s\" is negative (%d), will be reset to 1", String(urlStringRef).utf8().data(), visitedCount); visitedCount = 1; } CFBooleanRef lastVisitWasFailureRef = static_cast<CFBooleanRef>(CFDictionaryGetValue(dictionaryRef, lastVisitWasFailureKey)); if (lastVisitWasFailureRef && CFGetTypeID(lastVisitWasFailureRef) != CFBooleanGetTypeID()) return E_FAIL; bool lastVisitWasFailure = lastVisitWasFailureRef && CFBooleanGetValue(lastVisitWasFailureRef); CFBooleanRef lastVisitWasHTTPNonGetRef = static_cast<CFBooleanRef>(CFDictionaryGetValue(dictionaryRef, lastVisitWasHTTPNonGetKey)); if (lastVisitWasHTTPNonGetRef && CFGetTypeID(lastVisitWasHTTPNonGetRef) != CFBooleanGetTypeID()) return E_FAIL; bool lastVisitWasHTTPNonGet = lastVisitWasHTTPNonGetRef && CFBooleanGetValue(lastVisitWasHTTPNonGetRef); std::auto_ptr<Vector<String> > redirectURLsVector; if (CFArrayRef redirectURLsRef = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, redirectURLsKey))) { CFIndex size = CFArrayGetCount(redirectURLsRef); redirectURLsVector.reset(new Vector<String>(size)); for (CFIndex i = 0; i < size; ++i) (*redirectURLsVector)[i] = String(static_cast<CFStringRef>(CFArrayGetValueAtIndex(redirectURLsRef, i))); } CFArrayRef dailyCounts = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, dailyVisitCountKey)); if (dailyCounts && CFGetTypeID(dailyCounts) != CFArrayGetTypeID()) dailyCounts = 0; CFArrayRef weeklyCounts = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, weeklyVisitCountKey)); if (weeklyCounts && CFGetTypeID(weeklyCounts) != CFArrayGetTypeID()) weeklyCounts = 0; std::auto_ptr<Vector<int> > dailyVector, weeklyVector; if (dailyCounts || weeklyCounts) { CFIndex dailySize = dailyCounts ? CFArrayGetCount(dailyCounts) : 0; CFIndex weeklySize = weeklyCounts ? CFArrayGetCount(weeklyCounts) : 0; dailyVector.reset(new Vector<int>(dailySize)); weeklyVector.reset(new Vector<int>(weeklySize)); // Daily and weekly counts < 0 are errors in the data read from disk, so reset to 0. for (CFIndex i = 0; i < dailySize; ++i) { CFNumberRef dailyCount = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(dailyCounts, i)); if (CFGetTypeID(dailyCount) == CFNumberGetTypeID()) CFNumberGetValue(dailyCount, kCFNumberIntType, &(*dailyVector)[i]); if ((*dailyVector)[i] < 0) (*dailyVector)[i] = 0; } for (CFIndex i = 0; i < weeklySize; ++i) { CFNumberRef weeklyCount = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(weeklyCounts, i)); if (CFGetTypeID(weeklyCount) == CFNumberGetTypeID()) CFNumberGetValue(weeklyCount, kCFNumberIntType, &(*weeklyVector)[i]); if ((*weeklyVector)[i] < 0) (*weeklyVector)[i] = 0; } } historyItemWrappers().remove(m_historyItem.get()); m_historyItem = HistoryItem::create(urlStringRef, titleRef, lastVisitedTime); historyItemWrappers().set(m_historyItem.get(), this); m_historyItem->setVisitCount(visitedCount); if (lastVisitWasFailure) m_historyItem->setLastVisitWasFailure(true); if (lastVisitWasHTTPNonGet && (protocolIs(m_historyItem->urlString(), "http") || protocolIs(m_historyItem->urlString(), "https"))) m_historyItem->setLastVisitWasHTTPNonGet(true); if (redirectURLsVector.get()) m_historyItem->setRedirectURLs(redirectURLsVector); if (dailyVector.get()) m_historyItem->adoptVisitCounts(*dailyVector, *weeklyVector); return S_OK;}HRESULT STDMETHODCALLTYPE WebHistoryItem::dictionaryRepresentation(void** dictionary){ CFDictionaryRef* dictionaryRef = (CFDictionaryRef*) dictionary; static CFStringRef lastVisitedFormat = CFSTR("%.1lf"); CFStringRef lastVisitedStringRef = CFStringCreateWithFormat(0, 0, lastVisitedFormat, m_historyItem->lastVisitedTime()); if (!lastVisitedStringRef) return E_FAIL; int keyCount = 0; CFTypeRef keys[9]; CFTypeRef values[9]; if (!m_historyItem->urlString().isEmpty()) { keys[keyCount] = urlKey; values[keyCount++] = m_historyItem->urlString().createCFString(); } keys[keyCount] = lastVisitedDateKey; values[keyCount++] = lastVisitedStringRef; if (!m_historyItem->title().isEmpty()) { keys[keyCount] = titleKey; values[keyCount++] = m_historyItem->title().createCFString(); } keys[keyCount] = visitCountKey; int visitCount = m_historyItem->visitCount(); values[keyCount++] = CFNumberCreate(0, kCFNumberIntType, &visitCount); if (m_historyItem->lastVisitWasFailure()) { keys[keyCount] = lastVisitWasFailureKey; values[keyCount++] = CFRetain(kCFBooleanTrue); } if (m_historyItem->lastVisitWasHTTPNonGet()) { ASSERT(m_historyItem->urlString().startsWith("http:", false) || m_historyItem->urlString().startsWith("https:", false)); keys[keyCount] = lastVisitWasHTTPNonGetKey; values[keyCount++] = CFRetain(kCFBooleanTrue); } if (Vector<String>* redirectURLs = m_historyItem->redirectURLs()) { size_t size = redirectURLs->size(); ASSERT(size); CFStringRef* items = new CFStringRef[size]; for (size_t i = 0; i < size; ++i) items[i] = redirectURLs->at(i).createCFString(); CFArrayRef result = CFArrayCreate(0, (const void**)items, size, &kCFTypeArrayCallBacks); for (size_t i = 0; i < size; ++i) CFRelease(items[i]); delete[] items; keys[keyCount] = redirectURLsKey; values[keyCount++] = result; } const Vector<int>& dailyVisitCount(m_historyItem->dailyVisitCounts()); if (size_t size = dailyVisitCount.size()) { Vector<CFNumberRef, 13> numbers(size); for (size_t i = 0; i < size; ++i) numbers[i] = CFNumberCreate(0, kCFNumberIntType, &dailyVisitCount[i]); CFArrayRef result = CFArrayCreate(0, (const void**)numbers.data(), size, &kCFTypeArrayCallBacks); for (size_t i = 0; i < size; ++i) CFRelease(numbers[i]); keys[keyCount] = dailyVisitCountKey; values[keyCount++] = result; } const Vector<int>& weeklyVisitCount(m_historyItem->weeklyVisitCounts()); if (size_t size = weeklyVisitCount.size()) { Vector<CFNumberRef, 5> numbers(size); for (size_t i = 0; i < size; ++i) numbers[i] = CFNumberCreate(0, kCFNumberIntType, &weeklyVisitCount[i]); CFArrayRef result = CFArrayCreate(0, (const void**)numbers.data(), size, &kCFTypeArrayCallBacks); for (size_t i = 0; i < size; ++i) CFRelease(numbers[i]); keys[keyCount] = weeklyVisitCountKey; values[keyCount++] = result; } *dictionaryRef = CFDictionaryCreate(0, keys, values, keyCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for (int i = 0; i < keyCount; ++i) CFRelease(values[i]); return S_OK;}HRESULT STDMETHODCALLTYPE WebHistoryItem::hasURLString(BOOL *hasURL){ *hasURL = m_historyItem->urlString().isEmpty() ? FALSE : TRUE; return S_OK;}HRESULT STDMETHODCALLTYPE WebHistoryItem::visitCount(int *count){ *count = m_historyItem->visitCount(); return S_OK;}HRESULT STDMETHODCALLTYPE WebHistoryItem::setVisitCount(int count){ m_historyItem->setVisitCount(count); return S_OK;}HRESULT STDMETHODCALLTYPE WebHistoryItem::mergeAutoCompleteHints(IWebHistoryItem* otherItem){ if (!otherItem) return E_FAIL; COMPtr<WebHistoryItem> otherWebHistoryItem(Query, otherItem); if (!otherWebHistoryItem) return E_FAIL; m_historyItem->mergeAutoCompleteHints(otherWebHistoryItem->historyItem());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -