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

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

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

Powered by Google App Engine
This is Rietveld 408576698