Commit 4442901e authored by Sylvain Defresne's avatar Sylvain Defresne Committed by Chromium LUCI CQ

[ios] Fix loss of incognito tabs on phones and some tablets

On devices that do not support multi-windows, iOS will still
interpret "swipe gesture" as a request from the user to close
the window and will use a new session identifier on following
startup.

To avoid losing state, there exist a workaround that load the
session using the old session identifier on those device but
the workaround was only applied to the regular tabs, thus it
was possible to lose incognito tabs in that case.

Refactor the code setting the session identifier in Browser
to be shared between regular and incognito BrowserState.

Bug: 1153606
Change-Id: I833978da3697c88d8d31ab956f91be840d1e74e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2622393
Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
Commit-Queue: Mohammad Refaat <mrefaat@chromium.org>
Reviewed-by: default avatarMohammad Refaat <mrefaat@chromium.org>
Auto-Submit: Sylvain Defresne <sdefresne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842648}
parent b4b7f02e
......@@ -166,24 +166,8 @@
[self dispatchToEndpointsForBrowser:_mainBrowser.get()];
std::string sessionID = base::SysNSStringToUTF8(self.sessionID);
SnapshotBrowserAgent::FromBrowser(_mainBrowser.get())
->SetSessionID(sessionID);
// If the OS doesn't support multiple scenes, use the previous run scene ID
// for the session restoration.
NSString* restoreSessionID = self.sessionID;
if (_sceneState.appState.previousSingleWindowSessionID) {
restoreSessionID = _sceneState.appState.previousSingleWindowSessionID;
}
SessionRestorationBrowserAgent* restorationAgent =
SessionRestorationBrowserAgent::FromBrowser(_mainBrowser.get());
restorationAgent->SetSessionID(base::SysNSStringToUTF8(restoreSessionID));
restorationAgent->RestoreSession();
restorationAgent->SetSessionID(sessionID);
if (base::SysNSStringToUTF8(restoreSessionID) != sessionID) {
restorationAgent->SaveSession(true);
}
[self setSessionIDForBrowser:_mainBrowser.get() restoreSession:YES];
breakpad::MonitorTabStateForWebStateList(_mainBrowser->GetWebStateList());
// Follow loaded URLs in the main tab model to send those in case of
// crashes.
......@@ -381,14 +365,9 @@
BrowserListFactory::GetForBrowserState(browser->GetBrowserState());
browserList->AddIncognitoBrowser(browser.get());
[self dispatchToEndpointsForBrowser:browser.get()];
std::string sessionID = base::SysNSStringToUTF8(self.sessionID);
SnapshotBrowserAgent::FromBrowser(browser.get())->SetSessionID(sessionID);
SessionRestorationBrowserAgent::FromBrowser(browser.get())
->SetSessionID(sessionID);
if (restorePersistedState) {
SessionRestorationBrowserAgent::FromBrowser(browser.get())
->RestoreSession();
}
[self setSessionIDForBrowser:browser.get()
restoreSession:restorePersistedState];
// Associate the same SceneState with the new OTR browser as is associated
// with the main browser.
......@@ -430,4 +409,55 @@
forProtocol:@protocol(BrowsingDataCommands)];
}
- (void)setSessionIDForBrowser:(Browser*)browser
restoreSession:(BOOL)restoreSession {
SnapshotBrowserAgent::FromBrowser(browser)->SetSessionID(
base::SysNSStringToUTF8(self.sessionID));
SessionRestorationBrowserAgent* restorationAgent =
SessionRestorationBrowserAgent::FromBrowser(browser);
// crbug.com/1153606: when the app is distributed with multi-window enabled,
// the "swipe gesture" is sometimes interpreted as a "close window" gesture
// by iOS (reproduce easily if the user launch app, swipe it away in a loop).
// On the next start after iOS has decided the gesture is "close window", the
// session identifier will be reset to a different value.
//
// For device that support multiple windows (recent iPads running iOS 13+),
// the user has the option to restore recently closed windows (presented by
// iOS when user ask to see all windows). For other devices however they have
// no option to re-open the closed window and lose their data.
//
// To workaround this behaviour, the session identifier is saved, and on each
// run, if the device does not support multi-window, compared to the current
// session identifier. If there is a mismatch, load the session using the old
// identifier (which is used to construct path to Chrome's session data), and
// immediately save it with the new identifier.
//
// TODO(crbug.com/1165798): clean up this by using fixed identifier when the
// device do no support multi-windows.
if (!IsMultipleScenesSupported() && restoreSession) {
NSString* previousSessionID =
_sceneState.appState.previousSingleWindowSessionID;
if (previousSessionID &&
![self.sessionID isEqualToString:previousSessionID]) {
restorationAgent->SetSessionID(
base::SysNSStringToUTF8(previousSessionID));
restorationAgent->RestoreSession();
restorationAgent->SetSessionID(base::SysNSStringToUTF8(self.sessionID));
restorationAgent->SaveSession(true);
// Fallback to the normal codepath. It will set the session identifier
// in the SessionRestorationBrowserAgent. Since the session has been
// loaded already, skip this step by setting |restoreSession| to NO.
restoreSession = NO;
}
}
restorationAgent->SetSessionID(base::SysNSStringToUTF8(self.sessionID));
if (restoreSession)
restorationAgent->RestoreSession();
}
@end
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