[email protected] | 27684f3 | 2012-04-25 18:28:43 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 5 | #include "base/logging.h" |
[email protected] | 420337c | 2012-10-27 12:25:57 | [diff] [blame] | 6 | #include "base/stl_util.h" |
[email protected] | e309f31 | 2013-06-07 21:50:08 | [diff] [blame] | 7 | #include "base/strings/utf_string_conversions.h" |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 8 | #include "chrome/browser/sync/glue/synced_session_tracker.h" |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 9 | |
| 10 | namespace browser_sync { |
| 11 | |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 12 | SyncedSessionTracker::SyncedSessionTracker() { |
| 13 | } |
| 14 | |
| 15 | SyncedSessionTracker::~SyncedSessionTracker() { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 16 | Clear(); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 17 | } |
| 18 | |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 19 | void SyncedSessionTracker::SetLocalSessionTag( |
| 20 | const std::string& local_session_tag) { |
| 21 | local_session_tag_ = local_session_tag; |
| 22 | } |
| 23 | |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 24 | bool SyncedSessionTracker::LookupAllForeignSessions( |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 25 | std::vector<const SyncedSession*>* sessions) const { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 26 | DCHECK(sessions); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 27 | sessions->clear(); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 28 | // Fill vector of sessions from our synced session map. |
| 29 | for (SyncedSessionMap::const_iterator i = |
| 30 | synced_session_map_.begin(); i != synced_session_map_.end(); ++i) { |
| 31 | // Only include foreign sessions with open tabs. |
| 32 | SyncedSession* foreign_session = i->second; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 33 | if (i->first != local_session_tag_ && !foreign_session->windows.empty()) { |
| 34 | bool found_tabs = false; |
| 35 | for (SyncedSession::SyncedWindowMap::const_iterator iter = |
| 36 | foreign_session->windows.begin(); |
| 37 | iter != foreign_session->windows.end(); ++iter) { |
| 38 | if (!SessionWindowHasNoTabsToSync(*(iter->second))) { |
| 39 | found_tabs = true; |
| 40 | break; |
| 41 | } |
| 42 | } |
| 43 | if (found_tabs) |
| 44 | sessions->push_back(foreign_session); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 45 | } |
| 46 | } |
| 47 | |
| 48 | return !sessions->empty(); |
| 49 | } |
| 50 | |
| 51 | bool SyncedSessionTracker::LookupSessionWindows( |
| 52 | const std::string& session_tag, |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 53 | std::vector<const sessions::SessionWindow*>* windows) const { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 54 | DCHECK(windows); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 55 | windows->clear(); |
| 56 | SyncedSessionMap::const_iterator iter = synced_session_map_.find(session_tag); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 57 | if (iter == synced_session_map_.end()) |
| 58 | return false; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 59 | windows->clear(); |
| 60 | for (SyncedSession::SyncedWindowMap::const_iterator window_iter = |
| 61 | iter->second->windows.begin(); |
| 62 | window_iter != iter->second->windows.end(); window_iter++) { |
| 63 | windows->push_back(window_iter->second); |
| 64 | } |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 65 | return true; |
| 66 | } |
| 67 | |
| 68 | bool SyncedSessionTracker::LookupSessionTab( |
| 69 | const std::string& tag, |
| 70 | SessionID::id_type tab_id, |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 71 | const sessions::SessionTab** tab) const { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 72 | DCHECK(tab); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 73 | SyncedTabMap::const_iterator tab_map_iter = synced_tab_map_.find(tag); |
| 74 | if (tab_map_iter == synced_tab_map_.end()) { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 75 | // We have no record of this session. |
| 76 | *tab = NULL; |
| 77 | return false; |
| 78 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 79 | IDToSessionTabMap::const_iterator tab_iter = |
| 80 | tab_map_iter->second.find(tab_id); |
| 81 | if (tab_iter == tab_map_iter->second.end()) { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 82 | // We have no record of this tab. |
| 83 | *tab = NULL; |
| 84 | return false; |
| 85 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 86 | *tab = tab_iter->second.tab_ptr; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 87 | return true; |
| 88 | } |
| 89 | |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 90 | bool SyncedSessionTracker::LookupTabNodeIds( |
| 91 | const std::string& session_tag, std::set<int>* tab_node_ids) { |
| 92 | tab_node_ids->clear(); |
| 93 | SyncedTabMap::const_iterator tab_map_iter = |
| 94 | synced_tab_map_.find(session_tag); |
| 95 | if (tab_map_iter == synced_tab_map_.end()) |
| 96 | return false; |
| 97 | |
| 98 | IDToSessionTabMap::const_iterator tab_iter = tab_map_iter->second.begin(); |
| 99 | while (tab_iter != tab_map_iter->second.end()) { |
| 100 | if (tab_iter->second.tab_node_id != TabNodePool::kInvalidTabNodeID) |
| 101 | tab_node_ids->insert(tab_iter->second.tab_node_id); |
| 102 | ++tab_iter; |
| 103 | } |
| 104 | return true; |
| 105 | } |
| 106 | |
[email protected] | 85622cd | 2013-12-18 17:32:27 | [diff] [blame] | 107 | bool SyncedSessionTracker::LookupLocalSession(const SyncedSession** output) |
| 108 | const { |
| 109 | SyncedSessionMap::const_iterator it = |
| 110 | synced_session_map_.find(local_session_tag_); |
| 111 | if (it != synced_session_map_.end()) { |
| 112 | *output = it->second; |
| 113 | return true; |
| 114 | } |
| 115 | return false; |
| 116 | } |
| 117 | |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 118 | SyncedSession* SyncedSessionTracker::GetSession( |
| 119 | const std::string& session_tag) { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 120 | SyncedSession* synced_session = NULL; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 121 | if (synced_session_map_.find(session_tag) != |
| 122 | synced_session_map_.end()) { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 123 | synced_session = synced_session_map_[session_tag]; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 124 | } else { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 125 | synced_session = new SyncedSession; |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 126 | DVLOG(1) << "Creating new session with tag " << session_tag << " at " |
| 127 | << synced_session; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 128 | synced_session->session_tag = session_tag; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 129 | synced_session_map_[session_tag] = synced_session; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 130 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 131 | DCHECK(synced_session); |
| 132 | return synced_session; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 133 | } |
| 134 | |
[email protected] | 1649906 | 2011-10-11 07:02:40 | [diff] [blame] | 135 | bool SyncedSessionTracker::DeleteSession(const std::string& session_tag) { |
| 136 | bool found_session = false; |
| 137 | SyncedSessionMap::iterator iter = synced_session_map_.find(session_tag); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 138 | if (iter != synced_session_map_.end()) { |
[email protected] | 1649906 | 2011-10-11 07:02:40 | [diff] [blame] | 139 | SyncedSession* session = iter->second; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 140 | synced_session_map_.erase(iter); |
[email protected] | 1649906 | 2011-10-11 07:02:40 | [diff] [blame] | 141 | delete session; // Delete the SyncedSession object. |
| 142 | found_session = true; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 143 | } |
[email protected] | 1649906 | 2011-10-11 07:02:40 | [diff] [blame] | 144 | synced_window_map_.erase(session_tag); |
| 145 | // It's possible there was no header node but there were tab nodes. |
| 146 | if (synced_tab_map_.erase(session_tag) > 0) { |
| 147 | found_session = true; |
| 148 | } |
| 149 | return found_session; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 150 | } |
| 151 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 152 | void SyncedSessionTracker::ResetSessionTracking( |
| 153 | const std::string& session_tag) { |
| 154 | // Reset window tracking. |
| 155 | GetSession(session_tag)->windows.clear(); |
| 156 | SyncedWindowMap::iterator window_iter = synced_window_map_.find(session_tag); |
| 157 | if (window_iter != synced_window_map_.end()) { |
| 158 | for (IDToSessionWindowMap::iterator window_map_iter = |
| 159 | window_iter->second.begin(); |
| 160 | window_map_iter != window_iter->second.end(); ++window_map_iter) { |
| 161 | window_map_iter->second.owned = false; |
| 162 | // We clear out the tabs to prevent double referencing of the same tab. |
| 163 | // All tabs that are in use will be added back as needed. |
| 164 | window_map_iter->second.window_ptr->tabs.clear(); |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 165 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | // Reset tab tracking. |
| 169 | SyncedTabMap::iterator tab_iter = synced_tab_map_.find(session_tag); |
| 170 | if (tab_iter != synced_tab_map_.end()) { |
| 171 | for (IDToSessionTabMap::iterator tab_map_iter = |
| 172 | tab_iter->second.begin(); |
| 173 | tab_map_iter != tab_iter->second.end(); ++tab_map_iter) { |
| 174 | tab_map_iter->second.owned = false; |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | bool SyncedSessionTracker::DeleteOldSessionWindowIfNecessary( |
| 180 | SessionWindowWrapper window_wrapper) { |
[email protected] | 420337c | 2012-10-27 12:25:57 | [diff] [blame] | 181 | // Clear the tabs first, since we don't want the destructor to destroy |
| 182 | // them. Their deletion will be handled by DeleteOldSessionTab below. |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 183 | if (!window_wrapper.owned) { |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 184 | DVLOG(1) << "Deleting closed window " |
| 185 | << window_wrapper.window_ptr->window_id.id(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 186 | window_wrapper.window_ptr->tabs.clear(); |
| 187 | delete window_wrapper.window_ptr; |
| 188 | return true; |
| 189 | } |
| 190 | return false; |
| 191 | } |
| 192 | |
| 193 | bool SyncedSessionTracker::DeleteOldSessionTabIfNecessary( |
| 194 | SessionTabWrapper tab_wrapper) { |
| 195 | if (!tab_wrapper.owned) { |
| 196 | if (VLOG_IS_ON(1)) { |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 197 | sessions::SessionTab* tab_ptr = tab_wrapper.tab_ptr; |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 198 | std::string title; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 199 | if (tab_ptr->navigations.size() > 0) { |
[email protected] | f911df5 | 2013-12-24 23:24:23 | [diff] [blame] | 200 | title = " (" + base::UTF16ToUTF8( |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 201 | tab_ptr->navigations[tab_ptr->navigations.size()-1].title()) + ")"; |
| 202 | } |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 203 | DVLOG(1) << "Deleting closed tab " << tab_ptr->tab_id.id() << title |
| 204 | << " from window " << tab_ptr->window_id.id(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 205 | } |
| 206 | unmapped_tabs_.erase(tab_wrapper.tab_ptr); |
| 207 | delete tab_wrapper.tab_ptr; |
| 208 | return true; |
| 209 | } |
| 210 | return false; |
| 211 | } |
| 212 | |
| 213 | void SyncedSessionTracker::CleanupSession(const std::string& session_tag) { |
| 214 | // Go through and delete any windows or tabs without owners. |
| 215 | SyncedWindowMap::iterator window_iter = synced_window_map_.find(session_tag); |
| 216 | if (window_iter != synced_window_map_.end()) { |
| 217 | for (IDToSessionWindowMap::iterator iter = window_iter->second.begin(); |
| 218 | iter != window_iter->second.end();) { |
| 219 | SessionWindowWrapper window_wrapper = iter->second; |
| 220 | if (DeleteOldSessionWindowIfNecessary(window_wrapper)) |
| 221 | window_iter->second.erase(iter++); |
| 222 | else |
| 223 | ++iter; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | SyncedTabMap::iterator tab_iter = synced_tab_map_.find(session_tag); |
| 228 | if (tab_iter != synced_tab_map_.end()) { |
| 229 | for (IDToSessionTabMap::iterator iter = tab_iter->second.begin(); |
| 230 | iter != tab_iter->second.end();) { |
| 231 | SessionTabWrapper tab_wrapper = iter->second; |
| 232 | if (DeleteOldSessionTabIfNecessary(tab_wrapper)) |
| 233 | tab_iter->second.erase(iter++); |
| 234 | else |
| 235 | ++iter; |
| 236 | } |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | void SyncedSessionTracker::PutWindowInSession(const std::string& session_tag, |
| 241 | SessionID::id_type window_id) { |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 242 | sessions::SessionWindow* window_ptr = NULL; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 243 | IDToSessionWindowMap::iterator iter = |
| 244 | synced_window_map_[session_tag].find(window_id); |
| 245 | if (iter != synced_window_map_[session_tag].end()) { |
| 246 | iter->second.owned = true; |
| 247 | window_ptr = iter->second.window_ptr; |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 248 | DVLOG(1) << "Putting seen window " << window_id << " at " << window_ptr |
| 249 | << "in " << (session_tag == local_session_tag_ ? |
| 250 | "local session" : session_tag); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 251 | } else { |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 252 | // Create the window. |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 253 | window_ptr = new sessions::SessionWindow(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 254 | window_ptr->window_id.set_id(window_id); |
| 255 | synced_window_map_[session_tag][window_id] = |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 256 | SessionWindowWrapper(window_ptr, IS_OWNED); |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 257 | DVLOG(1) << "Putting new window " << window_id << " at " << window_ptr |
| 258 | << "in " << (session_tag == local_session_tag_ ? |
| 259 | "local session" : session_tag); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 260 | } |
| 261 | DCHECK(window_ptr); |
| 262 | DCHECK_EQ(window_ptr->window_id.id(), window_id); |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 263 | DCHECK_EQ(reinterpret_cast<sessions::SessionWindow*>(NULL), |
[email protected] | 420337c | 2012-10-27 12:25:57 | [diff] [blame] | 264 | GetSession(session_tag)->windows[window_id]); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 265 | GetSession(session_tag)->windows[window_id] = window_ptr; |
| 266 | } |
| 267 | |
| 268 | void SyncedSessionTracker::PutTabInWindow(const std::string& session_tag, |
| 269 | SessionID::id_type window_id, |
| 270 | SessionID::id_type tab_id, |
| 271 | size_t tab_index) { |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 272 | // We're called here for two reasons. 1) We've received an update to the |
| 273 | // SessionWindow information of a SessionHeader node for a foreign session, |
| 274 | // and 2) The SessionHeader node for our local session changed. In both cases |
| 275 | // we need to update our tracking state to reflect the change. |
| 276 | // |
| 277 | // Because the SessionHeader nodes are separate from the individual tab nodes |
| 278 | // and we don't store tab_node_ids in the header / SessionWindow specifics, |
| 279 | // the tab_node_ids are not always available when processing headers. |
| 280 | // We know that we will eventually process (via GetTab) every single tab node |
| 281 | // in the system, so we permit ourselves to use kInvalidTabNodeID here and |
| 282 | // rely on the later update to build the mapping (or a restart). |
| 283 | // TODO(tim): Bug 98892. Update comment when Sync API conversion finishes to |
| 284 | // mention that in the meantime, the only ill effect is that we may not be |
| 285 | // able to fully clean up a stale foreign session, but it will get garbage |
| 286 | // collected eventually. |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 287 | sessions::SessionTab* tab_ptr = GetTabImpl( |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 288 | session_tag, tab_id, TabNodePool::kInvalidTabNodeID); |
[email protected] | abb35c1 | 2014-08-21 20:13:44 | [diff] [blame] | 289 | |
| 290 | // It's up to the caller to ensure this never happens. Tabs should not |
| 291 | // belong to more than one window or appear twice within the same window. |
| 292 | // |
| 293 | // If this condition were violated, we would double-free during shutdown. |
| 294 | // That could cause all sorts of hard to diagnose crashes, possibly in code |
| 295 | // far away from here. We crash early to avoid this. |
| 296 | // |
| 297 | // See http://crbug.com/360822. |
| 298 | CHECK(!synced_tab_map_[session_tag][tab_id].owned); |
| 299 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 300 | unmapped_tabs_.erase(tab_ptr); |
| 301 | synced_tab_map_[session_tag][tab_id].owned = true; |
[email protected] | abb35c1 | 2014-08-21 20:13:44 | [diff] [blame] | 302 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 303 | tab_ptr->window_id.set_id(window_id); |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 304 | DVLOG(1) << " - tab " << tab_id << " added to window "<< window_id; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 305 | DCHECK(GetSession(session_tag)->windows.find(window_id) != |
| 306 | GetSession(session_tag)->windows.end()); |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 307 | std::vector<sessions::SessionTab*>& window_tabs = |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 308 | GetSession(session_tag)->windows[window_id]->tabs; |
| 309 | if (window_tabs.size() <= tab_index) { |
| 310 | window_tabs.resize(tab_index+1, NULL); |
| 311 | } |
[email protected] | 9dd1d58 | 2012-09-19 04:04:16 | [diff] [blame] | 312 | DCHECK(!window_tabs[tab_index]); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 313 | window_tabs[tab_index] = tab_ptr; |
| 314 | } |
| 315 | |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 316 | sessions::SessionTab* SyncedSessionTracker::GetTab( |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 317 | const std::string& session_tag, |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 318 | SessionID::id_type tab_id, |
| 319 | int tab_node_id) { |
| 320 | DCHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id); |
| 321 | return GetTabImpl(session_tag, tab_id, tab_node_id); |
| 322 | } |
| 323 | |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 324 | sessions::SessionTab* SyncedSessionTracker::GetTabImpl( |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 325 | const std::string& session_tag, |
| 326 | SessionID::id_type tab_id, |
| 327 | int tab_node_id) { |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 328 | sessions::SessionTab* tab_ptr = NULL; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 329 | IDToSessionTabMap::iterator iter = |
| 330 | synced_tab_map_[session_tag].find(tab_id); |
| 331 | if (iter != synced_tab_map_[session_tag].end()) { |
| 332 | tab_ptr = iter->second.tab_ptr; |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 333 | if (tab_node_id != TabNodePool::kInvalidTabNodeID && |
| 334 | tab_id != TabNodePool::kInvalidTabID) { |
[email protected] | c7a73c99 | 2014-03-05 10:00:40 | [diff] [blame] | 335 | // TabIDs are not stable across restarts of a client. Consider this |
| 336 | // example with two tabs: |
| 337 | // |
| 338 | // http://a.com TabID1 --> NodeIDA |
| 339 | // http://b.com TabID2 --> NodeIDB |
| 340 | // |
| 341 | // After restart, tab ids are reallocated. e.g, one possibility: |
| 342 | // http://a.com TabID2 --> NodeIDA |
| 343 | // http://b.com TabID1 --> NodeIDB |
| 344 | // |
| 345 | // If that happend on a remote client, here we will see an update to |
| 346 | // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2 |
| 347 | // with tab_node_id changing from NodeIDB to NodeIDA. |
| 348 | // |
| 349 | // We can also wind up here if we created this tab as an out-of-order |
| 350 | // update to the header node for this session before actually associating |
| 351 | // the tab itself, so the tab node id wasn't available at the time and |
| 352 | // is currenlty kInvalidTabNodeID. |
| 353 | // |
| 354 | // In both cases, we update the tab_node_id. |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 355 | iter->second.tab_node_id = tab_node_id; |
| 356 | } |
| 357 | |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 358 | if (VLOG_IS_ON(1)) { |
| 359 | std::string title; |
| 360 | if (tab_ptr->navigations.size() > 0) { |
[email protected] | f911df5 | 2013-12-24 23:24:23 | [diff] [blame] | 361 | title = " (" + base::UTF16ToUTF8( |
[email protected] | 35d849dc | 2011-10-21 23:49:05 | [diff] [blame] | 362 | tab_ptr->navigations[tab_ptr->navigations.size()-1].title()) + ")"; |
| 363 | } |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 364 | DVLOG(1) << "Getting " |
| 365 | << (session_tag == local_session_tag_ ? |
| 366 | "local session" : session_tag) |
| 367 | << "'s seen tab " << tab_id << " at " << tab_ptr << title; |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 368 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 369 | } else { |
skuhne | b7409dcf | 2014-11-14 04:06:55 | [diff] [blame^] | 370 | tab_ptr = new sessions::SessionTab(); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 371 | tab_ptr->tab_id.set_id(tab_id); |
[email protected] | 98f589d | 2013-08-01 05:14:01 | [diff] [blame] | 372 | synced_tab_map_[session_tag][tab_id] = SessionTabWrapper(tab_ptr, |
| 373 | NOT_OWNED, |
| 374 | tab_node_id); |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 375 | unmapped_tabs_.insert(tab_ptr); |
[email protected] | 060588c | 2011-11-29 21:38:41 | [diff] [blame] | 376 | DVLOG(1) << "Getting " |
| 377 | << (session_tag == local_session_tag_ ? |
| 378 | "local session" : session_tag) |
| 379 | << "'s new tab " << tab_id << " at " << tab_ptr; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 380 | } |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 381 | DCHECK(tab_ptr); |
| 382 | DCHECK_EQ(tab_ptr->tab_id.id(), tab_id); |
| 383 | return tab_ptr; |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 384 | } |
| 385 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 386 | void SyncedSessionTracker::Clear() { |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 387 | // Delete SyncedSession objects (which also deletes all their windows/tabs). |
[email protected] | 420337c | 2012-10-27 12:25:57 | [diff] [blame] | 388 | STLDeleteValues(&synced_session_map_); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 389 | |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 390 | // Go through and delete any tabs we had allocated but had not yet placed into |
| 391 | // a SyncedSessionobject. |
[email protected] | 420337c | 2012-10-27 12:25:57 | [diff] [blame] | 392 | STLDeleteElements(&unmapped_tabs_); |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 393 | |
[email protected] | 13daae6d | 2011-10-04 13:43:12 | [diff] [blame] | 394 | // Get rid of our Window/Tab maps (does not delete the actual Window/Tabs |
| 395 | // themselves; they should have all been deleted above). |
| 396 | synced_window_map_.clear(); |
| 397 | synced_tab_map_.clear(); |
| 398 | |
[email protected] | 819f753f | 2011-07-15 21:56:02 | [diff] [blame] | 399 | local_session_tag_.clear(); |
[email protected] | d70fb36 | 2011-06-15 15:07:39 | [diff] [blame] | 400 | } |
| 401 | |
| 402 | } // namespace browser_sync |