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

Side by Side Diff: components/sync_sessions/sessions_sync_manager.cc

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

Powered by Google App Engine
This is Rietveld 408576698