WebHistoryItem.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*
  2. * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "WebKitDLL.h"
  27. #include "WebHistoryItem.h"
  28. #include "COMEnumVariant.h"
  29. #include "MarshallingHelpers.h"
  30. #include "WebKit.h"
  31. #include <WebCore/BString.h>
  32. #include <WebCore/COMPtr.h>
  33. #include <WebCore/HistoryItem.h>
  34. #include <WebCore/KURL.h>
  35. #include <wtf/PassOwnPtr.h>
  36. #include <wtf/RetainPtr.h>
  37. #include <wtf/text/CString.h>
  38. using namespace WebCore;
  39. // WebHistoryItem ----------------------------------------------------------------
  40. static HashMap<HistoryItem*, WebHistoryItem*>& historyItemWrappers()
  41. {
  42. static HashMap<HistoryItem*, WebHistoryItem*> staticHistoryItemWrappers;
  43. return staticHistoryItemWrappers;
  44. }
  45. WebHistoryItem::WebHistoryItem(PassRefPtr<HistoryItem> historyItem)
  46. : m_refCount(0)
  47. , m_historyItem(historyItem)
  48. {
  49. ASSERT(!historyItemWrappers().contains(m_historyItem.get()));
  50. historyItemWrappers().set(m_historyItem.get(), this);
  51. gClassCount++;
  52. gClassNameCount.add("WebHistoryItem");
  53. }
  54. WebHistoryItem::~WebHistoryItem()
  55. {
  56. ASSERT(historyItemWrappers().contains(m_historyItem.get()));
  57. historyItemWrappers().remove(m_historyItem.get());
  58. gClassCount--;
  59. gClassNameCount.remove("WebHistoryItem");
  60. }
  61. WebHistoryItem* WebHistoryItem::createInstance()
  62. {
  63. WebHistoryItem* instance = new WebHistoryItem(HistoryItem::create());
  64. instance->AddRef();
  65. return instance;
  66. }
  67. WebHistoryItem* WebHistoryItem::createInstance(PassRefPtr<HistoryItem> historyItem)
  68. {
  69. WebHistoryItem* instance;
  70. instance = historyItemWrappers().get(historyItem.get());
  71. if (!instance)
  72. instance = new WebHistoryItem(historyItem);
  73. instance->AddRef();
  74. return instance;
  75. }
  76. // IWebHistoryItemPrivate -----------------------------------------------------
  77. static CFStringRef urlKey = CFSTR("");
  78. static CFStringRef lastVisitedDateKey = CFSTR("lastVisitedDate");
  79. static CFStringRef titleKey = CFSTR("title");
  80. static CFStringRef visitCountKey = CFSTR("visitCount");
  81. static CFStringRef lastVisitWasFailureKey = CFSTR("lastVisitWasFailure");
  82. static CFStringRef lastVisitWasHTTPNonGetKey = CFSTR("lastVisitWasHTTPNonGet");
  83. static CFStringRef redirectURLsKey = CFSTR("redirectURLs");
  84. static CFStringRef dailyVisitCountKey = CFSTR("D"); // short key to save space
  85. static CFStringRef weeklyVisitCountKey = CFSTR("W"); // short key to save space
  86. HRESULT STDMETHODCALLTYPE WebHistoryItem::initFromDictionaryRepresentation(void* dictionary)
  87. {
  88. CFDictionaryRef dictionaryRef = (CFDictionaryRef) dictionary;
  89. CFStringRef urlStringRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, urlKey);
  90. if (urlStringRef && CFGetTypeID(urlStringRef) != CFStringGetTypeID())
  91. return E_FAIL;
  92. CFStringRef lastVisitedRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, lastVisitedDateKey);
  93. if (!lastVisitedRef || CFGetTypeID(lastVisitedRef) != CFStringGetTypeID())
  94. return E_FAIL;
  95. CFAbsoluteTime lastVisitedTime = CFStringGetDoubleValue(lastVisitedRef);
  96. CFStringRef titleRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, titleKey);
  97. if (titleRef && CFGetTypeID(titleRef) != CFStringGetTypeID())
  98. return E_FAIL;
  99. CFNumberRef visitCountRef = (CFNumberRef) CFDictionaryGetValue(dictionaryRef, visitCountKey);
  100. if (!visitCountRef || CFGetTypeID(visitCountRef) != CFNumberGetTypeID())
  101. return E_FAIL;
  102. int visitedCount = 0;
  103. if (!CFNumberGetValue(visitCountRef, kCFNumberIntType, &visitedCount))
  104. return E_FAIL;
  105. // Can't trust data on disk, and we've had at least one report of this (<rdar://6572300>).
  106. if (visitedCount < 0) {
  107. LOG_ERROR("visit count for history item \"%s\" is negative (%d), will be reset to 1", String(urlStringRef).utf8().data(), visitedCount);
  108. visitedCount = 1;
  109. }
  110. CFBooleanRef lastVisitWasFailureRef = static_cast<CFBooleanRef>(CFDictionaryGetValue(dictionaryRef, lastVisitWasFailureKey));
  111. if (lastVisitWasFailureRef && CFGetTypeID(lastVisitWasFailureRef) != CFBooleanGetTypeID())
  112. return E_FAIL;
  113. bool lastVisitWasFailure = lastVisitWasFailureRef && CFBooleanGetValue(lastVisitWasFailureRef);
  114. CFBooleanRef lastVisitWasHTTPNonGetRef = static_cast<CFBooleanRef>(CFDictionaryGetValue(dictionaryRef, lastVisitWasHTTPNonGetKey));
  115. if (lastVisitWasHTTPNonGetRef && CFGetTypeID(lastVisitWasHTTPNonGetRef) != CFBooleanGetTypeID())
  116. return E_FAIL;
  117. bool lastVisitWasHTTPNonGet = lastVisitWasHTTPNonGetRef && CFBooleanGetValue(lastVisitWasHTTPNonGetRef);
  118. OwnPtr<Vector<String> > redirectURLsVector;
  119. if (CFArrayRef redirectURLsRef = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, redirectURLsKey))) {
  120. CFIndex size = CFArrayGetCount(redirectURLsRef);
  121. redirectURLsVector = adoptPtr(new Vector<String>(size));
  122. for (CFIndex i = 0; i < size; ++i)
  123. (*redirectURLsVector)[i] = String(static_cast<CFStringRef>(CFArrayGetValueAtIndex(redirectURLsRef, i)));
  124. }
  125. CFArrayRef dailyCounts = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, dailyVisitCountKey));
  126. if (dailyCounts && CFGetTypeID(dailyCounts) != CFArrayGetTypeID())
  127. dailyCounts = 0;
  128. CFArrayRef weeklyCounts = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, weeklyVisitCountKey));
  129. if (weeklyCounts && CFGetTypeID(weeklyCounts) != CFArrayGetTypeID())
  130. weeklyCounts = 0;
  131. std::auto_ptr<Vector<int> > dailyVector, weeklyVector;
  132. if (dailyCounts || weeklyCounts) {
  133. CFIndex dailySize = dailyCounts ? CFArrayGetCount(dailyCounts) : 0;
  134. CFIndex weeklySize = weeklyCounts ? CFArrayGetCount(weeklyCounts) : 0;
  135. dailyVector.reset(new Vector<int>(dailySize));
  136. weeklyVector.reset(new Vector<int>(weeklySize));
  137. // Daily and weekly counts < 0 are errors in the data read from disk, so reset to 0.
  138. for (CFIndex i = 0; i < dailySize; ++i) {
  139. CFNumberRef dailyCount = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(dailyCounts, i));
  140. if (CFGetTypeID(dailyCount) == CFNumberGetTypeID())
  141. CFNumberGetValue(dailyCount, kCFNumberIntType, &(*dailyVector)[i]);
  142. if ((*dailyVector)[i] < 0)
  143. (*dailyVector)[i] = 0;
  144. }
  145. for (CFIndex i = 0; i < weeklySize; ++i) {
  146. CFNumberRef weeklyCount = static_cast<CFNumberRef>(CFArrayGetValueAtIndex(weeklyCounts, i));
  147. if (CFGetTypeID(weeklyCount) == CFNumberGetTypeID())
  148. CFNumberGetValue(weeklyCount, kCFNumberIntType, &(*weeklyVector)[i]);
  149. if ((*weeklyVector)[i] < 0)
  150. (*weeklyVector)[i] = 0;
  151. }
  152. }
  153. historyItemWrappers().remove(m_historyItem.get());
  154. m_historyItem = HistoryItem::create(urlStringRef, titleRef, lastVisitedTime);
  155. historyItemWrappers().set(m_historyItem.get(), this);
  156. m_historyItem->setVisitCount(visitedCount);
  157. if (lastVisitWasFailure)
  158. m_historyItem->setLastVisitWasFailure(true);
  159. if (lastVisitWasHTTPNonGet && (protocolIs(m_historyItem->urlString(), "http") || protocolIs(m_historyItem->urlString(), "https")))
  160. m_historyItem->setLastVisitWasHTTPNonGet(true);
  161. if (redirectURLsVector)
  162. m_historyItem->setRedirectURLs(redirectURLsVector.release());
  163. if (dailyVector.get())
  164. m_historyItem->adoptVisitCounts(*dailyVector, *weeklyVector);
  165. return S_OK;
  166. }
  167. HRESULT STDMETHODCALLTYPE WebHistoryItem::dictionaryRepresentation(void** dictionary)
  168. {
  169. CFDictionaryRef* dictionaryRef = (CFDictionaryRef*) dictionary;
  170. static CFStringRef lastVisitedFormat = CFSTR("%.1lf");
  171. CFStringRef lastVisitedStringRef =
  172. CFStringCreateWithFormat(0, 0, lastVisitedFormat, m_historyItem->lastVisitedTime());
  173. if (!lastVisitedStringRef)
  174. return E_FAIL;
  175. int keyCount = 0;
  176. CFTypeRef keys[9];
  177. CFTypeRef values[9];
  178. if (!m_historyItem->urlString().isEmpty()) {
  179. keys[keyCount] = urlKey;
  180. values[keyCount++] = m_historyItem->urlString().createCFString().leakRef();
  181. }
  182. keys[keyCount] = lastVisitedDateKey;
  183. values[keyCount++] = lastVisitedStringRef;
  184. if (!m_historyItem->title().isEmpty()) {
  185. keys[keyCount] = titleKey;
  186. values[keyCount++] = m_historyItem->title().createCFString().leakRef();
  187. }
  188. keys[keyCount] = visitCountKey;
  189. int visitCount = m_historyItem->visitCount();
  190. values[keyCount++] = CFNumberCreate(0, kCFNumberIntType, &visitCount);
  191. if (m_historyItem->lastVisitWasFailure()) {
  192. keys[keyCount] = lastVisitWasFailureKey;
  193. values[keyCount++] = CFRetain(kCFBooleanTrue);
  194. }
  195. if (m_historyItem->lastVisitWasHTTPNonGet()) {
  196. ASSERT(m_historyItem->urlString().startsWith("http:", false) || m_historyItem->urlString().startsWith("https:", false));
  197. keys[keyCount] = lastVisitWasHTTPNonGetKey;
  198. values[keyCount++] = CFRetain(kCFBooleanTrue);
  199. }
  200. if (Vector<String>* redirectURLs = m_historyItem->redirectURLs()) {
  201. size_t size = redirectURLs->size();
  202. ASSERT(size);
  203. CFStringRef* items = new CFStringRef[size];
  204. for (size_t i = 0; i < size; ++i)
  205. items[i] = redirectURLs->at(i).createCFString().leakRef();
  206. CFArrayRef result = CFArrayCreate(0, (const void**)items, size, &kCFTypeArrayCallBacks);
  207. for (size_t i = 0; i < size; ++i)
  208. CFRelease(items[i]);
  209. delete[] items;
  210. keys[keyCount] = redirectURLsKey;
  211. values[keyCount++] = result;
  212. }
  213. const Vector<int>& dailyVisitCount(m_historyItem->dailyVisitCounts());
  214. if (size_t size = dailyVisitCount.size()) {
  215. Vector<CFNumberRef, 13> numbers(size);
  216. for (size_t i = 0; i < size; ++i)
  217. numbers[i] = CFNumberCreate(0, kCFNumberIntType, &dailyVisitCount[i]);
  218. CFArrayRef result = CFArrayCreate(0, (const void**)numbers.data(), size, &kCFTypeArrayCallBacks);
  219. for (size_t i = 0; i < size; ++i)
  220. CFRelease(numbers[i]);
  221. keys[keyCount] = dailyVisitCountKey;
  222. values[keyCount++] = result;
  223. }
  224. const Vector<int>& weeklyVisitCount(m_historyItem->weeklyVisitCounts());
  225. if (size_t size = weeklyVisitCount.size()) {
  226. Vector<CFNumberRef, 5> numbers(size);
  227. for (size_t i = 0; i < size; ++i)
  228. numbers[i] = CFNumberCreate(0, kCFNumberIntType, &weeklyVisitCount[i]);
  229. CFArrayRef result = CFArrayCreate(0, (const void**)numbers.data(), size, &kCFTypeArrayCallBacks);
  230. for (size_t i = 0; i < size; ++i)
  231. CFRelease(numbers[i]);
  232. keys[keyCount] = weeklyVisitCountKey;
  233. values[keyCount++] = result;
  234. }
  235. *dictionaryRef = CFDictionaryCreate(0, keys, values, keyCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
  236. for (int i = 0; i < keyCount; ++i)
  237. CFRelease(values[i]);
  238. return S_OK;
  239. }
  240. HRESULT STDMETHODCALLTYPE WebHistoryItem::hasURLString(BOOL *hasURL)
  241. {
  242. *hasURL = m_historyItem->urlString().isEmpty() ? FALSE : TRUE;
  243. return S_OK;
  244. }
  245. HRESULT STDMETHODCALLTYPE WebHistoryItem::visitCount(int *count)
  246. {
  247. *count = m_historyItem->visitCount();
  248. return S_OK;
  249. }
  250. HRESULT STDMETHODCALLTYPE WebHistoryItem::setVisitCount(int count)
  251. {
  252. m_historyItem->setVisitCount(count);
  253. return S_OK;
  254. }
  255. HRESULT STDMETHODCALLTYPE WebHistoryItem::mergeAutoCompleteHints(IWebHistoryItem* otherItem)
  256. {
  257. if (!otherItem)
  258. return E_FAIL;
  259. COMPtr<WebHistoryItem> otherWebHistoryItem(Query, otherItem);
  260. if (!otherWebHistoryItem)
  261. return E_FAIL;
  262. m_historyItem->mergeAutoCompleteHints(otherWebHistoryItem->historyItem());
  263. return S_OK;
  264. }
  265. HRESULT STDMETHODCALLTYPE WebHistoryItem::setLastVisitedTimeInterval(DATE time)
  266. {
  267. m_historyItem->setLastVisitedTime(MarshallingHelpers::DATEToCFAbsoluteTime(time));
  268. return S_OK;
  269. }
  270. HRESULT STDMETHODCALLTYPE WebHistoryItem::setTitle(BSTR title)
  271. {
  272. m_historyItem->setTitle(String(title, SysStringLen(title)));
  273. return S_OK;
  274. }
  275. HRESULT STDMETHODCALLTYPE WebHistoryItem::RSSFeedReferrer(BSTR* url)
  276. {
  277. BString str(m_historyItem->referrer());
  278. *url = str.release();
  279. return S_OK;
  280. }
  281. HRESULT STDMETHODCALLTYPE WebHistoryItem::setRSSFeedReferrer(BSTR url)
  282. {
  283. m_historyItem->setReferrer(String(url, SysStringLen(url)));
  284. return S_OK;
  285. }
  286. HRESULT STDMETHODCALLTYPE WebHistoryItem::hasPageCache(BOOL* /*hasCache*/)
  287. {
  288. // FIXME - TODO
  289. ASSERT_NOT_REACHED();
  290. return E_NOTIMPL;
  291. }
  292. HRESULT STDMETHODCALLTYPE WebHistoryItem::setHasPageCache(BOOL /*hasCache*/)
  293. {
  294. // FIXME - TODO
  295. return E_NOTIMPL;
  296. }
  297. HRESULT STDMETHODCALLTYPE WebHistoryItem::target(BSTR* target)
  298. {
  299. if (!target) {
  300. ASSERT_NOT_REACHED();
  301. return E_POINTER;
  302. }
  303. *target = BString(m_historyItem->target()).release();
  304. return S_OK;
  305. }
  306. HRESULT STDMETHODCALLTYPE WebHistoryItem::isTargetItem(BOOL* result)
  307. {
  308. if (!result) {
  309. ASSERT_NOT_REACHED();
  310. return E_POINTER;
  311. }
  312. *result = m_historyItem->isTargetItem() ? TRUE : FALSE;
  313. return S_OK;
  314. }
  315. HRESULT STDMETHODCALLTYPE WebHistoryItem::children(unsigned* outChildCount, SAFEARRAY** outChildren)
  316. {
  317. if (!outChildCount || !outChildren) {
  318. ASSERT_NOT_REACHED();
  319. return E_POINTER;
  320. }
  321. *outChildCount = 0;
  322. *outChildren = 0;
  323. const HistoryItemVector& coreChildren = m_historyItem->children();
  324. if (coreChildren.isEmpty())
  325. return S_OK;
  326. size_t childCount = coreChildren.size();
  327. SAFEARRAY* children = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast<ULONG>(childCount));
  328. if (!children)
  329. return E_OUTOFMEMORY;
  330. for (unsigned i = 0; i < childCount; ++i) {
  331. COMPtr<WebHistoryItem> item(AdoptCOM, WebHistoryItem::createInstance(coreChildren[i]));
  332. if (!item) {
  333. SafeArrayDestroy(children);
  334. return E_OUTOFMEMORY;
  335. }
  336. LONG longI = i;
  337. HRESULT hr = SafeArrayPutElement(children, &longI, item.get());
  338. if (FAILED(hr)) {
  339. SafeArrayDestroy(children);
  340. return hr;
  341. }
  342. }
  343. *outChildCount = static_cast<unsigned>(childCount);
  344. *outChildren = children;
  345. return S_OK;
  346. }
  347. HRESULT STDMETHODCALLTYPE WebHistoryItem::lastVisitWasFailure(BOOL* wasFailure)
  348. {
  349. if (!wasFailure) {
  350. ASSERT_NOT_REACHED();
  351. return E_POINTER;
  352. }
  353. *wasFailure = m_historyItem->lastVisitWasFailure();
  354. return S_OK;
  355. }
  356. HRESULT STDMETHODCALLTYPE WebHistoryItem::setLastVisitWasFailure(BOOL wasFailure)
  357. {
  358. m_historyItem->setLastVisitWasFailure(wasFailure);
  359. return S_OK;
  360. }
  361. HRESULT STDMETHODCALLTYPE WebHistoryItem::lastVisitWasHTTPNonGet(BOOL* HTTPNonGet)
  362. {
  363. if (!HTTPNonGet) {
  364. ASSERT_NOT_REACHED();
  365. return E_POINTER;
  366. }
  367. *HTTPNonGet = m_historyItem->lastVisitWasHTTPNonGet();
  368. return S_OK;
  369. }
  370. HRESULT STDMETHODCALLTYPE WebHistoryItem::setLastVisitWasHTTPNonGet(BOOL HTTPNonGet)
  371. {
  372. m_historyItem->setLastVisitWasHTTPNonGet(HTTPNonGet);
  373. return S_OK;
  374. }
  375. HRESULT STDMETHODCALLTYPE WebHistoryItem::redirectURLs(IEnumVARIANT** urls)
  376. {
  377. if (!urls) {
  378. ASSERT_NOT_REACHED();
  379. return E_POINTER;
  380. }
  381. Vector<String>* urlVector = m_historyItem->redirectURLs();
  382. if (!urlVector) {
  383. *urls = 0;
  384. return S_OK;
  385. }
  386. COMPtr<COMEnumVariant<Vector<String> > > enumVariant(AdoptCOM, COMEnumVariant<Vector<String> >::createInstance(*urlVector));
  387. *urls = enumVariant.leakRef();
  388. return S_OK;
  389. }
  390. HRESULT STDMETHODCALLTYPE WebHistoryItem::visitedWithTitle(BSTR title, BOOL increaseVisitCount)
  391. {
  392. m_historyItem->visited(title, CFAbsoluteTimeGetCurrent(), increaseVisitCount ? IncreaseVisitCount : DoNotIncreaseVisitCount);
  393. return S_OK;
  394. }
  395. HRESULT STDMETHODCALLTYPE WebHistoryItem::getDailyVisitCounts(int* number, int** counts)
  396. {
  397. if (!number || !counts) {
  398. ASSERT_NOT_REACHED();
  399. return E_POINTER;
  400. }
  401. *counts = const_cast<int*>(m_historyItem->dailyVisitCounts().data());
  402. *number = m_historyItem->dailyVisitCounts().size();
  403. return S_OK;
  404. }
  405. HRESULT STDMETHODCALLTYPE WebHistoryItem::getWeeklyVisitCounts(int* number, int** counts)
  406. {
  407. if (!number || !counts) {
  408. ASSERT_NOT_REACHED();
  409. return E_POINTER;
  410. }
  411. *counts = const_cast<int*>(m_historyItem->weeklyVisitCounts().data());
  412. *number = m_historyItem->weeklyVisitCounts().size();
  413. return S_OK;
  414. }
  415. HRESULT STDMETHODCALLTYPE WebHistoryItem::recordInitialVisit()
  416. {
  417. m_historyItem->recordInitialVisit();
  418. return S_OK;
  419. }
  420. // IUnknown -------------------------------------------------------------------
  421. HRESULT STDMETHODCALLTYPE WebHistoryItem::QueryInterface(REFIID riid, void** ppvObject)
  422. {
  423. *ppvObject = 0;
  424. if (IsEqualGUID(riid, __uuidof(WebHistoryItem)))
  425. *ppvObject = this;
  426. else if (IsEqualGUID(riid, IID_IUnknown))
  427. *ppvObject = static_cast<IWebHistoryItem*>(this);
  428. else if (IsEqualGUID(riid, IID_IWebHistoryItem))
  429. *ppvObject = static_cast<IWebHistoryItem*>(this);
  430. else if (IsEqualGUID(riid, IID_IWebHistoryItemPrivate))
  431. *ppvObject = static_cast<IWebHistoryItemPrivate*>(this);
  432. else
  433. return E_NOINTERFACE;
  434. AddRef();
  435. return S_OK;
  436. }
  437. ULONG STDMETHODCALLTYPE WebHistoryItem::AddRef(void)
  438. {
  439. return ++m_refCount;
  440. }
  441. ULONG STDMETHODCALLTYPE WebHistoryItem::Release(void)
  442. {
  443. ULONG newRef = --m_refCount;
  444. if (!newRef)
  445. delete(this);
  446. return newRef;
  447. }
  448. // IWebHistoryItem -------------------------------------------------------------
  449. HRESULT STDMETHODCALLTYPE WebHistoryItem::initWithURLString(
  450. /* [in] */ BSTR urlString,
  451. /* [in] */ BSTR title,
  452. /* [in] */ DATE lastVisited)
  453. {
  454. historyItemWrappers().remove(m_historyItem.get());
  455. m_historyItem = HistoryItem::create(String(urlString, SysStringLen(urlString)), String(title, SysStringLen(title)), MarshallingHelpers::DATEToCFAbsoluteTime(lastVisited));
  456. historyItemWrappers().set(m_historyItem.get(), this);
  457. return S_OK;
  458. }
  459. HRESULT STDMETHODCALLTYPE WebHistoryItem::originalURLString(
  460. /* [retval][out] */ BSTR* url)
  461. {
  462. if (!url)
  463. return E_POINTER;
  464. BString str = m_historyItem->originalURLString();
  465. *url = str.release();
  466. return S_OK;
  467. }
  468. HRESULT STDMETHODCALLTYPE WebHistoryItem::URLString(
  469. /* [retval][out] */ BSTR* url)
  470. {
  471. if (!url)
  472. return E_POINTER;
  473. BString str = m_historyItem->urlString();
  474. *url = str.release();
  475. return S_OK;
  476. }
  477. HRESULT STDMETHODCALLTYPE WebHistoryItem::title(
  478. /* [retval][out] */ BSTR* pageTitle)
  479. {
  480. if (!pageTitle)
  481. return E_POINTER;
  482. BString str(m_historyItem->title());
  483. *pageTitle = str.release();
  484. return S_OK;
  485. }
  486. HRESULT STDMETHODCALLTYPE WebHistoryItem::lastVisitedTimeInterval(
  487. /* [retval][out] */ DATE* lastVisited)
  488. {
  489. if (!lastVisited)
  490. return E_POINTER;
  491. *lastVisited = MarshallingHelpers::CFAbsoluteTimeToDATE(m_historyItem->lastVisitedTime());
  492. return S_OK;
  493. }
  494. HRESULT STDMETHODCALLTYPE WebHistoryItem::setAlternateTitle(
  495. /* [in] */ BSTR title)
  496. {
  497. m_alternateTitle = String(title, SysStringLen(title));
  498. return S_OK;
  499. }
  500. HRESULT STDMETHODCALLTYPE WebHistoryItem::alternateTitle(
  501. /* [retval][out] */ BSTR* title)
  502. {
  503. if (!title) {
  504. ASSERT_NOT_REACHED();
  505. return E_POINTER;
  506. }
  507. *title = BString(m_alternateTitle).release();
  508. return S_OK;
  509. }
  510. HRESULT STDMETHODCALLTYPE WebHistoryItem::icon(
  511. /* [out, retval] */ OLE_HANDLE* /*hBitmap*/)
  512. {
  513. ASSERT_NOT_REACHED();
  514. return E_NOTIMPL;
  515. }
  516. // WebHistoryItem -------------------------------------------------------------
  517. HistoryItem* WebHistoryItem::historyItem() const
  518. {
  519. return m_historyItem.get();
  520. }