OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 return internal::IsTabletUi() ? | 75 return internal::IsTabletUi() ? |
76 sync_pb::SessionHeader_DeviceType_TYPE_TABLET : | 76 sync_pb::SessionHeader_DeviceType_TYPE_TABLET : |
77 sync_pb::SessionHeader_DeviceType_TYPE_PHONE; | 77 sync_pb::SessionHeader_DeviceType_TYPE_PHONE; |
78 #else | 78 #else |
79 return sync_pb::SessionHeader_DeviceType_TYPE_OTHER; | 79 return sync_pb::SessionHeader_DeviceType_TYPE_OTHER; |
80 #endif | 80 #endif |
81 } | 81 } |
82 | 82 |
83 } // namespace | 83 } // namespace |
84 | 84 |
85 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service) | 85 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service, |
| 86 DataTypeErrorHandler* error_handler) |
86 : tab_pool_(sync_service), | 87 : tab_pool_(sync_service), |
87 local_session_syncid_(sync_api::kInvalidId), | 88 local_session_syncid_(sync_api::kInvalidId), |
88 sync_service_(sync_service), | 89 sync_service_(sync_service), |
89 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), | 90 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), |
90 setup_for_test_(false), | 91 setup_for_test_(false), |
91 waiting_for_change_(false), | 92 waiting_for_change_(false), |
92 ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)), | 93 ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)), |
93 profile_(sync_service->profile()), | 94 profile_(sync_service->profile()), |
94 pref_service_(profile_->GetPrefs()) { | 95 pref_service_(profile_->GetPrefs()), |
| 96 error_handler_(error_handler) { |
95 DCHECK(CalledOnValidThread()); | 97 DCHECK(CalledOnValidThread()); |
96 DCHECK(sync_service_); | 98 DCHECK(sync_service_); |
97 DCHECK(profile_); | 99 DCHECK(profile_); |
98 if (pref_service_->FindPreference(kSyncSessionsGUID) == NULL) { | 100 if (pref_service_->FindPreference(kSyncSessionsGUID) == NULL) { |
99 pref_service_->RegisterStringPref(kSyncSessionsGUID, | 101 pref_service_->RegisterStringPref(kSyncSessionsGUID, |
100 std::string(), | 102 std::string(), |
101 PrefService::UNSYNCABLE_PREF); | 103 PrefService::UNSYNCABLE_PREF); |
102 } | 104 } |
103 } | 105 } |
104 | 106 |
105 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service, | 107 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service, |
106 bool setup_for_test) | 108 bool setup_for_test) |
107 : tab_pool_(sync_service), | 109 : tab_pool_(sync_service), |
108 local_session_syncid_(sync_api::kInvalidId), | 110 local_session_syncid_(sync_api::kInvalidId), |
109 sync_service_(sync_service), | 111 sync_service_(sync_service), |
110 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), | 112 stale_session_threshold_days_(kDefaultStaleSessionThresholdDays), |
111 setup_for_test_(setup_for_test), | 113 setup_for_test_(setup_for_test), |
112 waiting_for_change_(false), | 114 waiting_for_change_(false), |
113 ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)), | 115 ALLOW_THIS_IN_INITIALIZER_LIST(test_weak_factory_(this)), |
114 profile_(sync_service->profile()), | 116 profile_(sync_service->profile()), |
115 pref_service_(NULL) { | 117 pref_service_(NULL), |
| 118 error_handler_(NULL) { |
116 DCHECK(CalledOnValidThread()); | 119 DCHECK(CalledOnValidThread()); |
117 DCHECK(sync_service_); | 120 DCHECK(sync_service_); |
118 DCHECK(profile_); | 121 DCHECK(profile_); |
119 DCHECK(setup_for_test); | 122 DCHECK(setup_for_test); |
120 } | 123 } |
121 | 124 |
122 SessionModelAssociator::~SessionModelAssociator() { | 125 SessionModelAssociator::~SessionModelAssociator() { |
123 DCHECK(CalledOnValidThread()); | 126 DCHECK(CalledOnValidThread()); |
124 } | 127 } |
125 | 128 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 &synced_session_tracker_); | 261 &synced_session_tracker_); |
259 } | 262 } |
260 } | 263 } |
261 } | 264 } |
262 // Free memory for closed windows and tabs. | 265 // Free memory for closed windows and tabs. |
263 synced_session_tracker_.CleanupSession(local_tag); | 266 synced_session_tracker_.CleanupSession(local_tag); |
264 | 267 |
265 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 268 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
266 sync_api::WriteNode header_node(&trans); | 269 sync_api::WriteNode header_node(&trans); |
267 if (!header_node.InitByIdLookup(local_session_syncid_)) { | 270 if (!header_node.InitByIdLookup(local_session_syncid_)) { |
268 error->Reset(FROM_HERE, | 271 if (error) { |
269 "Failed to load local session header node.", | 272 *error = error_handler_->CreateAndUploadError( |
270 model_type()); | 273 FROM_HERE, |
| 274 "Failed to load local session header node.", |
| 275 model_type()); |
| 276 } |
271 return false; | 277 return false; |
272 } | 278 } |
273 header_node.SetSessionSpecifics(specifics); | 279 header_node.SetSessionSpecifics(specifics); |
274 if (waiting_for_change_) QuitLoopForSubtleTesting(); | 280 if (waiting_for_change_) QuitLoopForSubtleTesting(); |
275 return true; | 281 return true; |
276 } | 282 } |
277 | 283 |
278 // Static. | 284 // Static. |
279 bool SessionModelAssociator::ShouldSyncWindow( | 285 bool SessionModelAssociator::ShouldSyncWindow( |
280 const SyncedWindowDelegate* window) { | 286 const SyncedWindowDelegate* window) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 } | 321 } |
316 | 322 |
317 if (!ShouldSyncTab(tab)) | 323 if (!ShouldSyncTab(tab)) |
318 return true; | 324 return true; |
319 | 325 |
320 TabLinksMap::const_iterator tablink = tab_map_.find(id); | 326 TabLinksMap::const_iterator tablink = tab_map_.find(id); |
321 if (tablink == tab_map_.end()) { | 327 if (tablink == tab_map_.end()) { |
322 // This is a new tab, get a sync node for it. | 328 // This is a new tab, get a sync node for it. |
323 sync_id = tab_pool_.GetFreeTabNode(); | 329 sync_id = tab_pool_.GetFreeTabNode(); |
324 if (sync_id == sync_api::kInvalidId) { | 330 if (sync_id == sync_api::kInvalidId) { |
325 error->Reset(FROM_HERE, | 331 if (error) { |
326 "Received invalid tab node from tab pool. Reassociation " | 332 *error = error_handler_->CreateAndUploadError( |
327 "needed.", | 333 FROM_HERE, |
328 model_type()); | 334 "Received invalid tab node from tab pool.", |
| 335 model_type()); |
| 336 } |
329 return false; | 337 return false; |
330 } | 338 } |
331 } else { | 339 } else { |
332 // This tab is already associated with a sync node, reuse it. | 340 // This tab is already associated with a sync node, reuse it. |
333 sync_id = tablink->second.sync_id(); | 341 sync_id = tablink->second.sync_id(); |
334 } | 342 } |
335 | 343 |
336 DVLOG(1) << "Reloading tab " << id << " from window " << tab.GetWindowId(); | 344 DVLOG(1) << "Reloading tab " << id << " from window " << tab.GetWindowId(); |
337 const SyncedWindowDelegate* window = | 345 const SyncedWindowDelegate* window = |
338 SyncedWindowDelegate::FindSyncedWindowDelegateWithId( | 346 SyncedWindowDelegate::FindSyncedWindowDelegateWithId( |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 synced_session_tracker_.GetSession(GetCurrentMachineTag())->modified_time = | 399 synced_session_tracker_.GetSession(GetCurrentMachineTag())->modified_time = |
392 base::Time::Now(); | 400 base::Time::Now(); |
393 PopulateSessionTabFromSpecifics(*tab_s, | 401 PopulateSessionTabFromSpecifics(*tab_s, |
394 base::Time::Now(), | 402 base::Time::Now(), |
395 session_tab); | 403 session_tab); |
396 | 404 |
397 // Write into the actual sync model. | 405 // Write into the actual sync model. |
398 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 406 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
399 sync_api::WriteNode tab_node(&trans); | 407 sync_api::WriteNode tab_node(&trans); |
400 if (!tab_node.InitByIdLookup(sync_id)) { | 408 if (!tab_node.InitByIdLookup(sync_id)) { |
401 error->Reset(FROM_HERE, "Failed to look up local tab node", model_type()); | 409 if (error) { |
| 410 *error = error_handler_->CreateAndUploadError( |
| 411 FROM_HERE, |
| 412 "Failed to look up local tab node", |
| 413 model_type()); |
| 414 } |
402 return false; | 415 return false; |
403 } | 416 } |
404 tab_node.SetSessionSpecifics(session_s); | 417 tab_node.SetSessionSpecifics(session_s); |
405 return true; | 418 return true; |
406 } | 419 } |
407 | 420 |
408 // Static | 421 // Static |
409 // TODO(zea): perhaps sync state (scroll position, form entries, etc.) as well? | 422 // TODO(zea): perhaps sync state (scroll position, form entries, etc.) as well? |
410 // See http://crbug.com/67068. | 423 // See http://crbug.com/67068. |
411 void SessionModelAssociator::PopulateSessionSpecificsNavigation( | 424 void SessionModelAssociator::PopulateSessionSpecificsNavigation( |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 void SessionModelAssociator::Associate(const SyncedTabDelegate* tab, | 499 void SessionModelAssociator::Associate(const SyncedTabDelegate* tab, |
487 int64 sync_id) { | 500 int64 sync_id) { |
488 NOTIMPLEMENTED(); | 501 NOTIMPLEMENTED(); |
489 } | 502 } |
490 | 503 |
491 void SessionModelAssociator::Disassociate(int64 sync_id) { | 504 void SessionModelAssociator::Disassociate(int64 sync_id) { |
492 DCHECK(CalledOnValidThread()); | 505 DCHECK(CalledOnValidThread()); |
493 NOTIMPLEMENTED(); | 506 NOTIMPLEMENTED(); |
494 } | 507 } |
495 | 508 |
496 bool SessionModelAssociator::AssociateModels(SyncError* error) { | 509 SyncError SessionModelAssociator::AssociateModels() { |
497 DCHECK(CalledOnValidThread()); | 510 DCHECK(CalledOnValidThread()); |
| 511 SyncError error; |
498 | 512 |
499 // Ensure that we disassociated properly, otherwise memory might leak. | 513 // Ensure that we disassociated properly, otherwise memory might leak. |
500 DCHECK(synced_session_tracker_.Empty()); | 514 DCHECK(synced_session_tracker_.Empty()); |
501 DCHECK_EQ(0U, tab_pool_.capacity()); | 515 DCHECK_EQ(0U, tab_pool_.capacity()); |
502 | 516 |
503 local_session_syncid_ = sync_api::kInvalidId; | 517 local_session_syncid_ = sync_api::kInvalidId; |
504 | 518 |
505 // Read any available foreign sessions and load any session data we may have. | 519 // Read any available foreign sessions and load any session data we may have. |
506 // If we don't have any local session data in the db, create a header node. | 520 // If we don't have any local session data in the db, create a header node. |
507 { | 521 { |
508 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 522 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
509 | 523 |
510 sync_api::ReadNode root(&trans); | 524 sync_api::ReadNode root(&trans); |
511 if (!root.InitByTagLookup(syncable::ModelTypeToRootTag(model_type()))) { | 525 if (!root.InitByTagLookup(syncable::ModelTypeToRootTag(model_type()))) { |
512 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); | 526 return error_handler_->CreateAndUploadError( |
513 return false; | 527 FROM_HERE, |
| 528 kNoSessionsFolderError, |
| 529 model_type()); |
514 } | 530 } |
515 | 531 |
516 // Make sure we have a machine tag. | 532 // Make sure we have a machine tag. |
517 if (current_machine_tag_.empty()) { | 533 if (current_machine_tag_.empty()) { |
518 InitializeCurrentMachineTag(&trans); | 534 InitializeCurrentMachineTag(&trans); |
519 // The session name is retrieved asynchronously so it might not come back | 535 // The session name is retrieved asynchronously so it might not come back |
520 // for the writing of the session. However, we write to the session often | 536 // for the writing of the session. However, we write to the session often |
521 // enough (on every navigation) that we'll pick it up quickly. | 537 // enough (on every navigation) that we'll pick it up quickly. |
522 InitializeCurrentSessionName(); | 538 InitializeCurrentSessionName(); |
523 } | 539 } |
524 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); | 540 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); |
525 if (!UpdateAssociationsFromSyncModel(root, &trans, error)) | 541 if (!UpdateAssociationsFromSyncModel(root, &trans, &error)) { |
526 return false; | 542 DCHECK(error.IsSet()); |
| 543 return error; |
| 544 } |
527 | 545 |
528 if (local_session_syncid_ == sync_api::kInvalidId) { | 546 if (local_session_syncid_ == sync_api::kInvalidId) { |
529 // The sync db didn't have a header node for us, we need to create one. | 547 // The sync db didn't have a header node for us, we need to create one. |
530 sync_api::WriteNode write_node(&trans); | 548 sync_api::WriteNode write_node(&trans); |
531 if (!write_node.InitUniqueByCreation(SESSIONS, root, | 549 if (!write_node.InitUniqueByCreation(SESSIONS, root, |
532 current_machine_tag_)) { | 550 current_machine_tag_)) { |
533 error->Reset(FROM_HERE, | 551 return error_handler_->CreateAndUploadError( |
534 "Failed to create sessions header sync node.", | 552 FROM_HERE, |
535 model_type()); | 553 "Failed to create sessions header sync node.", |
536 return false; | 554 model_type()); |
537 } | 555 } |
538 write_node.SetTitle(UTF8ToWide(current_machine_tag_)); | 556 write_node.SetTitle(UTF8ToWide(current_machine_tag_)); |
539 local_session_syncid_ = write_node.GetId(); | 557 local_session_syncid_ = write_node.GetId(); |
540 } | 558 } |
541 } | 559 } |
542 | 560 |
543 // Check if anything has changed on the client side. | 561 // Check if anything has changed on the client side. |
544 if (!UpdateSyncModelDataFromClient(error)) | 562 if (!UpdateSyncModelDataFromClient(&error)) { |
545 return false; | 563 DCHECK(error.IsSet()); |
| 564 return error; |
| 565 } |
546 | 566 |
547 DVLOG(1) << "Session models associated."; | 567 DVLOG(1) << "Session models associated."; |
548 return true; | 568 DCHECK(!error.IsSet()); |
| 569 return error; |
549 } | 570 } |
550 | 571 |
551 bool SessionModelAssociator::DisassociateModels(SyncError* error) { | 572 SyncError SessionModelAssociator::DisassociateModels() { |
552 DCHECK(CalledOnValidThread()); | 573 DCHECK(CalledOnValidThread()); |
553 DVLOG(1) << "Disassociating local session " << GetCurrentMachineTag(); | 574 DVLOG(1) << "Disassociating local session " << GetCurrentMachineTag(); |
554 synced_session_tracker_.Clear(); | 575 synced_session_tracker_.Clear(); |
555 tab_map_.clear(); | 576 tab_map_.clear(); |
556 tab_pool_.clear(); | 577 tab_pool_.clear(); |
557 local_session_syncid_ = sync_api::kInvalidId; | 578 local_session_syncid_ = sync_api::kInvalidId; |
558 current_machine_tag_ = ""; | 579 current_machine_tag_ = ""; |
559 current_session_name_ = ""; | 580 current_session_name_ = ""; |
560 | 581 |
561 // There is no local model stored with which to disassociate, just notify | 582 // There is no local model stored with which to disassociate, just notify |
562 // foreign session handlers. | 583 // foreign session handlers. |
563 content::NotificationService::current()->Notify( | 584 content::NotificationService::current()->Notify( |
564 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED, | 585 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED, |
565 content::Source<Profile>(sync_service_->profile()), | 586 content::Source<Profile>(sync_service_->profile()), |
566 content::NotificationService::NoDetails()); | 587 content::NotificationService::NoDetails()); |
567 return true; | 588 return SyncError(); |
568 } | 589 } |
569 | 590 |
570 void SessionModelAssociator::InitializeCurrentMachineTag( | 591 void SessionModelAssociator::InitializeCurrentMachineTag( |
571 sync_api::WriteTransaction* trans) { | 592 sync_api::WriteTransaction* trans) { |
572 DCHECK(CalledOnValidThread()); | 593 DCHECK(CalledOnValidThread()); |
573 DCHECK(current_machine_tag_.empty()); | 594 DCHECK(current_machine_tag_.empty()); |
574 std::string persisted_guid; | 595 std::string persisted_guid; |
575 if (pref_service_) | 596 if (pref_service_) |
576 persisted_guid = pref_service_->GetString(kSyncSessionsGUID); | 597 persisted_guid = pref_service_->GetString(kSyncSessionsGUID); |
577 if (!persisted_guid.empty()) { | 598 if (!persisted_guid.empty()) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 SyncError* error) { | 637 SyncError* error) { |
617 DCHECK(CalledOnValidThread()); | 638 DCHECK(CalledOnValidThread()); |
618 DCHECK(tab_pool_.empty()); | 639 DCHECK(tab_pool_.empty()); |
619 DCHECK_EQ(local_session_syncid_, sync_api::kInvalidId); | 640 DCHECK_EQ(local_session_syncid_, sync_api::kInvalidId); |
620 | 641 |
621 // Iterate through the nodes and associate any foreign sessions. | 642 // Iterate through the nodes and associate any foreign sessions. |
622 int64 id = root.GetFirstChildId(); | 643 int64 id = root.GetFirstChildId(); |
623 while (id != sync_api::kInvalidId) { | 644 while (id != sync_api::kInvalidId) { |
624 sync_api::WriteNode sync_node(trans); | 645 sync_api::WriteNode sync_node(trans); |
625 if (!sync_node.InitByIdLookup(id)) { | 646 if (!sync_node.InitByIdLookup(id)) { |
626 error->Reset(FROM_HERE, "Failed to load sync node", model_type()); | 647 if (error) { |
| 648 *error = error_handler_->CreateAndUploadError( |
| 649 FROM_HERE, |
| 650 "Failed to load sync node", |
| 651 model_type()); |
| 652 } |
627 return false; | 653 return false; |
628 } | 654 } |
629 int64 next_id = sync_node.GetSuccessorId(); | 655 int64 next_id = sync_node.GetSuccessorId(); |
630 | 656 |
631 const sync_pb::SessionSpecifics& specifics = | 657 const sync_pb::SessionSpecifics& specifics = |
632 sync_node.GetSessionSpecifics(); | 658 sync_node.GetSessionSpecifics(); |
633 const base::Time& modification_time = sync_node.GetModificationTime(); | 659 const base::Time& modification_time = sync_node.GetModificationTime(); |
634 if (specifics.session_tag() != GetCurrentMachineTag()) { | 660 if (specifics.session_tag() != GetCurrentMachineTag()) { |
635 AssociateForeignSpecifics(specifics, modification_time); | 661 AssociateForeignSpecifics(specifics, modification_time); |
636 } else { | 662 } else { |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 bool SessionModelAssociator::CryptoReadyIfNecessary() { | 1184 bool SessionModelAssociator::CryptoReadyIfNecessary() { |
1159 // We only access the cryptographer while holding a transaction. | 1185 // We only access the cryptographer while holding a transaction. |
1160 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 1186 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
1161 const syncable::ModelTypeSet encrypted_types = | 1187 const syncable::ModelTypeSet encrypted_types = |
1162 sync_api::GetEncryptedTypes(&trans); | 1188 sync_api::GetEncryptedTypes(&trans); |
1163 return !encrypted_types.Has(SESSIONS) || | 1189 return !encrypted_types.Has(SESSIONS) || |
1164 sync_service_->IsCryptographerReady(&trans); | 1190 sync_service_->IsCryptographerReady(&trans); |
1165 } | 1191 } |
1166 | 1192 |
1167 } // namespace browser_sync | 1193 } // namespace browser_sync |
OLD | NEW |