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