OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/sync/glue/session_model_associator.h" | 5 #include "chrome/browser/sync/glue/session_model_associator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 for (std::vector<SyncedTabDelegate*>::const_iterator i = tabs.begin(); | 209 for (std::vector<SyncedTabDelegate*>::const_iterator i = tabs.begin(); |
210 i != tabs.end(); | 210 i != tabs.end(); |
211 ++i) { | 211 ++i) { |
212 ReassociateTab(**i); | 212 ReassociateTab(**i); |
213 } | 213 } |
214 if (waiting_for_change_) QuitLoopForTest(); | 214 if (waiting_for_change_) QuitLoopForTest(); |
215 } | 215 } |
216 | 216 |
217 void SessionModelAssociator::ReassociateTab(const SyncedTabDelegate& tab) { | 217 void SessionModelAssociator::ReassociateTab(const SyncedTabDelegate& tab) { |
218 DCHECK(CalledOnValidThread()); | 218 DCHECK(CalledOnValidThread()); |
219 if (!IsValidTab(tab)) | |
220 return; | |
221 | |
222 int64 sync_id; | 219 int64 sync_id; |
223 SessionID::id_type id = tab.GetSessionId(); | 220 SessionID::id_type id = tab.GetSessionId(); |
224 if (tab.IsBeingDestroyed()) { | 221 if (tab.IsBeingDestroyed()) { |
225 // This tab is closing. | 222 // This tab is closing. |
226 TabLinksMap::iterator tab_iter = tab_map_.find(id); | 223 TabLinksMap::iterator tab_iter = tab_map_.find(id); |
227 if (tab_iter == tab_map_.end()) { | 224 if (tab_iter == tab_map_.end()) { |
228 // We aren't tracking this tab (for example, sync setting page). | 225 // We aren't tracking this tab (for example, sync setting page). |
229 return; | 226 return; |
230 } | 227 } |
231 tab_pool_.FreeTabNode(tab_iter->second.sync_id()); | 228 tab_pool_.FreeTabNode(tab_iter->second.sync_id()); |
232 tab_map_.erase(tab_iter); | 229 tab_map_.erase(tab_iter); |
233 return; | 230 return; |
234 } | 231 } |
235 | 232 |
| 233 if (!IsValidTab(tab)) |
| 234 return; |
| 235 |
236 TabLinksMap::const_iterator tablink = tab_map_.find(id); | 236 TabLinksMap::const_iterator tablink = tab_map_.find(id); |
237 if (tablink == tab_map_.end()) { | 237 if (tablink == tab_map_.end()) { |
238 // This is a new tab, get a sync node for it. | 238 // This is a new tab, get a sync node for it. |
239 sync_id = tab_pool_.GetFreeTabNode(); | 239 sync_id = tab_pool_.GetFreeTabNode(); |
| 240 if (sync_id == sync_api::kInvalidId) |
| 241 return; |
240 } else { | 242 } else { |
241 // This tab is already associated with a sync node, reuse it. | 243 // This tab is already associated with a sync node, reuse it. |
242 sync_id = tablink->second.sync_id(); | 244 sync_id = tablink->second.sync_id(); |
243 } | 245 } |
244 Associate(&tab, sync_id); | 246 Associate(&tab, sync_id); |
245 } | 247 } |
246 | 248 |
247 void SessionModelAssociator::Associate(const SyncedTabDelegate* tab, | 249 void SessionModelAssociator::Associate(const SyncedTabDelegate* tab, |
248 int64 sync_id) { | 250 int64 sync_id) { |
249 DCHECK(CalledOnValidThread()); | 251 DCHECK(CalledOnValidThread()); |
250 SessionID::id_type session_id = tab->GetSessionId(); | 252 SessionID::id_type session_id = tab->GetSessionId(); |
251 const SyncedWindowDelegate* window = | 253 const SyncedWindowDelegate* window = |
252 SyncedWindowDelegate::FindSyncedWindowDelegateWithId( | 254 SyncedWindowDelegate::FindSyncedWindowDelegateWithId( |
253 tab->GetWindowId()); | 255 tab->GetWindowId()); |
254 if (!window) { // Can happen for weird things like developer console. | 256 DCHECK(window); |
255 tab_pool_.FreeTabNode(sync_id); | |
256 return; | |
257 } | |
258 | 257 |
259 TabLinks t(sync_id, tab); | 258 TabLinks t(sync_id, tab); |
260 tab_map_[session_id] = t; | 259 tab_map_[session_id] = t; |
261 | 260 |
262 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 261 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
263 WriteTabContentsToSyncModel(*window, *tab, sync_id, &trans); | 262 WriteTabContentsToSyncModel(*window, *tab, sync_id, &trans); |
264 } | 263 } |
265 | 264 |
266 bool SessionModelAssociator::WriteTabContentsToSyncModel( | 265 bool SessionModelAssociator::WriteTabContentsToSyncModel( |
267 const SyncedWindowDelegate& window, | 266 const SyncedWindowDelegate& window, |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 sync_api::ReadNode root(&trans); | 423 sync_api::ReadNode root(&trans); |
425 if (!root.InitByTagLookup(kSessionsTag)) { | 424 if (!root.InitByTagLookup(kSessionsTag)) { |
426 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); | 425 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); |
427 return false; | 426 return false; |
428 } | 427 } |
429 | 428 |
430 // Make sure we have a machine tag. | 429 // Make sure we have a machine tag. |
431 if (current_machine_tag_.empty()) | 430 if (current_machine_tag_.empty()) |
432 InitializeCurrentMachineTag(&trans); | 431 InitializeCurrentMachineTag(&trans); |
433 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); | 432 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); |
434 UpdateAssociationsFromSyncModel(root, &trans); | 433 if (!UpdateAssociationsFromSyncModel(root, &trans)) { |
| 434 error->Reset(FROM_HERE, |
| 435 "Failed to update associations from sync", |
| 436 model_type()); |
| 437 return false; |
| 438 } |
435 | 439 |
436 if (local_session_syncid_ == sync_api::kInvalidId) { | 440 if (local_session_syncid_ == sync_api::kInvalidId) { |
437 // The sync db didn't have a header node for us, we need to create one. | 441 // The sync db didn't have a header node for us, we need to create one. |
438 sync_api::WriteNode write_node(&trans); | 442 sync_api::WriteNode write_node(&trans); |
439 if (!write_node.InitUniqueByCreation(syncable::SESSIONS, root, | 443 if (!write_node.InitUniqueByCreation(syncable::SESSIONS, root, |
440 current_machine_tag_)) { | 444 current_machine_tag_)) { |
441 error->Reset(FROM_HERE, | 445 error->Reset(FROM_HERE, |
442 "Failed to create sessions header sync node.", | 446 "Failed to create sessions header sync node.", |
443 model_type()); | 447 model_type()); |
444 return false; | 448 return false; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 const sync_pb::SessionSpecifics& specifics = | 510 const sync_pb::SessionSpecifics& specifics = |
507 sync_node.GetSessionSpecifics(); | 511 sync_node.GetSessionSpecifics(); |
508 const int64 modification_time = sync_node.GetModificationTime(); | 512 const int64 modification_time = sync_node.GetModificationTime(); |
509 if (specifics.session_tag() != GetCurrentMachineTag()) { | 513 if (specifics.session_tag() != GetCurrentMachineTag()) { |
510 if (!AssociateForeignSpecifics(specifics, modification_time)) { | 514 if (!AssociateForeignSpecifics(specifics, modification_time)) { |
511 return false; | 515 return false; |
512 } | 516 } |
513 } else if (id != local_session_syncid_) { | 517 } else if (id != local_session_syncid_) { |
514 // This is previously stored local session information. | 518 // This is previously stored local session information. |
515 if (specifics.has_header()) { | 519 if (specifics.has_header()) { |
516 DCHECK_EQ(sync_api::kInvalidId, local_session_syncid_); | 520 if (sync_api::kInvalidId != local_session_syncid_) |
| 521 return false; |
517 | 522 |
518 // This is our previous header node, reuse it. | 523 // This is our previous header node, reuse it. |
519 local_session_syncid_ = id; | 524 local_session_syncid_ = id; |
520 } else { | 525 } else { |
521 DCHECK(specifics.has_tab()); | 526 if (!specifics.has_tab()) |
| 527 return false; |
522 | 528 |
523 // This is a tab node. We want to track these to reuse them in our free | 529 // This is a tab node. We want to track these to reuse them in our free |
524 // tab node pool. They will be overwritten eventually, so need to do | 530 // tab node pool. They will be overwritten eventually, so need to do |
525 // anything else. | 531 // anything else. |
526 tab_pool_.AddTabNode(id); | 532 tab_pool_.AddTabNode(id); |
527 } | 533 } |
528 } | 534 } |
529 | 535 |
530 id = sync_node.GetSuccessorId(); | 536 id = sync_node.GetSuccessorId(); |
531 } | 537 } |
532 | 538 |
533 // After updating from sync model all tabid's should be free. | 539 // After updating from sync model all tabid's should be free. |
534 DCHECK(tab_pool_.full()); | 540 if (!tab_pool_.full()) |
| 541 return false; |
535 | 542 |
536 return true; | 543 return true; |
537 } | 544 } |
538 | 545 |
539 bool SessionModelAssociator::AssociateForeignSpecifics( | 546 bool SessionModelAssociator::AssociateForeignSpecifics( |
540 const sync_pb::SessionSpecifics& specifics, | 547 const sync_pb::SessionSpecifics& specifics, |
541 const int64 modification_time) { | 548 const int64 modification_time) { |
542 DCHECK(CalledOnValidThread()); | 549 DCHECK(CalledOnValidThread()); |
543 std::string foreign_session_tag = specifics.session_tag(); | 550 std::string foreign_session_tag = specifics.session_tag(); |
544 DCHECK(foreign_session_tag != GetCurrentMachineTag() || setup_for_test_); | 551 if (foreign_session_tag == GetCurrentMachineTag() && !setup_for_test_) |
| 552 return false; |
545 | 553 |
546 if (specifics.has_header()) { | 554 if (specifics.has_header()) { |
547 // Read in the header data for this foreign session. | 555 // Read in the header data for this foreign session. |
548 // Header data contains window information and ordered tab id's for each | 556 // Header data contains window information and ordered tab id's for each |
549 // window. | 557 // window. |
550 | 558 |
551 // Load (or create) the SyncedSession object for this client. | 559 // Load (or create) the SyncedSession object for this client. |
552 SyncedSession* foreign_session = | 560 SyncedSession* foreign_session = |
553 synced_session_tracker_.GetSession(foreign_session_tag); | 561 synced_session_tracker_.GetSession(foreign_session_tag); |
554 | 562 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 } | 769 } |
762 | 770 |
763 int64 SessionModelAssociator::TabNodePool::GetFreeTabNode() { | 771 int64 SessionModelAssociator::TabNodePool::GetFreeTabNode() { |
764 DCHECK_GT(machine_tag_.length(), 0U); | 772 DCHECK_GT(machine_tag_.length(), 0U); |
765 if (tab_pool_fp_ == -1) { | 773 if (tab_pool_fp_ == -1) { |
766 // Tab pool has no free nodes, allocate new one. | 774 // Tab pool has no free nodes, allocate new one. |
767 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 775 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
768 sync_api::ReadNode root(&trans); | 776 sync_api::ReadNode root(&trans); |
769 if (!root.InitByTagLookup(kSessionsTag)) { | 777 if (!root.InitByTagLookup(kSessionsTag)) { |
770 LOG(ERROR) << kNoSessionsFolderError; | 778 LOG(ERROR) << kNoSessionsFolderError; |
771 return 0; | 779 return sync_api::kInvalidId; |
772 } | 780 } |
773 size_t tab_node_id = tab_syncid_pool_.size(); | 781 size_t tab_node_id = tab_syncid_pool_.size(); |
774 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); | 782 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); |
775 sync_api::WriteNode tab_node(&trans); | 783 sync_api::WriteNode tab_node(&trans); |
776 if (!tab_node.InitUniqueByCreation(syncable::SESSIONS, root, | 784 if (!tab_node.InitUniqueByCreation(syncable::SESSIONS, root, |
777 tab_node_tag)) { | 785 tab_node_tag)) { |
778 LOG(ERROR) << "Could not create new node!"; | 786 LOG(ERROR) << "Could not create new node with tag " |
779 return -1; | 787 << tab_node_tag << "!"; |
| 788 return sync_api::kInvalidId; |
780 } | 789 } |
781 tab_node.SetTitle(UTF8ToWide(tab_node_tag)); | 790 tab_node.SetTitle(UTF8ToWide(tab_node_tag)); |
782 | 791 |
783 // Grow the pool by 1 since we created a new node. We don't actually need | 792 // Grow the pool by 1 since we created a new node. We don't actually need |
784 // to put the node's id in the pool now, since the pool is still empty. | 793 // to put the node's id in the pool now, since the pool is still empty. |
785 // The id will be added when that tab is closed and the node is freed. | 794 // The id will be added when that tab is closed and the node is freed. |
786 tab_syncid_pool_.resize(tab_node_id + 1); | 795 tab_syncid_pool_.resize(tab_node_id + 1); |
787 VLOG(1) << "Adding sync node " << tab_node.GetId() << " to tab syncid pool"; | 796 VLOG(1) << "Adding sync node " << tab_node.GetId() << " to tab syncid pool"; |
788 return tab_node.GetId(); | 797 return tab_node.GetId(); |
789 } else { | 798 } else { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 } | 850 } |
842 if (num_populated == 0) | 851 if (num_populated == 0) |
843 return true; | 852 return true; |
844 return false; | 853 return false; |
845 } | 854 } |
846 | 855 |
847 // Valid local tab? | 856 // Valid local tab? |
848 bool SessionModelAssociator::IsValidTab(const SyncedTabDelegate& tab) { | 857 bool SessionModelAssociator::IsValidTab(const SyncedTabDelegate& tab) { |
849 DCHECK(CalledOnValidThread()); | 858 DCHECK(CalledOnValidThread()); |
850 if ((tab.profile() == sync_service_->profile() || | 859 if ((tab.profile() == sync_service_->profile() || |
851 sync_service_->profile() == NULL)) { | 860 sync_service_->profile() == NULL)) { // For tests. |
| 861 const SyncedWindowDelegate* window = |
| 862 SyncedWindowDelegate::FindSyncedWindowDelegateWithId( |
| 863 tab.GetWindowId()); |
| 864 if (!window) |
| 865 return false; |
852 const NavigationEntry* entry = tab.GetActiveEntry(); | 866 const NavigationEntry* entry = tab.GetActiveEntry(); |
853 if (!entry) | 867 if (!entry) |
854 return false; | 868 return false; |
855 if (entry->virtual_url().is_valid() && | 869 if (entry->virtual_url().is_valid() && |
856 (entry->virtual_url() != GURL(chrome::kChromeUINewTabURL) || | 870 (entry->virtual_url() != GURL(chrome::kChromeUINewTabURL) || |
857 tab.GetEntryCount() > 1)) { | 871 tab.GetEntryCount() > 1)) { |
858 return true; | 872 return true; |
859 } | 873 } |
860 } | 874 } |
861 return false; | 875 return false; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 } | 1004 } |
991 } | 1005 } |
992 | 1006 |
993 bool SessionModelAssociator::SyncLocalWindowToSyncModel( | 1007 bool SessionModelAssociator::SyncLocalWindowToSyncModel( |
994 const SessionWindow& window) { | 1008 const SessionWindow& window) { |
995 DCHECK(CalledOnValidThread()); | 1009 DCHECK(CalledOnValidThread()); |
996 DCHECK(tab_map_.empty()); | 1010 DCHECK(tab_map_.empty()); |
997 for (size_t i = 0; i < window.tabs.size(); ++i) { | 1011 for (size_t i = 0; i < window.tabs.size(); ++i) { |
998 SessionTab* tab = window.tabs[i]; | 1012 SessionTab* tab = window.tabs[i]; |
999 int64 id = tab_pool_.GetFreeTabNode(); | 1013 int64 id = tab_pool_.GetFreeTabNode(); |
1000 if (id == -1) { | 1014 if (id == sync_api::kInvalidId) { |
1001 LOG(ERROR) << "Failed to find/generate free sync node for tab."; | 1015 LOG(ERROR) << "Failed to find/generate free sync node for tab."; |
1002 return false; | 1016 return false; |
1003 } | 1017 } |
1004 | 1018 |
1005 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 1019 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
1006 if (!WriteSessionTabToSyncModel(*tab, id, &trans)) { | 1020 if (!WriteSessionTabToSyncModel(*tab, id, &trans)) { |
1007 return false; | 1021 return false; |
1008 } | 1022 } |
1009 | 1023 |
1010 TabLinks t(id, tab); | 1024 TabLinks t(id, tab); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 bool SessionModelAssociator::CryptoReadyIfNecessary() { | 1070 bool SessionModelAssociator::CryptoReadyIfNecessary() { |
1057 // We only access the cryptographer while holding a transaction. | 1071 // We only access the cryptographer while holding a transaction. |
1058 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 1072 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
1059 syncable::ModelTypeSet encrypted_types; | 1073 syncable::ModelTypeSet encrypted_types; |
1060 encrypted_types = sync_api::GetEncryptedTypes(&trans); | 1074 encrypted_types = sync_api::GetEncryptedTypes(&trans); |
1061 return encrypted_types.count(syncable::SESSIONS) == 0 || | 1075 return encrypted_types.count(syncable::SESSIONS) == 0 || |
1062 sync_service_->IsCryptographerReady(&trans); | 1076 sync_service_->IsCryptographerReady(&trans); |
1063 } | 1077 } |
1064 | 1078 |
1065 } // namespace browser_sync | 1079 } // namespace browser_sync |
OLD | NEW |