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

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

Issue 8533013: SessionRestore: Store session cookies and restore them if chrome crashes or auto-restarts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 1 month 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/command_line.h"
12 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_vector.h" 15 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop.h" 16 #include "base/message_loop.h"
15 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
16 #include "base/pickle.h" 18 #include "base/pickle.h"
17 #include "base/threading/thread.h" 19 #include "base/threading/thread.h"
18 #include "chrome/browser/extensions/extension_tab_helper.h" 20 #include "chrome/browser/extensions/extension_tab_helper.h"
21 #include "chrome/browser/net/chrome_cookie_notification_details.h"
19 #include "chrome/browser/prefs/session_startup_pref.h" 22 #include "chrome/browser/prefs/session_startup_pref.h"
20 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/sessions/restore_tab_helper.h" 24 #include "chrome/browser/sessions/restore_tab_helper.h"
22 #include "chrome/browser/sessions/session_backend.h" 25 #include "chrome/browser/sessions/session_backend.h"
23 #include "chrome/browser/sessions/session_command.h" 26 #include "chrome/browser/sessions/session_command.h"
24 #include "chrome/browser/sessions/session_restore.h" 27 #include "chrome/browser/sessions/session_restore.h"
25 #include "chrome/browser/sessions/session_types.h" 28 #include "chrome/browser/sessions/session_types.h"
26 #include "chrome/browser/tabs/tab_strip_model.h" 29 #include "chrome/browser/tabs/tab_strip_model.h"
27 #include "chrome/browser/ui/browser_init.h" 30 #include "chrome/browser/ui/browser_init.h"
28 #include "chrome/browser/ui/browser_list.h" 31 #include "chrome/browser/ui/browser_list.h"
29 #include "chrome/browser/ui/browser_window.h" 32 #include "chrome/browser/ui/browser_window.h"
30 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 33 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
31 #include "chrome/common/chrome_notification_types.h" 34 #include "chrome/common/chrome_notification_types.h"
35 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/extensions/extension.h" 36 #include "chrome/common/extensions/extension.h"
33 #include "content/browser/tab_contents/navigation_details.h" 37 #include "content/browser/tab_contents/navigation_details.h"
34 #include "content/browser/tab_contents/navigation_entry.h" 38 #include "content/browser/tab_contents/navigation_entry.h"
35 #include "content/browser/tab_contents/tab_contents.h" 39 #include "content/browser/tab_contents/tab_contents.h"
40 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/notification_service.h" 41 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/notification_details.h" 42 #include "content/public/browser/notification_details.h"
43 #include "net/url_request/url_request_context.h"
44 #include "net/url_request/url_request_context_getter.h"
38 45
39 #if defined(OS_MACOSX) 46 #if defined(OS_MACOSX)
40 #include "chrome/browser/app_controller_cppsafe_mac.h" 47 #include "chrome/browser/app_controller_cppsafe_mac.h"
41 #endif 48 #endif
42 49
43 using base::Time; 50 using base::Time;
44 51
45 // Identifier for commands written to file. 52 // Identifier for commands written to file.
46 static const SessionCommand::id_type kCommandSetTabWindow = 0; 53 static const SessionCommand::id_type kCommandSetTabWindow = 0;
47 // OBSOLETE Superseded by kCommandSetWindowBounds3. 54 // OBSOLETE Superseded by kCommandSetWindowBounds3.
48 // static const SessionCommand::id_type kCommandSetWindowBounds = 1; 55 // static const SessionCommand::id_type kCommandSetWindowBounds = 1;
49 static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2; 56 static const SessionCommand::id_type kCommandSetTabIndexInWindow = 2;
50 static const SessionCommand::id_type kCommandTabClosed = 3; 57 static const SessionCommand::id_type kCommandTabClosed = 3;
51 static const SessionCommand::id_type kCommandWindowClosed = 4; 58 static const SessionCommand::id_type kCommandWindowClosed = 4;
52 static const SessionCommand::id_type 59 static const SessionCommand::id_type
53 kCommandTabNavigationPathPrunedFromBack = 5; 60 kCommandTabNavigationPathPrunedFromBack = 5;
54 static const SessionCommand::id_type kCommandUpdateTabNavigation = 6; 61 static const SessionCommand::id_type kCommandUpdateTabNavigation = 6;
55 static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7; 62 static const SessionCommand::id_type kCommandSetSelectedNavigationIndex = 7;
56 static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8; 63 static const SessionCommand::id_type kCommandSetSelectedTabInIndex = 8;
57 static const SessionCommand::id_type kCommandSetWindowType = 9; 64 static const SessionCommand::id_type kCommandSetWindowType = 9;
58 // OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration. 65 // OBSOLETE Superseded by kCommandSetWindowBounds3. Except for data migration.
59 // static const SessionCommand::id_type kCommandSetWindowBounds2 = 10; 66 // static const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
60 static const SessionCommand::id_type 67 static const SessionCommand::id_type
61 kCommandTabNavigationPathPrunedFromFront = 11; 68 kCommandTabNavigationPathPrunedFromFront = 11;
62 static const SessionCommand::id_type kCommandSetPinnedState = 12; 69 static const SessionCommand::id_type kCommandSetPinnedState = 12;
63 static const SessionCommand::id_type kCommandSetExtensionAppID = 13; 70 static const SessionCommand::id_type kCommandSetExtensionAppID = 13;
64 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14; 71 static const SessionCommand::id_type kCommandSetWindowBounds3 = 14;
72 static const SessionCommand::id_type kCommandSessionCookieCreated = 15;
65 73
66 // Every kWritesPerReset commands triggers recreating the file. 74 // Every kWritesPerReset commands triggers recreating the file.
67 static const int kWritesPerReset = 250; 75 static const int kWritesPerReset = 250;
68 76
69 namespace { 77 namespace {
70 78
71 // The callback from GetLastSession is internally routed to SessionService 79 // The callback from GetLastSession is internally routed to SessionService
72 // first and then the caller. This is done so that the SessionWindows can be 80 // first and then the caller. This is done so that the SessionWindows can be
73 // recreated from the SessionCommands and the SessionWindows passed to the 81 // recreated from the SessionCommands and the SessionWindows passed to the
74 // caller. The following class is used for this. 82 // caller. The following class is used for this.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 138
131 typedef IDAndIndexPayload WindowTypePayload; 139 typedef IDAndIndexPayload WindowTypePayload;
132 140
133 typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload; 141 typedef IDAndIndexPayload TabNavigationPathPrunedFromFrontPayload;
134 142
135 struct PinnedStatePayload { 143 struct PinnedStatePayload {
136 SessionID::id_type tab_id; 144 SessionID::id_type tab_id;
137 bool pinned_state; 145 bool pinned_state;
138 }; 146 };
139 147
148 struct CookieListHolder : public base::RefCountedThreadSafe<CookieListHolder> {
149 net::CookieList cookie_list;
150 };
151
152 void RestoreCookies(
153 net::URLRequestContextGetter* url_request_context_getter,
154 CookieListHolder* cookie_list_holder) {
155 net::CookieMonster* cookie_monster =
156 url_request_context_getter->GetURLRequestContext()->cookie_store()->
157 GetCookieMonster();
158 cookie_monster->InitializeFrom(cookie_list_holder->cookie_list);
159 }
160
140 } // namespace 161 } // namespace
141 162
142 // SessionService ------------------------------------------------------------- 163 // SessionService -------------------------------------------------------------
143 164
144 SessionService::SessionService(Profile* profile) 165 SessionService::SessionService(Profile* profile)
145 : BaseSessionService(SESSION_RESTORE, profile, FilePath()), 166 : BaseSessionService(SESSION_RESTORE, profile, FilePath()),
146 has_open_trackable_browsers_(false), 167 has_open_trackable_browsers_(false),
147 move_on_new_browser_(false), 168 move_on_new_browser_(false),
148 save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)), 169 save_delay_in_millis_(base::TimeDelta::FromMilliseconds(2500)),
149 save_delay_in_mins_(base::TimeDelta::FromMinutes(10)), 170 save_delay_in_mins_(base::TimeDelta::FromMinutes(10)),
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 RecordSessionUpdateHistogramData( 479 RecordSessionUpdateHistogramData(
459 chrome::NOTIFICATION_SESSION_SERVICE_SAVED, 480 chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
460 &last_updated_save_time_); 481 &last_updated_save_time_);
461 content::NotificationService::current()->Notify( 482 content::NotificationService::current()->Notify(
462 chrome::NOTIFICATION_SESSION_SERVICE_SAVED, 483 chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
463 content::Source<Profile>(profile()), 484 content::Source<Profile>(profile()),
464 content::NotificationService::NoDetails()); 485 content::NotificationService::NoDetails());
465 } 486 }
466 } 487 }
467 488
489 void SessionService::StoreSessionCookie(
490 const net::CookieMonster::CanonicalCookie* cookie,
491 bool removed) {
492 if (!removed) {
493 Pickle saved_cookie;
494 saved_cookie.WriteString(cookie->Source());
495 saved_cookie.WriteString(cookie->Name());
496 saved_cookie.WriteString(cookie->Value());
497 saved_cookie.WriteString(cookie->Domain());
498 saved_cookie.WriteString(cookie->Path());
499 saved_cookie.WriteString(cookie->MACKey());
500 saved_cookie.WriteString(cookie->MACAlgorithm());
501 saved_cookie.WriteInt64(cookie->CreationDate().ToInternalValue());
502 saved_cookie.WriteInt64(cookie->ExpiryDate().ToInternalValue());
503 saved_cookie.WriteBool(cookie->IsSecure());
504 saved_cookie.WriteBool(cookie->IsHttpOnly());
505 saved_cookie.WriteBool(cookie->IsPersistent());
506 SessionCommand* command = new SessionCommand(kCommandSessionCookieCreated,
507 saved_cookie);
508 ScheduleCommand(command);
509 }
510 }
511
468 void SessionService::Init() { 512 void SessionService::Init() {
469 // Register for the notifications we're interested in. 513 // Register for the notifications we're interested in.
470 registrar_.Add(this, content::NOTIFICATION_TAB_PARENTED, 514 registrar_.Add(this, content::NOTIFICATION_TAB_PARENTED,
471 content::NotificationService::AllSources()); 515 content::NotificationService::AllSources());
472 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSED, 516 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSED,
473 content::NotificationService::AllSources()); 517 content::NotificationService::AllSources());
474 registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED, 518 registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED,
475 content::NotificationService::AllSources()); 519 content::NotificationService::AllSources());
476 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED, 520 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED,
477 content::NotificationService::AllSources()); 521 content::NotificationService::AllSources());
478 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 522 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
479 content::NotificationService::AllSources()); 523 content::NotificationService::AllSources());
480 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, 524 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
481 content::NotificationService::AllBrowserContextsAndSources()); 525 content::NotificationService::AllBrowserContextsAndSources());
482 registrar_.Add( 526 registrar_.Add(
483 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, 527 this, chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
484 content::NotificationService::AllSources()); 528 content::NotificationService::AllSources());
529 registrar_.Add(
530 this, chrome::NOTIFICATION_COOKIE_CHANGED,
531 content::Source<Profile>(profile()));
485 } 532 }
486 533
487 bool SessionService::ShouldNewWindowStartSession() { 534 bool SessionService::ShouldNewWindowStartSession() {
488 if (!has_open_trackable_browsers_ && !BrowserInit::InProcessStartup() && 535 if (!has_open_trackable_browsers_ && !BrowserInit::InProcessStartup() &&
489 !SessionRestore::IsRestoring() 536 !SessionRestore::IsRestoring()
490 #if defined(OS_MACOSX) 537 #if defined(OS_MACOSX)
491 // OSX has a fairly different idea of application lifetime than the 538 // OSX has a fairly different idea of application lifetime than the
492 // other platforms. We need to check that we aren't opening a window 539 // other platforms. We need to check that we aren't opening a window
493 // from the dock or the menubar. 540 // from the dock or the menubar.
494 && !app_controller_mac::IsOpeningNewWindow() 541 && !app_controller_mac::IsOpeningNewWindow()
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 if (extension_tab_helper->extension_app()) { 690 if (extension_tab_helper->extension_app()) {
644 RestoreTabHelper* helper = 691 RestoreTabHelper* helper =
645 extension_tab_helper->tab_contents_wrapper()->restore_tab_helper(); 692 extension_tab_helper->tab_contents_wrapper()->restore_tab_helper();
646 SetTabExtensionAppID(helper->window_id(), 693 SetTabExtensionAppID(helper->window_id(),
647 helper->session_id(), 694 helper->session_id(),
648 extension_tab_helper->extension_app()->id()); 695 extension_tab_helper->extension_app()->id());
649 } 696 }
650 break; 697 break;
651 } 698 }
652 699
700 case chrome::NOTIFICATION_COOKIE_CHANGED: {
701 if (CommandLine::ForCurrentProcess()->HasSwitch(
702 switches::kEnableRestoreSessionCookies)) {
703 ChromeCookieDetails* cookie_details =
704 content::Details<ChromeCookieDetails>(details).ptr();
705 if (!cookie_details->cookie->IsPersistent()) {
706 StoreSessionCookie(cookie_details->cookie, cookie_details->removed);
707 }
708 }
709 break;
710 }
711
653 default: 712 default:
654 NOTREACHED(); 713 NOTREACHED();
655 } 714 }
656 } 715 }
657 716
658 void SessionService::SetTabExtensionAppID( 717 void SessionService::SetTabExtensionAppID(
659 const SessionID& window_id, 718 const SessionID& window_id,
660 const SessionID& tab_id, 719 const SessionID& tab_id,
661 const std::string& extension_app_id) { 720 const std::string& extension_app_id) {
662 if (!ShouldTrackChangesToWindow(window_id)) 721 if (!ShouldTrackChangesToWindow(window_id))
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 } 1001 }
943 } 1002 }
944 1003
945 bool SessionService::CreateTabsAndWindows( 1004 bool SessionService::CreateTabsAndWindows(
946 const std::vector<SessionCommand*>& data, 1005 const std::vector<SessionCommand*>& data,
947 std::map<int, SessionTab*>* tabs, 1006 std::map<int, SessionTab*>* tabs,
948 std::map<int, SessionWindow*>* windows) { 1007 std::map<int, SessionWindow*>* windows) {
949 // If the file is corrupt (command with wrong size, or unknown command), we 1008 // If the file is corrupt (command with wrong size, or unknown command), we
950 // still return true and attempt to restore what we we can. 1009 // still return true and attempt to restore what we we can.
951 1010
1011 // Session cookies are collected here and restored all at once.
1012 scoped_refptr<CookieListHolder> cookie_list_holder = new CookieListHolder;
1013 bool restore_session_cookies = CommandLine::ForCurrentProcess()->HasSwitch(
1014 switches::kEnableRestoreSessionCookies);
1015
952 for (std::vector<SessionCommand*>::const_iterator i = data.begin(); 1016 for (std::vector<SessionCommand*>::const_iterator i = data.begin();
953 i != data.end(); ++i) { 1017 i != data.end(); ++i) {
954 const SessionCommand::id_type kCommandSetWindowBounds2 = 10; 1018 const SessionCommand::id_type kCommandSetWindowBounds2 = 10;
955 const SessionCommand* command = *i; 1019 const SessionCommand* command = *i;
956 1020
957 switch (command->id()) { 1021 switch (command->id()) {
958 case kCommandSetTabWindow: { 1022 case kCommandSetTabWindow: {
959 SessionID::id_type payload[2]; 1023 SessionID::id_type payload[2];
960 if (!command->GetPayload(payload, sizeof(payload))) 1024 if (!command->GetPayload(payload, sizeof(payload)))
961 return true; 1025 return true;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 std::string extension_app_id; 1179 std::string extension_app_id;
1116 if (!RestoreSetTabExtensionAppIDCommand( 1180 if (!RestoreSetTabExtensionAppIDCommand(
1117 *command, &tab_id, &extension_app_id)) { 1181 *command, &tab_id, &extension_app_id)) {
1118 return true; 1182 return true;
1119 } 1183 }
1120 1184
1121 GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id); 1185 GetTab(tab_id, tabs)->extension_app_id.swap(extension_app_id);
1122 break; 1186 break;
1123 } 1187 }
1124 1188
1189 case kCommandSessionCookieCreated: {
jochen (gone - plz use gerrit) 2011/11/15 10:42:14 does this restore the cookies even if you just re-
marja 2011/11/17 12:54:46 Done.
1190 if (restore_session_cookies) {
1191 scoped_ptr<Pickle> pickle(command->PayloadAsPickle());
1192 std::string source, name, value, domain, path, mac_key, mac_algorithm;
1193 int64 creation_date_internal, expiry_date_internal;
1194 bool secure, http_only, persistent;
1195 void* iter = NULL;
1196 pickle->ReadString(&iter, &source);
1197 pickle->ReadString(&iter, &name);
1198 pickle->ReadString(&iter, &value);
1199 pickle->ReadString(&iter, &domain);
1200 pickle->ReadString(&iter, &path);
1201 pickle->ReadString(&iter, &mac_key);
1202 pickle->ReadString(&iter, &mac_algorithm);
1203 pickle->ReadInt64(&iter, &creation_date_internal);
1204 pickle->ReadInt64(&iter, &expiry_date_internal);
1205 pickle->ReadBool(&iter, &secure);
1206 pickle->ReadBool(&iter, &http_only);
1207 pickle->ReadBool(&iter, &persistent);
1208 scoped_ptr<net::CookieMonster::CanonicalCookie> cc(
1209 net::CookieMonster::CanonicalCookie::Create(
1210 GURL(source), name, value, domain, path, mac_key,
1211 mac_algorithm,
1212 base::Time::FromInternalValue(creation_date_internal),
1213 base::Time::FromInternalValue(expiry_date_internal),
1214 secure, http_only, persistent));
1215 cookie_list_holder->cookie_list.push_back(*cc);
1216 break;
1217 }
1218 }
1219
1125 default: 1220 default:
1126 return true; 1221 return true;
1127 } 1222 }
1128 } 1223 }
1224
1225 if (cookie_list_holder->cookie_list.size() > 0) {
1226 content::BrowserThread::PostTask(
1227 content::BrowserThread::IO, FROM_HERE,
1228 NewRunnableFunction(&RestoreCookies,
1229 make_scoped_refptr(profile()->GetRequestContext()),
1230 cookie_list_holder));
1231 }
1232
1129 return true; 1233 return true;
1130 } 1234 }
1131 1235
1132 void SessionService::BuildCommandsForTab( 1236 void SessionService::BuildCommandsForTab(
1133 const SessionID& window_id, 1237 const SessionID& window_id,
1134 TabContentsWrapper* tab, 1238 TabContentsWrapper* tab,
1135 int index_in_window, 1239 int index_in_window,
1136 bool is_pinned, 1240 bool is_pinned,
1137 std::vector<SessionCommand*>* commands, 1241 std::vector<SessionCommand*>* commands,
1138 IdToRange* tab_to_available_range) { 1242 IdToRange* tab_to_available_range) {
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 50); 1637 50);
1534 if (use_long_period) { 1638 if (use_long_period) {
1535 std::string long_name_("SessionRestore.SaveLongPeriod"); 1639 std::string long_name_("SessionRestore.SaveLongPeriod");
1536 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_, 1640 UMA_HISTOGRAM_CUSTOM_TIMES(long_name_,
1537 delta, 1641 delta,
1538 save_delay_in_mins_, 1642 save_delay_in_mins_,
1539 save_delay_in_hrs_, 1643 save_delay_in_hrs_,
1540 50); 1644 50);
1541 } 1645 }
1542 } 1646 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698