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 "base/mac/objc_property_releaser.h" | 7 #include "base/mac/objc_property_releaser.h" |
8 #include "base/mac/scoped_nsobject.h" | 8 #include "base/mac/scoped_nsobject.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
11 #include "ios/web/navigation/navigation_item_impl.h" | 11 #include "ios/web/navigation/navigation_item_impl.h" |
12 #include "ios/web/navigation/nscoder_util.h" | 12 #include "ios/web/navigation/nscoder_util.h" |
13 #include "ios/web/public/navigation_item.h" | 13 #include "ios/web/public/navigation_item.h" |
14 #include "ios/web/public/web_state/page_scroll_state.h" | 14 #include "ios/web/public/web_state/page_scroll_state.h" |
15 #import "net/base/mac/url_conversions.h" | 15 #import "net/base/mac/url_conversions.h" |
16 | 16 |
17 namespace { | 17 namespace { |
18 // Keys used to serialize web::PageScrollState properties. | 18 // Keys used to serialize web::PageScrollState properties. |
19 NSString* const kScrollOffsetXKey = @"scrollX"; | 19 NSString* const kScrollOffsetXKey = @"scrollX"; |
20 NSString* const kScrollOffsetYKey = @"scrollY"; | 20 NSString* const kScrollOffsetYKey = @"scrollY"; |
21 NSString* const kMinimumZoomScaleKey = @"minZoom"; | 21 NSString* const kMinimumZoomScaleKey = @"minZoom"; |
22 NSString* const kMaximumZoomScaleKey = @"maxZoom"; | 22 NSString* const kMaximumZoomScaleKey = @"maxZoom"; |
23 NSString* const kZoomScaleKey = @"zoom"; | 23 NSString* const kZoomScaleKey = @"zoom"; |
24 } | 24 } |
25 | 25 |
26 @interface CRWSessionEntry () { | 26 @interface CRWSessionEntry () { |
27 // The index in the CRWSessionController. | |
28 // | |
29 // This is used when determining the selected CRWSessionEntry and only useful | |
30 // to the SessionServiceIOS. | |
31 NSInteger _index; | |
32 | |
33 // The original URL of the page. In cases where a redirect occurred, |url_| | 27 // The original URL of the page. In cases where a redirect occurred, |url_| |
34 // will contain the final post-redirect URL, and |originalUrl_| will contain | 28 // will contain the final post-redirect URL, and |originalUrl_| will contain |
35 // the pre-redirect URL. This field is not persisted to disk. | 29 // the pre-redirect URL. This field is not persisted to disk. |
36 GURL _originalUrl; | 30 GURL _originalUrl; |
37 | 31 |
38 // Headers passed along with the request. For POST requests, these are | |
39 // persisted, to be able to resubmit them. Some specialized non-POST requests | |
40 // may also pass custom headers. | |
41 base::scoped_nsobject<NSMutableDictionary> _httpHeaders; | |
42 | |
43 // Data submitted with a POST request, persisted for resubmits. | |
44 NSData* _POSTData; | |
45 | |
46 // Serialized representation of the state object that was used in conjunction | |
47 // with a JavaScript window.history.pushState() or | |
48 // window.history.replaceState() call that created or modified this | |
49 // CRWSessionEntry. Intended to be used for JavaScript history operations and | |
50 // will be nil in most cases. | |
51 NSString* _serializedStateObject; | |
52 | |
53 // Whether or not this entry was created by calling history.pushState(). | |
54 BOOL _createdFromPushState; | |
55 | |
56 // If |YES| use a desktop user agent in HTTP requests and UIWebView. | |
57 BOOL _useDesktopUserAgent; | |
58 | |
59 // If |YES| the page was last fetched through the data reduction proxy. | |
60 BOOL _usedDataReductionProxy; | |
61 | |
62 // Whether or not to bypass showing the resubmit data confirmation when | |
63 // loading a POST request. Set to YES for browser-generated POST requests such | |
64 // as search-by-image requests. | |
65 BOOL _skipResubmitDataConfirmation; | |
66 | |
67 // The NavigationItemImpl corresponding to this CRWSessionEntry. | 32 // The NavigationItemImpl corresponding to this CRWSessionEntry. |
68 // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. | 33 // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. |
69 scoped_ptr<web::NavigationItemImpl> _navigationItem; | 34 scoped_ptr<web::NavigationItemImpl> _navigationItem; |
70 | 35 |
71 base::mac::ObjCPropertyReleaser _propertyReleaser_CRWSessionEntry; | 36 base::mac::ObjCPropertyReleaser _propertyReleaser_CRWSessionEntry; |
72 } | 37 } |
73 // Redefine originalUrl to be read-write. | 38 // Redefine originalUrl to be read-write. |
74 @property(nonatomic, readwrite) const GURL& originalUrl; | 39 @property(nonatomic, readwrite) const GURL& originalUrl; |
75 | 40 |
76 // Converts a serialized NSDictionary to a web::PageScrollState. | 41 // Converts a serialized NSDictionary to a web::PageScrollState. |
77 + (web::PageScrollState)scrollStateFromDictionary:(NSDictionary*)dictionary; | 42 + (web::PageScrollState)scrollStateFromDictionary:(NSDictionary*)dictionary; |
78 // Serializes a web::PageScrollState to an NSDictionary. | 43 // Serializes a web::PageScrollState to an NSDictionary. |
79 + (NSDictionary*)dictionaryFromScrollState: | 44 + (NSDictionary*)dictionaryFromScrollState: |
80 (const web::PageScrollState&)scrollState; | 45 (const web::PageScrollState&)scrollState; |
81 // Returns a readable description of |scrollState|. | 46 // Returns a readable description of |scrollState|. |
82 + (NSString*)scrollStateDescription:(const web::PageScrollState&)scrollState; | 47 + (NSString*)scrollStateDescription:(const web::PageScrollState&)scrollState; |
83 @end | 48 @end |
84 | 49 |
85 @implementation CRWSessionEntry | 50 @implementation CRWSessionEntry |
86 | 51 |
87 @synthesize POSTData = _POSTData; | |
88 @synthesize originalUrl = _originalUrl; | 52 @synthesize originalUrl = _originalUrl; |
89 @synthesize useDesktopUserAgent = _useDesktopUserAgent; | |
90 @synthesize usedDataReductionProxy = _usedDataReductionProxy; | |
91 @synthesize index = _index; | |
92 @synthesize serializedStateObject = _serializedStateObject; | |
93 @synthesize createdFromPushState = _createdFromPushState; | |
94 @synthesize skipResubmitDataConfirmation = _skipResubmitDataConfirmation; | |
95 | 53 |
96 // Creates a new session entry. These may be nil. | 54 - (instancetype)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item { |
97 - (instancetype)initWithUrl:(const GURL&)url | |
98 referrer:(const web::Referrer&)referrer | |
99 transition:(ui::PageTransition)transition | |
100 useDesktopUserAgent:(BOOL)useDesktopUserAgent | |
101 rendererInitiated:(BOOL)rendererInitiated { | |
102 self = [super init]; | |
103 if (self) { | |
104 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); | |
105 _navigationItem.reset(new web::NavigationItemImpl()); | |
106 | |
107 _navigationItem->SetURL(url); | |
108 _navigationItem->SetReferrer(referrer); | |
109 _navigationItem->SetTransitionType(transition); | |
110 _navigationItem->set_is_renderer_initiated(rendererInitiated); | |
111 | |
112 self.originalUrl = url; | |
113 self.useDesktopUserAgent = useDesktopUserAgent; | |
114 } | |
115 return self; | |
116 } | |
117 | |
118 - (instancetype)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item | |
119 index:(int)index { | |
120 self = [super init]; | 55 self = [super init]; |
121 if (self) { | 56 if (self) { |
122 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); | 57 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); |
123 _navigationItem.reset( | 58 _navigationItem.reset( |
124 static_cast<web::NavigationItemImpl*>(item.release())); | 59 static_cast<web::NavigationItemImpl*>(item.release())); |
125 | |
126 self.index = index; | |
127 self.originalUrl = _navigationItem->GetURL(); | 60 self.originalUrl = _navigationItem->GetURL(); |
128 self.useDesktopUserAgent = NO; | |
129 } | 61 } |
130 return self; | 62 return self; |
131 } | 63 } |
132 | 64 |
133 - (instancetype)initWithCoder:(NSCoder*)aDecoder { | 65 - (instancetype)initWithCoder:(NSCoder*)aDecoder { |
134 self = [super init]; | 66 self = [super init]; |
135 if (self) { | 67 if (self) { |
136 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); | 68 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); |
137 _navigationItem.reset(new web::NavigationItemImpl()); | 69 _navigationItem.reset(new web::NavigationItemImpl()); |
138 | 70 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 102 } |
171 | 103 |
172 NSString* title = [aDecoder decodeObjectForKey:@"title"]; | 104 NSString* title = [aDecoder decodeObjectForKey:@"title"]; |
173 // Use a transition type of reload so that we don't incorrectly increase | 105 // Use a transition type of reload so that we don't incorrectly increase |
174 // the typed count. This is what desktop chrome does. | 106 // the typed count. This is what desktop chrome does. |
175 _navigationItem->SetPageID(-1); | 107 _navigationItem->SetPageID(-1); |
176 _navigationItem->SetTitle(base::SysNSStringToUTF16(title)); | 108 _navigationItem->SetTitle(base::SysNSStringToUTF16(title)); |
177 _navigationItem->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); | 109 _navigationItem->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); |
178 _navigationItem->SetPageScrollState([[self class] | 110 _navigationItem->SetPageScrollState([[self class] |
179 scrollStateFromDictionary:[aDecoder decodeObjectForKey:@"state"]]); | 111 scrollStateFromDictionary:[aDecoder decodeObjectForKey:@"state"]]); |
180 self.index = [aDecoder decodeIntForKey:@"index"]; | 112 _navigationItem->SetShouldSkipResubmitDataConfirmation( |
181 self.useDesktopUserAgent = | 113 [aDecoder decodeBoolForKey:@"skipResubmitDataConfirmation"]); |
182 [aDecoder decodeBoolForKey:@"useDesktopUserAgent"]; | 114 _navigationItem->SetIsOverridingUserAgent( |
183 self.usedDataReductionProxy = | 115 [aDecoder decodeBoolForKey:@"useDesktopUserAgent"]); |
184 [aDecoder decodeBoolForKey:@"usedDataReductionProxy"]; | 116 _navigationItem->SetPostData([aDecoder decodeObjectForKey:@"POSTData"]); |
185 [self addHTTPHeaders:[aDecoder decodeObjectForKey:@"httpHeaders"]]; | 117 _navigationItem->AddHttpRequestHeaders( |
186 self.POSTData = [aDecoder decodeObjectForKey:@"POSTData"]; | 118 [aDecoder decodeObjectForKey:@"httpHeaders"]); |
187 self.skipResubmitDataConfirmation = | |
188 [aDecoder decodeBoolForKey:@"skipResubmitDataConfirmation"]; | |
189 } | 119 } |
190 return self; | 120 return self; |
191 } | 121 } |
192 | 122 |
193 - (void)encodeWithCoder:(NSCoder*)aCoder { | 123 - (void)encodeWithCoder:(NSCoder*)aCoder { |
194 // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only | 124 // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only |
195 // |virtualUrl_|. | 125 // |virtualUrl_|. |
196 [aCoder encodeInt:self.index forKey:@"index"]; | |
197 web::nscoder_util::EncodeString(aCoder, @"virtualUrlString", | 126 web::nscoder_util::EncodeString(aCoder, @"virtualUrlString", |
198 _navigationItem->GetVirtualURL().spec()); | 127 _navigationItem->GetVirtualURL().spec()); |
199 web::nscoder_util::EncodeString(aCoder, @"referrerUrlString", | 128 web::nscoder_util::EncodeString(aCoder, @"referrerUrlString", |
200 _navigationItem->GetReferrer().url.spec()); | 129 _navigationItem->GetReferrer().url.spec()); |
201 [aCoder encodeInt:_navigationItem->GetReferrer().policy | 130 [aCoder encodeInt:_navigationItem->GetReferrer().policy |
202 forKey:@"referrerPolicy"]; | 131 forKey:@"referrerPolicy"]; |
203 [aCoder encodeInt64:_navigationItem->GetTimestamp().ToInternalValue() | 132 [aCoder encodeInt64:_navigationItem->GetTimestamp().ToInternalValue() |
204 forKey:@"timestamp"]; | 133 forKey:@"timestamp"]; |
205 | 134 |
206 [aCoder encodeObject:base::SysUTF16ToNSString(_navigationItem->GetTitle()) | 135 [aCoder encodeObject:base::SysUTF16ToNSString(_navigationItem->GetTitle()) |
207 forKey:@"title"]; | 136 forKey:@"title"]; |
208 [aCoder encodeObject:[[self class] dictionaryFromScrollState: | 137 [aCoder encodeObject:[[self class] dictionaryFromScrollState: |
209 _navigationItem->GetPageScrollState()] | 138 _navigationItem->GetPageScrollState()] |
210 forKey:@"state"]; | 139 forKey:@"state"]; |
211 [aCoder encodeBool:self.useDesktopUserAgent forKey:@"useDesktopUserAgent"]; | 140 [aCoder encodeBool:_navigationItem->ShouldSkipResubmitDataConfirmation() |
212 [aCoder encodeBool:self.usedDataReductionProxy | |
213 forKey:@"usedDataReductionProxy"]; | |
214 [aCoder encodeObject:self.httpHeaders forKey:@"httpHeaders"]; | |
215 [aCoder encodeObject:self.POSTData forKey:@"POSTData"]; | |
216 [aCoder encodeBool:self.skipResubmitDataConfirmation | |
217 forKey:@"skipResubmitDataConfirmation"]; | 141 forKey:@"skipResubmitDataConfirmation"]; |
| 142 [aCoder encodeBool:_navigationItem->IsOverridingUserAgent() |
| 143 forKey:@"useDesktopUserAgent"]; |
| 144 [aCoder encodeObject:_navigationItem->GetPostData() forKey:@"POSTData"]; |
| 145 [aCoder encodeObject:_navigationItem->GetHttpRequestHeaders() |
| 146 forKey:@"httpHeaders"]; |
218 } | 147 } |
219 | 148 |
220 // TODO(ios): Shall we overwrite EqualTo:? | 149 // TODO(ios): Shall we overwrite EqualTo:? |
221 | 150 |
222 - (instancetype)copyWithZone:(NSZone*)zone { | 151 - (instancetype)copyWithZone:(NSZone*)zone { |
223 CRWSessionEntry* copy = [[[self class] alloc] init]; | 152 CRWSessionEntry* copy = [[[self class] alloc] init]; |
224 copy->_propertyReleaser_CRWSessionEntry.Init(copy, [CRWSessionEntry class]); | 153 copy->_propertyReleaser_CRWSessionEntry.Init(copy, [CRWSessionEntry class]); |
225 copy->_navigationItem.reset( | 154 copy->_navigationItem.reset( |
226 new web::NavigationItemImpl(*_navigationItem.get())); | 155 new web::NavigationItemImpl(*_navigationItem.get())); |
227 copy->_index = _index; | |
228 copy->_originalUrl = _originalUrl; | 156 copy->_originalUrl = _originalUrl; |
229 copy->_useDesktopUserAgent = _useDesktopUserAgent; | |
230 copy->_usedDataReductionProxy = _usedDataReductionProxy; | |
231 copy->_POSTData = [_POSTData copy]; | |
232 copy->_httpHeaders.reset([_httpHeaders mutableCopy]); | |
233 copy->_skipResubmitDataConfirmation = _skipResubmitDataConfirmation; | |
234 return copy; | 157 return copy; |
235 } | 158 } |
236 | 159 |
237 - (NSString*)description { | 160 - (NSString*)description { |
238 return [NSString | 161 return [NSString |
239 stringWithFormat: | 162 stringWithFormat: |
240 @"url:%@ originalurl:%@ title:%@ transition:%d scrollState:%@ " | 163 @"url:%@ originalurl:%@ title:%@ transition:%d scrollState:%@ " |
241 @"desktopUA:%d " @"proxy:%d", | 164 @"desktopUA:%d", |
242 base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), | 165 base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), |
243 base::SysUTF8ToNSString(self.originalUrl.spec()), | 166 base::SysUTF8ToNSString(self.originalUrl.spec()), |
244 base::SysUTF16ToNSString(_navigationItem->GetTitle()), | 167 base::SysUTF16ToNSString(_navigationItem->GetTitle()), |
245 _navigationItem->GetTransitionType(), | 168 _navigationItem->GetTransitionType(), |
246 [[self class] | 169 [[self class] |
247 scrollStateDescription:_navigationItem->GetPageScrollState()], | 170 scrollStateDescription:_navigationItem->GetPageScrollState()], |
248 _useDesktopUserAgent, _usedDataReductionProxy]; | 171 _navigationItem->IsOverridingUserAgent()]; |
249 } | 172 } |
250 | 173 |
251 - (web::NavigationItem*)navigationItem { | 174 - (web::NavigationItem*)navigationItem { |
252 return _navigationItem.get(); | 175 return _navigationItem.get(); |
253 } | 176 } |
254 | 177 |
255 - (NSDictionary*)httpHeaders { | 178 - (web::NavigationItemImpl*)navigationItemImpl { |
256 return _httpHeaders ? [NSDictionary dictionaryWithDictionary:_httpHeaders] | 179 return _navigationItem.get(); |
257 : nil; | |
258 } | |
259 | |
260 - (void)addHTTPHeaders:(NSDictionary*)moreHTTPHeaders { | |
261 if (_httpHeaders) | |
262 [_httpHeaders addEntriesFromDictionary:moreHTTPHeaders]; | |
263 else | |
264 _httpHeaders.reset([moreHTTPHeaders mutableCopy]); | |
265 } | |
266 | |
267 - (void)removeHTTPHeaderForKey:(NSString*)key { | |
268 [_httpHeaders removeObjectForKey:key]; | |
269 if (![_httpHeaders count]) | |
270 _httpHeaders.reset(); | |
271 } | |
272 | |
273 - (void)resetHTTPHeaders { | |
274 _httpHeaders.reset(); | |
275 } | 180 } |
276 | 181 |
277 #pragma mark - Serialization helpers | 182 #pragma mark - Serialization helpers |
278 | 183 |
279 + (web::PageScrollState)scrollStateFromDictionary:(NSDictionary*)dictionary { | 184 + (web::PageScrollState)scrollStateFromDictionary:(NSDictionary*)dictionary { |
280 web::PageScrollState scrollState; | 185 web::PageScrollState scrollState; |
281 NSNumber* serializedValue = nil; | 186 NSNumber* serializedValue = nil; |
282 if ((serializedValue = dictionary[kScrollOffsetXKey])) | 187 if ((serializedValue = dictionary[kScrollOffsetXKey])) |
283 scrollState.set_scroll_offset_x([serializedValue doubleValue]); | 188 scrollState.set_scroll_offset_x([serializedValue doubleValue]); |
284 if ((serializedValue = dictionary[kScrollOffsetYKey])) | 189 if ((serializedValue = dictionary[kScrollOffsetYKey])) |
(...skipping 24 matching lines...) Expand all Loading... |
309 @"zoomScale:%0.2f }"; | 214 @"zoomScale:%0.2f }"; |
310 return [NSString stringWithFormat:kPageScrollStateDescriptionFormat, | 215 return [NSString stringWithFormat:kPageScrollStateDescriptionFormat, |
311 scrollState.scroll_offset_x(), | 216 scrollState.scroll_offset_x(), |
312 scrollState.scroll_offset_y(), | 217 scrollState.scroll_offset_y(), |
313 scrollState.minimum_zoom_scale(), | 218 scrollState.minimum_zoom_scale(), |
314 scrollState.maximum_zoom_scale(), | 219 scrollState.maximum_zoom_scale(), |
315 scrollState.zoom_scale()]; | 220 scrollState.zoom_scale()]; |
316 } | 221 } |
317 | 222 |
318 @end | 223 @end |
OLD | NEW |