| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/web/navigation/crw_session_entry.h" | 5 #import "ios/web/navigation/crw_session_entry.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #import "base/mac/scoped_nsobject.h" | 11 #import "base/mac/scoped_nsobject.h" |
| 12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
| 13 #import "ios/web/navigation/navigation_item_impl.h" | 13 #import "ios/web/navigation/navigation_item_impl.h" |
| 14 #import "ios/web/navigation/nscoder_util.h" | 14 #import "ios/web/navigation/nscoder_util.h" |
| 15 #import "ios/web/public/navigation_item.h" | 15 #import "ios/web/public/navigation_item.h" |
| 16 #include "ios/web/public/web_state/page_display_state.h" | 16 #include "ios/web/public/web_state/page_display_state.h" |
| 17 #import "net/base/mac/url_conversions.h" | 17 #import "net/base/mac/url_conversions.h" |
| 18 | 18 |
| 19 #if !defined(__has_feature) || !__has_feature(objc_arc) | 19 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 20 #error "This file requires ARC support." | 20 #error "This file requires ARC support." |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 namespace web { | |
| 24 // Keys used to serialize web::PageScrollState properties. | |
| 25 NSString* const kSessionEntryPageScrollStateKey = @"state"; | |
| 26 NSString* const kSessionEntryScrollOffsetXKey = @"scrollX"; | |
| 27 NSString* const kSessionEntryScrollOffsetYKey = @"scrollY"; | |
| 28 NSString* const kSessionEntryMinimumZoomScaleKey = @"minZoom"; | |
| 29 NSString* const kSessionEntryMaximumZoomScaleKey = @"maxZoom"; | |
| 30 NSString* const kSessionEntryZoomScaleKey = @"zoom"; | |
| 31 | |
| 32 // Keys used to serialize navigation properties. | |
| 33 NSString* const kSessionEntryURLKey = @"virtualUrlString"; | |
| 34 NSString* const kSessionEntryURLDeperecatedKey = @"virtualUrl"; | |
| 35 NSString* const kSessionEntryReferrerURLKey = @"referrerUrlString"; | |
| 36 NSString* const kSessionEntryReferrerURLDeprecatedKey = @"referrer"; | |
| 37 NSString* const kSessionEntryReferrerPolicyKey = @"referrerPolicy"; | |
| 38 NSString* const kSessionEntryTimestampKey = @"timestamp"; | |
| 39 NSString* const kSessionEntryTitleKey = @"title"; | |
| 40 NSString* const kSessionEntryPOSTDataKey = @"POSTData"; | |
| 41 NSString* const kSessionEntryHTTPRequestHeadersKey = @"httpHeaders"; | |
| 42 NSString* const kSessionEntrySkipRepostFormConfirmationKey = | |
| 43 @"skipResubmitDataConfirmation"; | |
| 44 NSString* const kSessionEntryUseDesktopUserAgentKey = @"useDesktopUserAgent"; | |
| 45 } | |
| 46 | |
| 47 @interface CRWSessionEntry () { | 23 @interface CRWSessionEntry () { |
| 48 // The NavigationItemImpl corresponding to this CRWSessionEntry. | 24 // The NavigationItemImpl corresponding to this CRWSessionEntry. |
| 49 // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. | 25 // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. |
| 50 std::unique_ptr<web::NavigationItemImpl> _navigationItem; | 26 std::unique_ptr<web::NavigationItemImpl> _navigationItem; |
| 51 } | 27 } |
| 52 | 28 |
| 53 // Converts a serialized NSDictionary to a web::PageDisplayState. | |
| 54 + (web::PageDisplayState)pageDisplayStateFromDictionary: | |
| 55 (NSDictionary*)dictionary; | |
| 56 // Serializes a web::PageDisplayState to an NSDictionary. | |
| 57 + (NSDictionary*)dictionaryFromPageDisplayState: | |
| 58 (const web::PageDisplayState&)displayState; | |
| 59 // Returns a readable description of |displayState|. | |
| 60 + (NSString*)descriptionForPageDisplayState: | |
| 61 (const web::PageDisplayState&)displayState; | |
| 62 @end | 29 @end |
| 63 | 30 |
| 64 @implementation CRWSessionEntry | 31 @implementation CRWSessionEntry |
| 65 | 32 |
| 66 - (instancetype)initWithNavigationItem: | 33 - (instancetype)initWithNavigationItem: |
| 67 (std::unique_ptr<web::NavigationItem>)item { | 34 (std::unique_ptr<web::NavigationItem>)item { |
| 68 self = [super init]; | 35 self = [super init]; |
| 69 if (self) { | 36 if (self) { |
| 70 _navigationItem.reset( | 37 _navigationItem.reset( |
| 71 static_cast<web::NavigationItemImpl*>(item.release())); | 38 static_cast<web::NavigationItemImpl*>(item.release())); |
| 72 } | 39 } |
| 73 return self; | 40 return self; |
| 74 } | 41 } |
| 75 | 42 |
| 76 - (instancetype)initWithCoder:(NSCoder*)aDecoder { | |
| 77 self = [super init]; | |
| 78 if (self) { | |
| 79 _navigationItem.reset(new web::NavigationItemImpl()); | |
| 80 | |
| 81 // Desktop chrome only persists virtualUrl_ and uses it to feed the url | |
| 82 // when creating a NavigationEntry. | |
| 83 GURL url; | |
| 84 if ([aDecoder containsValueForKey:web::kSessionEntryURLKey]) { | |
| 85 url = GURL( | |
| 86 web::nscoder_util::DecodeString(aDecoder, web::kSessionEntryURLKey)); | |
| 87 } else { | |
| 88 // Backward compatibility. | |
| 89 url = net::GURLWithNSURL( | |
| 90 [aDecoder decodeObjectForKey:web::kSessionEntryURLDeperecatedKey]); | |
| 91 } | |
| 92 _navigationItem->SetOriginalRequestURL(url); | |
| 93 _navigationItem->SetURL(url); | |
| 94 | |
| 95 if ([aDecoder containsValueForKey:web::kSessionEntryReferrerURLKey]) { | |
| 96 const std::string referrerString(web::nscoder_util::DecodeString( | |
| 97 aDecoder, web::kSessionEntryReferrerURLKey)); | |
| 98 web::ReferrerPolicy referrerPolicy = static_cast<web::ReferrerPolicy>( | |
| 99 [aDecoder decodeIntForKey:web::kSessionEntryReferrerPolicyKey]); | |
| 100 _navigationItem->SetReferrer( | |
| 101 web::Referrer(GURL(referrerString), referrerPolicy)); | |
| 102 } else { | |
| 103 // Backward compatibility. | |
| 104 NSURL* referrer = [aDecoder | |
| 105 decodeObjectForKey:web::kSessionEntryReferrerURLDeprecatedKey]; | |
| 106 _navigationItem->SetReferrer(web::Referrer( | |
| 107 net::GURLWithNSURL(referrer), web::ReferrerPolicyDefault)); | |
| 108 } | |
| 109 | |
| 110 if ([aDecoder containsValueForKey:web::kSessionEntryTimestampKey]) { | |
| 111 int64_t us = [aDecoder decodeInt64ForKey:web::kSessionEntryTimestampKey]; | |
| 112 _navigationItem->SetTimestamp(base::Time::FromInternalValue(us)); | |
| 113 } | |
| 114 | |
| 115 NSString* title = [aDecoder decodeObjectForKey:web::kSessionEntryTitleKey]; | |
| 116 // Use a transition type of reload so that we don't incorrectly increase | |
| 117 // the typed count. This is what desktop chrome does. | |
| 118 _navigationItem->SetTitle(base::SysNSStringToUTF16(title)); | |
| 119 _navigationItem->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); | |
| 120 _navigationItem->SetPageDisplayState([[self class] | |
| 121 pageDisplayStateFromDictionary: | |
| 122 [aDecoder | |
| 123 decodeObjectForKey:web::kSessionEntryPageScrollStateKey]]); | |
| 124 _navigationItem->SetShouldSkipRepostFormConfirmation([aDecoder | |
| 125 decodeBoolForKey:web::kSessionEntrySkipRepostFormConfirmationKey]); | |
| 126 _navigationItem->SetIsOverridingUserAgent( | |
| 127 [aDecoder decodeBoolForKey:web::kSessionEntryUseDesktopUserAgentKey]); | |
| 128 _navigationItem->SetPostData( | |
| 129 [aDecoder decodeObjectForKey:web::kSessionEntryPOSTDataKey]); | |
| 130 _navigationItem->AddHttpRequestHeaders( | |
| 131 [aDecoder decodeObjectForKey:web::kSessionEntryHTTPRequestHeadersKey]); | |
| 132 } | |
| 133 return self; | |
| 134 } | |
| 135 | |
| 136 - (void)encodeWithCoder:(NSCoder*)aCoder { | |
| 137 // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only | |
| 138 // |virtualUrl_|. | |
| 139 web::nscoder_util::EncodeString(aCoder, web::kSessionEntryURLKey, | |
| 140 _navigationItem->GetVirtualURL().spec()); | |
| 141 web::nscoder_util::EncodeString(aCoder, web::kSessionEntryReferrerURLKey, | |
| 142 _navigationItem->GetReferrer().url.spec()); | |
| 143 [aCoder encodeInt:_navigationItem->GetReferrer().policy | |
| 144 forKey:web::kSessionEntryReferrerPolicyKey]; | |
| 145 [aCoder encodeInt64:_navigationItem->GetTimestamp().ToInternalValue() | |
| 146 forKey:web::kSessionEntryTimestampKey]; | |
| 147 | |
| 148 [aCoder encodeObject:base::SysUTF16ToNSString(_navigationItem->GetTitle()) | |
| 149 forKey:web::kSessionEntryTitleKey]; | |
| 150 [aCoder encodeObject:[[self class] dictionaryFromPageDisplayState: | |
| 151 _navigationItem->GetPageDisplayState()] | |
| 152 forKey:web::kSessionEntryPageScrollStateKey]; | |
| 153 [aCoder encodeBool:_navigationItem->ShouldSkipRepostFormConfirmation() | |
| 154 forKey:web::kSessionEntrySkipRepostFormConfirmationKey]; | |
| 155 [aCoder encodeBool:_navigationItem->IsOverridingUserAgent() | |
| 156 forKey:web::kSessionEntryUseDesktopUserAgentKey]; | |
| 157 [aCoder encodeObject:_navigationItem->GetPostData() | |
| 158 forKey:web::kSessionEntryPOSTDataKey]; | |
| 159 [aCoder encodeObject:_navigationItem->GetHttpRequestHeaders() | |
| 160 forKey:web::kSessionEntryHTTPRequestHeadersKey]; | |
| 161 } | |
| 162 | |
| 163 // TODO(ios): Shall we overwrite EqualTo:? | 43 // TODO(ios): Shall we overwrite EqualTo:? |
| 164 | 44 |
| 165 - (instancetype)copyWithZone:(NSZone*)zone { | 45 - (instancetype)copyWithZone:(NSZone*)zone { |
| 166 CRWSessionEntry* copy = [[[self class] alloc] init]; | 46 CRWSessionEntry* copy = [[[self class] alloc] init]; |
| 167 copy->_navigationItem.reset( | 47 copy->_navigationItem.reset( |
| 168 new web::NavigationItemImpl(*_navigationItem.get())); | 48 new web::NavigationItemImpl(*_navigationItem.get())); |
| 169 return copy; | 49 return copy; |
| 170 } | 50 } |
| 171 | 51 |
| 172 - (NSString*)description { | 52 - (NSString*)description { |
| 173 return [NSString | 53 return [NSString |
| 174 stringWithFormat: | 54 stringWithFormat: |
| 175 @"url:%@ originalurl:%@ title:%@ transition:%d displayState:%@ " | 55 @"url:%@ originalurl:%@ title:%@ transition:%d displayState:%@ " |
| 176 @"desktopUA:%d", | 56 @"desktopUA:%d", |
| 177 base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), | 57 base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), |
| 178 base::SysUTF8ToNSString( | 58 base::SysUTF8ToNSString( |
| 179 _navigationItem->GetOriginalRequestURL().spec()), | 59 _navigationItem->GetOriginalRequestURL().spec()), |
| 180 base::SysUTF16ToNSString(_navigationItem->GetTitle()), | 60 base::SysUTF16ToNSString(_navigationItem->GetTitle()), |
| 181 _navigationItem->GetTransitionType(), | 61 _navigationItem->GetTransitionType(), |
| 182 [[self class] | 62 _navigationItem->GetPageDisplayState().GetDescription(), |
| 183 descriptionForPageDisplayState:_navigationItem | |
| 184 ->GetPageDisplayState()], | |
| 185 _navigationItem->IsOverridingUserAgent()]; | 63 _navigationItem->IsOverridingUserAgent()]; |
| 186 } | 64 } |
| 187 | 65 |
| 188 - (web::NavigationItem*)navigationItem { | 66 - (web::NavigationItem*)navigationItem { |
| 189 return _navigationItem.get(); | 67 return _navigationItem.get(); |
| 190 } | 68 } |
| 191 | 69 |
| 192 - (web::NavigationItemImpl*)navigationItemImpl { | 70 - (web::NavigationItemImpl*)navigationItemImpl { |
| 193 return _navigationItem.get(); | 71 return _navigationItem.get(); |
| 194 } | 72 } |
| 195 | 73 |
| 196 #pragma mark - Serialization helpers | |
| 197 | |
| 198 + (web::PageDisplayState)pageDisplayStateFromDictionary: | |
| 199 (NSDictionary*)dictionary { | |
| 200 NSNumber* serializedValue = nil; | |
| 201 web::PageScrollState scrollState; | |
| 202 if ((serializedValue = dictionary[web::kSessionEntryScrollOffsetXKey])) | |
| 203 scrollState.set_offset_x([serializedValue doubleValue]); | |
| 204 if ((serializedValue = dictionary[web::kSessionEntryScrollOffsetYKey])) | |
| 205 scrollState.set_offset_y([serializedValue doubleValue]); | |
| 206 web::PageZoomState zoomState; | |
| 207 if ((serializedValue = dictionary[web::kSessionEntryMinimumZoomScaleKey])) | |
| 208 zoomState.set_minimum_zoom_scale([serializedValue doubleValue]); | |
| 209 if ((serializedValue = dictionary[web::kSessionEntryMaximumZoomScaleKey])) | |
| 210 zoomState.set_maximum_zoom_scale([serializedValue doubleValue]); | |
| 211 if ((serializedValue = dictionary[web::kSessionEntryZoomScaleKey])) | |
| 212 zoomState.set_zoom_scale([serializedValue doubleValue]); | |
| 213 return web::PageDisplayState(scrollState, zoomState); | |
| 214 } | |
| 215 | |
| 216 + (NSDictionary*)dictionaryFromPageDisplayState: | |
| 217 (const web::PageDisplayState&)displayState { | |
| 218 return @{ | |
| 219 web::kSessionEntryScrollOffsetXKey : | |
| 220 @(displayState.scroll_state().offset_x()), | |
| 221 web::kSessionEntryScrollOffsetYKey : | |
| 222 @(displayState.scroll_state().offset_y()), | |
| 223 web::kSessionEntryMinimumZoomScaleKey : | |
| 224 @(displayState.zoom_state().minimum_zoom_scale()), | |
| 225 web::kSessionEntryMaximumZoomScaleKey : | |
| 226 @(displayState.zoom_state().maximum_zoom_scale()), | |
| 227 web::kSessionEntryZoomScaleKey : | |
| 228 @(displayState.zoom_state().zoom_scale()) | |
| 229 }; | |
| 230 } | |
| 231 | |
| 232 + (NSString*)descriptionForPageDisplayState: | |
| 233 (const web::PageDisplayState&)displayState { | |
| 234 NSString* const kPageScrollStateDescriptionFormat = | |
| 235 @"{ scrollOffset:(%0.2f, %0.2f), zoomScaleRange:(%0.2f, %0.2f), " | |
| 236 @"zoomScale:%0.2f }"; | |
| 237 return | |
| 238 [NSString stringWithFormat:kPageScrollStateDescriptionFormat, | |
| 239 displayState.scroll_state().offset_x(), | |
| 240 displayState.scroll_state().offset_y(), | |
| 241 displayState.zoom_state().minimum_zoom_scale(), | |
| 242 displayState.zoom_state().maximum_zoom_scale(), | |
| 243 displayState.zoom_state().zoom_scale()]; | |
| 244 } | |
| 245 | |
| 246 @end | 74 @end |
| OLD | NEW |