WebHistoryItem.mm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Copyright (C) 2005, 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. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #import "WebHistoryItemInternal.h"
  29. #import "WebHistoryItemPrivate.h"
  30. #import "WebFrameInternal.h"
  31. #import "WebFrameView.h"
  32. #import "WebHTMLViewInternal.h"
  33. #import "WebIconDatabase.h"
  34. #import "WebKitLogging.h"
  35. #import "WebKitNSStringExtras.h"
  36. #import "WebNSArrayExtras.h"
  37. #import "WebNSDictionaryExtras.h"
  38. #import "WebNSObjectExtras.h"
  39. #import "WebNSURLExtras.h"
  40. #import "WebNSURLRequestExtras.h"
  41. #import "WebNSViewExtras.h"
  42. #import "WebPluginController.h"
  43. #import "WebTypesInternal.h"
  44. #import <WebCore/HistoryItem.h>
  45. #import <WebCore/Image.h>
  46. #import <WebCore/KURL.h>
  47. #import <WebCore/PageCache.h>
  48. #import <WebCore/RunLoop.h>
  49. #import <WebCore/ThreadCheck.h>
  50. #import <WebCore/WebCoreObjCExtras.h>
  51. #import <runtime/InitializeThreading.h>
  52. #import <wtf/Assertions.h>
  53. #import <wtf/MainThread.h>
  54. #import <wtf/StdLibExtras.h>
  55. #import <wtf/text/WTFString.h>
  56. // Private keys used in the WebHistoryItem's dictionary representation.
  57. // see 3245793 for explanation of "lastVisitedDate"
  58. static NSString *lastVisitedTimeIntervalKey = @"lastVisitedDate";
  59. static NSString *visitCountKey = @"visitCount";
  60. static NSString *titleKey = @"title";
  61. static NSString *childrenKey = @"children";
  62. static NSString *displayTitleKey = @"displayTitle";
  63. static NSString *lastVisitWasFailureKey = @"lastVisitWasFailure";
  64. static NSString *lastVisitWasHTTPNonGetKey = @"lastVisitWasHTTPNonGet";
  65. static NSString *redirectURLsKey = @"redirectURLs";
  66. static NSString *dailyVisitCountKey = @"D"; // short key to save space
  67. static NSString *weeklyVisitCountKey = @"W"; // short key to save space
  68. // Notification strings.
  69. NSString *WebHistoryItemChangedNotification = @"WebHistoryItemChangedNotification";
  70. using namespace WebCore;
  71. typedef HashMap<HistoryItem*, WebHistoryItem*> HistoryItemMap;
  72. static inline WebHistoryItemPrivate* kitPrivate(WebCoreHistoryItem* list) { return (WebHistoryItemPrivate*)list; }
  73. static inline WebCoreHistoryItem* core(WebHistoryItemPrivate* list) { return (WebCoreHistoryItem*)list; }
  74. static HistoryItemMap& historyItemWrappers()
  75. {
  76. DEFINE_STATIC_LOCAL(HistoryItemMap, historyItemWrappers, ());
  77. return historyItemWrappers;
  78. }
  79. void WKNotifyHistoryItemChanged(HistoryItem*)
  80. {
  81. [[NSNotificationCenter defaultCenter]
  82. postNotificationName:WebHistoryItemChangedNotification object:nil userInfo:nil];
  83. }
  84. @implementation WebHistoryItem
  85. + (void)initialize
  86. {
  87. JSC::initializeThreading();
  88. WTF::initializeMainThreadToProcessMainThread();
  89. WebCore::RunLoop::initializeMainRunLoop();
  90. WebCoreObjCFinalizeOnMainThread(self);
  91. }
  92. - (id)init
  93. {
  94. return [self initWithWebCoreHistoryItem:HistoryItem::create()];
  95. }
  96. - (id)initWithURLString:(NSString *)URLString title:(NSString *)title lastVisitedTimeInterval:(NSTimeInterval)time
  97. {
  98. WebCoreThreadViolationCheckRoundOne();
  99. return [self initWithWebCoreHistoryItem:HistoryItem::create(URLString, title, time)];
  100. }
  101. - (void)dealloc
  102. {
  103. if (WebCoreObjCScheduleDeallocateOnMainThread([WebHistoryItem class], self))
  104. return;
  105. if (_private) {
  106. HistoryItem* coreItem = core(_private);
  107. coreItem->deref();
  108. historyItemWrappers().remove(coreItem);
  109. }
  110. [super dealloc];
  111. }
  112. - (void)finalize
  113. {
  114. WebCoreThreadViolationCheckRoundOne();
  115. // FIXME: ~HistoryItem is what releases the history item's icon from the icon database
  116. // It's probably not good to release icons from the database only when the object is garbage-collected.
  117. // Need to change design so this happens at a predictable time.
  118. if (_private) {
  119. HistoryItem* coreItem = core(_private);
  120. coreItem->deref();
  121. historyItemWrappers().remove(coreItem);
  122. }
  123. [super finalize];
  124. }
  125. - (id)copyWithZone:(NSZone *)zone
  126. {
  127. WebCoreThreadViolationCheckRoundOne();
  128. WebHistoryItem *copy = [[[self class] alloc] initWithWebCoreHistoryItem:core(_private)->copy()];
  129. historyItemWrappers().set(core(copy->_private), copy);
  130. return copy;
  131. }
  132. // FIXME: Need to decide if this class ever returns URLs and decide on the name of this method
  133. - (NSString *)URLString
  134. {
  135. ASSERT_MAIN_THREAD();
  136. return nsStringNilIfEmpty(core(_private)->urlString());
  137. }
  138. // The first URL we loaded to get to where this history item points. Includes both client
  139. // and server redirects.
  140. - (NSString *)originalURLString
  141. {
  142. ASSERT_MAIN_THREAD();
  143. return nsStringNilIfEmpty(core(_private)->originalURLString());
  144. }
  145. - (NSString *)title
  146. {
  147. ASSERT_MAIN_THREAD();
  148. return nsStringNilIfEmpty(core(_private)->title());
  149. }
  150. - (void)setAlternateTitle:(NSString *)alternateTitle
  151. {
  152. core(_private)->setAlternateTitle(alternateTitle);
  153. }
  154. - (NSString *)alternateTitle
  155. {
  156. return nsStringNilIfEmpty(core(_private)->alternateTitle());
  157. }
  158. - (NSImage *)icon
  159. {
  160. return [[WebIconDatabase sharedIconDatabase] iconForURL:[self URLString] withSize:WebIconSmallSize];
  161. }
  162. - (NSTimeInterval)lastVisitedTimeInterval
  163. {
  164. ASSERT_MAIN_THREAD();
  165. return core(_private)->lastVisitedTime();
  166. }
  167. - (NSUInteger)hash
  168. {
  169. return [(NSString*)core(_private)->urlString() hash];
  170. }
  171. - (BOOL)isEqual:(id)anObject
  172. {
  173. ASSERT_MAIN_THREAD();
  174. if (![anObject isMemberOfClass:[WebHistoryItem class]]) {
  175. return NO;
  176. }
  177. return core(_private)->urlString() == core(((WebHistoryItem*)anObject)->_private)->urlString();
  178. }
  179. - (NSString *)description
  180. {
  181. ASSERT_MAIN_THREAD();
  182. HistoryItem* coreItem = core(_private);
  183. NSMutableString *result = [NSMutableString stringWithFormat:@"%@ %@", [super description], (NSString*)coreItem->urlString()];
  184. if (!coreItem->target().isEmpty()) {
  185. NSString *target = coreItem->target();
  186. [result appendFormat:@" in \"%@\"", target];
  187. }
  188. if (coreItem->isTargetItem()) {
  189. [result appendString:@" *target*"];
  190. }
  191. if (coreItem->formData()) {
  192. [result appendString:@" *POST*"];
  193. }
  194. if (coreItem->children().size()) {
  195. const HistoryItemVector& children = coreItem->children();
  196. int currPos = [result length];
  197. unsigned size = children.size();
  198. for (unsigned i = 0; i < size; ++i) {
  199. WebHistoryItem *child = kit(children[i].get());
  200. [result appendString:@"\n"];
  201. [result appendString:[child description]];
  202. }
  203. // shift all the contents over. A bit slow, but hey, this is for debugging.
  204. NSRange replRange = { static_cast<NSUInteger>(currPos), [result length] - currPos };
  205. [result replaceOccurrencesOfString:@"\n" withString:@"\n " options:0 range:replRange];
  206. }
  207. return result;
  208. }
  209. @end
  210. @implementation WebHistoryItem (WebInternal)
  211. HistoryItem* core(WebHistoryItem *item)
  212. {
  213. if (!item)
  214. return 0;
  215. ASSERT(historyItemWrappers().get(core(item->_private)) == item);
  216. return core(item->_private);
  217. }
  218. WebHistoryItem *kit(HistoryItem* item)
  219. {
  220. if (!item)
  221. return nil;
  222. WebHistoryItem *kitItem = historyItemWrappers().get(item);
  223. if (kitItem)
  224. return kitItem;
  225. return [[[WebHistoryItem alloc] initWithWebCoreHistoryItem:item] autorelease];
  226. }
  227. + (WebHistoryItem *)entryWithURL:(NSURL *)URL
  228. {
  229. return [[[self alloc] initWithURL:URL title:nil] autorelease];
  230. }
  231. - (id)initWithURL:(NSURL *)URL target:(NSString *)target parent:(NSString *)parent title:(NSString *)title
  232. {
  233. return [self initWithWebCoreHistoryItem:HistoryItem::create(URL, target, parent, title)];
  234. }
  235. - (id)initWithURLString:(NSString *)URLString title:(NSString *)title displayTitle:(NSString *)displayTitle lastVisitedTimeInterval:(NSTimeInterval)time
  236. {
  237. return [self initWithWebCoreHistoryItem:HistoryItem::create(URLString, title, displayTitle, time)];
  238. }
  239. - (id)initWithWebCoreHistoryItem:(PassRefPtr<HistoryItem>)item
  240. {
  241. WebCoreThreadViolationCheckRoundOne();
  242. // Need to tell WebCore what function to call for the
  243. // "History Item has Changed" notification - no harm in doing this
  244. // everytime a WebHistoryItem is created
  245. // Note: We also do this in [WebFrameView initWithFrame:] where we do
  246. // other "init before WebKit is used" type things
  247. WebCore::notifyHistoryItemChanged = WKNotifyHistoryItemChanged;
  248. self = [super init];
  249. _private = kitPrivate(item.leakRef());
  250. ASSERT(!historyItemWrappers().get(core(_private)));
  251. historyItemWrappers().set(core(_private), self);
  252. return self;
  253. }
  254. - (void)setTitle:(NSString *)title
  255. {
  256. core(_private)->setTitle(title);
  257. }
  258. - (void)setVisitCount:(int)count
  259. {
  260. core(_private)->setVisitCount(count);
  261. }
  262. - (void)setViewState:(id)statePList
  263. {
  264. core(_private)->setViewState(statePList);
  265. }
  266. - (void)_mergeAutoCompleteHints:(WebHistoryItem *)otherItem
  267. {
  268. ASSERT_ARG(otherItem, otherItem);
  269. core(_private)->mergeAutoCompleteHints(core(otherItem->_private));
  270. }
  271. - (id)initFromDictionaryRepresentation:(NSDictionary *)dict
  272. {
  273. ASSERT_MAIN_THREAD();
  274. NSString *URLString = [dict _webkit_stringForKey:@""];
  275. NSString *title = [dict _webkit_stringForKey:titleKey];
  276. // Do an existence check to avoid calling doubleValue on a nil string. Leave
  277. // time interval at 0 if there's no value in dict.
  278. NSString *timeIntervalString = [dict _webkit_stringForKey:lastVisitedTimeIntervalKey];
  279. NSTimeInterval lastVisited = timeIntervalString == nil ? 0 : [timeIntervalString doubleValue];
  280. self = [self initWithURLString:URLString title:title displayTitle:[dict _webkit_stringForKey:displayTitleKey] lastVisitedTimeInterval:lastVisited];
  281. // Check if we've read a broken URL from the file that has non-Latin1 chars. If so, try to convert
  282. // as if it was from user typing.
  283. if (![URLString canBeConvertedToEncoding:NSISOLatin1StringEncoding]) {
  284. NSURL *tempURL = [NSURL _web_URLWithUserTypedString:URLString];
  285. ASSERT(tempURL);
  286. NSString *newURLString = [tempURL _web_originalDataAsString];
  287. core(_private)->setURLString(newURLString);
  288. core(_private)->setOriginalURLString(newURLString);
  289. }
  290. int visitCount = [dict _webkit_intForKey:visitCountKey];
  291. // Can't trust data on disk, and we've had at least one report of this (<rdar://6572300>).
  292. if (visitCount < 0) {
  293. LOG_ERROR("visit count for history item \"%@\" is negative (%d), will be reset to 1", URLString, visitCount);
  294. visitCount = 1;
  295. }
  296. core(_private)->setVisitCount(visitCount);
  297. if ([dict _webkit_boolForKey:lastVisitWasFailureKey])
  298. core(_private)->setLastVisitWasFailure(true);
  299. BOOL lastVisitWasHTTPNonGet = [dict _webkit_boolForKey:lastVisitWasHTTPNonGetKey];
  300. NSString *tempURLString = [URLString lowercaseString];
  301. if (lastVisitWasHTTPNonGet && ([tempURLString hasPrefix:@"http:"] || [tempURLString hasPrefix:@"https:"]))
  302. core(_private)->setLastVisitWasHTTPNonGet(lastVisitWasHTTPNonGet);
  303. if (NSArray *redirectURLs = [dict _webkit_arrayForKey:redirectURLsKey]) {
  304. NSUInteger size = [redirectURLs count];
  305. OwnPtr<Vector<String> > redirectURLsVector = adoptPtr(new Vector<String>(size));
  306. for (NSUInteger i = 0; i < size; ++i)
  307. (*redirectURLsVector)[i] = String([redirectURLs _webkit_stringAtIndex:i]);
  308. core(_private)->setRedirectURLs(redirectURLsVector.release());
  309. }
  310. NSArray *dailyCounts = [dict _webkit_arrayForKey:dailyVisitCountKey];
  311. NSArray *weeklyCounts = [dict _webkit_arrayForKey:weeklyVisitCountKey];
  312. if (dailyCounts || weeklyCounts) {
  313. Vector<int> coreDailyCounts([dailyCounts count]);
  314. Vector<int> coreWeeklyCounts([weeklyCounts count]);
  315. // Daily and weekly counts < 0 are errors in the data read from disk, so reset to 0.
  316. for (size_t i = 0; i < coreDailyCounts.size(); ++i)
  317. coreDailyCounts[i] = std::max([[dailyCounts _webkit_numberAtIndex:i] intValue], 0);
  318. for (size_t i = 0; i < coreWeeklyCounts.size(); ++i)
  319. coreWeeklyCounts[i] = std::max([[weeklyCounts _webkit_numberAtIndex:i] intValue], 0);
  320. core(_private)->adoptVisitCounts(coreDailyCounts, coreWeeklyCounts);
  321. }
  322. NSArray *childDicts = [dict objectForKey:childrenKey];
  323. if (childDicts) {
  324. for (int i = [childDicts count] - 1; i >= 0; i--) {
  325. WebHistoryItem *child = [[WebHistoryItem alloc] initFromDictionaryRepresentation:[childDicts objectAtIndex:i]];
  326. core(_private)->addChildItem(core(child->_private));
  327. [child release];
  328. }
  329. }
  330. return self;
  331. }
  332. - (NSPoint)scrollPoint
  333. {
  334. ASSERT_MAIN_THREAD();
  335. return core(_private)->scrollPoint();
  336. }
  337. - (void)_visitedWithTitle:(NSString *)title increaseVisitCount:(BOOL)increaseVisitCount
  338. {
  339. core(_private)->visited(title, [NSDate timeIntervalSinceReferenceDate], increaseVisitCount ? IncreaseVisitCount : DoNotIncreaseVisitCount);
  340. }
  341. - (void)_recordInitialVisit
  342. {
  343. core(_private)->recordInitialVisit();
  344. }
  345. @end
  346. @implementation WebHistoryItem (WebPrivate)
  347. - (id)initWithURL:(NSURL *)URL title:(NSString *)title
  348. {
  349. return [self initWithURLString:[URL _web_originalDataAsString] title:title lastVisitedTimeInterval:0];
  350. }
  351. - (NSDictionary *)dictionaryRepresentation
  352. {
  353. ASSERT_MAIN_THREAD();
  354. NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:8];
  355. HistoryItem* coreItem = core(_private);
  356. if (!coreItem->urlString().isEmpty())
  357. [dict setObject:(NSString*)coreItem->urlString() forKey:@""];
  358. if (!coreItem->title().isEmpty())
  359. [dict setObject:(NSString*)coreItem->title() forKey:titleKey];
  360. if (!coreItem->alternateTitle().isEmpty())
  361. [dict setObject:(NSString*)coreItem->alternateTitle() forKey:displayTitleKey];
  362. if (coreItem->lastVisitedTime() != 0.0) {
  363. // Store as a string to maintain backward compatibility. (See 3245793)
  364. [dict setObject:[NSString stringWithFormat:@"%.1lf", coreItem->lastVisitedTime()]
  365. forKey:lastVisitedTimeIntervalKey];
  366. }
  367. if (coreItem->visitCount())
  368. [dict setObject:[NSNumber numberWithInt:coreItem->visitCount()] forKey:visitCountKey];
  369. if (coreItem->lastVisitWasFailure())
  370. [dict setObject:[NSNumber numberWithBool:YES] forKey:lastVisitWasFailureKey];
  371. if (coreItem->lastVisitWasHTTPNonGet()) {
  372. ASSERT(coreItem->urlString().startsWith("http:", false) || coreItem->urlString().startsWith("https:", false));
  373. [dict setObject:[NSNumber numberWithBool:YES] forKey:lastVisitWasHTTPNonGetKey];
  374. }
  375. if (Vector<String>* redirectURLs = coreItem->redirectURLs()) {
  376. size_t size = redirectURLs->size();
  377. ASSERT(size);
  378. NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:size];
  379. for (size_t i = 0; i < size; ++i)
  380. [result addObject:(NSString*)redirectURLs->at(i)];
  381. [dict setObject:result forKey:redirectURLsKey];
  382. [result release];
  383. }
  384. const Vector<int>& dailyVisitCounts = coreItem->dailyVisitCounts();
  385. if (dailyVisitCounts.size()) {
  386. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:13];
  387. for (size_t i = 0; i < dailyVisitCounts.size(); ++i)
  388. [array addObject:[NSNumber numberWithInt:dailyVisitCounts[i]]];
  389. [dict setObject:array forKey:dailyVisitCountKey];
  390. [array release];
  391. }
  392. const Vector<int>& weeklyVisitCounts = coreItem->weeklyVisitCounts();
  393. if (weeklyVisitCounts.size()) {
  394. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:5];
  395. for (size_t i = 0; i < weeklyVisitCounts.size(); ++i)
  396. [array addObject:[NSNumber numberWithInt:weeklyVisitCounts[i]]];
  397. [dict setObject:array forKey:weeklyVisitCountKey];
  398. [array release];
  399. }
  400. if (coreItem->children().size()) {
  401. const HistoryItemVector& children = coreItem->children();
  402. NSMutableArray *childDicts = [NSMutableArray arrayWithCapacity:children.size()];
  403. for (int i = children.size() - 1; i >= 0; i--)
  404. [childDicts addObject:[kit(children[i].get()) dictionaryRepresentation]];
  405. [dict setObject: childDicts forKey:childrenKey];
  406. }
  407. return dict;
  408. }
  409. - (NSString *)target
  410. {
  411. ASSERT_MAIN_THREAD();
  412. return nsStringNilIfEmpty(core(_private)->target());
  413. }
  414. - (BOOL)isTargetItem
  415. {
  416. return core(_private)->isTargetItem();
  417. }
  418. - (int)visitCount
  419. {
  420. ASSERT_MAIN_THREAD();
  421. return core(_private)->visitCount();
  422. }
  423. - (NSString *)RSSFeedReferrer
  424. {
  425. return nsStringNilIfEmpty(core(_private)->referrer());
  426. }
  427. - (void)setRSSFeedReferrer:(NSString *)referrer
  428. {
  429. core(_private)->setReferrer(referrer);
  430. }
  431. - (NSArray *)children
  432. {
  433. ASSERT_MAIN_THREAD();
  434. const HistoryItemVector& children = core(_private)->children();
  435. if (!children.size())
  436. return nil;
  437. unsigned size = children.size();
  438. NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:size] autorelease];
  439. for (unsigned i = 0; i < size; ++i)
  440. [result addObject:kit(children[i].get())];
  441. return result;
  442. }
  443. - (void)setAlwaysAttemptToUsePageCache:(BOOL)flag
  444. {
  445. // Safari 2.0 uses this for SnapBack, so we stub it out to avoid a crash.
  446. }
  447. - (NSURL *)URL
  448. {
  449. ASSERT_MAIN_THREAD();
  450. const KURL& url = core(_private)->url();
  451. if (url.isEmpty())
  452. return nil;
  453. return url;
  454. }
  455. // This should not be called directly for WebHistoryItems that are already included
  456. // in WebHistory. Use -[WebHistory setLastVisitedTimeInterval:forItem:] instead.
  457. - (void)_setLastVisitedTimeInterval:(NSTimeInterval)time
  458. {
  459. core(_private)->setLastVisitedTime(time);
  460. }
  461. // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
  462. // Once that task is complete, this accessor can go away
  463. - (NSCalendarDate *)_lastVisitedDate
  464. {
  465. ASSERT_MAIN_THREAD();
  466. return [[[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:core(_private)->lastVisitedTime()] autorelease];
  467. }
  468. - (WebHistoryItem *)targetItem
  469. {
  470. ASSERT_MAIN_THREAD();
  471. return kit(core(_private)->targetItem());
  472. }
  473. + (void)_releaseAllPendingPageCaches
  474. {
  475. }
  476. - (id)_transientPropertyForKey:(NSString *)key
  477. {
  478. return core(_private)->getTransientProperty(key);
  479. }
  480. - (void)_setTransientProperty:(id)property forKey:(NSString *)key
  481. {
  482. core(_private)->setTransientProperty(key, property);
  483. }
  484. - (BOOL)lastVisitWasFailure
  485. {
  486. return core(_private)->lastVisitWasFailure();
  487. }
  488. - (void)_setLastVisitWasFailure:(BOOL)failure
  489. {
  490. core(_private)->setLastVisitWasFailure(failure);
  491. }
  492. - (BOOL)_lastVisitWasHTTPNonGet
  493. {
  494. return core(_private)->lastVisitWasHTTPNonGet();
  495. }
  496. - (NSArray *)_redirectURLs
  497. {
  498. Vector<String>* redirectURLs = core(_private)->redirectURLs();
  499. if (!redirectURLs)
  500. return nil;
  501. size_t size = redirectURLs->size();
  502. ASSERT(size);
  503. NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:size];
  504. for (size_t i = 0; i < size; ++i)
  505. [result addObject:(NSString*)redirectURLs->at(i)];
  506. return [result autorelease];
  507. }
  508. - (size_t)_getDailyVisitCounts:(const int**)counts
  509. {
  510. HistoryItem* coreItem = core(_private);
  511. *counts = coreItem->dailyVisitCounts().data();
  512. return coreItem->dailyVisitCounts().size();
  513. }
  514. - (size_t)_getWeeklyVisitCounts:(const int**)counts
  515. {
  516. HistoryItem* coreItem = core(_private);
  517. *counts = coreItem->weeklyVisitCounts().data();
  518. return coreItem->weeklyVisitCounts().size();
  519. }
  520. - (BOOL)_isInPageCache
  521. {
  522. return core(_private)->isInPageCache();
  523. }
  524. - (BOOL)_hasCachedPageExpired
  525. {
  526. return core(_private)->hasCachedPageExpired();
  527. }
  528. @end