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

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: Self review 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) {
skym 2016/12/03 01:20:46 Is duplicating in anonymous namespaces between .cc
Nicolas Zea 2016/12/06 01:32:55 Given it's just a one-liner with no real logic, it
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) << "Reloading 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 session_tracker_.ReassociateLocalTab(specifics.tab_node_id(),
skym 2016/12/03 01:20:46 Err, is this really correct? What if you've alread
Nicolas Zea 2016/12/06 01:32:55 InitFromSyncModel is called before OnLocalTabModif
669 restored_tabs->push_back(*it); 669 specifics.tab().tab_id());
670 UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime());
670 } 671 }
671 } 672 }
672 } 673 }
673 } 674 }
674 675
675 // Cleanup all foreign sessions, since orphaned tabs may have been added after 676 // Cleanup all foreign sessions, since orphaned tabs may have been added after
676 // the header. 677 // the header.
677 std::vector<const SyncedSession*> sessions; 678 std::vector<const SyncedSession*> sessions;
678 session_tracker_.LookupAllForeignSessions(&sessions, 679 session_tracker_.LookupAllForeignSessions(&sessions,
679 SyncedSessionTracker::RAW); 680 SyncedSessionTracker::RAW);
680 for (const auto* session : sessions) { 681 for (const auto* session : sessions) {
681 session_tracker_.CleanupSession(session->session_tag); 682 session_tracker_.CleanupForeignSession(session->session_tag);
682 } 683 }
683 684
684 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount", 685 UMA_HISTOGRAM_COUNTS_100("Sync.SessionsBadForeignHashOnMergeCount",
685 bad_foreign_hash_count); 686 bad_foreign_hash_count);
686 687
687 return found_current_header; 688 return found_current_header;
688 } 689 }
689 690
690 void SessionsSyncManager::UpdateTrackerWithForeignSession( 691 void SessionsSyncManager::UpdateTrackerWithSpecifics(
691 const sync_pb::SessionSpecifics& specifics, 692 const sync_pb::SessionSpecifics& specifics,
692 const base::Time& modification_time) { 693 const base::Time& modification_time) {
693 std::string foreign_session_tag = specifics.session_tag(); 694 std::string session_tag = specifics.session_tag();
694 DCHECK_NE(foreign_session_tag, current_machine_tag()); 695 SyncedSession* session = session_tracker_.GetSession(session_tag);
695
696 SyncedSession* foreign_session =
697 session_tracker_.GetSession(foreign_session_tag);
698 if (specifics.has_header()) { 696 if (specifics.has_header()) {
699 // Read in the header data for this foreign session. Header data is 697 // 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 698 // essentially a collection of windows, each of which has an ordered id list
701 // for their tabs. 699 // for their tabs.
702 700
703 if (!IsValidSessionHeader(specifics.header())) { 701 if (!IsValidSessionHeader(specifics.header())) {
704 LOG(WARNING) << "Ignoring foreign session node with invalid header " 702 LOG(WARNING) << "Ignoring session node with invalid header "
705 << "and tag " << foreign_session_tag << "."; 703 << "and tag " << session_tag << ".";
706 return; 704 return;
707 } 705 }
708 706
709 // Load (or create) the SyncedSession object for this client. 707 // Load (or create) the SyncedSession object for this client.
710 const sync_pb::SessionHeader& header = specifics.header(); 708 const sync_pb::SessionHeader& header = specifics.header();
711 PopulateSessionHeaderFromSpecifics(header, modification_time, 709 PopulateSessionHeaderFromSpecifics(header, modification_time, session);
712 foreign_session);
713 710
714 // Reset the tab/window tracking for this session (must do this before 711 // Reset the tab/window tracking for this session (must do this before
715 // we start calling PutWindowInSession and PutTabInWindow so that all 712 // we start calling PutWindowInSession and PutTabInWindow so that all
716 // unused tabs/windows get cleared by the CleanupSession(...) call). 713 // unused tabs/windows get cleared by the CleanupSession(...) call).
717 session_tracker_.ResetSessionTracking(foreign_session_tag); 714 session_tracker_.ResetSessionTracking(session_tag);
718 715
719 // Process all the windows and their tab information. 716 // Process all the windows and their tab information.
720 int num_windows = header.window_size(); 717 int num_windows = header.window_size();
721 DVLOG(1) << "Associating " << foreign_session_tag << " with " << num_windows 718 DVLOG(1) << "Associating " << session_tag << " with " << num_windows
722 << " windows."; 719 << " windows.";
723 720
724 for (int i = 0; i < num_windows; ++i) { 721 for (int i = 0; i < num_windows; ++i) {
725 const sync_pb::SessionWindow& window_s = header.window(i); 722 const sync_pb::SessionWindow& window_s = header.window(i);
726 SessionID::id_type window_id = window_s.window_id(); 723 SessionID::id_type window_id = window_s.window_id();
727 session_tracker_.PutWindowInSession(foreign_session_tag, window_id); 724 session_tracker_.PutWindowInSession(session_tag, window_id);
728 BuildSyncedSessionFromSpecifics( 725 BuildSyncedSessionFromSpecifics(session_tag, window_s, modification_time,
729 foreign_session_tag, window_s, modification_time, 726 session->windows[window_id].get());
730 foreign_session->windows[window_id].get());
731 } 727 }
732 // Delete any closed windows and unused tabs as necessary. 728 // Delete any closed windows and unused tabs as necessary.
733 session_tracker_.CleanupSession(foreign_session_tag); 729 session_tracker_.CleanupForeignSession(session_tag);
734 } else if (specifics.has_tab()) { 730 } else if (specifics.has_tab()) {
735 const sync_pb::SessionTab& tab_s = specifics.tab(); 731 const sync_pb::SessionTab& tab_s = specifics.tab();
736 SessionID::id_type tab_id = tab_s.tab_id(); 732 SessionID::id_type tab_id = tab_s.tab_id();
737 733
734 DVLOG(1) << "Associating tab " << tab_id << " with node "
skym 2016/12/03 01:20:46 Nit: We only actually associate the tab_id with ta
skym 2016/12/05 19:16:57 Errm, now I'm confused by my comment from last wee
Nicolas Zea 2016/12/06 01:32:55 Are you referring to the if conditional just below
735 << specifics.tab_node_id();
736 session_tracker_.AddTabNode(session_tag, specifics.tab_node_id());
skym 2016/12/05 19:16:57 I think AddX(...) is a much better method name tha
Nicolas Zea 2016/12/06 01:32:55 Cleaned up the comments here. PTAL! Also re: AddX
skym 2016/12/06 19:37:21 Both options sound good to me.
Nicolas Zea 2016/12/06 22:31:37 Switched to OnTabNodeSeen.
737
738 const sessions::SessionTab* existing_tab; 738 const sessions::SessionTab* existing_tab;
739 if (session_tracker_.LookupSessionTab(foreign_session_tag, tab_id, 739 if (session_tracker_.LookupSessionTab(session_tag, tab_id, &existing_tab) &&
740 &existing_tab) &&
741 existing_tab->timestamp > modification_time) { 740 existing_tab->timestamp > modification_time) {
742 // Force the tracker to remember this tab node id, even if it isn't 741 DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id
743 // currently being used. 742 << " with earlier modification time";
744 session_tracker_.GetTab(foreign_session_tag, tab_id,
745 specifics.tab_node_id());
746 DVLOG(1) << "Ignoring " << foreign_session_tag << "'s session tab "
747 << tab_id << " with earlier modification time";
748 return; 743 return;
749 } 744 }
750 745
751 sessions::SessionTab* tab = session_tracker_.GetTab( 746 sessions::SessionTab* tab = session_tracker_.GetTab(session_tag, tab_id);
skym 2016/12/05 19:16:57 Without passing tab node id to this call, why do w
Nicolas Zea 2016/12/06 01:32:55 Good point, the calls can be combined. Done.
752 foreign_session_tag, tab_id, specifics.tab_node_id());
753 747
754 // Update SessionTab based on protobuf. 748 // Update SessionTab based on protobuf.
755 tab->SetFromSyncData(tab_s, modification_time); 749 tab->SetFromSyncData(tab_s, modification_time);
756 750
757 // If a favicon or favicon urls are present, load the URLs and visit 751 // If a favicon or favicon urls are present, load the URLs and visit
758 // times into the in-memory favicon cache. 752 // times into the in-memory favicon cache.
759 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time); 753 RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time);
760 754
761 // Update the last modified time. 755 // Update the last modified time.
762 if (foreign_session->modified_time < modification_time) 756 if (session->modified_time < modification_time)
763 foreign_session->modified_time = modification_time; 757 session->modified_time = modification_time;
764 } else { 758 } else {
765 LOG(WARNING) << "Ignoring foreign session node with missing header/tab " 759 LOG(WARNING) << "Ignoring session node with missing header/tab "
766 << "fields and tag " << foreign_session_tag << "."; 760 << "fields and tag " << session_tag << ".";
767 } 761 }
768 } 762 }
769 763
770 void SessionsSyncManager::InitializeCurrentMachineTag() { 764 void SessionsSyncManager::InitializeCurrentMachineTag() {
771 DCHECK(current_machine_tag_.empty()); 765 DCHECK(current_machine_tag_.empty());
772 std::string persisted_guid; 766 std::string persisted_guid;
773 persisted_guid = sync_prefs_->GetSyncSessionsGUID(); 767 persisted_guid = sync_prefs_->GetSyncSessionsGUID();
774 if (!persisted_guid.empty()) { 768 if (!persisted_guid.empty()) {
775 current_machine_tag_ = persisted_guid; 769 current_machine_tag_ = persisted_guid;
776 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid; 770 DVLOG(1) << "Restoring persisted session sync guid: " << persisted_guid;
777 } else { 771 } else {
778 DCHECK(local_device_); 772 DCHECK(local_device_);
779 std::string cache_guid = local_device_->GetLocalSyncCacheGUID(); 773 std::string cache_guid = local_device_->GetLocalSyncCacheGUID();
780 DCHECK(!cache_guid.empty()); 774 DCHECK(!cache_guid.empty());
781 current_machine_tag_ = BuildMachineTag(cache_guid); 775 current_machine_tag_ = BuildMachineTag(cache_guid);
782 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_; 776 DVLOG(1) << "Creating session sync guid: " << current_machine_tag_;
783 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_); 777 sync_prefs_->SetSyncSessionsGUID(current_machine_tag_);
784 } 778 }
785
786 local_tab_pool_.SetMachineTag(current_machine_tag_);
787 } 779 }
788 780
789 // static 781 // static
790 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics( 782 void SessionsSyncManager::PopulateSessionHeaderFromSpecifics(
791 const sync_pb::SessionHeader& header_specifics, 783 const sync_pb::SessionHeader& header_specifics,
792 base::Time mtime, 784 base::Time mtime,
793 SyncedSession* session_header) { 785 SyncedSession* session_header) {
794 if (header_specifics.has_client_name()) 786 if (header_specifics.has_client_name())
795 session_header->session_name = header_specifics.client_name(); 787 session_header->session_name = header_specifics.client_name();
796 if (header_specifics.has_device_type()) { 788 if (header_specifics.has_device_type()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 void SessionsSyncManager::DeleteForeignSessionInternal( 878 void SessionsSyncManager::DeleteForeignSessionInternal(
887 const std::string& tag, 879 const std::string& tag,
888 syncer::SyncChangeList* change_output) { 880 syncer::SyncChangeList* change_output) {
889 if (tag == current_machine_tag()) { 881 if (tag == current_machine_tag()) {
890 LOG(ERROR) << "Attempting to delete local session. This is not currently " 882 LOG(ERROR) << "Attempting to delete local session. This is not currently "
891 << "supported."; 883 << "supported.";
892 return; 884 return;
893 } 885 }
894 886
895 std::set<int> tab_node_ids_to_delete; 887 std::set<int> tab_node_ids_to_delete;
896 session_tracker_.LookupTabNodeIds(tag, &tab_node_ids_to_delete); 888 session_tracker_.LookupForeignTabNodeIds(tag, &tab_node_ids_to_delete);
897 if (DisassociateForeignSession(tag)) { 889 if (DisassociateForeignSession(tag)) {
898 // Only tell sync to delete the header if there was one. 890 // Only tell sync to delete the header if there was one.
899 change_output->push_back( 891 change_output->push_back(
900 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, 892 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
901 SyncData::CreateLocalDelete(tag, syncer::SESSIONS))); 893 SyncData::CreateLocalDelete(tag, syncer::SESSIONS)));
902 } 894 }
903 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin(); 895 for (std::set<int>::const_iterator it = tab_node_ids_to_delete.begin();
904 it != tab_node_ids_to_delete.end(); ++it) { 896 it != tab_node_ids_to_delete.end(); ++it) {
905 change_output->push_back(syncer::SyncChange( 897 change_output->push_back(
906 FROM_HERE, SyncChange::ACTION_DELETE, 898 syncer::SyncChange(FROM_HERE, SyncChange::ACTION_DELETE,
907 SyncData::CreateLocalDelete(TabNodePool::TabIdToTag(tag, *it), 899 SyncData::CreateLocalDelete(TabNodeIdToTag(tag, *it),
908 syncer::SESSIONS))); 900 syncer::SESSIONS)));
909 } 901 }
910 if (!sessions_updated_callback_.is_null()) 902 if (!sessions_updated_callback_.is_null())
911 sessions_updated_callback_.Run(); 903 sessions_updated_callback_.Run();
912 } 904 }
913 905
914 bool SessionsSyncManager::DisassociateForeignSession( 906 bool SessionsSyncManager::DisassociateForeignSession(
915 const std::string& foreign_session_tag) { 907 const std::string& foreign_session_tag) {
916 DCHECK_NE(foreign_session_tag, current_machine_tag()); 908 DCHECK_NE(foreign_session_tag, current_machine_tag());
917 DVLOG(1) << "Disassociating session " << foreign_session_tag; 909 DVLOG(1) << "Disassociating session " << foreign_session_tag;
918 return session_tracker_.DeleteSession(foreign_session_tag); 910 return session_tracker_.DeleteForeignSession(foreign_session_tag);
919 } 911 }
920 912
921 bool SessionsSyncManager::GetForeignSession( 913 bool SessionsSyncManager::GetForeignSession(
922 const std::string& tag, 914 const std::string& tag,
923 std::vector<const sessions::SessionWindow*>* windows) { 915 std::vector<const sessions::SessionWindow*>* windows) {
924 return session_tracker_.LookupSessionWindows(tag, windows); 916 return session_tracker_.LookupSessionWindows(tag, windows);
925 } 917 }
926 918
927 bool SessionsSyncManager::GetForeignSessionTabs( 919 bool SessionsSyncManager::GetForeignSessionTabs(
928 const std::string& tag, 920 const std::string& tag,
(...skipping 25 matching lines...) Expand all
954 bool SessionsSyncManager::GetForeignTab(const std::string& tag, 946 bool SessionsSyncManager::GetForeignTab(const std::string& tag,
955 const SessionID::id_type tab_id, 947 const SessionID::id_type tab_id,
956 const sessions::SessionTab** tab) { 948 const sessions::SessionTab** tab) {
957 const sessions::SessionTab* synced_tab = nullptr; 949 const sessions::SessionTab* synced_tab = nullptr;
958 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab); 950 bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab);
959 if (success) 951 if (success)
960 *tab = synced_tab; 952 *tab = synced_tab;
961 return success; 953 return success;
962 } 954 }
963 955
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( 956 void SessionsSyncManager::AssociateRestoredPlaceholderTab(
980 const SyncedTabDelegate& tab_delegate, 957 const SyncedTabDelegate& tab_delegate,
981 SessionID::id_type new_tab_id, 958 SessionID::id_type new_tab_id,
982 SessionID::id_type new_window_id, 959 SessionID::id_type new_window_id,
983 const syncer::SyncDataList& restored_tabs,
984 syncer::SyncChangeList* change_output) { 960 syncer::SyncChangeList* change_output) {
985 DCHECK_NE(tab_delegate.GetSyncId(), TabNodePool::kInvalidTabNodeID); 961 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 962
992 for (syncer::SyncDataList::const_iterator it = restored_tabs.begin(); 963 // Update tracker with the new association (and inform it of the tab node
993 it != restored_tabs.end(); ++it) { 964 // in the process).
994 if (it->GetSpecifics().session().tab_node_id() != 965 session_tracker_.ReassociateLocalTab(tab_delegate.GetSyncId(), new_tab_id);
995 tab_delegate.GetSyncId()) {
996 continue;
997 }
998 966
999 sync_pb::EntitySpecifics entity; 967 // Update the window id on the SessionTab itself.
1000 sync_pb::SessionSpecifics* specifics = entity.mutable_session(); 968 sessions::SessionTab* local_tab =
1001 specifics->CopyFrom(it->GetSpecifics().session()); 969 session_tracker_.GetTab(current_machine_tag(), new_tab_id);
1002 DCHECK(specifics->has_tab()); 970 local_tab->window_id.set_id(new_window_id);
1003 971
1004 // Update tab node pool with the new association. 972 // Rewrite the specifics based on the reassociated SessionTab to preserve
1005 local_tab_pool_.ReassociateTabNode(tab_delegate.GetSyncId(), new_tab_id); 973 // the new tab and window ids.
1006 TabLink* tab_link = new TabLink(tab_delegate.GetSyncId(), &tab_delegate); 974 sync_pb::EntitySpecifics entity;
1007 local_tab_map_[new_tab_id] = make_linked_ptr<TabLink>(tab_link); 975 entity.mutable_session()->CopyFrom(SessionTabToSpecifics(
1008 976 *local_tab, current_machine_tag(), tab_delegate.GetSyncId()));
1009 if (specifics->tab().tab_id() == new_tab_id && 977 syncer::SyncData data = syncer::SyncData::CreateLocalData(
1010 specifics->tab().window_id() == new_window_id) 978 TabNodeIdToTag(current_machine_tag(), tab_delegate.GetSyncId()),
1011 return; 979 current_session_name_, entity);
1012 980 change_output->push_back(
1013 // Either the tab_id or window_id changed (e.g due to session restore), so 981 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 } 982 }
1025 983
1026 // static 984 // static
1027 void SessionsSyncManager::SetSessionTabFromDelegate( 985 void SessionsSyncManager::SetSessionTabFromDelegate(
1028 const SyncedTabDelegate& tab_delegate, 986 const SyncedTabDelegate& tab_delegate,
1029 base::Time mtime, 987 base::Time mtime,
1030 sessions::SessionTab* session_tab) { 988 sessions::SessionTab* session_tab) {
1031 DCHECK(session_tab); 989 DCHECK(session_tab);
1032 session_tab->window_id.set_id(tab_delegate.GetWindowId()); 990 session_tab->window_id.set_id(tab_delegate.GetWindowId());
1033 session_tab->tab_id.set_id(tab_delegate.GetSessionId()); 991 session_tab->tab_id.set_id(tab_delegate.GetSessionId());
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 } 1090 }
1133 1091
1134 // static 1092 // static
1135 std::string SessionsSyncManager::TagHashFromSpecifics( 1093 std::string SessionsSyncManager::TagHashFromSpecifics(
1136 const sync_pb::SessionSpecifics& specifics) { 1094 const sync_pb::SessionSpecifics& specifics) {
1137 return syncer::GenerateSyncableHash(syncer::SESSIONS, 1095 return syncer::GenerateSyncableHash(syncer::SESSIONS,
1138 TagFromSpecifics(specifics)); 1096 TagFromSpecifics(specifics));
1139 } 1097 }
1140 1098
1141 }; // namespace sync_sessions 1099 }; // namespace sync_sessions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698