blob: ec5c1d207da6a0243f79741d42d42991d2eb65ec [file] [log] [blame]
// Copyright 2021 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/web_state/web_state_impl_serialized_data.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
#import "ios/web/public/navigation/web_state_policy_decider.h"
#import "ios/web/public/session/crw_navigation_item_storage.h"
#import "ios/web/public/session/crw_session_storage.h"
#import "ios/web/public/session/serializable_user_data_manager.h"
#import "ios/web/public/web_state_observer.h"
namespace web {
namespace {
// The key under which the WebState's stable identifier was saved in the user
// serializable data before the M98 release.
NSString* const kTabIdKey = @"TabId";
}
WebStateImpl::SerializedData::SerializedData(WebStateImpl* owner,
const CreateParams& create_params,
CRWSessionStorage* session_storage)
: owner_(owner),
create_params_(create_params),
session_storage_(session_storage) {
DCHECK(owner_);
DCHECK(session_storage_);
// Restore the serializable user data as user code may depend on accessing
// on those values even for an unrealized WebState.
if (session_storage_.userData) {
SerializableUserDataManager::FromWebState(owner_)->SetUserDataFromSession(
session_storage_.userData);
}
}
WebStateImpl::SerializedData::~SerializedData() = default;
void WebStateImpl::SerializedData::TearDown() {
for (auto& observer : observers())
observer.WebStateDestroyed(owner_);
for (auto& observer : policy_deciders())
observer.WebStateDestroyed();
for (auto& observer : policy_deciders())
observer.ResetWebState();
}
WebState::CreateParams WebStateImpl::SerializedData::GetCreateParams() const {
return create_params_;
}
CRWSessionStorage* WebStateImpl::SerializedData::GetSessionStorage() const {
// If a SerializableUserDataManager is attached to the WebState, the user
// may have changed its content. Thus, update the serializable user data
// if needed. Use a const pointer to the WebState to avoid creating the
// manager if it does not exists yet.
const SerializableUserDataManager* user_data_manager =
SerializableUserDataManager::FromWebState(
const_cast<const WebStateImpl*>(owner_));
if (user_data_manager) {
session_storage_.userData = user_data_manager->GetUserDataForSession();
}
return session_storage_;
}
base::Time WebStateImpl::SerializedData::GetLastActiveTime() const {
if (!create_params_.last_active_time.is_null())
return create_params_.last_active_time;
return session_storage_.lastActiveTime;
}
BrowserState* WebStateImpl::SerializedData::GetBrowserState() const {
return create_params_.browser_state;
}
NSString* WebStateImpl::SerializedData::GetStableIdentifier() const {
DCHECK(session_storage_.stableIdentifier.length);
return [session_storage_.stableIdentifier copy];
}
const std::u16string& WebStateImpl::SerializedData::GetTitle() const {
static const std::u16string kEmptyString16;
CRWNavigationItemStorage* item = GetLastCommittedItem();
return item ? item.title : kEmptyString16;
}
const FaviconStatus& WebStateImpl::SerializedData::GetFaviconStatus() const {
return favicon_status_;
}
void WebStateImpl::SerializedData::SetFaviconStatus(
const FaviconStatus& favicon_status) {
favicon_status_ = favicon_status;
}
int WebStateImpl::SerializedData::GetNavigationItemCount() const {
return session_storage_.itemStorages.count;
}
const GURL& WebStateImpl::SerializedData::GetVisibleURL() const {
// A restored WebState has no pending item. Thus the visible item is the
// last committed item. This means that GetVisibleURL() must return the
// same URL as GetLastCommittedURL().
return GetLastCommittedURL();
}
const GURL& WebStateImpl::SerializedData::GetLastCommittedURL() const {
CRWNavigationItemStorage* item = GetLastCommittedItem();
return item ? item.virtualURL : GURL::EmptyGURL();
}
// TODO(crbug.com/1264451): this private method allow to implement `GetTitle()`
// and `GetLastCommittedURL()` without duplicating code. As of today, the title
// and URL for the WebState are not saved directly, so this method access them
// via the serialized NavigationManager state. This will be removed once the
// format of the WebState serialization is changed to directly saved the title
// and URL. This implementation allow to test unrealized WebState before the
// new format is used. This slightly break encapsulation, but this is a private
// method of a private class and the file format is quite stable, so this seem
// reasonable as a temporary solution.
CRWNavigationItemStorage* WebStateImpl::SerializedData::GetLastCommittedItem()
const {
const NSInteger index = session_storage_.lastCommittedItemIndex;
if (index < 0)
return nil;
const NSUInteger uindex = static_cast<NSUInteger>(index);
if (session_storage_.itemStorages.count <= uindex) {
return nil;
}
return session_storage_.itemStorages[uindex];
}
} // namespace web