From 3acb70efe8e81a9a9851f1b1c700dad3e6d94045 Mon Sep 17 00:00:00 2001 From: "albertb@google.com" Date: Mon, 1 Mar 2010 18:44:38 +0000 Subject: Added a new method to SessionService that returns a snapshot of the current session. The snapshot is computed directly from memory or, if there are pending closed windows, by reading the session commands from disk. BUG=35040 TEST=unit tests Review URL: http://codereview.chromium.org/661055 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40284 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/sessions/base_session_service.cc | 17 +++++++ chrome/browser/sessions/base_session_service.h | 6 +++ chrome/browser/sessions/session_backend.cc | 18 +++++++ chrome/browser/sessions/session_backend.h | 13 ++++- chrome/browser/sessions/session_restore.cc | 2 +- chrome/browser/sessions/session_service.cc | 58 ++++++++++++++++------ chrome/browser/sessions/session_service.h | 16 ++++-- .../browser/sessions/session_service_unittest.cc | 34 ++++++++++++- 8 files changed, 143 insertions(+), 21 deletions(-) (limited to 'chrome') diff --git a/chrome/browser/sessions/base_session_service.cc b/chrome/browser/sessions/base_session_service.cc index a8be23d..acd685b 100644 --- a/chrome/browser/sessions/base_session_service.cc +++ b/chrome/browser/sessions/base_session_service.cc @@ -267,3 +267,20 @@ BaseSessionService::Handle BaseSessionService::ScheduleGetLastSessionCommands( } return request->handle(); } + +BaseSessionService::Handle + BaseSessionService::ScheduleGetCurrentSessionCommands( + InternalGetCommandsRequest* request, + CancelableRequestConsumerBase* consumer) { + scoped_refptr request_wrapper(request); + AddRequest(request, consumer); + if (backend_thread()) { + backend_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(backend(), + &SessionBackend::ReadCurrentSessionCommands, + request_wrapper)); + } else { + backend()->ReadCurrentSessionCommands(request); + } + return request->handle(); +} diff --git a/chrome/browser/sessions/base_session_service.h b/chrome/browser/sessions/base_session_service.h index e6ba7d8..39dbeca 100644 --- a/chrome/browser/sessions/base_session_service.h +++ b/chrome/browser/sessions/base_session_service.h @@ -152,6 +152,12 @@ class BaseSessionService : public CancelableRequestProvider, InternalGetCommandsRequest* request, CancelableRequestConsumerBase* consumer); + // Invokes ReadCurrentSessionCommands with request on the backend thread. + // If testing, ReadLastSessionCommands is invoked directly. + Handle ScheduleGetCurrentSessionCommands( + InternalGetCommandsRequest* request, + CancelableRequestConsumerBase* consumer); + // Max number of navigation entries in each direction we'll persist. static const int max_persist_navigation_count; diff --git a/chrome/browser/sessions/session_backend.cc b/chrome/browser/sessions/session_backend.cc index 6658673..f9de317 100644 --- a/chrome/browser/sessions/session_backend.cc +++ b/chrome/browser/sessions/session_backend.cc @@ -281,6 +281,24 @@ void SessionBackend::MoveCurrentSessionToLastSession() { ResetFile(); } +void SessionBackend::ReadCurrentSessionCommands( + scoped_refptr request) { + if (request->canceled()) + return; + Init(); + ReadCurrentSessionCommandsImpl(&(request->commands)); + request->ForwardResult( + BaseSessionService::InternalGetCommandsRequest::TupleType( + request->handle(), request)); +} + +bool SessionBackend::ReadCurrentSessionCommandsImpl( + std::vector* commands) { + Init(); + SessionFileReader file_reader(GetCurrentSessionPath()); + return file_reader.Read(type_, commands); +} + bool SessionBackend::AppendCommandsToFile(net::FileStream* file, const std::vector& commands) { for (std::vector::const_iterator i = commands.begin(); diff --git a/chrome/browser/sessions/session_backend.h b/chrome/browser/sessions/session_backend.h index 51485c8..91c9bb7 100644 --- a/chrome/browser/sessions/session_backend.h +++ b/chrome/browser/sessions/session_backend.h @@ -62,7 +62,7 @@ class SessionBackend : public base::RefCountedThreadSafe { bool reset_first); // Invoked from the service to read the commands that make up the last - // session, invokes ReadSessionImpl to do the work. + // session, invokes ReadLastSessionCommandsImpl to do the work. void ReadLastSessionCommands( scoped_refptr request); @@ -80,6 +80,17 @@ class SessionBackend : public base::RefCountedThreadSafe { // browsers are running. void MoveCurrentSessionToLastSession(); + // Invoked from the service to read the commands that make up the current + // session, invokes ReadCurrentSessionCommandsImpl to do the work. + void ReadCurrentSessionCommands( + scoped_refptr request); + + // Reads the commands from the current file. + // + // On success, the read commands are added to commands. It is up to the + // caller to delete the commands. + bool ReadCurrentSessionCommandsImpl(std::vector* commands); + private: friend class base::RefCountedThreadSafe; diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index 3776666..99451b2 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc @@ -189,7 +189,7 @@ class SessionRestoreImpl : public NotificationObserver { void Restore() { SessionService* session_service = profile_->GetSessionService(); DCHECK(session_service); - SessionService::LastSessionCallback* callback = + SessionService::SessionCallback* callback = NewCallback(this, &SessionRestoreImpl::OnGotSession); session_service->GetLastSession(&request_consumer_, callback); diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 6c5b3d9..0031f618 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -67,23 +67,23 @@ namespace { // first and then the caller. This is done so that the SessionWindows can be // recreated from the SessionCommands and the SessionWindows passed to the // caller. The following class is used for this. -class InternalLastSessionRequest +class InternalSessionRequest : public BaseSessionService::InternalGetCommandsRequest { public: - InternalLastSessionRequest( + InternalSessionRequest( CallbackType* callback, - SessionService::LastSessionCallback* real_callback) + SessionService::SessionCallback* real_callback) : BaseSessionService::InternalGetCommandsRequest(callback), real_callback(real_callback) { } - // The callback supplied to GetLastSession. - scoped_ptr real_callback; + // The callback supplied to GetLastSession and GetCurrentSession. + scoped_ptr real_callback; private: - ~InternalLastSessionRequest() {} + ~InternalSessionRequest() {} - DISALLOW_COPY_AND_ASSIGN(InternalLastSessionRequest); + DISALLOW_COPY_AND_ASSIGN(InternalSessionRequest); }; // Various payload structures. @@ -385,13 +385,41 @@ void SessionService::SetSelectedTabInWindow(const SessionID& window_id, SessionService::Handle SessionService::GetLastSession( CancelableRequestConsumerBase* consumer, - LastSessionCallback* callback) { + SessionCallback* callback) { return ScheduleGetLastSessionCommands( - new InternalLastSessionRequest( - NewCallback(this, &SessionService::OnGotLastSessionCommands), + new InternalSessionRequest( + NewCallback(this, &SessionService::OnGotSessionCommands), callback), consumer); } +SessionService::Handle SessionService::GetCurrentSession( + CancelableRequestConsumerBase* consumer, + SessionCallback* callback) { + if (pending_window_close_ids_.empty()) { + // If there are no pending window closes, we can get the current session + // from memory. + InternalSessionRequest* request = new InternalSessionRequest( + NewCallback(this, &SessionService::OnGotSessionCommands), + callback); + AddRequest(request, consumer); + IdToRange tab_to_available_range; + std::set windows_to_track; + BuildCommandsFromBrowsers(&(request->commands), + &tab_to_available_range, + &windows_to_track); + request->ForwardResult( + BaseSessionService::InternalGetCommandsRequest::TupleType( + request->handle(), request)); + return request->handle(); + } else { + // If there are pending window closes, read the current session from disk. + return ScheduleGetCurrentSessionCommands( + new InternalSessionRequest( + NewCallback(this, &SessionService::OnGotSessionCommands), + callback), consumer); + } +} + void SessionService::Init() { // Register for the notifications we're interested in. registrar_.Add(this, NotificationType::TAB_PARENTED, @@ -650,7 +678,7 @@ SessionCommand* SessionService::CreatePinnedStateCommand( return command; } -void SessionService::OnGotLastSessionCommands( +void SessionService::OnGotSessionCommands( Handle handle, scoped_refptr request) { if (request->canceled()) @@ -658,10 +686,10 @@ void SessionService::OnGotLastSessionCommands( ScopedVector valid_windows; RestoreSessionFromCommands( request->commands, &(valid_windows.get())); - static_cast(request.get())-> + static_cast(request.get())-> real_callback->RunWithParams( - LastSessionCallback::TupleType(request->handle(), - &(valid_windows.get()))); + SessionCallback::TupleType(request->handle(), + &(valid_windows.get()))); } void SessionService::RestoreSessionFromCommands( @@ -1045,7 +1073,7 @@ void SessionService::BuildCommandsForBrowser( for (int i = 0; i < browser->tab_count(); ++i) { TabContents* tab = browser->GetTabContentsAt(i); DCHECK(tab); - if (tab->profile() == profile()) { + if (tab->profile() == profile() || profile() == NULL) { BuildCommandsForTab(browser->session_id(), &tab->controller(), i, browser->tabstrip_model()->IsTabPinned(i), commands, tab_to_available_range); diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index 018263e..a950224 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h @@ -137,7 +137,7 @@ class SessionService : public BaseSessionService, // // The time gives the time the session was closed. typedef Callback2*>::Type - LastSessionCallback; + SessionCallback; // Fetches the contents of the last session, notifying the callback when // done. If the callback is supplied an empty vector of SessionWindows @@ -147,7 +147,17 @@ class SessionService : public BaseSessionService, // callback invokes OnGotSessionCommands from which we map the // SessionCommands to browser state, then notify the callback. Handle GetLastSession(CancelableRequestConsumerBase* consumer, - LastSessionCallback* callback); + SessionCallback* callback); + + // Fetches the contents of the current session, notifying the callback when + // done. If the callback is supplied an empty vector of SessionWindows + // it means the session could not be restored. + // + // The created request does NOT directly invoke the callback, rather the + // callback invokes OnGotSessionCommands from which we map the + // SessionCommands to browser state, then notify the callback. + Handle GetCurrentSession(CancelableRequestConsumerBase* consumer, + SessionCallback* callback); private: typedef std::map > IdToRange; @@ -211,7 +221,7 @@ class SessionService : public BaseSessionService, // Callback form the backend for getting the commands from the previous // or save file. Converts the commands in SessionWindows and notifies // the real callback. - void OnGotLastSessionCommands( + void OnGotSessionCommands( Handle handle, scoped_refptr request); diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 8d2a9da..20451b6 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc @@ -16,15 +16,17 @@ #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/common/chrome_paths.h" +#include "chrome/test/browser_with_test_window_test.h" #include "chrome/test/file_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -class SessionServiceTest : public testing::Test { +class SessionServiceTest : public BrowserWithTestWindowTest { public: SessionServiceTest() : window_bounds(0, 1, 2, 3) {} protected: virtual void SetUp() { + BrowserWithTestWindowTest::SetUp(); std::string b = Int64ToString(base::Time::Now().ToInternalValue()); PathService::Get(base::DIR_TEMP, &path_); @@ -585,3 +587,33 @@ TEST_F(SessionServiceTest, PinnedTrue) { EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true)); } + +class GetCurrentSessionCallbackHandler { + public: + void OnGotSession(int handle, std::vector* windows) { + EXPECT_EQ(1U, windows->size()); + EXPECT_EQ(2U, (*windows)[0]->tabs.size()); + EXPECT_EQ(2U, (*windows)[0]->tabs[0]->navigations.size()); + EXPECT_EQ(GURL("http://bar/1"), + (*windows)[0]->tabs[0]->navigations[0].url()); + EXPECT_EQ(GURL("http://bar/2"), + (*windows)[0]->tabs[0]->navigations[1].url()); + EXPECT_EQ(2U, (*windows)[0]->tabs[1]->navigations.size()); + EXPECT_EQ(GURL("http://foo/1"), + (*windows)[0]->tabs[1]->navigations[0].url()); + EXPECT_EQ(GURL("http://foo/2"), + (*windows)[0]->tabs[1]->navigations[1].url()); + } +}; + +TEST_F(SessionServiceTest, GetCurrentSession) { + AddTab(browser(), GURL("http://foo/1")); + NavigateAndCommitActiveTab(GURL("http://foo/2")); + AddTab(browser(), GURL("http://bar/1")); + NavigateAndCommitActiveTab(GURL("http://bar/2")); + + CancelableRequestConsumer consumer; + GetCurrentSessionCallbackHandler handler; + service()->GetCurrentSession(&consumer, + NewCallback(&handler, &GetCurrentSessionCallbackHandler::OnGotSession)); +} -- cgit v1.1