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

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: respond to comments 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/extension_host.h"
21 #include "chrome/browser/extensions/tab_helper.h" 22 #include "chrome/browser/extensions/tab_helper.h"
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"
(...skipping 37 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 if (host->extension()->is_platform_app()) {
744 running_apps_.insert(host);
745 ScheduleCommand(CreateRunAppCommand(host->extension()->id()));
746 }
747 break;
748 }
749
750 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
751 extensions::ExtensionHost* host =
752 content::Details<extensions::ExtensionHost>(details).ptr();
753 if (host->extension()->is_platform_app()) {
754 running_apps_.erase(host);
755 ScheduleCommand(CreateStopAppCommand(host->extension()->id()));
756 }
757 break;
758 }
759
731 default: 760 default:
732 NOTREACHED(); 761 NOTREACHED();
733 } 762 }
734 } 763 }
735 764
736 void SessionService::SetTabExtensionAppID( 765 void SessionService::SetTabExtensionAppID(
737 const SessionID& window_id, 766 const SessionID& window_id,
738 const SessionID& tab_id, 767 const SessionID& tab_id,
739 const std::string& extension_app_id) { 768 const std::string& extension_app_id) {
740 if (!ShouldTrackChangesToWindow(window_id)) 769 if (!ShouldTrackChangesToWindow(window_id))
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 892
864 SessionCommand* SessionService::CreateSessionStorageAssociatedCommand( 893 SessionCommand* SessionService::CreateSessionStorageAssociatedCommand(
865 const SessionID& tab_id, 894 const SessionID& tab_id,
866 const std::string& session_storage_persistent_id) { 895 const std::string& session_storage_persistent_id) {
867 Pickle pickle; 896 Pickle pickle;
868 pickle.WriteInt(tab_id.id()); 897 pickle.WriteInt(tab_id.id());
869 pickle.WriteString(session_storage_persistent_id); 898 pickle.WriteString(session_storage_persistent_id);
870 return new SessionCommand(kCommandSessionStorageAssociated, pickle); 899 return new SessionCommand(kCommandSessionStorageAssociated, pickle);
871 } 900 }
872 901
902 SessionCommand* SessionService::CreateRunAppCommand(
903 const std::string& extension_id) {
904 Pickle pickle;
905 pickle.WriteString(extension_id);
906 return new SessionCommand(kCommandAppStarted, pickle);
907 }
908
909 SessionCommand* SessionService::CreateStopAppCommand(
910 const std::string& extension_id) {
911 Pickle pickle;
912 pickle.WriteString(extension_id);
913 return new SessionCommand(kCommandAppStopped, pickle);
914 }
915
873 void SessionService::OnGotSessionCommands( 916 void SessionService::OnGotSessionCommands(
874 Handle handle, 917 Handle handle,
875 scoped_refptr<InternalGetCommandsRequest> request) { 918 scoped_refptr<InternalGetCommandsRequest> request) {
876 if (request->canceled()) 919 if (request->canceled())
877 return; 920 return;
878 921
879 ScopedVector<SessionWindow> valid_windows; 922 ScopedVector<SessionWindow> valid_windows;
923 std::set<std::string> apps;
880 RestoreSessionFromCommands( 924 RestoreSessionFromCommands(
881 request->commands, &(valid_windows.get())); 925 request->commands, &(valid_windows.get()), &apps);
882 static_cast<InternalSessionRequest*>(request.get())-> 926 static_cast<InternalSessionRequest*>(request.get())->
883 real_callback.Run(request->handle(), &(valid_windows.get())); 927 real_callback.Run(request->handle(), &(valid_windows.get()), &apps);
884 } 928 }
885 929
886 void SessionService::RestoreSessionFromCommands( 930 void SessionService::RestoreSessionFromCommands(
887 const std::vector<SessionCommand*>& commands, 931 const std::vector<SessionCommand*>& commands,
888 std::vector<SessionWindow*>* valid_windows) { 932 std::vector<SessionWindow*>* valid_windows,
933 std::set<std::string>* apps) {
889 std::map<int, SessionTab*> tabs; 934 std::map<int, SessionTab*> tabs;
890 std::map<int, SessionWindow*> windows; 935 std::map<int, SessionWindow*> windows;
891 936
892 VLOG(1) << "RestoreSessionFromCommands " << commands.size(); 937 VLOG(1) << "RestoreSessionFromCommands " << commands.size();
893 if (CreateTabsAndWindows(commands, &tabs, &windows)) { 938 if (CreateTabsAndWindows(commands, &tabs, &windows, apps)) {
894 AddTabsToWindows(&tabs, &windows); 939 AddTabsToWindows(&tabs, &windows);
895 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows); 940 SortTabsBasedOnVisualOrderAndPrune(&windows, valid_windows);
896 UpdateSelectedTabIndex(valid_windows); 941 UpdateSelectedTabIndex(valid_windows);
897 } 942 }
898 STLDeleteValues(&tabs); 943 STLDeleteValues(&tabs);
899 // Don't delete conents of windows, that is done by the caller as all 944 // Don't delete conents of windows, that is done by the caller as all
900 // valid windows are added to valid_windows. 945 // valid windows are added to valid_windows.
901 } 946 }
902 947
903 void SessionService::UpdateSelectedTabIndex( 948 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 1075 // Never got a set tab index in window, or tabs are empty, nothing
1031 // to do. 1076 // to do.
1032 ++i; 1077 ++i;
1033 } 1078 }
1034 } 1079 }
1035 } 1080 }
1036 1081
1037 bool SessionService::CreateTabsAndWindows( 1082 bool SessionService::CreateTabsAndWindows(
1038 const std::vector<SessionCommand*>& data, 1083 const std::vector<SessionCommand*>& data,
1039 std::map<int, SessionTab*>* tabs, 1084 std::map<int, SessionTab*>* tabs,
1040 std::map<int, SessionWindow*>* windows) { 1085 std::map<int, SessionWindow*>* windows,
1086 std::set<std::string>* apps) {
1041 // If the file is corrupt (command with wrong size, or unknown command), we 1087 // 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. 1088 // still return true and attempt to restore what we we can.
1043 VLOG(1) << "CreateTabsAndWindows"; 1089 VLOG(1) << "CreateTabsAndWindows";
1044 1090
1045 for (std::vector<SessionCommand*>::const_iterator i = data.begin(); 1091 for (std::vector<SessionCommand*>::const_iterator i = data.begin();
1046 i != data.end(); ++i) { 1092 i != data.end(); ++i) {
1047 const SessionCommand::id_type kCommandSetWindowBounds2 = 10; 1093 const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
1048 const SessionCommand* command = *i; 1094 const SessionCommand* command = *i;
1049 1095
1050 VLOG(1) << "Read command " << (int) command->id(); 1096 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()); 1319 PickleIterator iter(*command_pickle.get());
1274 if (!command_pickle->ReadInt(&iter, &command_tab_id) || 1320 if (!command_pickle->ReadInt(&iter, &command_tab_id) ||
1275 !command_pickle->ReadString(&iter, &session_storage_persistent_id)) 1321 !command_pickle->ReadString(&iter, &session_storage_persistent_id))
1276 return true; 1322 return true;
1277 // Associate the session storage back. 1323 // Associate the session storage back.
1278 GetTab(command_tab_id, tabs)->session_storage_persistent_id = 1324 GetTab(command_tab_id, tabs)->session_storage_persistent_id =
1279 session_storage_persistent_id; 1325 session_storage_persistent_id;
1280 break; 1326 break;
1281 } 1327 }
1282 1328
1329 case kCommandAppStarted: {
1330 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
1331 PickleIterator iter(*command_pickle);
1332 std::string extension_id;
1333 if (!command_pickle->ReadString(&iter, &extension_id)) {
sky 2012/08/23 16:23:52 no {} here and 1344
koz (OOO until 15th September) 2012/08/24 02:08:57 Done.
1334 return true;
1335 }
1336 apps->insert(extension_id);
1337 break;
1338 }
1339
1340 case kCommandAppStopped: {
1341 scoped_ptr<Pickle> command_pickle(command->PayloadAsPickle());
1342 PickleIterator iter(*command_pickle);
1343 std::string extension_id;
1344 if (!command_pickle->ReadString(&iter, &extension_id)) {
1345 return true;
1346 }
1347 apps->erase(extension_id);
1348 break;
1349 }
1350
1283 default: 1351 default:
1284 VLOG(1) << "Failed reading an unknown command " << command->id(); 1352 VLOG(1) << "Failed reading an unknown command " << command->id();
1285 return true; 1353 return true;
1286 } 1354 }
1287 } 1355 }
1288 return true; 1356 return true;
1289 } 1357 }
1290 1358
1291 void SessionService::BuildCommandsForTab( 1359 void SessionService::BuildCommandsForTab(
1292 const SessionID& window_id, 1360 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; 1491 AppType app_type = browser->is_app() ? TYPE_APP : TYPE_NORMAL;
1424 if (should_track_changes_for_browser_type(browser->type(), app_type) && 1492 if (should_track_changes_for_browser_type(browser->type(), app_type) &&
1425 browser->tab_count() && 1493 browser->tab_count() &&
1426 browser->window()) { 1494 browser->window()) {
1427 BuildCommandsForBrowser(browser, commands, tab_to_available_range, 1495 BuildCommandsForBrowser(browser, commands, tab_to_available_range,
1428 windows_to_track); 1496 windows_to_track);
1429 } 1497 }
1430 } 1498 }
1431 } 1499 }
1432 1500
1501 void SessionService::BuildCommandsFromRunningApps(
1502 std::vector<SessionCommand*>* commands) {
1503 DCHECK(commands);
1504 for (std::set<extensions::ExtensionHost*>::const_iterator it =
1505 running_apps_.begin(); it != running_apps_.end(); it++)
1506 commands->push_back(CreateRunAppCommand((*it)->extension()->id()));
1507 }
1508
1433 void SessionService::ScheduleReset() { 1509 void SessionService::ScheduleReset() {
1434 set_pending_reset(true); 1510 set_pending_reset(true);
1435 STLDeleteElements(&pending_commands()); 1511 STLDeleteElements(&pending_commands());
1436 tab_to_available_range_.clear(); 1512 tab_to_available_range_.clear();
1437 windows_tracking_.clear(); 1513 windows_tracking_.clear();
1438 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_, 1514 BuildCommandsFromBrowsers(&pending_commands(), &tab_to_available_range_,
1439 &windows_tracking_); 1515 &windows_tracking_);
1516 BuildCommandsFromRunningApps(&pending_commands());
1440 if (!windows_tracking_.empty()) { 1517 if (!windows_tracking_.empty()) {
1441 // We're lazily created on startup and won't get an initial batch of 1518 // 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. 1519 // SetWindowType messages. Set these here to make sure our state is correct.
1443 has_open_trackable_browsers_ = true; 1520 has_open_trackable_browsers_ = true;
1444 move_on_new_browser_ = true; 1521 move_on_new_browser_ = true;
1445 } 1522 }
1446 StartSaveTimer(); 1523 StartSaveTimer();
1447 } 1524 }
1448 1525
1449 bool SessionService::ReplacePendingCommand(SessionCommand* command) { 1526 bool SessionService::ReplacePendingCommand(SessionCommand* command) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1731 50); 1808 50);
1732 if (use_long_period) { 1809 if (use_long_period) {
1733 std::string long_name_("SessionRestore.SaveLongPeriod"); 1810 std::string long_name_("SessionRestore.SaveLongPeriod");
1734 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1811 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
1735 delta, 1812 delta,
1736 save_delay_in_mins_, 1813 save_delay_in_mins_,
1737 save_delay_in_hrs_, 1814 save_delay_in_hrs_,
1738 50); 1815 50);
1739 } 1816 }
1740 } 1817 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698