OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/web/navigation/crw_session_entry.h" |
| 6 |
| 7 #include "base/mac/objc_property_releaser.h" |
| 8 #include "base/mac/scoped_nsobject.h" |
| 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/sys_string_conversions.h" |
| 11 #include "ios/web/navigation/navigation_item_impl.h" |
| 12 #include "ios/web/navigation/nscoder_util.h" |
| 13 #include "ios/web/public/navigation_item.h" |
| 14 #import "net/base/mac/url_conversions.h" |
| 15 |
| 16 @interface CRWSessionEntry () { |
| 17 // The index in the CRWSessionController. |
| 18 // |
| 19 // This is used when determining the selected CRWSessionEntry and only useful |
| 20 // to the SessionServiceIOS. |
| 21 NSInteger _index; |
| 22 |
| 23 // The original URL of the page. In cases where a redirect occurred, |url_| |
| 24 // will contain the final post-redirect URL, and |originalUrl_| will contain |
| 25 // the pre-redirect URL. This field is not persisted to disk. |
| 26 GURL _originalUrl; |
| 27 |
| 28 // Content state is an opaque dictionary created by WebKit that represents the |
| 29 // state of the page. This includes form entries and scroll position for each |
| 30 // frame. We store it so that we can supply it back to WebKit to restore form |
| 31 // state properly when the user goes back and forward. |
| 32 // TODO(pinkerton): Figure out exactly what this contains given that we |
| 33 // don't have anywhere near the access to WebKit that the desktop does. |
| 34 NSDictionary* _state; |
| 35 |
| 36 // Headers passed along with the request. For POST requests, these are |
| 37 // persisted, to be able to resubmit them. Some specialized non-POST requests |
| 38 // may also pass custom headers. |
| 39 base::scoped_nsobject<NSMutableDictionary> _httpHeaders; |
| 40 |
| 41 // Data submitted with a POST request, persisted for resubmits. |
| 42 NSData* _POSTData; |
| 43 |
| 44 // Serialized representation of the state object that was used in conjunction |
| 45 // with a JavaScript window.history.pushState() or |
| 46 // window.history.replaceState() call that created or modified this |
| 47 // CRWSessionEntry. Intended to be used for JavaScript history operations and |
| 48 // will be nil in most cases. |
| 49 NSString* _serializedStateObject; |
| 50 |
| 51 // Whether or not this entry was created by calling history.pushState(). |
| 52 BOOL _createdFromPushState; |
| 53 |
| 54 // If |YES| use a desktop user agent in HTTP requests and UIWebView. |
| 55 BOOL _useDesktopUserAgent; |
| 56 |
| 57 // If |YES| the page was last fetched through the data reduction proxy. |
| 58 BOOL _usedDataReductionProxy; |
| 59 |
| 60 // Whether or not to bypass showing the resubmit data confirmation when |
| 61 // loading a POST request. Set to YES for browser-generated POST requests such |
| 62 // as search-by-image requests. |
| 63 BOOL _skipResubmitDataConfirmation; |
| 64 |
| 65 // The NavigationItemImpl corresponding to this CRWSessionEntry. |
| 66 // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. |
| 67 scoped_ptr<web::NavigationItemImpl> _navigationItem; |
| 68 |
| 69 base::mac::ObjCPropertyReleaser _propertyReleaser_CRWSessionEntry; |
| 70 } |
| 71 // Redefine originalUrl to be read-write. |
| 72 @property(nonatomic, readwrite) const GURL& originalUrl; |
| 73 |
| 74 @end |
| 75 |
| 76 @implementation CRWSessionEntry |
| 77 |
| 78 @synthesize POSTData = _POSTData; |
| 79 @synthesize originalUrl = _originalUrl; |
| 80 @synthesize useDesktopUserAgent = _useDesktopUserAgent; |
| 81 @synthesize usedDataReductionProxy = _usedDataReductionProxy; |
| 82 @synthesize state = _state; |
| 83 @synthesize index = _index; |
| 84 @synthesize serializedStateObject = _serializedStateObject; |
| 85 @synthesize createdFromPushState = _createdFromPushState; |
| 86 @synthesize skipResubmitDataConfirmation = _skipResubmitDataConfirmation; |
| 87 |
| 88 // Creates a new session entry. These may be nil. |
| 89 - (id)initWithUrl:(const GURL&)url |
| 90 referrer:(const web::Referrer&)referrer |
| 91 transition:(ui::PageTransition)transition |
| 92 useDesktopUserAgent:(BOOL)useDesktopUserAgent |
| 93 rendererInitiated:(BOOL)rendererInitiated { |
| 94 self = [super init]; |
| 95 if (self) { |
| 96 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); |
| 97 _navigationItem.reset(new web::NavigationItemImpl()); |
| 98 |
| 99 _navigationItem->SetURL(url); |
| 100 _navigationItem->SetReferrer(referrer); |
| 101 _navigationItem->SetTransitionType(transition); |
| 102 _navigationItem->set_is_renderer_initiated(rendererInitiated); |
| 103 |
| 104 self.originalUrl = url; |
| 105 self.useDesktopUserAgent = useDesktopUserAgent; |
| 106 } |
| 107 return self; |
| 108 } |
| 109 |
| 110 - (id)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item |
| 111 index:(int)index { |
| 112 self = [super init]; |
| 113 if (self) { |
| 114 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); |
| 115 _navigationItem.reset( |
| 116 static_cast<web::NavigationItemImpl*>(item.release())); |
| 117 |
| 118 self.index = index; |
| 119 self.originalUrl = _navigationItem->GetURL(); |
| 120 self.useDesktopUserAgent = NO; |
| 121 } |
| 122 return self; |
| 123 } |
| 124 |
| 125 - (id)initWithCoder:(NSCoder*)aDecoder { |
| 126 self = [super init]; |
| 127 if (self) { |
| 128 _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); |
| 129 _navigationItem.reset(new web::NavigationItemImpl()); |
| 130 |
| 131 // Desktop chrome only persists virtualUrl_ and uses it to feed the url |
| 132 // when creating a NavigationEntry. |
| 133 GURL url; |
| 134 if ([aDecoder containsValueForKey:@"virtualUrlString"]) { |
| 135 url = GURL( |
| 136 web::nscoder_util::DecodeString(aDecoder, @"virtualUrlString")); |
| 137 } else { |
| 138 // Backward compatibility. |
| 139 url = net::GURLWithNSURL([aDecoder decodeObjectForKey:@"virtualUrl"]); |
| 140 } |
| 141 _navigationItem->SetURL(url); |
| 142 self.originalUrl = url; |
| 143 |
| 144 if ([aDecoder containsValueForKey:@"referrerUrlString"]) { |
| 145 const std::string referrerString(web::nscoder_util::DecodeString( |
| 146 aDecoder, @"referrerUrlString")); |
| 147 web::ReferrerPolicy referrerPolicy = |
| 148 static_cast<web::ReferrerPolicy>( |
| 149 [aDecoder decodeIntForKey:@"referrerPolicy"]); |
| 150 _navigationItem->SetReferrer( |
| 151 web::Referrer(GURL(referrerString), referrerPolicy)); |
| 152 } else { |
| 153 // Backward compatibility. |
| 154 NSURL* referrer = [aDecoder decodeObjectForKey:@"referrer"]; |
| 155 _navigationItem->SetReferrer(web::Referrer( |
| 156 net::GURLWithNSURL(referrer), web::ReferrerPolicyDefault)); |
| 157 } |
| 158 |
| 159 if ([aDecoder containsValueForKey:@"timestamp"]) { |
| 160 int64 us = [aDecoder decodeInt64ForKey:@"timestamp"]; |
| 161 _navigationItem->SetTimestamp(base::Time::FromInternalValue(us)); |
| 162 } |
| 163 |
| 164 NSString* title = [aDecoder decodeObjectForKey:@"title"]; |
| 165 // Use a transition type of reload so that we don't incorrectly increase |
| 166 // the typed count. This is what desktop chrome does. |
| 167 _navigationItem->SetPageID(-1); |
| 168 _navigationItem->SetTitle(base::SysNSStringToUTF16(title)); |
| 169 _navigationItem->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); |
| 170 self.index = [aDecoder decodeIntForKey:@"index"]; |
| 171 self.state = [aDecoder decodeObjectForKey:@"state"]; |
| 172 self.useDesktopUserAgent = |
| 173 [aDecoder decodeBoolForKey:@"useDesktopUserAgent"]; |
| 174 self.usedDataReductionProxy = |
| 175 [aDecoder decodeBoolForKey:@"usedDataReductionProxy"]; |
| 176 [self addHTTPHeaders:[aDecoder decodeObjectForKey:@"httpHeaders"]]; |
| 177 self.POSTData = [aDecoder decodeObjectForKey:@"POSTData"]; |
| 178 self.skipResubmitDataConfirmation = |
| 179 [aDecoder decodeBoolForKey:@"skipResubmitDataConfirmation"]; |
| 180 } |
| 181 return self; |
| 182 } |
| 183 |
| 184 - (void)encodeWithCoder:(NSCoder*)aCoder { |
| 185 // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only |
| 186 // |virtualUrl_|. |
| 187 [aCoder encodeInt:self.index forKey:@"index"]; |
| 188 web::nscoder_util::EncodeString(aCoder, @"virtualUrlString", |
| 189 _navigationItem->GetVirtualURL().spec()); |
| 190 web::nscoder_util::EncodeString(aCoder, @"referrerUrlString", |
| 191 _navigationItem->GetReferrer().url.spec()); |
| 192 [aCoder encodeInt:_navigationItem->GetReferrer().policy |
| 193 forKey:@"referrerPolicy"]; |
| 194 [aCoder encodeInt64:_navigationItem->GetTimestamp().ToInternalValue() |
| 195 forKey:@"timestamp"]; |
| 196 |
| 197 [aCoder encodeObject:base::SysUTF16ToNSString(_navigationItem->GetTitle()) |
| 198 forKey:@"title"]; |
| 199 [aCoder encodeObject:self.state forKey:@"state"]; |
| 200 [aCoder encodeBool:self.useDesktopUserAgent forKey:@"useDesktopUserAgent"]; |
| 201 [aCoder encodeBool:self.usedDataReductionProxy |
| 202 forKey:@"usedDataReductionProxy"]; |
| 203 [aCoder encodeObject:self.httpHeaders forKey:@"httpHeaders"]; |
| 204 [aCoder encodeObject:self.POSTData forKey:@"POSTData"]; |
| 205 [aCoder encodeBool:self.skipResubmitDataConfirmation |
| 206 forKey:@"skipResubmitDataConfirmation"]; |
| 207 } |
| 208 |
| 209 // TODO(ios): Shall we overwrite EqualTo:? |
| 210 |
| 211 - (id)copyWithZone:(NSZone *)zone { |
| 212 CRWSessionEntry* copy = [[[self class] alloc] init]; |
| 213 copy->_propertyReleaser_CRWSessionEntry.Init(copy, [CRWSessionEntry class]); |
| 214 copy->_navigationItem.reset( |
| 215 new web::NavigationItemImpl(*_navigationItem.get())); |
| 216 copy->_index = _index; |
| 217 copy->_originalUrl = _originalUrl; |
| 218 copy->_state = [_state copy]; |
| 219 copy->_useDesktopUserAgent = _useDesktopUserAgent; |
| 220 copy->_usedDataReductionProxy = _usedDataReductionProxy; |
| 221 copy->_POSTData = [_POSTData copy]; |
| 222 copy->_httpHeaders.reset([_httpHeaders mutableCopy]); |
| 223 copy->_skipResubmitDataConfirmation = _skipResubmitDataConfirmation; |
| 224 return copy; |
| 225 } |
| 226 |
| 227 - (NSString*)description { |
| 228 return [NSString stringWithFormat: |
| 229 @"url:%@ originalurl:%@ title:%@ transition:%d state:%@ desktopUA:%d " |
| 230 @"proxy:%d", |
| 231 base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), |
| 232 base::SysUTF8ToNSString(self.originalUrl.spec()), |
| 233 base::SysUTF16ToNSString(_navigationItem->GetTitle()), |
| 234 _navigationItem->GetTransitionType(), |
| 235 _state, _useDesktopUserAgent, _usedDataReductionProxy]; |
| 236 } |
| 237 |
| 238 - (web::NavigationItem*)navigationItem { |
| 239 return _navigationItem.get(); |
| 240 } |
| 241 |
| 242 - (NSDictionary*)httpHeaders { |
| 243 return _httpHeaders ? [NSDictionary dictionaryWithDictionary:_httpHeaders] |
| 244 : nil; |
| 245 } |
| 246 |
| 247 - (void)addHTTPHeaders:(NSDictionary*)moreHTTPHeaders { |
| 248 if (_httpHeaders) |
| 249 [_httpHeaders addEntriesFromDictionary:moreHTTPHeaders]; |
| 250 else |
| 251 _httpHeaders.reset([moreHTTPHeaders mutableCopy]); |
| 252 } |
| 253 |
| 254 - (void)removeHTTPHeaderForKey:(NSString*)key { |
| 255 [_httpHeaders removeObjectForKey:key]; |
| 256 if (![_httpHeaders count]) |
| 257 _httpHeaders.reset(); |
| 258 } |
| 259 |
| 260 - (void)resetHTTPHeaders { |
| 261 _httpHeaders.reset(); |
| 262 } |
| 263 |
| 264 @end |
OLD | NEW |