OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |