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

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

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

Powered by Google App Engine
This is Rietveld 408576698