Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKitLegacy / mac / History / WebHistoryItem.mm
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 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
29 #import "WebHistoryItemInternal.h"
30 #import "WebHistoryItemPrivate.h"
31
32 #import "WebFrameInternal.h"
33 #import "WebFrameView.h"
34 #import "WebHTMLViewInternal.h"
35 #import "WebIconDatabase.h"
36 #import "WebKitLogging.h"
37 #import "WebKitNSStringExtras.h"
38 #import "WebNSDictionaryExtras.h"
39 #import "WebNSObjectExtras.h"
40 #import "WebNSURLExtras.h"
41 #import "WebNSURLRequestExtras.h"
42 #import "WebNSViewExtras.h"
43 #import "WebPluginController.h"
44 #import "WebTypesInternal.h"
45 #import <JavaScriptCore/InitializeThreading.h>
46 #import <WebCore/HistoryItem.h>
47 #import <WebCore/Image.h>
48 #import <WebCore/PageCache.h>
49 #import <WebCore/ThreadCheck.h>
50 #import <WebCore/WebCoreObjCExtras.h>
51 #import <wtf/Assertions.h>
52 #import <wtf/MainThread.h>
53 #import <wtf/NeverDestroyed.h>
54 #import <wtf/RunLoop.h>
55 #import <wtf/StdLibExtras.h>
56 #import <wtf/URL.h>
57 #import <wtf/text/WTFString.h>
58
59 #if PLATFORM(IOS_FAMILY)
60 #import <WebCore/WebCoreThreadMessage.h>
61
62 NSString *WebViewportInitialScaleKey = @"initial-scale";
63 NSString *WebViewportMinimumScaleKey = @"minimum-scale";
64 NSString *WebViewportMaximumScaleKey = @"maximum-scale";
65 NSString *WebViewportUserScalableKey = @"user-scalable";
66 NSString *WebViewportShrinkToFitKey  = @"shrink-to-fit";
67 NSString *WebViewportFitKey          = @"viewport-fit";
68 NSString *WebViewportWidthKey        = @"width";
69 NSString *WebViewportHeightKey       = @"height";
70
71 NSString *WebViewportFitAutoValue    = @"auto";
72 NSString *WebViewportFitContainValue = @"contain";
73 NSString *WebViewportFitCoverValue   = @"cover";
74
75 static NSString *scaleKey = @"scale";
76 static NSString *scaleIsInitialKey = @"scaleIsInitial";
77 static NSString *scrollPointXKey = @"scrollPointX";
78 static NSString *scrollPointYKey = @"scrollPointY";
79 #endif
80
81 // Private keys used in the WebHistoryItem's dictionary representation.
82 // see 3245793 for explanation of "lastVisitedDate"
83 static NSString *lastVisitedTimeIntervalKey = @"lastVisitedDate";
84 static NSString *titleKey = @"title";
85 static NSString *childrenKey = @"children";
86 static NSString *displayTitleKey = @"displayTitle";
87 static NSString *lastVisitWasFailureKey = @"lastVisitWasFailure";
88 static NSString *redirectURLsKey = @"redirectURLs";
89
90 // Notification strings.
91 NSString *WebHistoryItemChangedNotification = @"WebHistoryItemChangedNotification";
92
93 using namespace WebCore;
94
95 @implementation WebHistoryItemPrivate
96
97 @end
98
99 typedef HashMap<HistoryItem*, WebHistoryItem*> HistoryItemMap;
100
101 static inline WebCoreHistoryItem* core(WebHistoryItemPrivate* itemPrivate)
102 {
103     return itemPrivate->_historyItem.get();
104 }
105
106 static HistoryItemMap& historyItemWrappers()
107 {
108     static NeverDestroyed<HistoryItemMap> historyItemWrappers;
109     return historyItemWrappers;
110 }
111
112 void WKNotifyHistoryItemChanged(HistoryItem&)
113 {
114 #if !PLATFORM(IOS_FAMILY)
115     [[NSNotificationCenter defaultCenter]
116         postNotificationName:WebHistoryItemChangedNotification object:nil userInfo:nil];
117 #else
118     WebThreadPostNotification(WebHistoryItemChangedNotification, nil, nil);
119 #endif
120 }
121
122 @implementation WebHistoryItem
123
124 + (void)initialize
125 {
126 #if !PLATFORM(IOS_FAMILY)
127     JSC::initializeThreading();
128     WTF::initializeMainThreadToProcessMainThread();
129     RunLoop::initializeMainRunLoop();
130 #endif
131 }
132
133 - (instancetype)init
134 {
135     return [self initWithWebCoreHistoryItem:HistoryItem::create()];
136 }
137
138 - (instancetype)initWithURLString:(NSString *)URLString title:(NSString *)title lastVisitedTimeInterval:(NSTimeInterval)time
139 {
140     WebCoreThreadViolationCheckRoundOne();
141
142     WebHistoryItem *item = [self initWithWebCoreHistoryItem:HistoryItem::create(URLString, title)];
143     item->_private->_lastVisitedTime = time;
144
145     return item;
146 }
147
148 - (void)dealloc
149 {
150     if (WebCoreObjCScheduleDeallocateOnMainThread([WebHistoryItem class], self))
151         return;
152
153     historyItemWrappers().remove(_private->_historyItem.get());
154     [_private release];
155
156     [super dealloc];
157 }
158
159 - (id)copyWithZone:(NSZone *)zone
160 {
161     WebCoreThreadViolationCheckRoundOne();
162     WebHistoryItem *copy = [[[self class] alloc] initWithWebCoreHistoryItem:core(_private)->copy()];
163
164     copy->_private->_lastVisitedTime = _private->_lastVisitedTime;
165
166     historyItemWrappers().set(core(copy->_private), copy);
167
168     return copy;
169 }
170
171 // FIXME: Need to decide if this class ever returns URLs and decide on the name of this method
172 - (NSString *)URLString
173 {
174     return nsStringNilIfEmpty(core(_private)->urlString());
175 }
176
177 // The first URL we loaded to get to where this history item points.  Includes both client
178 // and server redirects.
179 - (NSString *)originalURLString
180 {
181     return nsStringNilIfEmpty(core(_private)->originalURLString());
182 }
183
184 - (NSString *)title
185 {
186     return nsStringNilIfEmpty(core(_private)->title());
187 }
188
189 - (void)setAlternateTitle:(NSString *)alternateTitle
190 {
191     core(_private)->setAlternateTitle(alternateTitle);
192 }
193
194 - (NSString *)alternateTitle
195 {
196     return nsStringNilIfEmpty(core(_private)->alternateTitle());
197 }
198
199 #if !PLATFORM(IOS_FAMILY)
200 - (NSImage *)icon
201 {
202     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
203     return [[WebIconDatabase sharedIconDatabase] iconForURL:[self URLString] withSize:WebIconSmallSize];
204     ALLOW_DEPRECATED_DECLARATIONS_END
205 }
206 #endif
207
208 - (NSTimeInterval)lastVisitedTimeInterval
209 {
210     return _private->_lastVisitedTime;
211 }
212
213 - (NSUInteger)hash
214 {
215     return [(NSString*)core(_private)->urlString() hash];
216 }
217
218 - (BOOL)isEqual:(id)anObject
219 {
220     if (![anObject isMemberOfClass:[WebHistoryItem class]])
221         return NO;
222
223     return core(_private)->urlString() == core(((WebHistoryItem*)anObject)->_private)->urlString();
224 }
225
226 - (NSString *)description
227 {
228     HistoryItem* coreItem = core(_private);
229     NSMutableString *result = [NSMutableString stringWithFormat:@"%@ %@", [super description], (NSString*)coreItem->urlString()];
230     if (!coreItem->target().isEmpty()) {
231         NSString *target = coreItem->target();
232         [result appendFormat:@" in \"%@\"", target];
233     }
234     if (coreItem->isTargetItem()) {
235         [result appendString:@" *target*"];
236     }
237     if (coreItem->formData()) {
238         [result appendString:@" *POST*"];
239     }
240     
241     if (coreItem->children().size()) {
242         const auto& children = coreItem->children();
243         int currPos = [result length];
244         unsigned size = children.size();        
245         for (unsigned i = 0; i < size; ++i) {
246             WebHistoryItem *child = kit(const_cast<HistoryItem*>(children[i].ptr()));
247             [result appendString:@"\n"];
248             [result appendString:[child description]];
249         }
250         // shift all the contents over.  A bit slow, but hey, this is for debugging.
251         NSRange replRange = { static_cast<NSUInteger>(currPos), [result length] - currPos };
252         [result replaceOccurrencesOfString:@"\n" withString:@"\n    " options:0 range:replRange];
253     }
254     
255     return result;
256 }
257
258 HistoryItem* core(WebHistoryItem *item)
259 {
260     if (!item)
261         return 0;
262     
263     ASSERT(historyItemWrappers().get(core(item->_private)) == item);
264
265     return core(item->_private);
266 }
267
268 WebHistoryItem *kit(HistoryItem* item)
269 {
270     if (!item)
271         return nil;
272         
273     WebHistoryItem *kitItem = historyItemWrappers().get(item);
274     if (kitItem)
275         return kitItem;
276     
277     return [[[WebHistoryItem alloc] initWithWebCoreHistoryItem:*item] autorelease];
278 }
279
280 + (WebHistoryItem *)entryWithURL:(NSURL *)URL
281 {
282     return [[[self alloc] initWithURL:URL title:nil] autorelease];
283 }
284
285 - (id)initWithURLString:(NSString *)URLString title:(NSString *)title displayTitle:(NSString *)displayTitle lastVisitedTimeInterval:(NSTimeInterval)time
286 {
287     WebHistoryItem *item = [self initWithWebCoreHistoryItem:HistoryItem::create(URLString, title, displayTitle)];
288
289     item->_private->_lastVisitedTime = time;
290
291     return item;
292 }
293
294 - (id)initWithWebCoreHistoryItem:(Ref<HistoryItem>&&)item
295 {   
296     WebCoreThreadViolationCheckRoundOne();
297     // Need to tell WebCore what function to call for the 
298     // "History Item has Changed" notification - no harm in doing this
299     // everytime a WebHistoryItem is created
300     // Note: We also do this in [WebFrameView initWithFrame:] where we do
301     // other "init before WebKit is used" type things
302     WebCore::notifyHistoryItemChanged = WKNotifyHistoryItemChanged;
303     
304     if (!(self = [super init]))
305         return nil;
306
307     _private = [[WebHistoryItemPrivate alloc] init];
308     _private->_historyItem = WTFMove(item);
309
310     ASSERT(!historyItemWrappers().get(core(_private)));
311     historyItemWrappers().set(core(_private), self);
312     return self;
313 }
314
315 - (void)setTitle:(NSString *)title
316 {
317     core(_private)->setTitle(title);
318 }
319
320 - (void)setViewState:(id)statePList
321 {
322     core(_private)->setViewState(statePList);
323 }
324
325 - (id)initFromDictionaryRepresentation:(NSDictionary *)dict
326 {
327     NSString *URLString = [dict _webkit_stringForKey:@""];
328     NSString *title = [dict _webkit_stringForKey:titleKey];
329
330     // Do an existence check to avoid calling doubleValue on a nil string. Leave
331     // time interval at 0 if there's no value in dict.
332     NSString *timeIntervalString = [dict _webkit_stringForKey:lastVisitedTimeIntervalKey];
333     NSTimeInterval lastVisited = timeIntervalString == nil ? 0 : [timeIntervalString doubleValue];
334
335     self = [self initWithURLString:URLString title:title displayTitle:[dict _webkit_stringForKey:displayTitleKey] lastVisitedTimeInterval:lastVisited];
336     
337     // Check if we've read a broken URL from the file that has non-Latin1 chars.  If so, try to convert
338     // as if it was from user typing.
339     if (![URLString canBeConvertedToEncoding:NSISOLatin1StringEncoding]) {
340         NSURL *tempURL = [NSURL _webkit_URLWithUserTypedString:URLString];
341         ASSERT(tempURL);
342         NSString *newURLString = [tempURL _web_originalDataAsString];
343         core(_private)->setURLString(newURLString);
344         core(_private)->setOriginalURLString(newURLString);
345     } 
346
347     if ([dict _webkit_boolForKey:lastVisitWasFailureKey])
348         core(_private)->setLastVisitWasFailure(true);
349     
350     if (NSArray *redirectURLs = [dict _webkit_arrayForKey:redirectURLsKey]) {
351         auto redirectURLsVector = std::make_unique<Vector<String>>();
352         redirectURLsVector->reserveInitialCapacity([redirectURLs count]);
353
354         for (id redirectURL in redirectURLs) {
355             if (![redirectURL isKindOfClass:[NSString class]])
356                 continue;
357
358             redirectURLsVector->uncheckedAppend((NSString *)redirectURL);
359         }
360
361         _private->_redirectURLs = WTFMove(redirectURLsVector);
362     }
363
364     NSArray *childDicts = [dict objectForKey:childrenKey];
365     if (childDicts) {
366         for (int i = [childDicts count] - 1; i >= 0; i--) {
367             WebHistoryItem *child = [[WebHistoryItem alloc] initFromDictionaryRepresentation:[childDicts objectAtIndex:i]];
368             core(_private)->addChildItem(*core(child->_private));
369             [child release];
370         }
371     }
372
373 #if PLATFORM(IOS_FAMILY)
374     NSNumber *scaleValue = [dict objectForKey:scaleKey];
375     NSNumber *scaleIsInitialValue = [dict objectForKey:scaleIsInitialKey];
376     if (scaleValue && scaleIsInitialValue)
377         core(_private)->setScale([scaleValue floatValue], [scaleIsInitialValue boolValue]);
378
379     if (id viewportArguments = [dict objectForKey:@"WebViewportArguments"])
380         [self _setViewportArguments:viewportArguments];
381
382     NSNumber *scrollPointXValue = [dict objectForKey:scrollPointXKey];
383     NSNumber *scrollPointYValue = [dict objectForKey:scrollPointYKey];
384     if (scrollPointXValue && scrollPointYValue)
385         core(_private)->setScrollPosition(IntPoint([scrollPointXValue intValue], [scrollPointYValue intValue]));
386 #endif
387
388     return self;
389 }
390
391 - (NSPoint)scrollPoint
392 {
393     return core(_private)->scrollPosition();
394 }
395
396 - (void)_visitedWithTitle:(NSString *)title
397 {
398     core(_private)->setTitle(title);
399     _private->_lastVisitedTime = [NSDate timeIntervalSinceReferenceDate];
400 }
401
402 @end
403
404 @implementation WebHistoryItem (WebPrivate)
405
406 - (id)initWithURL:(NSURL *)URL title:(NSString *)title
407 {
408     return [self initWithURLString:[URL _web_originalDataAsString] title:title lastVisitedTimeInterval:0];
409 }
410
411 // FIXME: The only iOS difference here should be whether YES or NO is passed to dictionaryRepresentationIncludingChildren:
412 #if PLATFORM(IOS_FAMILY)
413 - (NSDictionary *)dictionaryRepresentation
414 {
415     return [self dictionaryRepresentationIncludingChildren:YES];
416 }
417
418 - (NSDictionary *)dictionaryRepresentationIncludingChildren:(BOOL)includesChildren
419 #else
420 - (NSDictionary *)dictionaryRepresentation
421 #endif
422 {
423     NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:8];
424
425     HistoryItem* coreItem = core(_private);
426     
427     if (!coreItem->urlString().isEmpty())
428         [dict setObject:(NSString*)coreItem->urlString() forKey:@""];
429     if (!coreItem->title().isEmpty())
430         [dict setObject:(NSString*)coreItem->title() forKey:titleKey];
431     if (!coreItem->alternateTitle().isEmpty())
432         [dict setObject:(NSString*)coreItem->alternateTitle() forKey:displayTitleKey];
433     if (_private->_lastVisitedTime) {
434         // Store as a string to maintain backward compatibility. (See 3245793)
435         [dict setObject:[NSString stringWithFormat:@"%.1lf", _private->_lastVisitedTime]
436                  forKey:lastVisitedTimeIntervalKey];
437     }
438     if (coreItem->lastVisitWasFailure())
439         [dict setObject:[NSNumber numberWithBool:YES] forKey:lastVisitWasFailureKey];
440     if (Vector<String>* redirectURLs = _private->_redirectURLs.get()) {
441         size_t size = redirectURLs->size();
442         ASSERT(size);
443         NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:size];
444         for (size_t i = 0; i < size; ++i)
445             [result addObject:(NSString *)redirectURLs->at(i)];
446         [dict setObject:result forKey:redirectURLsKey];
447         [result release];
448     }
449     
450 #if PLATFORM(IOS_FAMILY)
451     if (includesChildren && coreItem->children().size()) {
452 #else
453     if (coreItem->children().size()) {
454 #endif
455         const auto& children = coreItem->children();
456         NSMutableArray *childDicts = [NSMutableArray arrayWithCapacity:children.size()];
457         
458         for (int i = children.size() - 1; i >= 0; i--)
459             [childDicts addObject:[kit(const_cast<HistoryItem*>(children[i].ptr())) dictionaryRepresentation]];
460         [dict setObject: childDicts forKey:childrenKey];
461     }
462
463 #if PLATFORM(IOS_FAMILY)
464     [dict setObject:[NSNumber numberWithFloat:core(_private)->scale()] forKey:scaleKey];
465     [dict setObject:[NSNumber numberWithBool:core(_private)->scaleIsInitial()] forKey:scaleIsInitialKey];
466
467     NSDictionary *viewportArguments = [self _viewportArguments];
468     if (viewportArguments)
469         [dict setObject:viewportArguments forKey:@"WebViewportArguments"];
470
471     IntPoint scrollPosition = core(_private)->scrollPosition();
472     [dict setObject:[NSNumber numberWithInt:scrollPosition.x()] forKey:scrollPointXKey];
473     [dict setObject:[NSNumber numberWithInt:scrollPosition.y()] forKey:scrollPointYKey];
474 #endif
475
476     return dict;
477 }
478
479 - (NSString *)target
480 {
481     return nsStringNilIfEmpty(core(_private)->target());
482 }
483
484 - (BOOL)isTargetItem
485 {
486     return core(_private)->isTargetItem();
487 }
488
489 - (NSString *)RSSFeedReferrer
490 {
491     return nsStringNilIfEmpty(core(_private)->referrer());
492 }
493
494 - (void)setRSSFeedReferrer:(NSString *)referrer
495 {
496     core(_private)->setReferrer(referrer);
497 }
498
499 - (NSArray *)children
500 {
501     const auto& children = core(_private)->children();
502     if (!children.size())
503         return nil;
504
505     unsigned size = children.size();
506     NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:size] autorelease];
507     
508     for (unsigned i = 0; i < size; ++i)
509         [result addObject:kit(const_cast<HistoryItem*>(children[i].ptr()))];
510     
511     return result;
512 }
513
514 - (NSURL *)URL
515 {
516     const URL& url = core(_private)->url();
517     if (url.isEmpty())
518         return nil;
519     return url;
520 }
521
522 #if !PLATFORM(IOS_FAMILY)
523 + (void)_releaseAllPendingPageCaches
524 {
525 }
526 #endif
527
528 - (BOOL)lastVisitWasFailure
529 {
530     return core(_private)->lastVisitWasFailure();
531 }
532
533 - (NSArray *)_redirectURLs
534 {
535     Vector<String>* redirectURLs = _private->_redirectURLs.get();
536     if (!redirectURLs)
537         return nil;
538
539     size_t size = redirectURLs->size();
540     ASSERT(size);
541     NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:size];
542     for (size_t i = 0; i < size; ++i)
543         [result addObject:(NSString*)redirectURLs->at(i)];
544     return [result autorelease];
545 }
546
547 #if PLATFORM(IOS_FAMILY)
548 - (void)_setScale:(float)scale isInitial:(BOOL)aFlag
549 {
550     core(_private)->setScale(scale, aFlag);
551 }
552
553 - (float)_scale
554 {
555     return core(_private)->scale();
556 }
557
558 - (BOOL)_scaleIsInitial
559 {
560     return core(_private)->scaleIsInitial();
561 }
562
563 - (NSDictionary *)_viewportArguments
564 {
565     const ViewportArguments& viewportArguments = core(_private)->viewportArguments();
566     NSMutableDictionary *argumentsDictionary = [NSMutableDictionary dictionary];
567     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.zoom] forKey:WebViewportInitialScaleKey];
568     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.minZoom] forKey:WebViewportMinimumScaleKey];
569     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.maxZoom] forKey:WebViewportMaximumScaleKey];
570     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.width] forKey:WebViewportWidthKey];
571     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.height] forKey:WebViewportHeightKey];
572     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.userZoom] forKey:WebViewportUserScalableKey];
573     [argumentsDictionary setObject:[NSNumber numberWithFloat:viewportArguments.shrinkToFit] forKey:WebViewportShrinkToFitKey];
574     return argumentsDictionary;
575 }
576
577 - (void)_setViewportArguments:(NSDictionary *)arguments
578 {
579     ViewportArguments viewportArguments;
580     viewportArguments.zoom = [[arguments objectForKey:WebViewportInitialScaleKey] floatValue];
581     viewportArguments.minZoom = [[arguments objectForKey:WebViewportMinimumScaleKey] floatValue];
582     viewportArguments.maxZoom = [[arguments objectForKey:WebViewportMaximumScaleKey] floatValue];
583     viewportArguments.width = [[arguments objectForKey:WebViewportWidthKey] floatValue];
584     viewportArguments.height = [[arguments objectForKey:WebViewportHeightKey] floatValue];
585     viewportArguments.userZoom = [[arguments objectForKey:WebViewportUserScalableKey] floatValue];
586     viewportArguments.shrinkToFit = [[arguments objectForKey:WebViewportShrinkToFitKey] floatValue];
587     core(_private)->setViewportArguments(viewportArguments);
588 }
589
590 - (CGPoint)_scrollPoint
591 {
592     return core(_private)->scrollPosition();
593 }
594
595 - (void)_setScrollPoint:(CGPoint)scrollPoint
596 {
597     core(_private)->setScrollPosition(IntPoint(scrollPoint));
598 }
599
600 #endif // PLATFORM(IOS_FAMILY)
601
602 - (BOOL)_isInPageCache
603 {
604     return core(_private)->isInPageCache();
605 }
606
607 - (BOOL)_hasCachedPageExpired
608 {
609     return core(_private)->hasCachedPageExpired();
610 }
611
612 @end