Commit 0d702034 authored by edchin's avatar edchin Committed by Commit Bot

[ios] Move PerformBatchOperation() out of WebStateList serialization

This CL moves PerformBatchOperations() out of the responsibility of
WebStateList serialization and into the caller's responsibility.

This allows callers to define what a batch operation is. For example,
when restoring closed tabs, a batch operation includes modifying
TabRestoreService at the same time as adding WebStates to the WebStateList.

Note: PerformBatchOperation was recently added to web_state_list_serialization
in this CL:
https://chromium-review.googlesource.com/c/chromium/src/+/1865161

Bug: 1014526
Change-Id: I40b11e4fe9b30a5fe18e0e8e404c298b04676d1e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1867389
Commit-Queue: edchin <edchin@chromium.org>
Reviewed-by: default avataredchin <edchin@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707387}
parent e28890a5
......@@ -574,11 +574,14 @@ void RecordMainFrameNavigationMetric(web::WebState* web_state) {
int oldCount = _webStateList->count();
DCHECK_GE(oldCount, 0);
web::WebState::CreateParams createParams(_browserState);
DeserializeWebStateList(
_webStateList, window,
base::BindRepeating(&web::WebState::CreateWithStorageSession,
createParams));
_webStateList->PerformBatchOperation(
base::BindOnce(^(WebStateList* web_state_list) {
web::WebState::CreateParams createParams(_browserState);
DeserializeWebStateList(
web_state_list, window,
base::BindRepeating(&web::WebState::CreateWithStorageSession,
createParams));
}));
DCHECK_GT(_webStateList->count(), oldCount);
int restoredCount = _webStateList->count() - oldCount;
......
......@@ -330,26 +330,11 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list,
- (void)undoCloseAllItems {
if (!self.closedSessionWindow)
return;
DCHECK(self.tabModel.browserState);
// Don't trigger the initial load for these restored WebStates since the
// number of WKWebViews is unbounded and may lead to an OOM crash.
WebStateListWebUsageEnabler* webUsageEnabler =
WebStateListWebUsageEnablerFactory::GetInstance()->GetForBrowserState(
self.tabModel.browserState);
webUsageEnabler->SetTriggersInitialLoad(false);
web::WebState::CreateParams createParams(self.tabModel.browserState);
DeserializeWebStateList(
self.webStateList, self.closedSessionWindow,
base::BindRepeating(&web::WebState::CreateWithStorageSession,
createParams));
webUsageEnabler->SetTriggersInitialLoad(true);
self.closedSessionWindow = nil;
[self removeEntriesFromTabRestoreService];
self.closedTabsCount = 0;
// Unmark all images for deletion since they are now active tabs again.
ios::ChromeBrowserState* browserState = self.tabModel.browserState;
[SnapshotCacheFactory::GetForBrowserState(browserState) unmarkAllImages];
__weak TabGridMediator* weakSelf = self;
self.webStateList->PerformBatchOperation(
base::BindOnce(^(WebStateList* web_state_list) {
[weakSelf restoreClosedSessionWindowAndUpdateTabRestoreService];
}));
}
- (void)discardSavedClosedItems {
......@@ -451,6 +436,33 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list,
}
}
// Restores the saved |self.closedSessionWindow| and updates the
// TabRestoreService.
- (void)restoreClosedSessionWindowAndUpdateTabRestoreService {
if (!self.closedSessionWindow)
return;
DCHECK(self.tabModel.browserState);
// Don't trigger the initial load for these restored WebStates since the
// number of WKWebViews is unbounded and may lead to an OOM crash.
WebStateListWebUsageEnabler* webUsageEnabler =
WebStateListWebUsageEnablerFactory::GetInstance()->GetForBrowserState(
self.tabModel.browserState);
webUsageEnabler->SetTriggersInitialLoad(false);
web::WebState::CreateParams createParams(self.tabModel.browserState);
DeserializeWebStateList(
self.webStateList, self.closedSessionWindow,
base::BindRepeating(&web::WebState::CreateWithStorageSession,
createParams));
webUsageEnabler->SetTriggersInitialLoad(true);
self.closedSessionWindow = nil;
[self removeEntriesFromTabRestoreService];
self.closedTabsCount = 0;
// Unmark all images for deletion since they are now active tabs again.
ios::ChromeBrowserState* browserState = self.tabModel.browserState;
[SnapshotCacheFactory::GetForBrowserState(browserState) unmarkAllImages];
}
// Returns a SnapshotCache for the current BrowserState.
- (SnapshotCache*)snapshotCache {
if (!_tabModel.browserState)
......
......@@ -27,12 +27,47 @@ namespace {
// the WebStates stored in the WebStateList.
NSString* const kOpenerIndexKey = @"OpenerIndex";
NSString* const kOpenerNavigationIndexKey = @"OpenerNavigationIndex";
} // namespace
SessionWindowIOS* SerializeWebStateList(WebStateList* web_state_list) {
NSMutableArray<CRWSessionStorage*>* serialized_session =
[NSMutableArray arrayWithCapacity:web_state_list->count()];
// Helper for DeserializeWebStateList allowing the mutation to appears as a
// single batched operation.
void DeserializeWebStateListHelper(SessionWindowIOS* session_window,
const WebStateFactory& web_state_factory,
WebStateList* web_state_list) {
for (int index = 0; index < web_state_list->count(); ++index) {
web::WebState* web_state = web_state_list->GetWebStateAt(index);
WebStateOpener opener = web_state_list->GetOpenerOfWebStateAt(index);
web::SerializableUserDataManager* user_data_manager =
web::SerializableUserDataManager::FromWebState(web_state);
int opener_index = WebStateList::kInvalidIndex;
if (opener.opener) {
opener_index = web_state_list->GetIndexOfWebState(opener.opener);
DCHECK_NE(opener_index, WebStateList::kInvalidIndex);
user_data_manager->AddSerializableData(@(opener_index), kOpenerIndexKey);
user_data_manager->AddSerializableData(@(opener.navigation_index),
kOpenerNavigationIndexKey);
} else {
user_data_manager->AddSerializableData([NSNull null], kOpenerIndexKey);
user_data_manager->AddSerializableData([NSNull null],
kOpenerNavigationIndexKey);
}
[serialized_session addObject:web_state->BuildSessionStorage()];
}
NSUInteger selectedIndex =
web_state_list->active_index() != WebStateList::kInvalidIndex
? static_cast<NSUInteger>(web_state_list->active_index())
: static_cast<NSUInteger>(NSNotFound);
return [[SessionWindowIOS alloc] initWithSessions:[serialized_session copy]
selectedIndex:selectedIndex];
}
void DeserializeWebStateList(WebStateList* web_state_list,
SessionWindowIOS* session_window,
const WebStateFactory& web_state_factory) {
const int old_count = web_state_list->count();
for (CRWSessionStorage* session in session_window.sessions) {
std::unique_ptr<web::WebState> web_state = web_state_factory.Run(session);
......@@ -75,48 +110,3 @@ void DeserializeWebStateListHelper(SessionWindowIOS* session_window,
old_count + static_cast<int>(session_window.selectedIndex));
}
}
} // namespace
SessionWindowIOS* SerializeWebStateList(WebStateList* web_state_list) {
NSMutableArray<CRWSessionStorage*>* serialized_session =
[NSMutableArray arrayWithCapacity:web_state_list->count()];
for (int index = 0; index < web_state_list->count(); ++index) {
web::WebState* web_state = web_state_list->GetWebStateAt(index);
WebStateOpener opener = web_state_list->GetOpenerOfWebStateAt(index);
web::SerializableUserDataManager* user_data_manager =
web::SerializableUserDataManager::FromWebState(web_state);
int opener_index = WebStateList::kInvalidIndex;
if (opener.opener) {
opener_index = web_state_list->GetIndexOfWebState(opener.opener);
DCHECK_NE(opener_index, WebStateList::kInvalidIndex);
user_data_manager->AddSerializableData(@(opener_index), kOpenerIndexKey);
user_data_manager->AddSerializableData(@(opener.navigation_index),
kOpenerNavigationIndexKey);
} else {
user_data_manager->AddSerializableData([NSNull null], kOpenerIndexKey);
user_data_manager->AddSerializableData([NSNull null],
kOpenerNavigationIndexKey);
}
[serialized_session addObject:web_state->BuildSessionStorage()];
}
NSUInteger selectedIndex =
web_state_list->active_index() != WebStateList::kInvalidIndex
? static_cast<NSUInteger>(web_state_list->active_index())
: static_cast<NSUInteger>(NSNotFound);
return [[SessionWindowIOS alloc] initWithSessions:[serialized_session copy]
selectedIndex:selectedIndex];
}
void DeserializeWebStateList(WebStateList* web_state_list,
SessionWindowIOS* session_window,
const WebStateFactory& web_state_factory) {
web_state_list->PerformBatchOperation(
base::BindOnce(&DeserializeWebStateListHelper,
base::Unretained(session_window), web_state_factory));
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment