blob: f43159a53ec4f7ddf94945b14c5cb7b16ede2914 [file] [log] [blame]
// 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"
#include "base/strings/sys_string_conversions.h"
#import "ios/web/navigation/nscoder_util.h"
#import "ios/web/public/web_client.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 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 kNavigationItemStoragePageDisplayStateKey = @"state";
NSString* const kNavigationItemStoragePOSTDataKey = @"POSTData";
NSString* const kNavigationItemStorageHTTPRequestHeadersKey = @"httpHeaders";
NSString* const kNavigationItemStorageSkipRepostFormConfirmationKey =
@"skipResubmitDataConfirmation";
NSString* const kNavigationItemStorageUserAgentTypeKey = @"userAgentType";
NSString* const kNavigationItemStorageUseDesktopUserAgentDeprecatedKey =
@"useDesktopUserAgent";
} // namespace web
@implementation CRWNavigationItemStorage
@synthesize virtualURL = _virtualURL;
@synthesize referrer = _referrer;
@synthesize timestamp = _timestamp;
@synthesize title = _title;
@synthesize displayState = _displayState;
@synthesize shouldSkipRepostFormConfirmation =
_shouldSkipRepostFormConfirmation;
@synthesize userAgentType = _userAgentType;
@synthesize POSTData = _POSTData;
@synthesize HTTPRequestHeaders = _HTTPRequestHeaders;
#pragma mark - NSObject
- (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 : %@", _displayState.GetDescription()];
[description appendFormat:@"skipRepostConfirmation : %@, ",
@(_shouldSkipRepostFormConfirmation)];
[description
appendFormat:@"userAgentType : %s, ",
web::GetUserAgentTypeDescription(_userAgentType).c_str()];
[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);
}
if ([aDecoder
containsValueForKey:web::kNavigationItemStorageUserAgentTypeKey]) {
std::string userAgentDescription = web::nscoder_util::DecodeString(
aDecoder, web::kNavigationItemStorageUserAgentTypeKey);
_userAgentType =
web::GetUserAgentTypeWithDescription(userAgentDescription);
} else if (web::GetWebClient()->IsAppSpecificURL(_virtualURL)) {
// Legacy CRWNavigationItemStorages didn't have the concept of a NONE
// user agent for app-specific URLs, so check decoded virtual URL before
// attempting to decode the deprecated key.
_userAgentType = web::UserAgentType::NONE;
} else {
// The user agent type was previously recorded as a BOOL, where YES meant
// desktop user agent, and NO meant mobile user agent.
BOOL useDesktopUA = [aDecoder
decodeBoolForKey:
web::kNavigationItemStorageUseDesktopUserAgentDeprecatedKey];
_userAgentType = useDesktopUA ? web::UserAgentType::DESKTOP
: web::UserAgentType::MOBILE;
}
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 = web::PageDisplayState(serializedDisplayState);
_shouldSkipRepostFormConfirmation =
[aDecoder decodeBoolForKey:
web::kNavigationItemStorageSkipRepostFormConfirmationKey];
_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:_displayState.GetSerialization()
forKey:web::kNavigationItemStoragePageDisplayStateKey];
[aCoder encodeBool:_shouldSkipRepostFormConfirmation
forKey:web::kNavigationItemStorageSkipRepostFormConfirmationKey];
web::nscoder_util::EncodeString(
aCoder, web::kNavigationItemStorageUserAgentTypeKey,
web::GetUserAgentTypeDescription(_userAgentType));
[aCoder encodeObject:_POSTData forKey:web::kNavigationItemStoragePOSTDataKey];
[aCoder encodeObject:_HTTPRequestHeaders
forKey:web::kNavigationItemStorageHTTPRequestHeadersKey];
}
@end