OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/sync_sessions/sessions_sync_manager.h" | 5 #include "components/sync_sessions/sessions_sync_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
| 10 #include "base/format_macros.h" |
| 11 #include "base/logging.h" |
10 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
11 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
12 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/strings/stringprintf.h" |
13 #include "build/build_config.h" | 16 #include "build/build_config.h" |
14 #include "components/sync/base/hash_util.h" | 17 #include "components/sync/base/hash_util.h" |
15 #include "components/sync/device_info/local_device_info_provider.h" | 18 #include "components/sync/device_info/local_device_info_provider.h" |
16 #include "components/sync/model/sync_error.h" | 19 #include "components/sync/model/sync_error.h" |
17 #include "components/sync/model/sync_error_factory.h" | 20 #include "components/sync/model/sync_error_factory.h" |
18 #include "components/sync/model/sync_merge_result.h" | 21 #include "components/sync/model/sync_merge_result.h" |
19 #include "components/sync/model/time.h" | 22 #include "components/sync/model/time.h" |
20 #include "components/sync_sessions/sync_sessions_client.h" | 23 #include "components/sync_sessions/sync_sessions_client.h" |
21 #include "components/sync_sessions/synced_tab_delegate.h" | 24 #include "components/sync_sessions/synced_tab_delegate.h" |
22 #include "components/sync_sessions/synced_window_delegate.h" | 25 #include "components/sync_sessions/synced_window_delegate.h" |
23 #include "components/sync_sessions/synced_window_delegates_getter.h" | 26 #include "components/sync_sessions/synced_window_delegates_getter.h" |
| 27 #include "components/sync_sessions/tab_node_pool.h" |
24 #include "components/variations/variations_associated_data.h" | 28 #include "components/variations/variations_associated_data.h" |
25 | 29 |
26 using sessions::SerializedNavigationEntry; | 30 using sessions::SerializedNavigationEntry; |
27 using syncer::DeviceInfo; | 31 using syncer::DeviceInfo; |
28 using syncer::LocalDeviceInfoProvider; | 32 using syncer::LocalDeviceInfoProvider; |
29 using syncer::SyncChange; | 33 using syncer::SyncChange; |
30 using syncer::SyncData; | 34 using syncer::SyncData; |
31 | 35 |
32 namespace sync_sessions { | 36 namespace sync_sessions { |
33 | 37 |
(...skipping 21 matching lines...) Expand all Loading... |
55 return t1->timestamp > t2->timestamp; | 59 return t1->timestamp > t2->timestamp; |
56 } | 60 } |
57 | 61 |
58 // Comparator function for use with std::sort that will sort sessions by | 62 // Comparator function for use with std::sort that will sort sessions by |
59 // descending modified_time (i.e., most recent first). | 63 // descending modified_time (i.e., most recent first). |
60 bool SessionsRecencyComparator(const SyncedSession* s1, | 64 bool SessionsRecencyComparator(const SyncedSession* s1, |
61 const SyncedSession* s2) { | 65 const SyncedSession* s2) { |
62 return s1->modified_time > s2->modified_time; | 66 return s1->modified_time > s2->modified_time; |
63 } | 67 } |
64 | 68 |
| 69 std::string TabNodeIdToTag(const std::string& machine_tag, int tab_node_id) { |
| 70 CHECK_GT(tab_node_id, TabNodePool::kInvalidTabNodeID) << "crbug.com/673618"; |
| 71 return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id); |
| 72 } |
| 73 |
65 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { | 74 std::string TagFromSpecifics(const sync_pb::SessionSpecifics& specifics) { |
66 if (specifics.has_header()) { | 75 if (specifics.has_header()) { |
67 return specifics.session_tag(); | 76 return specifics.session_tag(); |
68 } else if (specifics.has_tab()) { | 77 } else if (specifics.has_tab()) { |
69 return TabNodePool::TabIdToTag(specifics.session_tag(), | 78 return TabNodeIdToTag(specifics.session_tag(), specifics.tab_node_id()); |
70 specifics.tab_node_id()); | |
71 } else { | 79 } else { |
72 return std::string(); | 80 return std::string(); |
73 } | 81 } |
74 } | 82 } |
75 | 83 |
| 84 sync_pb::SessionSpecifics SessionTabToSpecifics( |
| 85 const sessions::SessionTab& session_tab, |
| 86 const std::string& local_tag, |
| 87 int tab_node_id) { |
| 88 sync_pb::SessionSpecifics specifics; |
| 89 specifics.mutable_tab()->CopyFrom(session_tab.ToSyncData()); |
| 90 specifics.set_session_tag(local_tag); |
| 91 specifics.set_tab_node_id(tab_node_id); |
| 92 return specifics; |
| 93 } |
| 94 |
| 95 void AppendDeletionsForTabNodes(const std::set<int>& tab_node_ids, |
| 96 const std::string& machine_tag, |
| 97 syncer::SyncChangeList* change_output) { |
| 98 for (std::set<int>::const_iterator it = tab_node_ids.begin(); |
| 99 it != tab_node_ids.end(); ++it) { |
| 100 change_output->push_back(syncer::SyncChange( |
| 101 FROM_HERE, SyncChange::ACTION_DELETE, |
| 102 SyncData::CreateLocalDelete(TabNodeIdToTag(machine_tag, *it), |
| 103 syncer::SESSIONS))); |
| 104 } |
| 105 } |
| 106 |
| 107 // Ensure that the tab id is not invalid. |
| 108 bool ShouldSyncTabId(SessionID::id_type tab_id) { |
| 109 if (tab_id == TabNodePool::kInvalidTabID) |
| 110 return false; |
| 111 return true; |
| 112 } |
| 113 |
76 } // namespace | 114 } // namespace |
77 | 115 |
78 // |local_device| is owned by ProfileSyncService, its lifetime exceeds | 116 // |local_device| is owned by ProfileSyncService, its lifetime exceeds |
79 // lifetime of SessionSyncManager. | 117 // lifetime of SessionSyncManager. |
80 SessionsSyncManager::SessionsSyncManager( | 118 SessionsSyncManager::SessionsSyncManager( |
81 sync_sessions::SyncSessionsClient* sessions_client, | 119 sync_sessions::SyncSessionsClient* sessions_client, |
82 syncer::SyncPrefs* sync_prefs, | 120 syncer::SyncPrefs* sync_prefs, |
83 LocalDeviceInfoProvider* local_device, | 121 LocalDeviceInfoProvider* local_device, |
84 std::unique_ptr<LocalSessionEventRouter> router, | 122 std::unique_ptr<LocalSessionEventRouter> router, |
85 const base::Closure& sessions_updated_callback, | 123 const base::Closure& sessions_updated_callback, |
(...skipping 24 matching lines...) Expand all Loading... |
110 return machine_tag; | 148 return machine_tag; |
111 } | 149 } |
112 | 150 |
113 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( | 151 syncer::SyncMergeResult SessionsSyncManager::MergeDataAndStartSyncing( |
114 syncer::ModelType type, | 152 syncer::ModelType type, |
115 const syncer::SyncDataList& initial_sync_data, | 153 const syncer::SyncDataList& initial_sync_data, |
116 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | 154 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
117 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { | 155 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { |
118 syncer::SyncMergeResult merge_result(type); | 156 syncer::SyncMergeResult merge_result(type); |
119 DCHECK(session_tracker_.Empty()); | 157 DCHECK(session_tracker_.Empty()); |
120 DCHECK_EQ(0U, local_tab_pool_.Capacity()); | |
121 | 158 |
122 error_handler_ = std::move(error_handler); | 159 error_handler_ = std::move(error_handler); |
123 sync_processor_ = std::move(sync_processor); | 160 sync_processor_ = std::move(sync_processor); |
124 | 161 |
125 // SessionDataTypeController ensures that the local device info | 162 // SessionDataTypeController ensures that the local device info |
126 // is available before activating this datatype. | 163 // is available before activating this datatype. |
127 DCHECK(local_device_); | 164 DCHECK(local_device_); |
128 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); | 165 const DeviceInfo* local_device_info = local_device_->GetLocalDeviceInfo(); |
129 if (!local_device_info) { | 166 if (!local_device_info) { |
130 merge_result.set_error(error_handler_->CreateAndUploadError( | 167 merge_result.set_error(error_handler_->CreateAndUploadError( |
(...skipping 15 matching lines...) Expand all Loading... |
146 | 183 |
147 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 184 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
148 | 185 |
149 // Make sure we have a machine tag. We do this now (versus earlier) as it's | 186 // Make sure we have a machine tag. We do this now (versus earlier) as it's |
150 // a conveniently safe time to assert sync is ready and the cache_guid is | 187 // a conveniently safe time to assert sync is ready and the cache_guid is |
151 // initialized. | 188 // initialized. |
152 if (current_machine_tag_.empty()) { | 189 if (current_machine_tag_.empty()) { |
153 InitializeCurrentMachineTag(local_device_->GetLocalSyncCacheGUID()); | 190 InitializeCurrentMachineTag(local_device_->GetLocalSyncCacheGUID()); |
154 } | 191 } |
155 | 192 |
156 session_tracker_.SetLocalSessionTag(current_machine_tag_); | 193 session_tracker_.SetLocalSessionTag(current_machine_tag()); |
157 | 194 |
158 syncer::SyncChangeList new_changes; | 195 syncer::SyncChangeList new_changes; |
159 | 196 |
160 // First, we iterate over sync data to update our session_tracker_. | 197 // First, we iterate over sync data to update our session_tracker_. |
161 syncer::SyncDataList restored_tabs; | 198 if (!InitFromSyncModel(initial_sync_data, &new_changes)) { |
162 if (!InitFromSyncModel(initial_sync_data, &restored_tabs, &new_changes)) { | |
163 // The sync db didn't have a header node for us. Create one. | 199 // The sync db didn't have a header node for us. Create one. |
164 sync_pb::EntitySpecifics specifics; | 200 sync_pb::EntitySpecifics specifics; |
165 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); | 201 sync_pb::SessionSpecifics* base_specifics = specifics.mutable_session(); |
166 base_specifics->set_session_tag(current_machine_tag()); | 202 base_specifics->set_session_tag(current_machine_tag()); |
167 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); | 203 sync_pb::SessionHeader* header_s = base_specifics->mutable_header(); |
168 header_s->set_client_name(current_session_name_); | 204 header_s->set_client_name(current_session_name_); |
169 header_s->set_device_type(current_device_type_); | 205 header_s->set_device_type(current_device_type_); |
170 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 206 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
171 current_machine_tag(), current_session_name_, specifics); | 207 current_machine_tag(), current_session_name_, specifics); |
172 new_changes.push_back( | 208 new_changes.push_back( |
173 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); | 209 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data)); |
174 } | 210 } |
175 | 211 |
176 #if defined(OS_ANDROID) | 212 #if defined(OS_ANDROID) |
177 std::string sync_machine_tag( | 213 std::string sync_machine_tag( |
178 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); | 214 BuildMachineTag(local_device_->GetLocalSyncCacheGUID())); |
179 if (current_machine_tag_.compare(sync_machine_tag) != 0) | 215 if (current_machine_tag().compare(sync_machine_tag) != 0) |
180 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); | 216 DeleteForeignSessionInternal(sync_machine_tag, &new_changes); |
181 #endif | 217 #endif |
182 | 218 |
183 // Check if anything has changed on the local client side. | 219 // Check if anything has changed on the local client side. |
184 AssociateWindows(RELOAD_TABS, restored_tabs, &new_changes); | 220 AssociateWindows(RELOAD_TABS, &new_changes); |
185 local_tab_pool_out_of_sync_ = false; | 221 local_tab_pool_out_of_sync_ = false; |
186 | 222 |
187 merge_result.set_error( | 223 merge_result.set_error( |
188 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); | 224 sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes)); |
189 | 225 |
190 local_event_router_->StartRoutingTo(this); | 226 local_event_router_->StartRoutingTo(this); |
191 return merge_result; | 227 return merge_result; |
192 } | 228 } |
193 | 229 |
194 void SessionsSyncManager::AssociateWindows( | 230 void SessionsSyncManager::AssociateWindows( |
195 ReloadTabsOption option, | 231 ReloadTabsOption option, |
196 const syncer::SyncDataList& restored_tabs, | |
197 syncer::SyncChangeList* change_output) { | 232 syncer::SyncChangeList* change_output) { |
198 const std::string local_tag = current_machine_tag(); | 233 const std::string local_tag = current_machine_tag(); |
199 sync_pb::SessionSpecifics specifics; | 234 sync_pb::SessionSpecifics specifics; |
200 specifics.set_session_tag(local_tag); | 235 specifics.set_session_tag(local_tag); |
201 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 236 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
202 SyncedSession* current_session = session_tracker_.GetSession(local_tag); | 237 SyncedSession* current_session = session_tracker_.GetSession(local_tag); |
203 current_session->modified_time = base::Time::Now(); | 238 current_session->modified_time = base::Time::Now(); |
204 header_s->set_client_name(current_session_name_); | 239 header_s->set_client_name(current_session_name_); |
205 header_s->set_device_type(current_device_type_); | 240 header_s->set_device_type(current_device_type_); |
206 | 241 |
207 session_tracker_.ResetSessionTracking(local_tag); | 242 session_tracker_.ResetSessionTracking(local_tag); |
208 std::set<const SyncedWindowDelegate*> windows = | 243 SyncedWindowDelegatesGetter::SyncedWindowDelegateMap windows = |
209 synced_window_delegates_getter()->GetSyncedWindowDelegates(); | 244 synced_window_delegates_getter()->GetSyncedWindowDelegates(); |
210 | 245 |
211 if (option == RELOAD_TABS) { | 246 if (option == RELOAD_TABS) { |
212 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); | 247 UMA_HISTOGRAM_COUNTS("Sync.SessionWindows", windows.size()); |
213 } | 248 } |
214 if (windows.size() == 0) { | 249 if (windows.size() == 0) { |
215 // Assume that the window hasn't loaded. Attempting to associate now would | 250 // Assume that the window hasn't loaded. Attempting to associate now would |
216 // clobber any old windows, so just return. | 251 // clobber any old windows, so just return. |
217 LOG(ERROR) << "No windows present, see crbug.com/639009"; | 252 LOG(ERROR) << "No windows present, see crbug.com/639009"; |
218 return; | 253 return; |
219 } | 254 } |
220 for (const SyncedWindowDelegate* window_delegate : windows) { | 255 for (auto window_iter_pair : windows) { |
| 256 const SyncedWindowDelegate* window_delegate = window_iter_pair.second; |
221 if (option == RELOAD_TABS) { | 257 if (option == RELOAD_TABS) { |
222 UMA_HISTOGRAM_COUNTS("Sync.SessionTabs", window_delegate->GetTabCount()); | 258 UMA_HISTOGRAM_COUNTS("Sync.SessionTabs", window_delegate->GetTabCount()); |
223 } | 259 } |
224 | 260 |
225 // Make sure the window has tabs and a viewable window. The viewable window | 261 // Make sure the window has tabs and a viewable window. The viewable window |
226 // check is necessary because, for example, when a browser is closed the | 262 // check is necessary because, for example, when a browser is closed the |
227 // destructor is not necessarily run immediately. This means its possible | 263 // destructor is not necessarily run immediately. This means its possible |
228 // for us to get a handle to a browser that is about to be removed. If | 264 // for us to get a handle to a browser that is about to be removed. If |
229 // the tab count is 0 or the window is null, the browser is about to be | 265 // the tab count is 0 or the window is null, the browser is about to be |
230 // deleted, so we ignore it. | 266 // deleted, so we ignore it. |
(...skipping 23 matching lines...) Expand all Loading... |
254 | 290 |
255 bool found_tabs = false; | 291 bool found_tabs = false; |
256 for (int j = 0; j < window_delegate->GetTabCount(); ++j) { | 292 for (int j = 0; j < window_delegate->GetTabCount(); ++j) { |
257 SessionID::id_type tab_id = window_delegate->GetTabIdAt(j); | 293 SessionID::id_type tab_id = window_delegate->GetTabIdAt(j); |
258 SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j); | 294 SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j); |
259 | 295 |
260 // GetTabAt can return a null tab; in that case just skip it. | 296 // GetTabAt can return a null tab; in that case just skip it. |
261 if (!synced_tab) | 297 if (!synced_tab) |
262 continue; | 298 continue; |
263 | 299 |
| 300 if (!ShouldSyncTabId(tab_id)) { |
| 301 LOG(ERROR) << "Not syncing invalid tab with id " << tab_id; |
| 302 continue; |
| 303 } |
| 304 |
| 305 // Placeholder tabs are those without WebContents, either because they |
| 306 // were never loaded into memory or they were evicted from memory |
| 307 // (typically only on Android devices). They only have a tab id, window |
| 308 // id, and a saved synced id (corresponding to the tab node id). Note |
| 309 // that only placeholders have this sync id, as it's necessary to |
| 310 // properly reassociate the tab with the entity that was backing it. |
264 if (synced_tab->IsPlaceholderTab()) { | 311 if (synced_tab->IsPlaceholderTab()) { |
265 // For tabs without WebContents update the |tab_id| and |window_id|, | 312 // For tabs without WebContents update the |tab_id| and |window_id|, |
266 // as it could have changed after a session restore. | 313 // as it could have changed after a session restore. |
267 // Note: We cannot check if a tab is valid if it has no WebContents. | 314 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID) { |
268 // We assume any such tab is valid and leave the contents of | |
269 // corresponding sync node unchanged. | |
270 if (synced_tab->GetSyncId() > TabNodePool::kInvalidTabNodeID && | |
271 tab_id > TabNodePool::kInvalidTabID) { | |
272 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, | 315 AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, |
273 restored_tabs, change_output); | 316 change_output); |
274 found_tabs = true; | |
275 window_s.add_tab(tab_id); | |
276 } | 317 } |
277 continue; | 318 } else if (RELOAD_TABS == option) { |
| 319 AssociateTab(synced_tab, change_output); |
278 } | 320 } |
279 | 321 |
280 if (RELOAD_TABS == option) | 322 // If the tab was syncable, it would have been added to the tracker |
281 AssociateTab(synced_tab, change_output); | 323 // either by the above Associate[RestoredPlaceholder]Tab call or by the |
282 | 324 // OnLocalTabModified method invoking AssociateTab directly. Therefore, |
283 // If the tab is valid, it would have been added to the tracker either | 325 // we can key whether this window has valid tabs based on the tab's |
284 // by the above AssociateTab call (at association time), or by the | 326 // presence in the tracker. |
285 // change processor calling AssociateTab for all modified tabs. | |
286 // Therefore, we can key whether this window has valid tabs based on | |
287 // the tab's presence in the tracker. | |
288 const sessions::SessionTab* tab = nullptr; | 327 const sessions::SessionTab* tab = nullptr; |
289 if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { | 328 if (session_tracker_.LookupSessionTab(local_tag, tab_id, &tab)) { |
290 found_tabs = true; | 329 found_tabs = true; |
291 window_s.add_tab(tab_id); | 330 window_s.add_tab(tab_id); |
292 } | 331 } |
293 } | 332 } |
294 if (found_tabs) { | 333 if (found_tabs) { |
295 sync_pb::SessionWindow* header_window = header_s->add_window(); | 334 sync_pb::SessionWindow* header_window = header_s->add_window(); |
296 *header_window = window_s; | 335 *header_window = window_s; |
297 | 336 |
298 // Update this window's representation in the synced session tracker. | 337 // Update this window's representation in the synced session tracker. |
299 session_tracker_.PutWindowInSession(local_tag, window_id); | 338 session_tracker_.PutWindowInSession(local_tag, window_id); |
300 BuildSyncedSessionFromSpecifics( | 339 BuildSyncedSessionFromSpecifics( |
301 local_tag, window_s, current_session->modified_time, | 340 local_tag, window_s, current_session->modified_time, |
302 current_session->windows[window_id].get()); | 341 current_session->windows[window_id].get()); |
303 } | 342 } |
304 } | 343 } |
305 } | 344 } |
306 local_tab_pool_.DeleteUnassociatedTabNodes(change_output); | 345 std::set<int> deleted_tab_node_ids; |
307 session_tracker_.CleanupSession(local_tag); | 346 session_tracker_.CleanupLocalTabs(&deleted_tab_node_ids); |
| 347 AppendDeletionsForTabNodes(deleted_tab_node_ids, current_machine_tag(), |
| 348 change_output); |
308 | 349 |
309 // Always update the header. Sync takes care of dropping this update | 350 // Always update the header. Sync takes care of dropping this update |
310 // if the entity specifics are identical (i.e windows, client name did | 351 // if the entity specifics are identical (i.e windows, client name did |
311 // not change). | 352 // not change). |
312 sync_pb::EntitySpecifics entity; | 353 sync_pb::EntitySpecifics entity; |
313 entity.mutable_session()->CopyFrom(specifics); | 354 entity.mutable_session()->CopyFrom(specifics); |
314 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 355 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
315 current_machine_tag(), current_session_name_, entity); | 356 current_machine_tag(), current_session_name_, entity); |
316 change_output->push_back( | 357 change_output->push_back( |
317 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | 358 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
318 } | 359 } |
319 | 360 |
320 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab, | 361 void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab_delegate, |
321 syncer::SyncChangeList* change_output) { | 362 syncer::SyncChangeList* change_output) { |
322 DCHECK(!tab->IsPlaceholderTab()); | 363 DCHECK(!tab_delegate->IsPlaceholderTab()); |
323 SessionID::id_type tab_id = tab->GetSessionId(); | |
324 | 364 |
325 if (tab->IsBeingDestroyed()) { | 365 if (tab_delegate->IsBeingDestroyed()) { |
326 // This tab is closing. | 366 // Do nothing. By not proactively adding the tab to the session, it will be |
327 TabLinksMap::iterator tab_iter = local_tab_map_.find(tab_id); | 367 // removed if necessary during subsequent cleanup. |
328 if (tab_iter == local_tab_map_.end()) { | |
329 // We aren't tracking this tab (for example, sync setting page). | |
330 return; | |
331 } | |
332 local_tab_pool_.FreeTabNode(tab_iter->second->tab_node_id(), change_output); | |
333 local_tab_map_.erase(tab_iter); | |
334 return; | 368 return; |
335 } | 369 } |
336 | 370 |
337 if (!tab->ShouldSync(sessions_client_)) | 371 if (!tab_delegate->ShouldSync(sessions_client_)) |
338 return; | 372 return; |
339 | 373 |
340 TabLinksMap::iterator local_tab_map_iter = local_tab_map_.find(tab_id); | 374 SessionID::id_type tab_id = tab_delegate->GetSessionId(); |
341 TabLink* tab_link = nullptr; | 375 DVLOG(1) << "Syncing tab " << tab_id << " from window " |
| 376 << tab_delegate->GetWindowId(); |
342 | 377 |
343 if (local_tab_map_iter == local_tab_map_.end()) { | 378 int tab_node_id = TabNodePool::kInvalidTabNodeID; |
344 int tab_node_id = tab->GetSyncId(); | 379 bool existing_tab_node = |
345 // If there is an old sync node for the tab, reuse it. If this is a new | 380 session_tracker_.GetTabNodeFromLocalTabId(tab_id, &tab_node_id); |
346 // tab, get a sync node for it. | 381 CHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id) << "crbug.com/673618"; |
347 if (!local_tab_pool_.IsUnassociatedTabNode(tab_node_id)) { | 382 tab_delegate->SetSyncId(tab_node_id); |
348 tab_node_id = local_tab_pool_.GetFreeTabNode(change_output); | 383 sessions::SessionTab* session_tab = |
349 tab->SetSyncId(tab_node_id); | 384 session_tracker_.GetTab(current_machine_tag(), tab_id); |
350 } | |
351 local_tab_pool_.AssociateTabNode(tab_node_id, tab_id); | |
352 tab_link = new TabLink(tab_node_id, tab); | |
353 local_tab_map_[tab_id] = make_linked_ptr<TabLink>(tab_link); | |
354 } else { | |
355 // This tab is already associated with a sync node, reuse it. | |
356 // Note: on some platforms the tab object may have changed, so we ensure | |
357 // the tab link is up to date. | |
358 tab_link = local_tab_map_iter->second.get(); | |
359 local_tab_map_iter->second->set_tab(tab); | |
360 } | |
361 DCHECK(tab_link); | |
362 DCHECK_NE(tab_link->tab_node_id(), TabNodePool::kInvalidTabNodeID); | |
363 DVLOG(1) << "Reloading tab " << tab_id << " from window " | |
364 << tab->GetWindowId(); | |
365 | 385 |
366 // Write to sync model. | 386 // Get the previously synced url. |
367 sync_pb::EntitySpecifics specifics; | 387 int old_index = session_tab->normalized_navigation_index(); |
368 LocalTabDelegateToSpecifics(*tab, specifics.mutable_session()); | 388 GURL old_url; |
369 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 389 if (session_tab->navigations.size() > static_cast<size_t>(old_index)) |
370 TabNodePool::TabIdToTag(current_machine_tag_, tab_link->tab_node_id()), | 390 old_url = session_tab->navigations[old_index].virtual_url(); |
371 current_session_name_, specifics); | |
372 change_output->push_back( | |
373 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
374 | 391 |
375 int current_index = tab->GetCurrentEntryIndex(); | 392 // Update the tracker's session representation. |
376 const GURL new_url = tab->GetVirtualURLAtIndex(current_index); | 393 SetSessionTabFromDelegate(*tab_delegate, base::Time::Now(), session_tab); |
377 if (new_url != tab_link->url()) { | 394 SetVariationIds(session_tab); |
378 tab_link->set_url(new_url); | |
379 favicon_cache_.OnFaviconVisited(new_url, | |
380 tab->GetFaviconURLAtIndex(current_index)); | |
381 page_revisit_broadcaster_.OnPageVisit( | |
382 new_url, tab->GetTransitionAtIndex(current_index)); | |
383 } | |
384 | |
385 session_tracker_.GetSession(current_machine_tag())->modified_time = | 395 session_tracker_.GetSession(current_machine_tag())->modified_time = |
386 base::Time::Now(); | 396 base::Time::Now(); |
| 397 |
| 398 // Write to the sync model itself. |
| 399 sync_pb::EntitySpecifics specifics; |
| 400 specifics.mutable_session()->CopyFrom( |
| 401 SessionTabToSpecifics(*session_tab, current_machine_tag(), tab_node_id)); |
| 402 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
| 403 TabNodeIdToTag(current_machine_tag(), tab_node_id), current_session_name_, |
| 404 specifics); |
| 405 change_output->push_back( |
| 406 syncer::SyncChange(FROM_HERE, |
| 407 existing_tab_node ? syncer::SyncChange::ACTION_UPDATE |
| 408 : syncer::SyncChange::ACTION_ADD, |
| 409 data)); |
| 410 |
| 411 int current_index = tab_delegate->GetCurrentEntryIndex(); |
| 412 const GURL new_url = tab_delegate->GetVirtualURLAtIndex(current_index); |
| 413 if (new_url != old_url) { |
| 414 favicon_cache_.OnFaviconVisited( |
| 415 new_url, tab_delegate->GetFaviconURLAtIndex(current_index)); |
| 416 page_revisit_broadcaster_.OnPageVisit( |
| 417 new_url, tab_delegate->GetTransitionAtIndex(current_index)); |
| 418 } |
387 } | 419 } |
388 | 420 |
389 bool SessionsSyncManager::RebuildAssociations() { | 421 bool SessionsSyncManager::RebuildAssociations() { |
390 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); | 422 syncer::SyncDataList data(sync_processor_->GetAllSyncData(syncer::SESSIONS)); |
391 std::unique_ptr<syncer::SyncErrorFactory> error_handler( | 423 std::unique_ptr<syncer::SyncErrorFactory> error_handler( |
392 std::move(error_handler_)); | 424 std::move(error_handler_)); |
393 std::unique_ptr<syncer::SyncChangeProcessor> processor( | 425 std::unique_ptr<syncer::SyncChangeProcessor> processor( |
394 std::move(sync_processor_)); | 426 std::move(sync_processor_)); |
395 | 427 |
396 StopSyncing(syncer::SESSIONS); | 428 StopSyncing(syncer::SESSIONS); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); | 468 DCHECK(!rebuild_association_succeeded || !local_tab_pool_out_of_sync_); |
437 return; | 469 return; |
438 } | 470 } |
439 | 471 |
440 syncer::SyncChangeList changes; | 472 syncer::SyncChangeList changes; |
441 AssociateTab(modified_tab, &changes); | 473 AssociateTab(modified_tab, &changes); |
442 // Note, we always associate windows because it's possible a tab became | 474 // Note, we always associate windows because it's possible a tab became |
443 // "interesting" by going to a valid URL, in which case it needs to be added | 475 // "interesting" by going to a valid URL, in which case it needs to be added |
444 // to the window's tab information. Similarly, if a tab became | 476 // to the window's tab information. Similarly, if a tab became |
445 // "uninteresting", we remove it from the window's tab information. | 477 // "uninteresting", we remove it from the window's tab information. |
446 AssociateWindows(DONT_RELOAD_TABS, syncer::SyncDataList(), &changes); | 478 AssociateWindows(DONT_RELOAD_TABS, &changes); |
447 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | 479 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); |
448 } | 480 } |
449 | 481 |
450 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, | 482 void SessionsSyncManager::OnFaviconsChanged(const std::set<GURL>& page_urls, |
451 const GURL& /* icon_url */) { | 483 const GURL& /* icon_url */) { |
452 // TODO(zea): consider a separate container for tabs with outstanding favicon | 484 for (const GURL& page_url : page_urls) |
453 // loads so we don't have to iterate through all tabs comparing urls. | 485 favicon_cache_.OnPageFaviconUpdated(page_url); |
454 for (const GURL& page_url : page_urls) { | |
455 for (TabLinksMap::iterator tab_iter = local_tab_map_.begin(); | |
456 tab_iter != local_tab_map_.end(); ++tab_iter) { | |
457 if (tab_iter->second->url() == page_url) | |
458 favicon_cache_.OnPageFaviconUpdated(page_url); | |
459 } | |
460 } | |
461 } | 486 } |
462 | 487 |
463 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { | 488 void SessionsSyncManager::StopSyncing(syncer::ModelType type) { |
464 local_event_router_->Stop(); | 489 local_event_router_->Stop(); |
465 if (sync_processor_.get() && lost_navigations_recorder_.get()) { | 490 if (sync_processor_.get() && lost_navigations_recorder_.get()) { |
466 sync_processor_->RemoveLocalChangeObserver( | 491 sync_processor_->RemoveLocalChangeObserver( |
467 lost_navigations_recorder_.get()); | 492 lost_navigations_recorder_.get()); |
468 lost_navigations_recorder_.reset(); | 493 lost_navigations_recorder_.reset(); |
469 } | 494 } |
470 sync_processor_.reset(nullptr); | 495 sync_processor_.reset(nullptr); |
471 error_handler_.reset(); | 496 error_handler_.reset(); |
472 session_tracker_.Clear(); | 497 session_tracker_.Clear(); |
473 local_tab_map_.clear(); | |
474 local_tab_pool_.Clear(); | |
475 current_machine_tag_.clear(); | 498 current_machine_tag_.clear(); |
476 current_session_name_.clear(); | 499 current_session_name_.clear(); |
477 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; | 500 local_session_header_node_id_ = TabNodePool::kInvalidTabNodeID; |
478 } | 501 } |
479 | 502 |
480 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( | 503 syncer::SyncDataList SessionsSyncManager::GetAllSyncData( |
481 syncer::ModelType type) const { | 504 syncer::ModelType type) const { |
482 syncer::SyncDataList list; | 505 syncer::SyncDataList list; |
483 const SyncedSession* session = nullptr; | 506 const SyncedSession* session = nullptr; |
484 if (!session_tracker_.LookupLocalSession(&session)) | 507 if (!session_tracker_.LookupLocalSession(&session)) |
485 return syncer::SyncDataList(); | 508 return syncer::SyncDataList(); |
486 | 509 |
487 // First construct the header node. | 510 // First construct the header node. |
488 sync_pb::EntitySpecifics header_entity; | 511 sync_pb::EntitySpecifics header_entity; |
489 header_entity.mutable_session()->set_session_tag(current_machine_tag()); | 512 header_entity.mutable_session()->set_session_tag(current_machine_tag()); |
490 sync_pb::SessionHeader* header_specifics = | 513 sync_pb::SessionHeader* header_specifics = |
491 header_entity.mutable_session()->mutable_header(); | 514 header_entity.mutable_session()->mutable_header(); |
492 header_specifics->MergeFrom(session->ToSessionHeader()); | 515 header_specifics->MergeFrom(session->ToSessionHeader()); |
493 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 516 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
494 current_machine_tag(), current_session_name_, header_entity); | 517 current_machine_tag(), current_session_name_, header_entity); |
495 list.push_back(data); | 518 list.push_back(data); |
496 | 519 |
497 for (auto win_iter = session->windows.begin(); | 520 for (auto& win_iter : session->windows) { |
498 win_iter != session->windows.end(); ++win_iter) { | 521 for (auto& tab : win_iter.second->tabs) { |
499 for (auto tabs_iter = win_iter->second->tabs.begin(); | 522 // TODO(zea): replace with with the correct tab node id once there's a |
500 tabs_iter != win_iter->second->tabs.end(); ++tabs_iter) { | 523 // sync specific wrapper for SessionTab. This method is only used in |
| 524 // tests though, so it's fine for now. crbug.com/662597 |
| 525 int tab_node_id = 0; |
501 sync_pb::EntitySpecifics entity; | 526 sync_pb::EntitySpecifics entity; |
502 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 527 entity.mutable_session()->CopyFrom( |
503 specifics->mutable_tab()->MergeFrom((*tabs_iter)->ToSyncData()); | 528 SessionTabToSpecifics(*tab, current_machine_tag(), tab_node_id)); |
504 specifics->set_session_tag(current_machine_tag_); | |
505 | |
506 TabLinksMap::const_iterator tab_map_iter = | |
507 local_tab_map_.find((*tabs_iter)->tab_id.id()); | |
508 DCHECK(tab_map_iter != local_tab_map_.end()); | |
509 specifics->set_tab_node_id(tab_map_iter->second->tab_node_id()); | |
510 syncer::SyncData data = syncer::SyncData::CreateLocalData( | 529 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
511 TabNodePool::TabIdToTag(current_machine_tag_, | 530 TabNodeIdToTag(current_machine_tag(), tab_node_id), |
512 specifics->tab_node_id()), | |
513 current_session_name_, entity); | 531 current_session_name_, entity); |
514 list.push_back(data); | 532 list.push_back(data); |
515 } | 533 } |
516 } | 534 } |
517 return list; | 535 return list; |
518 } | 536 } |
519 | 537 |
520 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { | 538 bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) { |
521 if (current_machine_tag_.empty()) | 539 if (current_machine_tag().empty()) |
522 return false; | 540 return false; |
523 *local_session = session_tracker_.GetSession(current_machine_tag()); | 541 *local_session = session_tracker_.GetSession(current_machine_tag()); |
524 return true; | 542 return true; |
525 } | 543 } |
526 | 544 |
527 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( | 545 syncer::SyncError SessionsSyncManager::ProcessSyncChanges( |
528 const tracked_objects::Location& from_here, | 546 const tracked_objects::Location& from_here, |
529 const syncer::SyncChangeList& change_list) { | 547 const syncer::SyncChangeList& change_list) { |
530 if (!sync_processor_.get()) { | 548 if (!sync_processor_.get()) { |
531 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 549 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 break; | 589 break; |
572 case syncer::SyncChange::ACTION_ADD: | 590 case syncer::SyncChange::ACTION_ADD: |
573 case syncer::SyncChange::ACTION_UPDATE: | 591 case syncer::SyncChange::ACTION_UPDATE: |
574 if (current_machine_tag() == session.session_tag()) { | 592 if (current_machine_tag() == session.session_tag()) { |
575 // We should only ever receive a change to our own machine's session | 593 // We should only ever receive a change to our own machine's session |
576 // info if encryption was turned on. In that case, the data is still | 594 // info if encryption was turned on. In that case, the data is still |
577 // the same, so we can ignore. | 595 // the same, so we can ignore. |
578 LOG(WARNING) << "Dropping modification to local session."; | 596 LOG(WARNING) << "Dropping modification to local session."; |
579 return syncer::SyncError(); | 597 return syncer::SyncError(); |
580 } | 598 } |
581 UpdateTrackerWithForeignSession( | 599 UpdateTrackerWithSpecifics( |
582 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); | 600 session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime()); |
583 break; | 601 break; |
584 default: | 602 default: |
585 NOTREACHED() << "Processing sync changes failed, unknown change type."; | 603 NOTREACHED() << "Processing sync changes failed, unknown change type."; |
586 } | 604 } |
587 } | 605 } |
588 | 606 |
589 if (!sessions_updated_callback_.is_null()) | 607 if (!sessions_updated_callback_.is_null()) |
590 sessions_updated_callback_.Run(); | 608 sessions_updated_callback_.Run(); |
591 return syncer::SyncError(); | 609 return syncer::SyncError(); |
592 } | 610 } |
593 | 611 |
594 syncer::SyncChange SessionsSyncManager::TombstoneTab( | 612 syncer::SyncChange SessionsSyncManager::TombstoneTab( |
595 const sync_pb::SessionSpecifics& tab) { | 613 const sync_pb::SessionSpecifics& tab) { |
596 if (!tab.has_tab_node_id()) { | 614 if (!tab.has_tab_node_id()) { |
597 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; | 615 LOG(WARNING) << "Old sessions node without tab node id; can't tombstone."; |
598 return syncer::SyncChange(); | 616 return syncer::SyncChange(); |
599 } else { | 617 } else { |
600 return syncer::SyncChange( | 618 return syncer::SyncChange( |
601 FROM_HERE, SyncChange::ACTION_DELETE, | 619 FROM_HERE, SyncChange::ACTION_DELETE, |
602 SyncData::CreateLocalDelete( | 620 SyncData::CreateLocalDelete( |
603 TabNodePool::TabIdToTag(current_machine_tag(), tab.tab_node_id()), | 621 TabNodeIdToTag(current_machine_tag(), tab.tab_node_id()), |
604 syncer::SESSIONS)); | 622 syncer::SESSIONS)); |
605 } | 623 } |
606 } | 624 } |
607 | 625 |
608 bool SessionsSyncManager::GetAllForeignSessions( | 626 bool SessionsSyncManager::GetAllForeignSessions( |
609 std::vector<const SyncedSession*>* sessions) { | 627 std::vector<const SyncedSession*>* sessions) { |
610 if (!session_tracker_.LookupAllForeignSessions( | 628 if (!session_tracker_.LookupAllForeignSessions( |
611 sessions, SyncedSessionTracker::PRESENTABLE)) | 629 sessions, SyncedSessionTracker::PRESENTABLE)) |
612 return false; | 630 return false; |
613 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); | 631 std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator); |
614 return true; | 632 return true; |
615 } | 633 } |
616 | 634 |
617 bool SessionsSyncManager::InitFromSyncModel( | 635 bool SessionsSyncManager::InitFromSyncModel( |
618 const syncer::SyncDataList& sync_data, | 636 const syncer::SyncDataList& sync_data, |
619 syncer::SyncDataList* restored_tabs, | |
620 syncer::SyncChangeList* new_changes) { | 637 syncer::SyncChangeList* new_changes) { |
621 bool found_current_header = false; | 638 bool found_current_header = false; |
622 int bad_foreign_hash_count = 0; | 639 int bad_foreign_hash_count = 0; |
623 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); | 640 for (syncer::SyncDataList::const_iterator it = sync_data.begin(); |
624 it != sync_data.end(); ++it) { | 641 it != sync_data.end(); ++it) { |
625 const syncer::SyncData& data = *it; | 642 const syncer::SyncData& data = *it; |
626 DCHECK(data.GetSpecifics().has_session()); | 643 DCHECK(data.GetSpecifics().has_session()); |
627 syncer::SyncDataRemote remote(data); | 644 syncer::SyncDataRemote remote(data); |
628 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); | 645 const sync_pb::SessionSpecifics& specifics = data.GetSpecifics().session(); |
629 if (specifics.session_tag().empty() || | 646 if (specifics.session_tag().empty() || |
630 (specifics.has_tab() && | 647 (specifics.has_tab() && |
631 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { | 648 (!specifics.has_tab_node_id() || !specifics.tab().has_tab_id()))) { |
632 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 649 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
633 if (tombstone.IsValid()) | 650 if (tombstone.IsValid()) |
634 new_changes->push_back(tombstone); | 651 new_changes->push_back(tombstone); |
635 } else if (specifics.session_tag() != current_machine_tag()) { | 652 } else if (specifics.session_tag() != current_machine_tag()) { |
636 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { | 653 if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) { |
637 UpdateTrackerWithForeignSession(specifics, remote.GetModifiedTime()); | 654 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); |
638 } else { | 655 } else { |
639 // In the past, like years ago, we believe that some session data was | 656 // In the past, like years ago, we believe that some session data was |
640 // created with bad tag hashes. This causes any change this client makes | 657 // created with bad tag hashes. This causes any change this client makes |
641 // to that foreign data (like deletion through garbage collection) to | 658 // to that foreign data (like deletion through garbage collection) to |
642 // trigger a data type error because the tag looking mechanism fails. So | 659 // trigger a data type error because the tag looking mechanism fails. So |
643 // look for these and delete via remote SyncData, which uses a server id | 660 // look for these and delete via remote SyncData, which uses a server id |
644 // lookup mechanism instead, see crbug.com/604657. | 661 // lookup mechanism instead, see crbug.com/604657. |
645 bad_foreign_hash_count++; | 662 bad_foreign_hash_count++; |
646 new_changes->push_back( | 663 new_changes->push_back( |
647 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); | 664 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, remote)); |
648 } | 665 } |
649 } else { | 666 } else { |
650 // This is previously stored local session information. | 667 // This is previously stored local session information. |
651 if (specifics.has_header() && !found_current_header) { | 668 if (specifics.has_header() && !found_current_header) { |
652 // This is our previous header node, reuse it. | 669 // This is our previous header node, reuse it. |
653 found_current_header = true; | 670 found_current_header = true; |
654 if (specifics.header().has_client_name()) | 671 if (specifics.header().has_client_name()) |
655 current_session_name_ = specifics.header().client_name(); | 672 current_session_name_ = specifics.header().client_name(); |
| 673 |
| 674 // TODO(zea): crbug.com/639009 update the tracker with the specifics |
| 675 // from the header node as well. This will be necessary to preserve |
| 676 // the set of open tabs when a custom tab is opened. |
656 } else { | 677 } else { |
657 if (specifics.has_header() || !specifics.has_tab()) { | 678 if (specifics.has_header() || !specifics.has_tab()) { |
658 LOG(WARNING) << "Found more than one session header node with local " | 679 LOG(WARNING) << "Found more than one session header node with local " |
659 << "tag."; | 680 << "tag."; |
660 syncer::SyncChange tombstone(TombstoneTab(specifics)); | 681 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
661 if (tombstone.IsValid()) | 682 if (tombstone.IsValid()) |
662 new_changes->push_back(tombstone); | 683 new_changes->push_back(tombstone); |
| 684 } else if (specifics.tab().tab_id() == TabNodePool::kInvalidTabID) { |
| 685 LOG(WARNING) << "Found tab node with invalid tab id."; |
| 686 syncer::SyncChange tombstone(TombstoneTab(specifics)); |
| 687 if (tombstone.IsValid()) |
| 688 new_changes->push_back(tombstone); |
663 } else { | 689 } else { |
664 // This is a valid old tab node, add it to the pool so it can be | 690 // This is a valid old tab node, add it to the tracker and associate |
665 // reused for reassociation. | 691 // it. |
666 local_tab_pool_.AddTabNode(specifics.tab_node_id()); | 692 DVLOG(1) << "Associating local tab " << specifics.tab().tab_id() |
667 restored_tabs->push_back(*it); | 693 << " with node " << specifics.tab_node_id(); |
| 694 session_tracker_.ReassociateLocalTab(specifics.tab_node_id(), |
| 695 specifics.tab().tab_id()); |
| 696 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime()); |
668 } | 697 } |
669 } | 698 } |
670 } | 699 } |
671 } | 700 } |
672 | 701 |
673 // Cleanup all foreign sessions, since orphaned tabs may have been added after | 702 // Cleanup all foreign sessions, since orphaned tabs may have been added after |
674 // the header. | 703 // the header. |
675 std::vector<const SyncedSession*> sessions; | 704 std::vector<const SyncedSession*> sessions; |
676 session_tracker_.LookupAllForeignSessions(&sessions, | 705 session_tracker_.LookupAllForeignSessions(&sessions, |
677 SyncedSessionTracker::RAW); | 706 SyncedSessionTracker::RAW); |
678 for (const auto* session : sessions) { | 707 for (const auto* session : sessions) { |
679 session_tracker_.CleanupSession(session->session_tag); | 708 session_tracker_.CleanupForeignSession(session->session_tag); |
680 } | 709 } |
681 | 710 |
682 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", | 711 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", |
683 bad_foreign_hash_count); | 712 bad_foreign_hash_count); |
684 | 713 |
685 return found_current_header; | 714 return found_current_header; |
686 } | 715 } |
687 | 716 |
688 void SessionsSyncManager::UpdateTrackerWithForeignSession( | 717 void SessionsSyncManager::UpdateTrackerWithSpecifics( |
689 const sync_pb::SessionSpecifics& specifics, | 718 const sync_pb::SessionSpecifics& specifics, |
690 const base::Time& modification_time) { | 719 const base::Time& modification_time) { |
691 std::string foreign_session_tag = specifics.session_tag(); | 720 std::string session_tag = specifics.session_tag(); |
692 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 721 SyncedSession* session = session_tracker_.GetSession(session_tag); |
693 | |
694 SyncedSession* foreign_session = | |
695 session_tracker_.GetSession(foreign_session_tag); | |
696 if (specifics.has_header()) { | 722 if (specifics.has_header()) { |
697 // Read in the header data for this foreign session. Header data is | 723 // Read in the header data for this session. Header data is |
698 // essentially a collection of windows, each of which has an ordered id list | 724 // essentially a collection of windows, each of which has an ordered id list |
699 // for their tabs. | 725 // for their tabs. |
700 | 726 |
701 if (!IsValidSessionHeader(specifics.header())) { | 727 if (!IsValidSessionHeader(specifics.header())) { |
702 LOG(WARNING) << "Ignoring foreign session node with invalid header " | 728 LOG(WARNING) << "Ignoring session node with invalid header " |
703 << "and tag " << foreign_session_tag << "."; | 729 << "and tag " << session_tag << "."; |
704 return; | 730 return; |
705 } | 731 } |
706 | 732 |
707 // Load (or create) the SyncedSession object for this client. | 733 // Load (or create) the SyncedSession object for this client. |
708 const sync_pb::SessionHeader& header = specifics.header(); | 734 const sync_pb::SessionHeader& header = specifics.header(); |
709 PopulateSessionHeaderFromSpecifics(header, modification_time, | 735 PopulateSessionHeaderFromSpecifics(header, modification_time, session); |
710 foreign_session); | |
711 | 736 |
712 // Reset the tab/window tracking for this session (must do this before | 737 // Reset the tab/window tracking for this session (must do this before |
713 // we start calling PutWindowInSession and PutTabInWindow so that all | 738 // we start calling PutWindowInSession and PutTabInWindow so that all |
714 // unused tabs/windows get cleared by the CleanupSession(...) call). | 739 // unused tabs/windows get cleared by the CleanupSession(...) call). |
715 session_tracker_.ResetSessionTracking(foreign_session_tag); | 740 session_tracker_.ResetSessionTracking(session_tag); |
716 | 741 |
717 // Process all the windows and their tab information. | 742 // Process all the windows and their tab information. |
718 int num_windows = header.window_size(); | 743 int num_windows = header.window_size(); |
719 DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows | 744 DVLOG(1) << "Populating " << session_tag << " with " << num_windows |
720 << " windows."; | 745 << " windows."; |
721 | 746 |
722 for (int i = 0; i < num_windows; ++i) { | 747 for (int i = 0; i < num_windows; ++i) { |
723 const sync_pb::SessionWindow& window_s = header.window(i); | 748 const sync_pb::SessionWindow& window_s = header.window(i); |
724 SessionID::id_type window_id = window_s.window_id(); | 749 SessionID::id_type window_id = window_s.window_id(); |
725 session_tracker_.PutWindowInSession(foreign_session_tag, window_id); | 750 session_tracker_.PutWindowInSession(session_tag, window_id); |
726 BuildSyncedSessionFromSpecifics( | 751 BuildSyncedSessionFromSpecifics(session_tag, window_s, modification_time, |
727 foreign_session_tag, window_s, modification_time, | 752 session->windows[window_id].get()); |
728 foreign_session->windows[window_id].get()); | |
729 } | 753 } |
730 // Delete any closed windows and unused tabs as necessary. | 754 // Delete any closed windows and unused tabs as necessary. |
731 session_tracker_.CleanupSession(foreign_session_tag); | 755 session_tracker_.CleanupForeignSession(session_tag); |
732 } else if (specifics.has_tab()) { | 756 } else if (specifics.has_tab()) { |
733 const sync_pb::SessionTab& tab_s = specifics.tab(); | 757 const sync_pb::SessionTab& tab_s = specifics.tab(); |
734 SessionID::id_type tab_id = tab_s.tab_id(); | 758 SessionID::id_type tab_id = tab_s.tab_id(); |
| 759 DVLOG(1) << "Populating " << session_tag << "'s tab id " << tab_id |
| 760 << " from node " << specifics.tab_node_id(); |
735 | 761 |
736 const sessions::SessionTab* existing_tab; | 762 // Ensure the tracker is aware of the tab node id. Deleting foreign sessions |
737 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, | 763 // requires deleting all relevant tab nodes, and it's easier to track the |
738 &existing_tab) && | 764 // tab node ids themselves separately from the tab ids. |
739 existing_tab->timestamp > modification_time) { | 765 // |
740 // Force the tracker to remember this tab node id, even if it isn't | 766 // Note that TabIDs are not stable across restarts of a client. Consider |
741 // currently being used. | 767 // this example with two tabs: |
742 session_tracker_.GetTab(foreign_session_tag, tab_id, | 768 // |
743 specifics.tab_node_id()); | 769 // http://a.com TabID1 --> NodeIDA |
744 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab " | 770 // http://b.com TabID2 --> NodeIDB |
745 << tab_id << " with earlier modification time"; | 771 // |
| 772 // After restart, tab ids are reallocated. e.g, one possibility: |
| 773 // http://a.com TabID2 --> NodeIDA |
| 774 // http://b.com TabID1 --> NodeIDB |
| 775 // |
| 776 // If that happened on a remote client, here we will see an update to |
| 777 // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2 |
| 778 // with tab_node_id changing from NodeIDB to NodeIDA. |
| 779 // |
| 780 // We can also wind up here if we created this tab as an out-of-order |
| 781 // update to the header node for this session before actually associating |
| 782 // the tab itself, so the tab node id wasn't available at the time and |
| 783 // is currently kInvalidTabNodeID. |
| 784 // |
| 785 // In both cases, we can safely throw it into the set of node ids. |
| 786 session_tracker_.OnTabNodeSeen(session_tag, specifics.tab_node_id()); |
| 787 sessions::SessionTab* tab = session_tracker_.GetTab(session_tag, tab_id); |
| 788 if (!tab->timestamp.is_null() && tab->timestamp > modification_time) { |
| 789 DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id |
| 790 << " with earlier modification time: " << tab->timestamp |
| 791 << " vs " << modification_time; |
746 return; | 792 return; |
747 } | 793 } |
748 | 794 |
749 sessions::SessionTab* tab = session_tracker_.GetTab( | |
750 foreign_session_tag, tab_id, specifics.tab_node_id()); | |
751 | |
752 // Update SessionTab based on protobuf. | 795 // Update SessionTab based on protobuf. |
753 tab->SetFromSyncData(tab_s, modification_time); | 796 tab->SetFromSyncData(tab_s, modification_time); |
754 | 797 |
755 // If a favicon or favicon urls are present, load the URLs and visit | 798 // If a favicon or favicon urls are present, load the URLs and visit |
756 // times into the in-memory favicon cache. | 799 // times into the in-memory favicon cache. |
757 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); | 800 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); |
758 | 801 |
759 // Update the last modified time. | 802 // Update the last modified time. |
760 if (foreign_session->modified_time < modification_time) | 803 if (session->modified_time < modification_time) |
761 foreign_session->modified_time = modification_time; | 804 session->modified_time = modification_time; |
762 } else { | 805 } else { |
763 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " | 806 LOG(WARNING) << "Ignoring session node with missing header/tab " |
764 << "fields and tag " << foreign_session_tag << "."; | 807 << "fields and tag " << session_tag << "."; |
765 } | 808 } |
766 } | 809 } |
767 | 810 |
768 void SessionsSyncManager::InitializeCurrentMachineTag( | 811 void SessionsSyncManager::InitializeCurrentMachineTag( |
769 const std::string& cache_guid) { | 812 const std::string& cache_guid) { |
770 DCHECK(current_machine_tag_.empty()); | 813 DCHECK(current_machine_tag_.empty()); |
771 std::string persisted_guid; | 814 std::string persisted_guid; |
772 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); | 815 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); |
773 if (!persisted_guid.empty()) { | 816 if (!persisted_guid.empty()) { |
774 current_machine_tag_ = persisted_guid; | 817 current_machine_tag_ = persisted_guid; |
775 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; | 818 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; |
776 } else { | 819 } else { |
777 DCHECK(!cache_guid.empty()); | 820 DCHECK(!cache_guid.empty()); |
778 current_machine_tag_ = BuildMachineTag(cache_guid); | 821 current_machine_tag_ = BuildMachineTag(cache_guid); |
779 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; | 822 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; |
780 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); | 823 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); |
781 } | 824 } |
782 | |
783 local_tab_pool_.SetMachineTag(current_machine_tag_); | |
784 } | 825 } |
785 | 826 |
786 // static | 827 // static |
787 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( | 828 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( |
788 const sync_pb::SessionHeader& header_specifics, | 829 const sync_pb::SessionHeader& header_specifics, |
789 base::Time mtime, | 830 base::Time mtime, |
790 SyncedSession* session_header) { | 831 SyncedSession* session_header) { |
791 if (header_specifics.has_client_name()) | 832 if (header_specifics.has_client_name()) |
792 session_header->session_name = header_specifics.client_name(); | 833 session_header->session_name = header_specifics.client_name(); |
793 if (header_specifics.has_device_type()) { | 834 if (header_specifics.has_device_type()) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 if (specifics.browser_type() == | 878 if (specifics.browser_type() == |
838 sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { | 879 sync_pb::SessionWindow_BrowserType_TYPE_TABBED) { |
839 session_window->type = sessions::SessionWindow::TYPE_TABBED; | 880 session_window->type = sessions::SessionWindow::TYPE_TABBED; |
840 } else { | 881 } else { |
841 // Note: custom tabs are treated like popup windows on restore, as you can | 882 // Note: custom tabs are treated like popup windows on restore, as you can |
842 // restore a custom tab on a platform that doesn't support them. | 883 // restore a custom tab on a platform that doesn't support them. |
843 session_window->type = sessions::SessionWindow::TYPE_POPUP; | 884 session_window->type = sessions::SessionWindow::TYPE_POPUP; |
844 } | 885 } |
845 } | 886 } |
846 session_window->timestamp = mtime; | 887 session_window->timestamp = mtime; |
847 session_window->tabs.resize(specifics.tab_size()); | 888 session_window->tabs.clear(); |
848 for (int i = 0; i < specifics.tab_size(); i++) { | 889 for (int i = 0; i < specifics.tab_size(); i++) { |
849 SessionID::id_type tab_id = specifics.tab(i); | 890 SessionID::id_type tab_id = specifics.tab(i); |
850 session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(), | 891 session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(), |
851 tab_id, i); | 892 tab_id); |
852 } | 893 } |
853 } | 894 } |
854 | 895 |
855 void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( | 896 void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab( |
856 const sync_pb::SessionTab& tab, | 897 const sync_pb::SessionTab& tab, |
857 const base::Time& modification_time) { | 898 const base::Time& modification_time) { |
858 // First go through and iterate over all the navigations, checking if any | 899 // First go through and iterate over all the navigations, checking if any |
859 // have valid favicon urls. | 900 // have valid favicon urls. |
860 for (int i = 0; i < tab.navigation_size(); ++i) { | 901 for (int i = 0; i < tab.navigation_size(); ++i) { |
861 if (!tab.navigation(i).favicon_url().empty()) { | 902 if (!tab.navigation(i).favicon_url().empty()) { |
(...skipping 21 matching lines...) Expand all Loading... |
883 void SessionsSyncManager::DeleteForeignSessionInternal( | 924 void SessionsSyncManager::DeleteForeignSessionInternal( |
884 const std::string& tag, | 925 const std::string& tag, |
885 syncer::SyncChangeList* change_output) { | 926 syncer::SyncChangeList* change_output) { |
886 if (tag == current_machine_tag()) { | 927 if (tag == current_machine_tag()) { |
887 LOG(ERROR) << "Attempting to delete local session. This is not currently " | 928 LOG(ERROR) << "Attempting to delete local session. This is not currently " |
888 << "supported."; | 929 << "supported."; |
889 return; | 930 return; |
890 } | 931 } |
891 | 932 |
892 std::set<int> tab_node_ids_to_delete; | 933 std::set<int> tab_node_ids_to_delete; |
893 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); | 934 session_tracker_.LookupForeignTabNodeIds(tag, &tab_node_ids_to_delete); |
894 if (DisassociateForeignSession(tag)) { | 935 if (DisassociateForeignSession(tag)) { |
895 // Only tell sync to delete the header if there was one. | 936 // Only tell sync to delete the header if there was one. |
896 change_output->push_back( | 937 change_output->push_back( |
897 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, | 938 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, |
898 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); | 939 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); |
899 } | 940 } |
900 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); | 941 AppendDeletionsForTabNodes(tab_node_ids_to_delete, tag, change_output); |
901 it != tab_node_ids_to_delete.end(); ++it) { | |
902 change_output->push_back(syncer::SyncChange( | |
903 FROM_HERE, SyncChange::ACTION_DELETE, | |
904 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), | |
905 syncer::SESSIONS))); | |
906 } | |
907 if (!sessions_updated_callback_.is_null()) | 942 if (!sessions_updated_callback_.is_null()) |
908 sessions_updated_callback_.Run(); | 943 sessions_updated_callback_.Run(); |
909 } | 944 } |
910 | 945 |
911 bool SessionsSyncManager::DisassociateForeignSession( | 946 bool SessionsSyncManager::DisassociateForeignSession( |
912 const std::string& foreign_session_tag) { | 947 const std::string& foreign_session_tag) { |
913 DCHECK_NE(foreign_session_tag, current_machine_tag()); | 948 DCHECK_NE(foreign_session_tag, current_machine_tag()); |
914 DVLOG(1) << "Disassociating session " << foreign_session_tag; | 949 DVLOG(1) << "Disassociating session " << foreign_session_tag; |
915 return session_tracker_.DeleteSession(foreign_session_tag); | 950 return session_tracker_.DeleteForeignSession(foreign_session_tag); |
916 } | 951 } |
917 | 952 |
918 bool SessionsSyncManager::GetForeignSession( | 953 bool SessionsSyncManager::GetForeignSession( |
919 const std::string& tag, | 954 const std::string& tag, |
920 std::vector<const sessions::SessionWindow*>* windows) { | 955 std::vector<const sessions::SessionWindow*>* windows) { |
921 return session_tracker_.LookupSessionWindows(tag, windows); | 956 return session_tracker_.LookupSessionWindows(tag, windows); |
922 } | 957 } |
923 | 958 |
924 bool SessionsSyncManager::GetForeignSessionTabs( | 959 bool SessionsSyncManager::GetForeignSessionTabs( |
925 const std::string& tag, | 960 const std::string& tag, |
(...skipping 25 matching lines...) Expand all Loading... |
951 bool SessionsSyncManager::GetForeignTab(const std::string& tag, | 986 bool SessionsSyncManager::GetForeignTab(const std::string& tag, |
952 const SessionID::id_type tab_id, | 987 const SessionID::id_type tab_id, |
953 const sessions::SessionTab** tab) { | 988 const sessions::SessionTab** tab) { |
954 const sessions::SessionTab* synced_tab = nullptr; | 989 const sessions::SessionTab* synced_tab = nullptr; |
955 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); | 990 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); |
956 if (success) | 991 if (success) |
957 *tab = synced_tab; | 992 *tab = synced_tab; |
958 return success; | 993 return success; |
959 } | 994 } |
960 | 995 |
961 void SessionsSyncManager::LocalTabDelegateToSpecifics( | |
962 const SyncedTabDelegate& tab_delegate, | |
963 sync_pb::SessionSpecifics* specifics) { | |
964 sessions::SessionTab* session_tab = nullptr; | |
965 session_tab = session_tracker_.GetTab(current_machine_tag(), | |
966 tab_delegate.GetSessionId(), | |
967 tab_delegate.GetSyncId()); | |
968 SetSessionTabFromDelegate(tab_delegate, base::Time::Now(), session_tab); | |
969 SetVariationIds(session_tab); | |
970 sync_pb::SessionTab tab_s = session_tab->ToSyncData(); | |
971 specifics->set_session_tag(current_machine_tag_); | |
972 specifics->set_tab_node_id(tab_delegate.GetSyncId()); | |
973 specifics->mutable_tab()->CopyFrom(tab_s); | |
974 } | |
975 | |
976 void SessionsSyncManager::AssociateRestoredPlaceholderTab( | 996 void SessionsSyncManager::AssociateRestoredPlaceholderTab( |
977 const SyncedTabDelegate& tab_delegate, | 997 const SyncedTabDelegate& tab_delegate, |
978 SessionID::id_type new_tab_id, | 998 SessionID::id_type new_tab_id, |
979 SessionID::id_type new_window_id, | 999 SessionID::id_type new_window_id, |
980 const syncer::SyncDataList& restored_tabs, | |
981 syncer::SyncChangeList* change_output) { | 1000 syncer::SyncChangeList* change_output) { |
982 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); | 1001 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); |
983 // Rewrite the tab using |restored_tabs| to retrieve the specifics. | 1002 |
984 if (restored_tabs.empty()) { | 1003 // It's possible the placeholder tab is associated with a tab node that's |
985 DLOG(WARNING) << "Can't Update tab ID."; | 1004 // since been deleted. If that's the case, there's no way to reassociate it, |
| 1005 // so just return now without adding the tab to the session tracker. |
| 1006 if (!session_tracker_.IsLocalTabNodeAssociated(tab_delegate.GetSyncId())) { |
| 1007 DVLOG(1) << "Restored placeholder tab's node " << tab_delegate.GetSyncId() |
| 1008 << " deleted."; |
986 return; | 1009 return; |
987 } | 1010 } |
988 | 1011 |
989 for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); | 1012 // Update tracker with the new association (and inform it of the tab node |
990 it != restored_tabs.end(); ++it) { | 1013 // in the process). |
991 if (it->GetSpecifics().session().tab_node_id() != | 1014 session_tracker_.ReassociateLocalTab(tab_delegate.GetSyncId(), new_tab_id); |
992 tab_delegate.GetSyncId()) { | |
993 continue; | |
994 } | |
995 | 1015 |
996 sync_pb::EntitySpecifics entity; | 1016 // Update the window id on the SessionTab itself. |
997 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); | 1017 sessions::SessionTab* local_tab = |
998 specifics->CopyFrom(it->GetSpecifics().session()); | 1018 session_tracker_.GetTab(current_machine_tag(), new_tab_id); |
999 DCHECK(specifics->has_tab()); | 1019 local_tab->window_id.set_id(new_window_id); |
1000 | 1020 |
1001 // Update tab node pool with the new association. | 1021 // Rewrite the specifics based on the reassociated SessionTab to preserve |
1002 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); | 1022 // the new tab and window ids. |
1003 TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); | 1023 sync_pb::EntitySpecifics entity; |
1004 local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); | 1024 entity.mutable_session()->CopyFrom(SessionTabToSpecifics( |
1005 | 1025 *local_tab, current_machine_tag(), tab_delegate.GetSyncId())); |
1006 if (specifics->tab().tab_id() == new_tab_id && | 1026 syncer::SyncData data = syncer::SyncData::CreateLocalData( |
1007 specifics->tab().window_id() == new_window_id) | 1027 TabNodeIdToTag(current_machine_tag(), tab_delegate.GetSyncId()), |
1008 return; | 1028 current_session_name_, entity); |
1009 | 1029 change_output->push_back( |
1010 // Either the tab_id or window_id changed (e.g due to session restore), so | 1030 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); |
1011 // update the sync node. | |
1012 specifics->mutable_tab()->set_tab_id(new_tab_id); | |
1013 specifics->mutable_tab()->set_window_id(new_window_id); | |
1014 syncer::SyncData data = syncer::SyncData::CreateLocalData( | |
1015 TabNodePool::TabIdToTag(current_machine_tag_, specifics->tab_node_id()), | |
1016 current_session_name_, entity); | |
1017 change_output->push_back( | |
1018 syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); | |
1019 return; | |
1020 } | |
1021 } | 1031 } |
1022 | 1032 |
1023 // static | 1033 // static |
1024 void SessionsSyncManager::SetSessionTabFromDelegate( | 1034 void SessionsSyncManager::SetSessionTabFromDelegate( |
1025 const SyncedTabDelegate& tab_delegate, | 1035 const SyncedTabDelegate& tab_delegate, |
1026 base::Time mtime, | 1036 base::Time mtime, |
1027 sessions::SessionTab* session_tab) { | 1037 sessions::SessionTab* session_tab) { |
1028 DCHECK(session_tab); | 1038 DCHECK(session_tab); |
1029 session_tab->window_id.set_id(tab_delegate.GetWindowId()); | 1039 session_tab->window_id.set_id(tab_delegate.GetWindowId()); |
1030 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); | 1040 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 } | 1139 } |
1130 | 1140 |
1131 // static | 1141 // static |
1132 std::string SessionsSyncManager::TagHashFromSpecifics( | 1142 std::string SessionsSyncManager::TagHashFromSpecifics( |
1133 const sync_pb::SessionSpecifics& specifics) { | 1143 const sync_pb::SessionSpecifics& specifics) { |
1134 return syncer::GenerateSyncableHash(syncer::SESSIONS, | 1144 return syncer::GenerateSyncableHash(syncer::SESSIONS, |
1135 TagFromSpecifics(specifics)); | 1145 TagFromSpecifics(specifics)); |
1136 } | 1146 } |
1137 | 1147 |
1138 }; // namespace sync_sessions | 1148 }; // namespace sync_sessions |
OLD | NEW |