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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
|
||||
SettingsMessage* fSettings;
|
||||
SettingsMessage* fCookies;
|
||||
SettingsMessage* fSession;
|
||||
BUrlContext* fContext;
|
||||
|
||||
DownloadWindow* fDownloadWindow;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user