Web+: implement a simple session management system.

When quitting the app or closing the last window, all windows and tabs
are stored in a "Session" file. This is reloaded when the browser
starts, allowing to restore all windows and tabs.

Limitations: the page content and navigation history are not saved. The
file is written only at exit so this can't be used for crash recovery
(but you can make a backup of your default session).

Fixes #6680.
This commit is contained in:
Adrien Destugues
2015-11-13 14:32:13 +01:00
parent be741f6ec1
commit f86df64b91
4 changed files with 89 additions and 16 deletions
+65 -15
View File
@@ -77,6 +77,7 @@ BrowserApp::BrowserApp()
fInitialized(false), fInitialized(false),
fSettings(NULL), fSettings(NULL),
fCookies(NULL), fCookies(NULL),
fSession(NULL),
fContext(NULL), fContext(NULL),
fDownloadWindow(NULL), fDownloadWindow(NULL),
fSettingsWindow(NULL), fSettingsWindow(NULL),
@@ -92,6 +93,11 @@ BrowserApp::BrowserApp()
fContext = new BUrlContext(); fContext = new BUrlContext();
fContext->SetCookieJar(BNetworkCookieJar(&cookieArchive)); fContext->SetCookieJar(BNetworkCookieJar(&cookieArchive));
#endif #endif
BString sessionStorePath = kApplicationName;
sessionStorePath << "/Session";
fSession = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
sessionStorePath.String());
} }
@@ -100,6 +106,7 @@ BrowserApp::~BrowserApp()
delete fLaunchRefsMessage; delete fLaunchRefsMessage;
delete fSettings; delete fSettings;
delete fCookies; delete fCookies;
delete fSession;
delete fContext; delete fContext;
} }
@@ -223,6 +230,29 @@ BrowserApp::ReadyToRun()
delete fLaunchRefsMessage; delete fLaunchRefsMessage;
fLaunchRefsMessage = NULL; fLaunchRefsMessage = NULL;
} }
BMessage archivedWindow;
for (int i = 0; fSession->FindMessage("window", i, &archivedWindow) == B_OK;
i++) {
BRect frame = archivedWindow.FindRect("window frame");
BString url;
archivedWindow.FindString("tab", 0, &url);
BrowserWindow* window = new(std::nothrow) BrowserWindow(frame,
fSettings, url, fContext);
if (window != NULL) {
window->Show();
for (int j = 1; archivedWindow.FindString("tab", j, &url) == B_OK;
j++) {
printf("Create %d:%d\n", i, j);
_CreateNewTab(window, url, false);
pagesCreated++;
}
}
}
if (pagesCreated == 0) if (pagesCreated == 0)
_CreateNewWindow("", fullscreen); _CreateNewWindow("", fullscreen);
@@ -267,8 +297,11 @@ BrowserApp::MessageReceived(BMessage* message)
case WINDOW_CLOSED: case WINDOW_CLOSED:
fWindowCount--; fWindowCount--;
message->FindRect("window frame", &fLastWindowFrame); message->FindRect("window frame", &fLastWindowFrame);
if (fWindowCount <= 0) if (fWindowCount <= 0) {
PostMessage(B_QUIT_REQUESTED); BMessage* message = new BMessage(B_QUIT_REQUESTED);
message->AddMessage("window", DetachCurrentMessage());
PostMessage(message);
}
break; break;
case SHOW_DOWNLOAD_WINDOW: case SHOW_DOWNLOAD_WINDOW:
@@ -333,19 +366,36 @@ BrowserApp::QuitRequested()
} }
} }
for (int i = 0; BWindow* window = WindowAt(i); i++) { fSession->MakeEmpty();
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
if (!webWindow) /* See if we got here because the last window is already closed.
continue; * In that case we only need to save that one, which is already archived */
if (!webWindow->Lock()) BMessage* message = CurrentMessage();
continue; BMessage windowMessage;
if (webWindow->QuitRequested()) {
fLastWindowFrame = webWindow->WindowFrame(); status_t ret = message->FindMessage("window", &windowMessage);
webWindow->Quit(); if (ret == B_OK) {
i--; fSession->AddMessage("window", &windowMessage);
} else { } else {
webWindow->Unlock(); for (int i = 0; BWindow* window = WindowAt(i); i++) {
return false; BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
if (!webWindow)
continue;
if (!webWindow->Lock())
continue;
BMessage windowArchive;
webWindow->Archive(&windowArchive, true);
fSession->AddMessage("window", &windowArchive);
if (webWindow->QuitRequested()) {
fLastWindowFrame = webWindow->WindowFrame();
webWindow->Quit();
i--;
} else {
webWindow->Unlock();
return false;
}
} }
} }
+1
View File
@@ -79,6 +79,7 @@ private:
SettingsMessage* fSettings; SettingsMessage* fSettings;
SettingsMessage* fCookies; SettingsMessage* fCookies;
SettingsMessage* fSession;
BUrlContext* fContext; BUrlContext* fContext;
DownloadWindow* fDownloadWindow; DownloadWindow* fDownloadWindow;
+22 -1
View File
@@ -1186,18 +1186,39 @@ BrowserWindow::MessageReceived(BMessage* message)
} }
status_t
BrowserWindow::Archive(BMessage* archive, bool deep) const
{
status_t ret = archive->AddRect("window frame", Frame());
for (int i = 0; i < fTabManager->CountTabs(); i++) {
BWebView* view = dynamic_cast<BWebView*>(fTabManager->ViewForTab(i));
if (view == NULL) {
continue;
}
if (ret == B_OK)
ret = archive->AddString("tab", view->MainFrameURL());
}
return ret;
}
bool bool
BrowserWindow::QuitRequested() BrowserWindow::QuitRequested()
{ {
// TODO: Check for modified form data and ask user for confirmation, etc. // TODO: Check for modified form data and ask user for confirmation, etc.
BMessage message(WINDOW_CLOSED);
Archive(&message);
// Iterate over all tabs to delete all BWebViews. // Iterate over all tabs to delete all BWebViews.
// Do this here, so WebKit tear down happens earlier. // Do this here, so WebKit tear down happens earlier.
SetCurrentWebView(NULL); SetCurrentWebView(NULL);
while (fTabManager->CountTabs() > 0) while (fTabManager->CountTabs() > 0)
_ShutdownTab(0); _ShutdownTab(0);
BMessage message(WINDOW_CLOSED);
message.AddRect("window frame", WindowFrame()); message.AddRect("window frame", WindowFrame());
be_app->PostMessage(&message); be_app->PostMessage(&message);
return true; return true;
+1
View File
@@ -104,6 +104,7 @@ public:
virtual void DispatchMessage(BMessage* message, virtual void DispatchMessage(BMessage* message,
BHandler* target); BHandler* target);
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual status_t Archive(BMessage* archive, bool deep =true) const;
virtual bool QuitRequested(); virtual bool QuitRequested();
virtual void MenusBeginning(); virtual void MenusBeginning();
virtual void MenusEnded(); virtual void MenusEnded();