Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1377)

Side by Side Diff: chrome/browser/sessions/session_service.cc

Issue 10875027: Restart running apps when chrome restarts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sessions/session_service.h" 5 #include "chrome/browser/sessions/session_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/memory/scoped_vector.h" 16 #include "base/memory/scoped_vector.h"
17 #include "base/message_loop.h" 17 #include "base/message_loop.h"
18 #include "base/metrics/histogram.h" 18 #include "base/metrics/histogram.h"
19 #include "base/pickle.h" 19 #include "base/pickle.h"
20 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
21 #include "chrome/browser/extensions/tab_helper.h" 21 #include "chrome/browser/extensions/tab_helper.h"
22 #include "chrome/browser/extensions/extension_host.h"
marja 2012/08/23 07:31:18 The #include order is wrong.
koz (OOO until 15th September) 2012/08/23 07:59:04 Done.
22 #include "chrome/browser/prefs/session_startup_pref.h" 23 #include "chrome/browser/prefs/session_startup_pref.h"
23 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/sessions/restore_tab_helper.h" 25 #include "chrome/browser/sessions/restore_tab_helper.h"
25 #include "chrome/browser/sessions/session_backend.h" 26 #include "chrome/browser/sessions/session_backend.h"
26 #include "chrome/browser/sessions/session_command.h" 27 #include "chrome/browser/sessions/session_command.h"
27 #include "chrome/browser/sessions/session_restore.h" 28 #include "chrome/browser/sessions/session_restore.h"
28 #include "chrome/browser/sessions/session_types.h" 29 #include "chrome/browser/sessions/session_types.h"
29 #include "chrome/browser/ui/browser_list.h" 30 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/browser_tabstrip.h" 31 #include "chrome/browser/ui/browser_tabstrip.h"
31 #include "chrome/browser/ui/browser_window.h" 32 #include "chrome/browser/ui/browser_window.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 static const SessionCommand::id_type 69 static const SessionCommand::id_type
69 kCommandTabNavigationPathPrunedFromFront = 11; 70 kCommandTabNavigationPathPrunedFromFront = 11;
70 static const SessionCommand::id_type kCommandSetPinnedState = 12; 71 static const SessionCommand::id_type kCommandSetPinnedState = 12;
71 static const SessionCommand::id_type kCommandSetExtensionAppID = 13; 72 static const SessionCommand::id_type kCommandSetExtensionAppID = 13;
72 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14; 73 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14;
73 static const SessionCommand::id_type kCommandSetWindowAppName = 15; 74 static const SessionCommand::id_type kCommandSetWindowAppName = 15;
74 static const SessionCommand::id_type kCommandTabClosed = 16; 75 static const SessionCommand::id_type kCommandTabClosed = 16;
75 static const SessionCommand::id_type kCommandWindowClosed = 17; 76 static const SessionCommand::id_type kCommandWindowClosed = 17;
76 static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18; 77 static const SessionCommand::id_type kCommandSetTabUserAgentOverride = 18;
77 static const SessionCommand::id_type kCommandSessionStorageAssociated = 19; 78 static const SessionCommand::id_type kCommandSessionStorageAssociated = 19;
79 static const SessionCommand::id_type kCommandAppStarted = 20;
80 static const SessionCommand::id_type kCommandAppStopped = 21;
78 81
79 // Every kWritesPerReset commands triggers recreating the file. 82 // Every kWritesPerReset commands triggers recreating the file.
80 static const int kWritesPerReset = 250; 83 static const int kWritesPerReset = 250;
81 84
82 namespace { 85 namespace {
83 86
84 // The callback from GetLastSession is internally routed to SessionService 87 // The callback from GetLastSession is internally routed to SessionService
85 // first and then the caller. This is done so that the SessionWindows can be 88 // first and then the caller. This is done so that the SessionWindows can be
86 // recreated from the SessionCommands and the SessionWindows passed to the 89 // recreated from the SessionCommands and the SessionWindows passed to the
87 // caller. The following class is used for this. 90 // caller. The following class is used for this.
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED, 534 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED,
532 content::NotificationService::AllSources()); 535 content::NotificationService::AllSources());
533 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 536 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
534 content::NotificationService::AllSources()); 537 content::NotificationService::AllSources());
535 // Wait for NOTIFICATION_BROWSER_WINDOW_READY so that is_app() is set. 538 // Wait for NOTIFICATION_BROWSER_WINDOW_READY so that is_app() is set.
536 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, 539 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
537 content::NotificationService::AllBrowserContextsAndSources()); 540 content::NotificationService::AllBrowserContextsAndSources());
538 registrar_.Add( 541 registrar_.Add(
539 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, 542 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
540 content::NotificationService::AllSources()); 543 content::NotificationService::AllSources());
544 registrar_.Add(
545 this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
546 content::NotificationService::AllSources());
547 registrar_.Add(
548 this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
549 content::NotificationService::AllSources());
541 } 550 }
542 551
543 bool SessionService::ShouldNewWindowStartSession() { 552 bool SessionService::ShouldNewWindowStartSession() {
544 // ChromeOS and OSX have different ideas of application lifetime than 553 // ChromeOS and OSX have different ideas of application lifetime than
545 // the other platforms. 554 // the other platforms.
546 // On ChromeOS opening a new window should never start a new session. 555 // On ChromeOS opening a new window should never start a new session.
547 #if defined(OS_CHROMEOS) 556 #if defined(OS_CHROMEOS)
548 if (!force_browser_not_alive_with_no_windows_) 557 if (!force_browser_not_alive_with_no_windows_)
549 return false; 558 return false;
550 #endif 559 #endif
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (extension_tab_helper->extension_app()) { 730 if (extension_tab_helper->extension_app()) {
722 RestoreTabHelper* helper = 731 RestoreTabHelper* helper =
723 extension_tab_helper->tab_contents()->restore_tab_helper(); 732 extension_tab_helper->tab_contents()->restore_tab_helper();
724 SetTabExtensionAppID(helper->window_id(), 733 SetTabExtensionAppID(helper->window_id(),
725 helper->session_id(), 734 helper->session_id(),
726 extension_tab_helper->extension_app()->id()); 735 extension_tab_helper->extension_app()->id());
727 } 736 }
728 break; 737 break;
729 } 738 }
730 739
740 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
741 extensions::ExtensionHost* host =
742 content::Details<extensions::ExtensionHost>(details).ptr();
743 active_extensions_.insert(host);
744 if (host->extension()->is_platform_app())
745 ScheduleCommand(CreateRunAppCommand(host->extension()->id()));
746 break;
747 }
748
749 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
750 extensions::ExtensionHost* host =
751 content::Details<extensions::ExtensionHost>(details).ptr();
752 if (host->extension()->is_platform_app())
753 ScheduleCommand(CreateStopAppCommand(host->extension()->id()));
754 break;
755 }
756
731 default: 757 default:
732 NOTREACHED(); 758 NOTREACHED();
733 } 759 }
734 } 760 }
735 761
736 void SessionService::SetTabExtensionAppID( 762 void SessionService::SetTabExtensionAppID(
737 const SessionID& window_id, 763 const SessionID& window_id,
738 const SessionID& tab_id, 764 const SessionID& tab_id,
739 const std::string& extension_app_id) { 765 const std::string& extension_app_id) {
740 if (!ShouldTrackChangesToWindow(window_id)) 766 if (!ShouldTrackChangesToWindow(window_id))
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 889
864 SessionCommand* SessionService::CreateSessionStorageAssociatedCommand( 890 SessionCommand* SessionService::CreateSessionStorageAssociatedCommand(
865 const SessionID& tab_id, 891 const SessionID& tab_id,
866 const std::string& session_storage_persistent_id) { 892 const std::string& session_storage_persistent_id) {
867 Pickle pickle; 893 Pickle pickle;
868 pickle.WriteInt(tab_id.id()); 894 pickle.WriteInt(tab_id.id());
869 pickle.WriteString(session_storage_persistent_id); 895 pickle.WriteString(session_storage_persistent_id);
870 return new SessionCommand(kCommandSessionStorageAssociated, pickle); 896 return new SessionCommand(kCommandSessionStorageAssociated, pickle);
871 } 897 }
872 898
899 SessionCommand* SessionService::CreateRunAppCommand(
900 const std::string& extension_id) {
901 Pickle pickle;
902 pickle.WriteString(extension_id);
903 return new SessionCommand(kCommandAppStarted, pickle);
904 }
905
906 SessionCommand* SessionService::CreateStopAppCommand(
907 const std::string& extension_id) {
908 Pickle pickle;
909 pickle.WriteString(extension_id);
910 return new SessionCommand(kCommandAppStopped, pickle);
911 }
912
873 void SessionService::OnGotSessionCommands( 913 void SessionService::OnGotSessionCommands(
874 Handle handle, 914 Handle handle,
875 scoped_refptr<InternalGetCommandsRequest> request) { 915 scoped_refptr<InternalGetCommandsRequest> request) {
876 if (request->canceled()) 916 if (request->canceled())
877 return; 917 return;
878 918
879 ScopedVector<SessionWindow> valid_windows; 919 ScopedVector<SessionWindow> valid_windows;
920 std::set<std::string> apps;
880 RestoreSessionFromCommands( 921 RestoreSessionFromCommands(
881 request->commands, &(valid_windows.get())); 922 request->commands, &(valid_windows.get()), &apps);
882 static_cast<InternalSessionRequest*>(request.get())-> 923 static_cast<InternalSessionRequest*>(request.get())->
883 real_callback.Run(request->handle(), &(valid_windows.get())); 924 real_callback.Run(request->handle(), &(valid_windows.get()), &apps);
884 } 925 }
885 926
886 void SessionService::RestoreSessionFromCommands( 927 void SessionService::RestoreSessionFromCommands(
887 const std::vector<SessionCommand*>& commands, 928 const std::vector<SessionCommand*>& commands,
888 std::vector<SessionWindow*>* valid_windows) { 929 std::vector<SessionWindow*>* valid_windows,
930 std::set<std::string>* apps) {
889 std::map<int, SessionTab*> tabs; 931 std::map<int, SessionTab*> tabs;
890 std::map<int, SessionWindow*> windows; 932 std::map<int, SessionWindow*> windows;
891 933
892 VLOG(1) << "RestoreSessionFromCommands " << commands.size(); 934 VLOG(1) << "RestoreSessionFromCommands " << commands.size();
893 if (CreateTabsAndWindows(commands, &tabs, &windows)) { 935 if (CreateTabsAndWindows(commands, &tabs, &windows, apps)) {
894 AddTabsToWindows(&tabs, &windows); 936 AddTabsToWindows(&tabs, &windows);
895 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); 937 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows);
896 UpdateSelectedTabIndex(valid_windows); 938 UpdateSelectedTabIndex(valid_windows);
897 } 939 }
898 STLDeleteValues(&tabs); 940 STLDeleteValues(&tabs);
899 // Don't delete conents of windows, that is done by the caller as all 941 // Don't delete conents of windows, that is done by the caller as all
900 // valid windows are added to valid_windows. 942 // valid windows are added to valid_windows.
901 } 943 }
902 944
903 void SessionService::UpdateSelectedTabIndex( 945 void SessionService::UpdateSelectedTabIndex(
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 // Never got a set tab index in window, or tabs are empty, nothing 1072 // Never got a set tab index in window, or tabs are empty, nothing
1031 // to do. 1073 // to do.
1032 ++i; 1074 ++i;
1033 } 1075 }
1034 } 1076 }
1035 } 1077 }
1036 1078
1037 bool SessionService::CreateTabsAndWindows( 1079 bool SessionService::CreateTabsAndWindows(
1038 const std::vector<SessionCommand*>& data, 1080 const std::vector<SessionCommand*>& data,
1039 std::map<int, SessionTab*>* tabs, 1081 std::map<int, SessionTab*>* tabs,
1040 std::map<int, SessionWindow*>* windows) { 1082 std::map<int, SessionWindow*>* windows,
1083 std::set<std::string>* apps) {
1041 // If the file is corrupt (command with wrong size, or unknown command), we 1084 // If the file is corrupt (command with wrong size, or unknown command), we
1042 // still return true and attempt to restore what we we can. 1085 // still return true and attempt to restore what we we can.
1043 VLOG(1) << "CreateTabsAndWindows"; 1086 VLOG(1) << "CreateTabsAndWindows";
1044 1087
1045 for (std::vector<SessionCommand*>::const_iterator i = data.begin(); 1088 for (std::vector<SessionCommand*>::const_iterator i = data.begin();
1046 i != data.end(); ++i) { 1089 i != data.end(); ++i) {
1047 const SessionCommand::id_type kCommandSetWindowBounds2 = 10; 1090 const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
1048 const SessionCommand* command = *i; 1091 const SessionCommand* command = *i;
1049 1092
1050 VLOG(1) << "Read command " << (int) command->id(); 1093 VLOG(1) << "Read command " << (int) command->id();
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 PickleIterator iter(*command_pickle.get()); 1316 PickleIterator iter(*command_pickle.get());
1274 if (!command_pickle->ReadInt(&iter, &command_tab_id) || 1317 if (!command_pickle->ReadInt(&iter, &command_tab_id) ||
1275 !command_pickle->ReadString(&iter, &session_storage_persistent_id)) 1318 !command_pickle->ReadString(&iter, &session_storage_persistent_id))
1276 return true; 1319 return true;
1277 // Associate the session storage back. 1320 // Associate the session storage back.
1278 GetTab(command_tab_id, tabs)->session_storage_persistent_id = 1321 GetTab(command_tab_id, tabs)->session_storage_persistent_id =
1279 session_storage_persistent_id; 1322 session_storage_persistent_id;
1280 break; 1323 break;
1281 } 1324 }
1282 1325
1326 case kCommandAppStarted: {
1327 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
1328 PickleIterator iter(*command_pickle);
1329 std::string extension_id;
1330 if (!command_pickle->ReadString(&iter, &extension_id)) {
1331 return true;
1332 }
1333 apps->insert(extension_id);
1334 break;
1335 }
1336
1337 case kCommandAppStopped: {
1338 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
1339 PickleIterator iter(*command_pickle);
1340 std::string extension_id;
1341 if (!command_pickle->ReadString(&iter, &extension_id)) {
1342 return true;
1343 }
1344 apps->erase(extension_id);
1345 break;
1346 }
1347
1283 default: 1348 default:
1284 VLOG(1) << "Failed reading an unknown command " << command->id(); 1349 VLOG(1) << "Failed reading an unknown command " << command->id();
1285 return true; 1350 return true;
1286 } 1351 }
1287 } 1352 }
1288 return true; 1353 return true;
1289 } 1354 }
1290 1355
1291 void SessionService::BuildCommandsForTab( 1356 void SessionService::BuildCommandsForTab(
1292 const SessionID& window_id, 1357 const SessionID& window_id,
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL; 1488 AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
1424 if (should_track_changes_for_browser_type(browser->type(), app_type) && 1489 if (should_track_changes_for_browser_type(browser->type(), app_type) &&
1425 browser->tab_count() && 1490 browser->tab_count() &&
1426 browser->window()) { 1491 browser->window()) {
1427 BuildCommandsForBrowser(browser, commands, tab_to_available_range, 1492 BuildCommandsForBrowser(browser, commands, tab_to_available_range,
1428 windows_to_track); 1493 windows_to_track);
1429 } 1494 }
1430 } 1495 }
1431 } 1496 }
1432 1497
1433 void SessionService::ScheduleReset() { 1498 void SessionService::ScheduleReset() {
marja 2012/08/23 07:31:18 You'd need some code to recreate the app started /
koz (OOO until 15th September) 2012/08/23 07:59:05 Ah, I see. Yes, you're right. I've added a BuildCo
1434 set_pending_reset(true); 1499 set_pending_reset(true);
1435 STLDeleteElements(&pending_commands()); 1500 STLDeleteElements(&pending_commands());
1436 tab_to_available_range_.clear(); 1501 tab_to_available_range_.clear();
1437 windows_tracking_.clear(); 1502 windows_tracking_.clear();
1438 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_, 1503 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_,
1439 &windows_tracking_); 1504 &windows_tracking_);
1440 if (!windows_tracking_.empty()) { 1505 if (!windows_tracking_.empty()) {
1441 // We're lazily created on startup and won't get an initial batch of 1506 // We're lazily created on startup and won't get an initial batch of
1442 // SetWindowType messages. Set these here to make sure our state is correct. 1507 // SetWindowType messages. Set these here to make sure our state is correct.
1443 has_open_trackable_browsers_ = true; 1508 has_open_trackable_browsers_ = true;
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1731 50); 1796 50);
1732 if (use_long_period) { 1797 if (use_long_period) {
1733 std::string long_name_("SessionRestore.SaveLongPeriod"); 1798 std::string long_name_("SessionRestore.SaveLongPeriod");
1734 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1799 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
1735 delta, 1800 delta,
1736 save_delay_in_mins_, 1801 save_delay_in_mins_,
1737 save_delay_in_hrs_, 1802 save_delay_in_hrs_,
1738 50); 1803 50);
1739 } 1804 }
1740 } 1805 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698