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 #import "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 |