Index: ios/web/public/crw_navigation_item_storage.mm |
diff --git a/ios/web/public/crw_navigation_item_storage.mm b/ios/web/public/crw_navigation_item_storage.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3569dea2799a99ef60a88c0918e9a9e3ea3499c |
--- /dev/null |
+++ b/ios/web/public/crw_navigation_item_storage.mm |
@@ -0,0 +1,237 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/web/public/crw_navigation_item_storage.h" |
+ |
+#import "base/strings/sys_string_conversions.h" |
Eugene But (OOO till 7-30)
2017/01/31 22:12:26
nit: s/import/include
kkhorimoto
2017/02/03 00:36:09
Done.
|
+#import "ios/web/navigation/nscoder_util.h" |
+#import "net/base/mac/url_conversions.h" |
+ |
+#if !defined(__has_feature) || !__has_feature(objc_arc) |
+#error "This file requires ARC support." |
+#endif |
+ |
+namespace web { |
+ |
+// Keys used to serialize web::PageScrollState properties. |
+NSString* const kNavigationItemStoragePageDisplayStateKey = @"state"; |
+NSString* const kNavigationItemStorageScrollOffsetXKey = @"scrollX"; |
+NSString* const kNavigationItemStorageScrollOffsetYKey = @"scrollY"; |
+NSString* const kNavigationItemStorageMinimumZoomScaleKey = @"minZoom"; |
+NSString* const kNavigationItemStorageMaximumZoomScaleKey = @"maxZoom"; |
+NSString* const kNavigationItemStorageZoomScaleKey = @"zoom"; |
+ |
+// Keys used to serialize navigation properties. |
+NSString* const kNavigationItemStorageURLKey = @"virtualUrlString"; |
+NSString* const kNavigationItemStorageURLDeperecatedKey = @"virtualUrl"; |
+NSString* const kNavigationItemStorageReferrerURLKey = @"referrerUrlString"; |
+NSString* const kNavigationItemStorageReferrerURLDeprecatedKey = @"referrer"; |
+NSString* const kNavigationItemStorageReferrerPolicyKey = @"referrerPolicy"; |
+NSString* const kNavigationItemStorageTimestampKey = @"timestamp"; |
+NSString* const kNavigationItemStorageTitleKey = @"title"; |
+NSString* const kNavigationItemStoragePOSTDataKey = @"POSTData"; |
+NSString* const kNavigationItemStorageHTTPRequestHeadersKey = @"httpHeaders"; |
+NSString* const kNavigationItemStorageSkipRepostFormConfirmationKey = |
+ @"skipResubmitDataConfirmation"; |
+NSString* const kNavigationItemStorageUseDesktopUserAgentKey = |
+ @"useDesktopUserAgent"; |
+ |
+} // namespace web |
+ |
+namespace { |
+ |
+// Converts a serialized NSDictionary to a web::PageDisplayState. |
+web::PageDisplayState DisplayStateFromDictionary(NSDictionary* dictionary) { |
+ NSNumber* serializedValue = nil; |
+ web::PageScrollState scrollState; |
+ if ((serializedValue = |
+ dictionary[web::kNavigationItemStorageScrollOffsetXKey])) |
+ scrollState.set_offset_x([serializedValue doubleValue]); |
+ if ((serializedValue = |
+ dictionary[web::kNavigationItemStorageScrollOffsetYKey])) |
+ scrollState.set_offset_y([serializedValue doubleValue]); |
+ web::PageZoomState zoomState; |
+ if ((serializedValue = |
+ dictionary[web::kNavigationItemStorageMinimumZoomScaleKey])) |
+ zoomState.set_minimum_zoom_scale([serializedValue doubleValue]); |
+ if ((serializedValue = |
+ dictionary[web::kNavigationItemStorageMaximumZoomScaleKey])) |
+ zoomState.set_maximum_zoom_scale([serializedValue doubleValue]); |
+ if ((serializedValue = dictionary[web::kNavigationItemStorageZoomScaleKey])) |
+ zoomState.set_zoom_scale([serializedValue doubleValue]); |
+ return web::PageDisplayState(scrollState, zoomState); |
+} |
+ |
+// Serializes a web::PageDisplayState to an NSDictionary. |
+NSDictionary* DictionaryFromDisplayState(web::PageDisplayState display_state) { |
+ return @{ |
+ web::kNavigationItemStorageScrollOffsetXKey : |
+ @(display_state.scroll_state().offset_x()), |
+ web::kNavigationItemStorageScrollOffsetYKey : |
+ @(display_state.scroll_state().offset_y()), |
+ web::kNavigationItemStorageMinimumZoomScaleKey : |
+ @(display_state.zoom_state().minimum_zoom_scale()), |
+ web::kNavigationItemStorageMaximumZoomScaleKey : |
+ @(display_state.zoom_state().maximum_zoom_scale()), |
+ web::kNavigationItemStorageZoomScaleKey : |
+ @(display_state.zoom_state().zoom_scale()) |
+ }; |
+} |
+ |
+} // namespace |
+ |
+@implementation CRWNavigationItemStorage |
+ |
+@synthesize virtualURL = _virtualURL; |
+@synthesize referrer = _referrer; |
+@synthesize timestamp = _timestamp; |
+@synthesize title = _title; |
+@synthesize displayState = _displayState; |
+@synthesize shouldSkipRepostFormConfirmation = |
+ _shouldSkipRepostFormConfirmation; |
+@synthesize overridingUserAgent = _overridingUserAgent; |
+@synthesize POSTData = _POSTData; |
+@synthesize HTTPRequestHeaders = _HTTPRequestHeaders; |
+ |
+#pragma mark - NSObject |
+ |
+- (NSUInteger)hash { |
+ NSUInteger hash = 0; |
+ hash ^= [net::NSURLWithGURL(_virtualURL) hash]; |
+ hash ^= [net::NSURLWithGURL(_referrer.url) hash]; |
+ hash ^= _referrer.policy; |
+ hash ^= _timestamp.ToTimeT(); |
+ hash ^= [base::SysUTF16ToNSString(_title) hash]; |
+ hash ^= [DictionaryFromDisplayState(_displayState) hash]; |
+ hash ^= _shouldSkipRepostFormConfirmation; |
+ // Bit shift |_overridingUserAgent| so to differentiate it from |
+ // |_shouldSkipRepostFormConfirmation| in the hash. |
+ hash ^= _overridingUserAgent << 1; |
+ hash ^= [_POSTData hash]; |
+ hash ^= [_HTTPRequestHeaders hash]; |
+ return hash; |
+} |
+ |
+- (BOOL)isEqual:(id)object { |
+ return [object class] == [self class] && [object hash] == [self hash]; |
Eugene But (OOO till 7-30)
2017/01/31 22:12:26
Equality of hashes does not mean objects equality,
kkhorimoto
2017/02/03 00:36:09
Fixed.
Eugene But (OOO till 7-30)
2017/02/03 01:52:34
So the other question was: "Is this method used ou
Eugene But (OOO till 7-30)
2017/02/03 01:57:16
The other reason for not using |hash| and |isEqual
kkhorimoto
2017/02/03 02:47:23
Done.
|
+} |
+ |
+- (NSString*)description { |
+ NSMutableString* description = |
+ [NSMutableString stringWithString:[super description]]; |
+ [description appendFormat:@"virtualURL : %s, ", _virtualURL.spec().c_str()]; |
+ [description appendFormat:@"referrer : %s, ", _referrer.url.spec().c_str()]; |
+ [description appendFormat:@"timestamp : %f, ", _timestamp.ToCFAbsoluteTime()]; |
+ [description appendFormat:@"title : %@, ", base::SysUTF16ToNSString(_title)]; |
+ [description appendFormat:@"displayState : %@", |
+ DictionaryFromDisplayState(_displayState)]; |
+ [description appendFormat:@"skipRepostConfirmation : %@, ", |
+ @(_shouldSkipRepostFormConfirmation)]; |
+ [description |
+ appendFormat:@"overridingUserAgent : %@, ", @(_overridingUserAgent)]; |
+ [description appendFormat:@"POSTData : %@, ", _POSTData]; |
+ [description appendFormat:@"HTTPRequestHeaders : %@", _HTTPRequestHeaders]; |
+ return description; |
+} |
+ |
+#pragma mark - NSCoding |
+ |
+- (instancetype)initWithCoder:(NSCoder*)aDecoder { |
+ self = [super init]; |
+ if (self) { |
+ // Desktop chrome only persists virtualUrl_ and uses it to feed the url |
+ // when creating a NavigationEntry. |
+ if ([aDecoder containsValueForKey:web::kNavigationItemStorageURLKey]) { |
+ _virtualURL = GURL(web::nscoder_util::DecodeString( |
+ aDecoder, web::kNavigationItemStorageURLKey)); |
+ } else { |
+ // Backward compatibility. |
+ _virtualURL = net::GURLWithNSURL([aDecoder |
+ decodeObjectForKey:web::kNavigationItemStorageURLDeperecatedKey]); |
+ } |
+ |
+ if ([aDecoder |
+ containsValueForKey:web::kNavigationItemStorageReferrerURLKey]) { |
+ const std::string referrerString(web::nscoder_util::DecodeString( |
+ aDecoder, web::kNavigationItemStorageReferrerURLKey)); |
+ web::ReferrerPolicy referrerPolicy = |
+ static_cast<web::ReferrerPolicy>([aDecoder |
+ decodeIntForKey:web::kNavigationItemStorageReferrerPolicyKey]); |
+ _referrer = web::Referrer(GURL(referrerString), referrerPolicy); |
+ } else { |
+ // Backward compatibility. |
+ NSURL* referrerURL = |
+ [aDecoder decodeObjectForKey: |
+ web::kNavigationItemStorageReferrerURLDeprecatedKey]; |
+ _referrer = web::Referrer(net::GURLWithNSURL(referrerURL), |
+ web::ReferrerPolicyDefault); |
+ } |
+ |
+ if ([aDecoder |
+ containsValueForKey:web::kNavigationItemStorageTimestampKey]) { |
+ int64_t us = |
+ [aDecoder decodeInt64ForKey:web::kNavigationItemStorageTimestampKey]; |
+ _timestamp = base::Time::FromInternalValue(us); |
+ } |
+ |
+ NSString* title = |
+ [aDecoder decodeObjectForKey:web::kNavigationItemStorageTitleKey]; |
+ // Use a transition type of reload so that we don't incorrectly increase |
+ // the typed count. This is what desktop chrome does. |
+ _title = base::SysNSStringToUTF16(title); |
+ NSDictionary* serializedDisplayState = [aDecoder |
+ decodeObjectForKey:web::kNavigationItemStoragePageDisplayStateKey]; |
+ _displayState = DisplayStateFromDictionary(serializedDisplayState); |
+ _shouldSkipRepostFormConfirmation = |
+ [aDecoder decodeBoolForKey: |
+ web::kNavigationItemStorageSkipRepostFormConfirmationKey]; |
+ _overridingUserAgent = [aDecoder |
+ decodeBoolForKey:web::kNavigationItemStorageUseDesktopUserAgentKey]; |
+ _POSTData = |
+ [aDecoder decodeObjectForKey:web::kNavigationItemStoragePOSTDataKey]; |
+ _HTTPRequestHeaders = [aDecoder |
+ decodeObjectForKey:web::kNavigationItemStorageHTTPRequestHeadersKey]; |
+ } |
+ return self; |
+} |
+ |
+- (void)encodeWithCoder:(NSCoder*)aCoder { |
+ // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only |
+ // |virtualUrl_|. |
+ web::nscoder_util::EncodeString(aCoder, web::kNavigationItemStorageURLKey, |
+ _virtualURL.spec()); |
+ web::nscoder_util::EncodeString( |
+ aCoder, web::kNavigationItemStorageReferrerURLKey, _referrer.url.spec()); |
+ [aCoder encodeInt:_referrer.policy |
+ forKey:web::kNavigationItemStorageReferrerPolicyKey]; |
+ [aCoder encodeInt64:_timestamp.ToInternalValue() |
+ forKey:web::kNavigationItemStorageTimestampKey]; |
+ |
+ [aCoder encodeObject:base::SysUTF16ToNSString(_title) |
+ forKey:web::kNavigationItemStorageTitleKey]; |
+ [aCoder encodeObject:DictionaryFromDisplayState(_displayState) |
+ forKey:web::kNavigationItemStoragePageDisplayStateKey]; |
+ [aCoder encodeBool:_shouldSkipRepostFormConfirmation |
+ forKey:web::kNavigationItemStorageSkipRepostFormConfirmationKey]; |
+ [aCoder encodeBool:_overridingUserAgent |
+ forKey:web::kNavigationItemStorageUseDesktopUserAgentKey]; |
+ [aCoder encodeObject:_POSTData forKey:web::kNavigationItemStoragePOSTDataKey]; |
+ [aCoder encodeObject:_HTTPRequestHeaders |
+ forKey:web::kNavigationItemStorageHTTPRequestHeadersKey]; |
+} |
+ |
+@end |
+ |
+@implementation CRWNavigationItemStorage (Testing) |
+ |
++ (web::PageDisplayState)displayStateFromDictionary:(NSDictionary*)dictionary { |
+ return DisplayStateFromDictionary(dictionary); |
+} |
+ |
++ (NSDictionary*)dictionaryFromDisplayState: |
+ (web::PageDisplayState)displayState { |
+ return DictionaryFromDisplayState(displayState); |
+} |
+ |
+@end |