OLD | NEW |
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 "base/string_util.h" |
5 #include "chrome/browser/sync/glue/synced_session_tracker.h" | 6 #include "chrome/browser/sync/glue/synced_session_tracker.h" |
6 #include "chrome/browser/sync/glue/session_model_associator.h" | |
7 | 7 |
8 namespace browser_sync { | 8 namespace browser_sync { |
9 | 9 |
10 | |
11 SyncedSessionTracker::SyncedSessionTracker() { | 10 SyncedSessionTracker::SyncedSessionTracker() { |
12 } | 11 } |
13 | 12 |
14 SyncedSessionTracker::~SyncedSessionTracker() { | 13 SyncedSessionTracker::~SyncedSessionTracker() { |
15 clear(); | 14 Clear(); |
16 } | 15 } |
17 | 16 |
18 void SyncedSessionTracker::SetLocalSessionTag( | 17 void SyncedSessionTracker::SetLocalSessionTag( |
19 const std::string& local_session_tag) { | 18 const std::string& local_session_tag) { |
20 local_session_tag_ = local_session_tag; | 19 local_session_tag_ = local_session_tag; |
21 } | 20 } |
22 | 21 |
23 bool SyncedSessionTracker::LookupAllForeignSessions( | 22 bool SyncedSessionTracker::LookupAllForeignSessions( |
24 std::vector<const SyncedSession*>* sessions) { | 23 std::vector<const SyncedSession*>* sessions) const { |
25 DCHECK(sessions); | 24 DCHECK(sessions); |
| 25 sessions->clear(); |
26 // Fill vector of sessions from our synced session map. | 26 // Fill vector of sessions from our synced session map. |
27 for (SyncedSessionMap::const_iterator i = | 27 for (SyncedSessionMap::const_iterator i = |
28 synced_session_map_.begin(); i != synced_session_map_.end(); ++i) { | 28 synced_session_map_.begin(); i != synced_session_map_.end(); ++i) { |
29 // Only include foreign sessions with open tabs. | 29 // Only include foreign sessions with open tabs. |
30 SyncedSession* foreign_session = i->second; | 30 SyncedSession* foreign_session = i->second; |
31 if (i->first != local_session_tag_ && | 31 if (i->first != local_session_tag_ && !foreign_session->windows.empty()) { |
32 !foreign_session->windows.empty() && | 32 bool found_tabs = false; |
33 !SessionModelAssociator::SessionWindowHasNoTabsToSync( | 33 for (SyncedSession::SyncedWindowMap::const_iterator iter = |
34 *foreign_session->windows[0])) { | 34 foreign_session->windows.begin(); |
35 sessions->push_back(foreign_session); | 35 iter != foreign_session->windows.end(); ++iter) { |
| 36 if (!SessionWindowHasNoTabsToSync(*(iter->second))) { |
| 37 found_tabs = true; |
| 38 break; |
| 39 } |
| 40 } |
| 41 if (found_tabs) |
| 42 sessions->push_back(foreign_session); |
36 } | 43 } |
37 } | 44 } |
38 | 45 |
39 return !sessions->empty(); | 46 return !sessions->empty(); |
40 } | 47 } |
41 | 48 |
42 bool SyncedSessionTracker::LookupSessionWindows( | 49 bool SyncedSessionTracker::LookupSessionWindows( |
43 const std::string& session_tag, | 50 const std::string& session_tag, |
44 std::vector<SessionWindow*>* windows) { | 51 std::vector<const SessionWindow*>* windows) const { |
45 DCHECK(windows); | 52 DCHECK(windows); |
46 SyncedSessionMap::iterator iter = synced_session_map_.find(session_tag); | 53 windows->clear(); |
| 54 SyncedSessionMap::const_iterator iter = synced_session_map_.find(session_tag); |
47 if (iter == synced_session_map_.end()) | 55 if (iter == synced_session_map_.end()) |
48 return false; | 56 return false; |
49 *windows = iter->second->windows; | 57 windows->clear(); |
| 58 for (SyncedSession::SyncedWindowMap::const_iterator window_iter = |
| 59 iter->second->windows.begin(); |
| 60 window_iter != iter->second->windows.end(); window_iter++) { |
| 61 windows->push_back(window_iter->second); |
| 62 } |
50 return true; | 63 return true; |
51 } | 64 } |
52 | 65 |
53 bool SyncedSessionTracker::LookupSessionTab( | 66 bool SyncedSessionTracker::LookupSessionTab( |
54 const std::string& tag, | 67 const std::string& tag, |
55 SessionID::id_type tab_id, | 68 SessionID::id_type tab_id, |
56 const SessionTab** tab) { | 69 const SessionTab** tab) const { |
57 DCHECK(tab); | 70 DCHECK(tab); |
58 if (synced_tab_map_.find(tag) == synced_tab_map_.end()) { | 71 SyncedTabMap::const_iterator tab_map_iter = synced_tab_map_.find(tag); |
| 72 if (tab_map_iter == synced_tab_map_.end()) { |
59 // We have no record of this session. | 73 // We have no record of this session. |
60 *tab = NULL; | 74 *tab = NULL; |
61 return false; | 75 return false; |
62 } | 76 } |
63 if (synced_tab_map_[tag]->find(tab_id) == synced_tab_map_[tag]->end()) { | 77 IDToSessionTabMap::const_iterator tab_iter = |
| 78 tab_map_iter->second.find(tab_id); |
| 79 if (tab_iter == tab_map_iter->second.end()) { |
64 // We have no record of this tab. | 80 // We have no record of this tab. |
65 *tab = NULL; | 81 *tab = NULL; |
66 return false; | 82 return false; |
67 } | 83 } |
68 *tab = (*synced_tab_map_[tag])[tab_id]; | 84 *tab = tab_iter->second.tab_ptr; |
69 return true; | 85 return true; |
70 } | 86 } |
71 | 87 |
72 SyncedSession* SyncedSessionTracker::GetSession( | 88 SyncedSession* SyncedSessionTracker::GetSession( |
73 const std::string& session_tag) { | 89 const std::string& session_tag) { |
74 scoped_ptr<SyncedSession> synced_session; | 90 SyncedSession* synced_session = NULL; |
75 if (synced_session_map_.find(session_tag) != | 91 if (synced_session_map_.find(session_tag) != |
76 synced_session_map_.end()) { | 92 synced_session_map_.end()) { |
77 synced_session.reset(synced_session_map_[session_tag]); | 93 synced_session = synced_session_map_[session_tag]; |
78 } else { | 94 } else { |
79 synced_session.reset(new SyncedSession); | 95 synced_session = new SyncedSession; |
80 synced_session->session_tag = session_tag; | 96 synced_session->session_tag = session_tag; |
81 synced_session_map_[session_tag] = synced_session.get(); | 97 synced_session_map_[session_tag] = synced_session; |
82 } | 98 } |
83 DCHECK(synced_session.get()); | 99 DCHECK(synced_session); |
84 return synced_session.release(); | 100 return synced_session; |
85 } | 101 } |
86 | 102 |
87 bool SyncedSessionTracker::DeleteSession( | 103 bool SyncedSessionTracker::DeleteSession( |
88 const std::string& session_tag) { | 104 const std::string& session_tag) { |
89 SyncedSessionMap::iterator iter = | 105 SyncedSessionMap::iterator iter = |
90 synced_session_map_.find(session_tag); | 106 synced_session_map_.find(session_tag); |
91 if (iter != synced_session_map_.end()) { | 107 if (iter != synced_session_map_.end()) { |
92 delete iter->second; // Delete the SyncedSession object. | 108 delete iter->second; // Delete the SyncedSession object. |
93 synced_session_map_.erase(iter); | 109 synced_session_map_.erase(iter); |
94 return true; | 110 return true; |
95 } else { | 111 } else { |
96 return false; | 112 return false; |
97 } | 113 } |
98 } | 114 } |
99 | 115 |
100 SessionTab* SyncedSessionTracker::GetSessionTab( | 116 void SyncedSessionTracker::ResetSessionTracking( |
| 117 const std::string& session_tag) { |
| 118 // Reset window tracking. |
| 119 GetSession(session_tag)->windows.clear(); |
| 120 SyncedWindowMap::iterator window_iter = synced_window_map_.find(session_tag); |
| 121 if (window_iter != synced_window_map_.end()) { |
| 122 for (IDToSessionWindowMap::iterator window_map_iter = |
| 123 window_iter->second.begin(); |
| 124 window_map_iter != window_iter->second.end(); ++window_map_iter) { |
| 125 window_map_iter->second.owned = false; |
| 126 // We clear out the tabs to prevent double referencing of the same tab. |
| 127 // All tabs that are in use will be added back as needed. |
| 128 window_map_iter->second.window_ptr->tabs.clear(); |
| 129 } |
| 130 } |
| 131 |
| 132 // Reset tab tracking. |
| 133 SyncedTabMap::iterator tab_iter = synced_tab_map_.find(session_tag); |
| 134 if (tab_iter != synced_tab_map_.end()) { |
| 135 for (IDToSessionTabMap::iterator tab_map_iter = |
| 136 tab_iter->second.begin(); |
| 137 tab_map_iter != tab_iter->second.end(); ++tab_map_iter) { |
| 138 tab_map_iter->second.owned = false; |
| 139 } |
| 140 } |
| 141 } |
| 142 |
| 143 bool SyncedSessionTracker::DeleteOldSessionWindowIfNecessary( |
| 144 SessionWindowWrapper window_wrapper) { |
| 145 // Clear the tabs first, since we don't want the destructor to destroy |
| 146 // them. Their deletion will be handled by DeleteOldSessionTab below. |
| 147 if (!window_wrapper.owned) { |
| 148 VLOG(1) << "Deleting closed window " |
| 149 << window_wrapper.window_ptr->window_id.id(); |
| 150 window_wrapper.window_ptr->tabs.clear(); |
| 151 delete window_wrapper.window_ptr; |
| 152 return true; |
| 153 } |
| 154 return false; |
| 155 } |
| 156 |
| 157 bool SyncedSessionTracker::DeleteOldSessionTabIfNecessary( |
| 158 SessionTabWrapper tab_wrapper) { |
| 159 if (!tab_wrapper.owned) { |
| 160 if (VLOG_IS_ON(1)) { |
| 161 SessionTab* tab_ptr = tab_wrapper.tab_ptr; |
| 162 std::string title = ""; |
| 163 if (tab_ptr->navigations.size() > 0) { |
| 164 title = " (" + UTF16ToASCII( |
| 165 tab_ptr->navigations[tab_ptr->navigations.size()-1].title()) + ")"; |
| 166 } |
| 167 VLOG(1) << "Deleting closed tab " << tab_ptr->tab_id.id() << title |
| 168 << " from window " << tab_ptr->window_id.id(); |
| 169 } |
| 170 unmapped_tabs_.erase(tab_wrapper.tab_ptr); |
| 171 delete tab_wrapper.tab_ptr; |
| 172 return true; |
| 173 } |
| 174 return false; |
| 175 } |
| 176 |
| 177 void SyncedSessionTracker::CleanupSession(const std::string& session_tag) { |
| 178 // Go through and delete any windows or tabs without owners. |
| 179 SyncedWindowMap::iterator window_iter = synced_window_map_.find(session_tag); |
| 180 if (window_iter != synced_window_map_.end()) { |
| 181 for (IDToSessionWindowMap::iterator iter = window_iter->second.begin(); |
| 182 iter != window_iter->second.end();) { |
| 183 SessionWindowWrapper window_wrapper = iter->second; |
| 184 if (DeleteOldSessionWindowIfNecessary(window_wrapper)) |
| 185 window_iter->second.erase(iter++); |
| 186 else |
| 187 ++iter; |
| 188 } |
| 189 } |
| 190 |
| 191 SyncedTabMap::iterator tab_iter = synced_tab_map_.find(session_tag); |
| 192 if (tab_iter != synced_tab_map_.end()) { |
| 193 for (IDToSessionTabMap::iterator iter = tab_iter->second.begin(); |
| 194 iter != tab_iter->second.end();) { |
| 195 SessionTabWrapper tab_wrapper = iter->second; |
| 196 if (DeleteOldSessionTabIfNecessary(tab_wrapper)) |
| 197 tab_iter->second.erase(iter++); |
| 198 else |
| 199 ++iter; |
| 200 } |
| 201 } |
| 202 } |
| 203 |
| 204 void SyncedSessionTracker::PutWindowInSession(const std::string& session_tag, |
| 205 SessionID::id_type window_id) { |
| 206 SessionWindow* window_ptr = NULL; |
| 207 IDToSessionWindowMap::iterator iter = |
| 208 synced_window_map_[session_tag].find(window_id); |
| 209 if (iter != synced_window_map_[session_tag].end()) { |
| 210 iter->second.owned = true; |
| 211 window_ptr = iter->second.window_ptr; |
| 212 VLOG(1) << "Putting seen window " << window_id << " at " << window_ptr |
| 213 << "in " << (session_tag == local_session_tag_ ? |
| 214 "local session" : session_tag); |
| 215 } else { |
| 216 // Create the window. |
| 217 window_ptr = new SessionWindow(); |
| 218 window_ptr->window_id.set_id(window_id); |
| 219 synced_window_map_[session_tag][window_id] = |
| 220 SessionWindowWrapper(window_ptr, true); |
| 221 VLOG(1) << "Putting new window " << window_id << " at " << window_ptr |
| 222 << "in " << (session_tag == local_session_tag_ ? |
| 223 "local session" : session_tag); |
| 224 } |
| 225 DCHECK(window_ptr); |
| 226 DCHECK_EQ(window_ptr->window_id.id(), window_id); |
| 227 DCHECK_EQ((SessionWindow*)NULL, GetSession(session_tag)->windows[window_id]); |
| 228 GetSession(session_tag)->windows[window_id] = window_ptr; |
| 229 } |
| 230 |
| 231 void SyncedSessionTracker::PutTabInWindow(const std::string& session_tag, |
| 232 SessionID::id_type window_id, |
| 233 SessionID::id_type tab_id, |
| 234 size_t tab_index) { |
| 235 SessionTab* tab_ptr = GetTab(session_tag, tab_id); |
| 236 unmapped_tabs_.erase(tab_ptr); |
| 237 synced_tab_map_[session_tag][tab_id].owned = true; |
| 238 tab_ptr->window_id.set_id(window_id); |
| 239 VLOG(1) << " - tab " << tab_id << " added to window "<< window_id; |
| 240 DCHECK(GetSession(session_tag)->windows.find(window_id) != |
| 241 GetSession(session_tag)->windows.end()); |
| 242 std::vector<SessionTab*>& window_tabs = |
| 243 GetSession(session_tag)->windows[window_id]->tabs; |
| 244 if (window_tabs.size() <= tab_index) { |
| 245 window_tabs.resize(tab_index+1, NULL); |
| 246 } |
| 247 DCHECK_EQ((SessionTab*)NULL, window_tabs[tab_index]); |
| 248 window_tabs[tab_index] = tab_ptr; |
| 249 } |
| 250 |
| 251 SessionTab* SyncedSessionTracker::GetTab( |
101 const std::string& session_tag, | 252 const std::string& session_tag, |
102 SessionID::id_type tab_id, | 253 SessionID::id_type tab_id) { |
103 bool has_window) { | 254 SessionTab* tab_ptr = NULL; |
104 if (synced_tab_map_.find(session_tag) == synced_tab_map_.end()) | |
105 synced_tab_map_[session_tag] = new IDToSessionTabMap; | |
106 scoped_ptr<SessionTab> tab; | |
107 IDToSessionTabMap::iterator iter = | 255 IDToSessionTabMap::iterator iter = |
108 synced_tab_map_[session_tag]->find(tab_id); | 256 synced_tab_map_[session_tag].find(tab_id); |
109 if (iter != synced_tab_map_[session_tag]->end()) { | 257 if (iter != synced_tab_map_[session_tag].end()) { |
110 tab.reset(iter->second); | 258 tab_ptr = iter->second.tab_ptr; |
111 if (has_window) // This tab is linked to a window, so it's not an orphan. | 259 std::string title = ""; |
112 unmapped_tabs_.erase(tab.get()); | 260 if (tab_ptr->navigations.size() > 0) { |
113 if (tab->navigations.size() > 0) { | 261 title = " (" + UTF16ToASCII( |
114 VLOG(1) << "Getting " | 262 tab_ptr->navigations[tab_ptr->navigations.size()-1].title()) + ")"; |
115 << (session_tag == local_session_tag_ ? | |
116 "local session" : session_tag) | |
117 << "'s seen tab " << tab_id << " (" | |
118 << tab->navigations[tab->navigations.size()-1].title() | |
119 << ")"; | |
120 } | 263 } |
121 } else { | |
122 tab.reset(new SessionTab()); | |
123 (*synced_tab_map_[session_tag])[tab_id] = tab.get(); | |
124 if (!has_window) // This tab is not linked to a window, it's an orphan. | |
125 unmapped_tabs_.insert(tab.get()); | |
126 VLOG(1) << "Getting " | 264 VLOG(1) << "Getting " |
127 << (session_tag == local_session_tag_ ? | 265 << (session_tag == local_session_tag_ ? |
128 "local session" : session_tag) | 266 "local session" : session_tag) |
129 << "'s new tab " << tab_id << " at " << tab.get(); | 267 << "'s seen tab " << tab_id << " at " << tab_ptr << title; |
| 268 } else { |
| 269 tab_ptr = new SessionTab(); |
| 270 tab_ptr->tab_id.set_id(tab_id); |
| 271 synced_tab_map_[session_tag][tab_id] = SessionTabWrapper(tab_ptr, false); |
| 272 unmapped_tabs_.insert(tab_ptr); |
| 273 VLOG(1) << "Getting " |
| 274 << (session_tag == local_session_tag_ ? |
| 275 "local session" : session_tag) |
| 276 << "'s new tab " << tab_id << " at " << tab_ptr; |
130 } | 277 } |
131 DCHECK(tab.get()); | 278 DCHECK(tab_ptr); |
132 return tab.release(); | 279 DCHECK_EQ(tab_ptr->tab_id.id(), tab_id); |
| 280 return tab_ptr; |
133 } | 281 } |
134 | 282 |
135 void SyncedSessionTracker::clear() { | 283 void SyncedSessionTracker::Clear() { |
136 // Delete SyncedSession objects (which also deletes all their windows/tabs). | 284 // Delete SyncedSession objects (which also deletes all their windows/tabs). |
137 STLDeleteContainerPairSecondPointers(synced_session_map_.begin(), | 285 STLDeleteContainerPairSecondPointers(synced_session_map_.begin(), |
138 synced_session_map_.end()); | 286 synced_session_map_.end()); |
139 synced_session_map_.clear(); | 287 synced_session_map_.clear(); |
140 | 288 |
141 // Delete IDToSessTab maps. Does not delete the SessionTab objects, because | |
142 // they should already be referenced through synced_session_map_. | |
143 STLDeleteContainerPairSecondPointers(synced_tab_map_.begin(), | |
144 synced_tab_map_.end()); | |
145 synced_tab_map_.clear(); | |
146 | |
147 // Go through and delete any tabs we had allocated but had not yet placed into | 289 // Go through and delete any tabs we had allocated but had not yet placed into |
148 // a SyncedSessionobject. | 290 // a SyncedSessionobject. |
149 STLDeleteContainerPointers(unmapped_tabs_.begin(), unmapped_tabs_.end()); | 291 STLDeleteContainerPointers(unmapped_tabs_.begin(), unmapped_tabs_.end()); |
150 unmapped_tabs_.clear(); | 292 unmapped_tabs_.clear(); |
151 | 293 |
| 294 // Get rid of our Window/Tab maps (does not delete the actual Window/Tabs |
| 295 // themselves; they should have all been deleted above). |
| 296 synced_window_map_.clear(); |
| 297 synced_tab_map_.clear(); |
| 298 |
152 local_session_tag_.clear(); | 299 local_session_tag_.clear(); |
153 } | 300 } |
154 | 301 |
155 } // namespace browser_sync | 302 } // namespace browser_sync |
OLD | NEW |