diff options
-rw-r--r-- | chrome/browser/browser.cc | 9 | ||||
-rw-r--r-- | chrome/browser/browser.h | 5 | ||||
-rw-r--r-- | chrome/browser/browser_commands.cc | 3 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 93 | ||||
-rw-r--r-- | chrome/browser/browser_init.h | 9 | ||||
-rw-r--r-- | chrome/browser/browser_list.cc | 2 | ||||
-rw-r--r-- | chrome/browser/session_crashed_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/session_restore.cc | 46 | ||||
-rw-r--r-- | chrome/browser/session_restore.h | 2 | ||||
-rw-r--r-- | chrome/browser/session_service.cc | 62 | ||||
-rw-r--r-- | chrome/browser/session_service.h | 30 |
11 files changed, 182 insertions, 81 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index af660d4..af82f77 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -248,12 +248,6 @@ Browser::Browser(const gfx::Rect& initial_bounds, NotificationService::current()->AddObserver( this, NOTIFY_SSL_STATE_CHANGED, NotificationService::AllSources()); - if (profile->HasSessionService()) { - SessionService* session_service = profile->GetSessionService(); - if (session_service) - session_service->SetWindowType(session_id_, type_); - } - InitCommandState(); BrowserList::AddBrowser(this); @@ -1266,13 +1260,14 @@ TabContents* Browser::AddTabWithNavigationController( NavigationController* Browser::AddRestoredTab( const std::vector<TabNavigation>& navigations, + int tab_index, int selected_navigation, bool select) { NavigationController* restored_controller = BuildRestoredNavigationController(navigations, selected_navigation); tabstrip_model_.InsertTabContentsAt( - tabstrip_model_.count(), + tab_index, restored_controller->active_contents(), select, false); if (profile_->HasSessionService()) { diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index b63f540..c1b7b53 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -211,9 +211,12 @@ class Browser : public TabStripModelDelegate, // Add a tab with its session history restored from the SessionRestore // system. If select is true, the tab is selected. Returns the created - // NavigationController. + // NavigationController. |tab_index| gives the index to insert the tab at. + // |selected_navigation| is the index of the TabNavigation in |navigations| to + // select. NavigationController* AddRestoredTab( const std::vector<TabNavigation>& navigations, + int tab_index, int selected_navigation, bool select); diff --git a/chrome/browser/browser_commands.cc b/chrome/browser/browser_commands.cc index a4df1c1..6d7a122 100644 --- a/chrome/browser/browser_commands.cc +++ b/chrome/browser/browser_commands.cc @@ -699,7 +699,8 @@ void Browser::ExecuteCommand(int id) { break; const TabRestoreService::HistoricalTab& tab = tabs.front(); - AddRestoredTab(tab.navigations, tab.current_navigation_index, true); + AddRestoredTab(tab.navigations, tab_count(), tab.current_navigation_index, + true); service->RemoveHistoricalTabById(tab.id); break; } diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 24918f6..37364f6 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -70,10 +70,25 @@ BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { return !*result; } +SessionStartupPref GetSessionStartupPref(Profile* profile, + const CommandLine& command_line) { + SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile); + if (command_line.HasSwitch(switches::kRestoreLastSession)) + pref.type = SessionStartupPref::LAST; + return pref; +} + } // namespace // MessageWindow -------------------------------------------------------------- +static bool in_startup = false; + +// static +bool BrowserInit::InProcessStartup() { + return in_startup; +} + BrowserInit::MessageWindow::MessageWindow(const std::wstring& user_data_dir) : window_(NULL), locked_(false) { @@ -478,12 +493,13 @@ bool BrowserInit::LaunchWithProfile::OpenStartupURLs( bool is_process_startup, const CommandLine& command_line, const std::vector<GURL>& urls_to_open) { - SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile_); - if (command_line.HasSwitch(switches::kRestoreLastSession)) - pref.type = SessionStartupPref::LAST; + SessionStartupPref pref = GetSessionStartupPref(profile_, command_line); switch (pref.type) { case SessionStartupPref::LAST: - if (is_process_startup && !profile_->DidLastSessionExitCleanly() && + if (!is_process_startup) + return false; + + if (!profile_->DidLastSessionExitCleanly() && !command_line.HasSwitch(switches::kRestoreLastSession)) { // The last session crashed. It's possible automatically loading the // page will trigger another crash, locking the user out of chrome. @@ -491,29 +507,8 @@ bool BrowserInit::LaunchWithProfile::OpenStartupURLs( // infobar. return false; } - if (!is_process_startup) { - SessionService* service = profile_->GetSessionService(); - if (service) { - if (service->has_open_tabbed_browsers()) { - // There are tabbed browsers open. Don't restore the session. - return false; - } - if (service->tabbed_browser_created()) { - // The user created at least one tabbed browser (but none are open - // now), make the 'current' session the last and restore from it. - service->MoveCurrentSessionToLastSession(); - } // else case, user never created a tabbed browser (most likely they - // launched an app and then double clicked on chrome), fall through - // to restore from last session. - } - } - if (is_process_startup) { - SessionRestore::RestoreSessionSynchronously( - profile_, false, show_command_, urls_to_open); - } else { - SessionRestore::RestoreSession(profile_, false, false, true, - urls_to_open); - } + SessionRestore::RestoreSessionSynchronously( + profile_, false, show_command_, urls_to_open); return true; case SessionStartupPref::URLS: @@ -670,6 +665,34 @@ bool BrowserInit::LaunchBrowser(const CommandLine& parsed_command_line, Profile* profile, int show_command, const std::wstring& cur_dir, bool process_startup, int* return_code) { + in_startup = process_startup; + bool result = LaunchBrowserImpl(parsed_command_line, profile, show_command, + cur_dir, process_startup, return_code); + in_startup = false; + return result; +} + +template <class AutomationProviderClass> +void BrowserInit::CreateAutomationProvider(const std::wstring& channel_id, + Profile* profile, + size_t expected_tabs) { + scoped_refptr<AutomationProviderClass> automation = + new AutomationProviderClass(profile); + automation->ConnectToChannel(channel_id); + automation->SetExpectedTabCount(expected_tabs); + + AutomationProviderList* list = + g_browser_process->InitAutomationProviderList(); + DCHECK(list); + list->AddProvider(automation); +} + +bool BrowserInit::LaunchBrowserImpl(const CommandLine& parsed_command_line, + Profile* profile, + int show_command, + const std::wstring& cur_dir, + bool process_startup, + int* return_code) { DCHECK(profile); // Continue with the off-the-record profile from here on if --incognito @@ -704,19 +727,3 @@ bool BrowserInit::LaunchBrowser(const CommandLine& parsed_command_line, return true; } - -template <class AutomationProviderClass> -void BrowserInit::CreateAutomationProvider(const std::wstring& channel_id, - Profile* profile, - size_t expected_tabs) { - scoped_refptr<AutomationProviderClass> automation = - new AutomationProviderClass(profile); - automation->ConnectToChannel(channel_id); - automation->SetExpectedTabCount(expected_tabs); - - AutomationProviderList* list = - g_browser_process->InitAutomationProviderList(); - DCHECK(list); - list->AddProvider(automation); -} - diff --git a/chrome/browser/browser_init.h b/chrome/browser/browser_init.h index e947f6b..424de15 100644 --- a/chrome/browser/browser_init.h +++ b/chrome/browser/browser_init.h @@ -24,6 +24,9 @@ class TabContents; // and initialize the profile. class BrowserInit { public: + // Returns true if the browser is coming up. + static bool InProcessStartup(); + // MessageWindow ------------------------------------------------------------- // // Class for dealing with the invisible global message window for IPC. This @@ -174,6 +177,12 @@ class BrowserInit { size_t expected_tabs); private: + // Does the work of LaunchBrowser returning the result. + static bool LaunchBrowserImpl(const CommandLine& parsed_command_line, + Profile* profile, int show_command, + const std::wstring& cur_dir, + bool process_startup, int* return_code); + // This class is for scoping purposes. BrowserInit(); DISALLOW_EVIL_CONSTRUCTORS(BrowserInit); diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc index f3cc18f..cd1e488 100644 --- a/chrome/browser/browser_list.cc +++ b/chrome/browser/browser_list.cc @@ -178,7 +178,7 @@ Browser* BrowserList::GetLastActive() { // static Browser* BrowserList::FindBrowserWithType(Profile* p, BrowserType::Type t) { Browser* last_active = GetLastActive(); - if (last_active->profile() == p && last_active->GetType() == t) + if (last_active && last_active->profile() == p && last_active->GetType() == t) return last_active; BrowserList::const_iterator i; diff --git a/chrome/browser/session_crashed_view.cc b/chrome/browser/session_crashed_view.cc index 6d0f15f..6fa81e3d 100644 --- a/chrome/browser/session_crashed_view.cc +++ b/chrome/browser/session_crashed_view.cc @@ -29,7 +29,7 @@ SessionCrashedView::~SessionCrashedView() { void SessionCrashedView::OKButtonPressed() { // Restore the session. - SessionRestore::RestoreSession(profile_, false, true, false, + SessionRestore::RestoreSession(profile_, NULL, false, true, false, std::vector<GURL>()); // Close the info bar. diff --git a/chrome/browser/session_restore.cc b/chrome/browser/session_restore.cc index d8fb4be..5b981c3 100644 --- a/chrome/browser/session_restore.cc +++ b/chrome/browser/session_restore.cc @@ -13,6 +13,7 @@ #include "chrome/browser/navigation_controller.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents.h" +#include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" namespace { @@ -176,9 +177,10 @@ void TabLoader::RemoveListeners(NavigationController* controller) { // SessionRestoreImpl is responsible for fetching the set of tabs to create // from SessionService. SessionRestoreImpl deletes itself when done. -class SessionRestoreImpl { +class SessionRestoreImpl : public NotificationObserver { public: SessionRestoreImpl(Profile* profile, + Browser* browser, bool use_saved_session, int show_command, bool synchronous, @@ -186,6 +188,7 @@ class SessionRestoreImpl { bool always_create_tabbed_browser, const std::vector<GURL>& urls_to_open) : profile_(profile), + browser_(browser), show_command_(show_command), use_saved_session_(use_saved_session), synchronous_(synchronous), @@ -209,11 +212,24 @@ class SessionRestoreImpl { delete this; return; } + + if (browser_) + registrar_.Add(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(browser_)); } ~SessionRestoreImpl() { } + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type != NOTIFY_BROWSER_CLOSED) { + NOTREACHED(); + return; + } + delete this; + } + private: // Invoked when done with creating all the tabs/browsers. // @@ -265,7 +281,8 @@ class SessionRestoreImpl { tab_loader_.reset(new TabLoader()); - Browser* current_browser = BrowserList::GetLastActive(); + Browser* current_browser = + browser_ ? browser_ : BrowserList::GetLastActive(); // After the for loop this contains the last TABBED_BROWSER. Is null if no // tabbed browsers exist. Browser* last_browser = NULL; @@ -326,13 +343,21 @@ class SessionRestoreImpl { std::min(selected_index, static_cast<int>(tab.navigations.size() - 1))); tab_loader_->AddTab( - browser->AddRestoredTab(tab.navigations, selected_index, false)); + browser->AddRestoredTab(tab.navigations, + static_cast<int>(i - window.tabs.begin()), + selected_index, + false)); } } void ShowBrowser(Browser* browser, int initial_tab_count, int selected_session_index) { + if (browser_ == browser) { + browser->SelectTabContentsAt(browser->tab_count() - 1, true); + return; + } + DCHECK(browser); DCHECK(browser->tab_count()); browser->SelectTabContentsAt( @@ -359,6 +384,9 @@ class SessionRestoreImpl { // The profile to create the sessions for. Profile* profile_; + // The first browser to restore to, may be null. + Browser* browser_; + // Used when creating windows. Passed to the window. const int show_command_; @@ -385,6 +413,8 @@ class SessionRestoreImpl { // Responsible for loading the tabs. scoped_ptr<TabLoader> tab_loader_; + + NotificationRegistrar registrar_; }; } // namespace @@ -395,6 +425,7 @@ class SessionRestoreImpl { size_t SessionRestore::num_tabs_to_load_ = 0; static void Restore(Profile* profile, + Browser* browser, bool use_saved_session, int show_command, bool synchronous, @@ -406,7 +437,7 @@ static void Restore(Profile* profile, return; // SessionRestoreImpl takes care of deleting itself when done. SessionRestoreImpl* restorer = - new SessionRestoreImpl(profile, use_saved_session, show_command, + new SessionRestoreImpl(profile, browser, use_saved_session, show_command, synchronous, clobber_existing_window, always_create_tabbed_browser, urls_to_open); @@ -415,11 +446,12 @@ static void Restore(Profile* profile, // static void SessionRestore::RestoreSession(Profile* profile, + Browser* browser, bool use_saved_session, bool clobber_existing_window, bool always_create_tabbed_browser, const std::vector<GURL>& urls_to_open) { - Restore(profile, use_saved_session, SW_SHOW, false, + Restore(profile, browser, use_saved_session, SW_SHOW, false, clobber_existing_window, always_create_tabbed_browser, urls_to_open); } @@ -429,6 +461,6 @@ void SessionRestore::RestoreSessionSynchronously( bool use_saved_session, int show_command, const std::vector<GURL>& urls_to_open) { - Restore(profile, use_saved_session, SW_SHOW, true, false, true, urls_to_open); + Restore(profile, NULL, use_saved_session, SW_SHOW, true, false, true, + urls_to_open); } - diff --git a/chrome/browser/session_restore.h b/chrome/browser/session_restore.h index 1c765c8..a8987ee 100644 --- a/chrome/browser/session_restore.h +++ b/chrome/browser/session_restore.h @@ -19,6 +19,7 @@ class Profile; class SessionRestore { public: // Asnchronously restores the specified session. + // If |browser| is non-null the tabs for the first window are added to it. // If clobber_existing_window is true and there is an open browser window, // it is closed after restoring. // If always_create_tabbed_browser is true at least one tabbed browser is @@ -28,6 +29,7 @@ class SessionRestore { // // If urls_to_open is non-empty, a tab is added for each of the URLs. static void RestoreSession(Profile* profile, + Browser* browser, bool use_saved_session, bool clobber_existing_window, bool always_create_tabbed_browser, diff --git a/chrome/browser/session_service.cc b/chrome/browser/session_service.cc index 8305642..813b56a 100644 --- a/chrome/browser/session_service.cc +++ b/chrome/browser/session_service.cc @@ -10,6 +10,7 @@ #include "base/message_loop.h" #include "base/pickle.h" #include "base/thread.h" +#include "chrome/browser/browser_init.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" @@ -17,6 +18,8 @@ #include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/session_backend.h" +#include "chrome/browser/session_restore.h" +#include "chrome/browser/session_startup_pref.h" #include "chrome/browser/tab_contents.h" #include "chrome/common/notification_details.h" #include "chrome/common/notification_service.h" @@ -132,7 +135,7 @@ SessionService::SessionService(Profile* profile) save_factory_(this), pending_reset_(false), has_open_tabbed_browsers_(false), - tabbed_browser_created_(false) { + move_on_new_browser_(false) { DCHECK(profile); // We should never be created when off the record. DCHECK(!profile->IsOffTheRecord()); @@ -145,7 +148,7 @@ SessionService::SessionService(const std::wstring& save_path) save_factory_(this), pending_reset_(false), has_open_tabbed_browsers_(false), - tabbed_browser_created_(false) { + move_on_new_browser_(false) { Init(save_path); } @@ -169,6 +172,8 @@ SessionService::~SessionService() { this, NOTIFY_NAV_ENTRY_CHANGED, NotificationService::AllSources()); NotificationService::current()->RemoveObserver( this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); + NotificationService::current()->RemoveObserver( + this, NOTIFY_BROWSER_OPENED, NotificationService::AllSources()); } void SessionService::ResetFromCurrentBrowsers() { @@ -299,7 +304,7 @@ void SessionService::SetWindowType(const SessionID& window_id, CommitPendingCloses(); has_open_tabbed_browsers_ = true; - tabbed_browser_created_ = true; + move_on_new_browser_ = true; ScheduleCommand(CreateSetWindowTypeCommand(window_id, type)); } @@ -451,6 +456,8 @@ void SessionService::Init(const std::wstring& path) { this, NOTIFY_NAV_ENTRY_CHANGED, NotificationService::AllSources()); NotificationService::current()->AddObserver( this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); + NotificationService::current()->AddObserver( + this, NOTIFY_BROWSER_OPENED, NotificationService::AllSources()); DCHECK(!path.empty()); commands_since_reset_ = 0; @@ -465,15 +472,49 @@ void SessionService::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { // All of our messages have the NavigationController as the source. - NavigationController* controller = Source<NavigationController>(source).ptr(); switch (type) { - case NOTIFY_TAB_PARENTED: + case NOTIFY_BROWSER_OPENED: { + Browser* browser = Source<Browser>(source).ptr(); + if (browser->profile() != profile_ || + !should_track_changes_for_browser_type(browser->GetType())) { + return; + } + + if (!has_open_tabbed_browsers_ && !BrowserInit::InProcessStartup()) { + // We're going from no tabbed browsers to a tabbed browser (and not in + // process startup), restore the last session. + if (move_on_new_browser_) { + // Make the current session the last. + MoveCurrentSessionToLastSession(); + move_on_new_browser_ = false; + } + SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile_); + if (pref.type == SessionStartupPref::LAST) { + SessionRestore::RestoreSession( + profile_, browser, false, false, false, std::vector<GURL>()); + } + } + SetWindowType(browser->session_id(), browser->GetType()); + break; + } + + case NOTIFY_TAB_PARENTED: { + NavigationController* controller = + Source<NavigationController>(source).ptr(); SetTabWindow(controller->window_id(), controller->session_id()); break; - case NOTIFY_TAB_CLOSED: + } + + case NOTIFY_TAB_CLOSED: { + NavigationController* controller = + Source<NavigationController>(source).ptr(); TabClosed(controller->window_id(), controller->session_id()); break; + } + case NOTIFY_NAV_LIST_PRUNED: { + NavigationController* controller = + Source<NavigationController>(source).ptr(); Details<NavigationController::PrunedDetails> pruned_details(details); if (pruned_details->from_front) { TabNavigationPathPrunedFromFront(controller->window_id(), @@ -486,13 +527,19 @@ void SessionService::Observe(NotificationType type, } break; } + case NOTIFY_NAV_ENTRY_CHANGED: { + NavigationController* controller = + Source<NavigationController>(source).ptr(); Details<NavigationController::EntryChangedDetails> changed(details); UpdateTabNavigation(controller->window_id(), controller->session_id(), changed->index, *changed->changed_entry); break; } + case NOTIFY_NAV_ENTRY_COMMITTED: { + NavigationController* controller = + Source<NavigationController>(source).ptr(); int current_entry_index = controller->GetCurrentEntryIndex(); SetSelectedNavigationIndex(controller->window_id(), controller->session_id(), @@ -502,6 +549,7 @@ void SessionService::Observe(NotificationType type, *controller->GetEntryAtIndex(current_entry_index)); break; } + default: NOTREACHED(); } @@ -1089,7 +1137,7 @@ void SessionService::ScheduleReset() { // We're lazily created on startup and won't get an initial batch of // SetWindowType messages. Set these here to make sure our state is correct. has_open_tabbed_browsers_ = true; - tabbed_browser_created_ = true; + move_on_new_browser_ = true; } StartSaveTimer(); } diff --git a/chrome/browser/session_service.h b/chrome/browser/session_service.h index 9918605..68b6c74b 100644 --- a/chrome/browser/session_service.h +++ b/chrome/browser/session_service.h @@ -165,15 +165,22 @@ struct SessionWindow { // SessionService ------------------------------------------------------------ // SessionService is responsible for maintaining the state of open windows -// and tabs so that they can be restored at a later date. +// and tabs so that they can be restored at a later date. The state of the +// currently open browsers is referred to as the current session. // -// SessionService supports restoring from two distinct points: -// . The last run of the browser. +// SessionService supports restoring from two distinct points (or sessions): +// . The previous or last session. The previous session typically corresponds +// to the last run of the browser, but not always. For example, if the user +// has a tabbed browser and app window running, closes the tabbed browser, +// then creates a new tabbed browser the current session is made the last +// session and the current session reset. This is done to provide the +// illusion that app windows run in separate processes. // . A user defined point. That is, any time CreateSavedSession is invoked // the save session is reset from the current state of the browser. // // Additionally the current session can be made the 'last' session at any point -// by way of MoveCurrentSessionToLastSession. +// by way of MoveCurrentSessionToLastSession. This may be done at certain points +// during the browser that are viewed as changing the // // SessionService itself maintains a set of SessionCommands that allow // SessionService to rebuild the open state of the browser (as @@ -194,12 +201,6 @@ class SessionService : public CancelableRequestProvider, ~SessionService(); - // Returns true if there are any open tabbed browser windows. - bool has_open_tabbed_browsers() const { return has_open_tabbed_browsers_; } - - // Returns true if a tabbed browser has ever been created. - bool tabbed_browser_created() const { return tabbed_browser_created_; } - // Resets the contents of the file from the current state of all open // browsers whose profile matches our profile. void ResetFromCurrentBrowsers(); @@ -547,7 +548,7 @@ class SessionService : public CancelableRequestProvider, // Used to invoke Save. ScopedRunnableMethodFactory<SessionService> save_factory_; - // When the user closes the last window, where the last window is the the + // When the user closes the last window, where the last window is the // last tabbed browser and no more tabbed browsers are open with the same // profile, the window ID is added here. These IDs are only committed (which // marks them as closed) if the user creates a new tabbed browser. @@ -579,8 +580,11 @@ class SessionService : public CancelableRequestProvider, // Are there any open open tabbed browsers? bool has_open_tabbed_browsers_; - // Was a tabbed browser ever created? - bool tabbed_browser_created_; + // If true and a new tabbed browser is created and there are no opened tabbed + // browser (has_open_tabbed_browsers_ is false), then the current session + // is made the previous session. See description above class for details on + // current/previou session. + bool move_on_new_browser_; }; #endif // CHROME_BROWSER_SESSION_SERVICE_H__ |