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),
fSettings(NULL),
fCookies(NULL),
fSession(NULL),
fContext(NULL),
fDownloadWindow(NULL),
fSettingsWindow(NULL),
@@ -92,6 +93,11 @@ BrowserApp::BrowserApp()
fContext = new BUrlContext();
fContext->SetCookieJar(BNetworkCookieJar(&cookieArchive));
#endif
BString sessionStorePath = kApplicationName;
sessionStorePath << "/Session";
fSession = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
sessionStorePath.String());
}
@@ -100,6 +106,7 @@ BrowserApp::~BrowserApp()
delete fLaunchRefsMessage;
delete fSettings;
delete fCookies;
delete fSession;
delete fContext;
}
@@ -223,6 +230,29 @@ BrowserApp::ReadyToRun()
delete fLaunchRefsMessage;
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)
_CreateNewWindow("", fullscreen);
@@ -267,8 +297,11 @@ BrowserApp::MessageReceived(BMessage* message)
case WINDOW_CLOSED:
fWindowCount--;
message->FindRect("window frame", &fLastWindowFrame);
if (fWindowCount <= 0)
PostMessage(B_QUIT_REQUESTED);
if (fWindowCount <= 0) {
BMessage* message = new BMessage(B_QUIT_REQUESTED);
message->AddMessage("window", DetachCurrentMessage());
PostMessage(message);
}
break;
case SHOW_DOWNLOAD_WINDOW:
@@ -333,19 +366,36 @@ BrowserApp::QuitRequested()
}
}
for (int i = 0; BWindow* window = WindowAt(i); i++) {
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
if (!webWindow)
continue;
if (!webWindow->Lock())
continue;
if (webWindow->QuitRequested()) {
fLastWindowFrame = webWindow->WindowFrame();
webWindow->Quit();
i--;
} else {
webWindow->Unlock();
return false;
fSession->MakeEmpty();
/* See if we got here because the last window is already closed.
* In that case we only need to save that one, which is already archived */
BMessage* message = CurrentMessage();
BMessage windowMessage;
status_t ret = message->FindMessage("window", &windowMessage);
if (ret == B_OK) {
fSession->AddMessage("window", &windowMessage);
} else {
for (int i = 0; BWindow* window = WindowAt(i); i++) {
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* fCookies;
SettingsMessage* fSession;
BUrlContext* fContext;
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
BrowserWindow::QuitRequested()
{
// 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.
// Do this here, so WebKit tear down happens earlier.
SetCurrentWebView(NULL);
while (fTabManager->CountTabs() > 0)
_ShutdownTab(0);
BMessage message(WINDOW_CLOSED);
message.AddRect("window frame", WindowFrame());
be_app->PostMessage(&message);
return true;
+1
View File
@@ -104,6 +104,7 @@ public:
virtual void DispatchMessage(BMessage* message,
BHandler* target);
virtual void MessageReceived(BMessage* message);
virtual status_t Archive(BMessage* archive, bool deep =true) const;
virtual bool QuitRequested();
virtual void MenusBeginning();
virtual void MenusEnded();