diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKit/win/WebHistoryItem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKit/win/WebHistoryItem.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2006, 2007 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 "COMPtr.h" +#include "MarshallingHelpers.h" +#include "WebKit.h" + +#pragma warning(push, 0) +#include +#include +#pragma warning(pop) + +#include + +using namespace WebCore; + +// WebHistoryItem ---------------------------------------------------------------- + +static HashMap& historyItemWrappers() +{ + static HashMap staticHistoryItemWrappers; + return staticHistoryItemWrappers; +} + +WebHistoryItem::WebHistoryItem(PassRefPtr historyItem) +: m_refCount(0) +, m_historyItem(historyItem) +{ + ASSERT(!historyItemWrappers().contains(m_historyItem.get())); + historyItemWrappers().set(m_historyItem.get(), this); + + gClassCount++; +} + +WebHistoryItem::~WebHistoryItem() +{ + ASSERT(historyItemWrappers().contains(m_historyItem.get())); + historyItemWrappers().remove(m_historyItem.get()); + + gClassCount--; +} + +WebHistoryItem* WebHistoryItem::createInstance() +{ + WebHistoryItem* instance = new WebHistoryItem(new HistoryItem); + instance->AddRef(); + return instance; +} + +WebHistoryItem* WebHistoryItem::createInstance(PassRefPtr 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"); + +HRESULT STDMETHODCALLTYPE WebHistoryItem::initFromDictionaryRepresentation(void* dictionary) +{ + CFDictionaryRef dictionaryRef = (CFDictionaryRef) dictionary; + HRESULT hr = S_OK; + int visitedCount = 0; + CFAbsoluteTime lastVisitedTime = 0.0; + + CFStringRef urlStringRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, urlKey); + if (urlStringRef && CFGetTypeID(urlStringRef) != CFStringGetTypeID()) { + hr = E_FAIL; + goto exit; + } + + CFStringRef lastVisitedRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, lastVisitedDateKey); + if (!lastVisitedRef || CFGetTypeID(lastVisitedRef) != CFStringGetTypeID()) { + hr = E_FAIL; + goto exit; + } + lastVisitedTime = CFStringGetDoubleValue(lastVisitedRef); + + CFStringRef titleRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, titleKey); + if (titleRef && CFGetTypeID(titleRef) != CFStringGetTypeID()) { + hr = E_FAIL; + goto exit; + } + + CFNumberRef visitCountRef = (CFNumberRef) CFDictionaryGetValue(dictionaryRef, visitCountKey); + if (!visitCountRef || CFGetTypeID(visitCountRef) != CFNumberGetTypeID()) { + hr = E_FAIL; + goto exit; + } + + historyItemWrappers().remove(m_historyItem.get()); + m_historyItem = new HistoryItem(urlStringRef, titleRef, lastVisitedTime); + historyItemWrappers().set(m_historyItem.get(), this); + + if (!CFNumberGetValue(visitCountRef, kCFNumberIntType, &visitedCount)) { + hr = E_FAIL; + goto exit; + } + + m_historyItem->setVisitCount(visitedCount); +exit: + return hr; +} + +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[4]; + CFTypeRef values[4]; + 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); + + *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; + + if (otherItem == this) + return S_OK; + + IWebHistoryItemPrivate* otherItemPriv; + HRESULT hr = otherItem->QueryInterface(IID_IWebHistoryItemPrivate, (void**)&otherItemPriv); + if (FAILED(hr)) + return hr; + + int otherVisitCount; + hr = otherItemPriv->visitCount(&otherVisitCount); + otherItemPriv->Release(); + if (FAILED(hr)) + return hr; + + m_historyItem->setVisitCount(otherVisitCount); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::setLastVisitedTimeInterval(DATE time) +{ + m_historyItem->setLastVisitedTime(MarshallingHelpers::DATEToCFAbsoluteTime(time)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::setTitle(BSTR title) +{ + m_historyItem->setTitle(String(title, SysStringLen(title))); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::RSSFeedReferrer(BSTR* url) +{ + BString str(m_historyItem->rssFeedReferrer()); + *url = str.release(); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::setRSSFeedReferrer(BSTR url) +{ + m_historyItem->setRSSFeedReferrer(String(url, SysStringLen(url))); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::hasPageCache(BOOL* /*hasCache*/) +{ + // FIXME - TODO + ASSERT_NOT_REACHED(); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::setHasPageCache(BOOL /*hasCache*/) +{ + // FIXME - TODO + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::target(BSTR* target) +{ + if (!target) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + *target = BString(m_historyItem->target()).release(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::isTargetItem(BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + *result = m_historyItem->isTargetItem() ? TRUE : FALSE; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::children(unsigned* outChildCount, SAFEARRAY** outChildren) +{ + if (!outChildCount || !outChildren) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + *outChildCount = 0; + *outChildren = 0; + + const HistoryItemVector& coreChildren = m_historyItem->children(); + if (coreChildren.isEmpty()) + return S_OK; + size_t childCount = coreChildren.size(); + + SAFEARRAY* children = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast(childCount)); + if (!children) + return E_OUTOFMEMORY; + + for (unsigned i = 0; i < childCount; ++i) { + WebHistoryItem* item = WebHistoryItem::createInstance(coreChildren[i]); + if (!item) { + SafeArrayDestroy(children); + return E_OUTOFMEMORY; + } + + COMPtr unknown; + HRESULT hr = item->QueryInterface(IID_IUnknown, (void**)&unknown); + if (FAILED(hr)) { + SafeArrayDestroy(children); + return hr; + } + + LONG longI = i; + hr = SafeArrayPutElement(children, &longI, unknown.get()); + if (FAILED(hr)) { + SafeArrayDestroy(children); + return hr; + } + } + + *outChildCount = static_cast(childCount); + *outChildren = children; + return S_OK; + +} + +// IUnknown ------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WebHistoryItem::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, CLSID_WebHistoryItem)) + *ppvObject = this; + else if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast(this); + else if (IsEqualGUID(riid, IID_IWebHistoryItem)) + *ppvObject = static_cast(this); + else if (IsEqualGUID(riid, IID_IWebHistoryItemPrivate)) + *ppvObject = static_cast(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE WebHistoryItem::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE WebHistoryItem::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +// IWebHistoryItem ------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WebHistoryItem::initWithURLString( + /* [in] */ BSTR urlString, + /* [in] */ BSTR title, + /* [in] */ DATE lastVisited) +{ + historyItemWrappers().remove(m_historyItem.get()); + m_historyItem = new HistoryItem(String(urlString, SysStringLen(urlString)), String(title, SysStringLen(title)), MarshallingHelpers::DATEToCFAbsoluteTime(lastVisited)); + historyItemWrappers().set(m_historyItem.get(), this); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::originalURLString( + /* [retval][out] */ BSTR* url) +{ + if (!url) + return E_POINTER; + + BString str = m_historyItem->originalURLString(); + *url = str.release(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::URLString( + /* [retval][out] */ BSTR* url) +{ + if (!url) + return E_POINTER; + + BString str = m_historyItem->urlString(); + *url = str.release(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::title( + /* [retval][out] */ BSTR* pageTitle) +{ + if (!pageTitle) + return E_POINTER; + + BString str(m_historyItem->title()); + *pageTitle = str.release(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::lastVisitedTimeInterval( + /* [retval][out] */ DATE* lastVisited) +{ + if (!lastVisited) + return E_POINTER; + + *lastVisited = MarshallingHelpers::CFAbsoluteTimeToDATE(m_historyItem->lastVisitedTime()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::setAlternateTitle( + /* [in] */ BSTR title) +{ + m_alternateTitle = title; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::alternateTitle( + /* [retval][out] */ BSTR* title) +{ + if (!title) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + *title = m_alternateTitle; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebHistoryItem::icon( + /* [out, retval] */ OLE_HANDLE* /*hBitmap*/) +{ + ASSERT_NOT_REACHED(); + return E_NOTIMPL; +} + +// WebHistoryItem ------------------------------------------------------------- +HistoryItem* WebHistoryItem::historyItem() const +{ + return m_historyItem.get(); +}