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