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 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/sys_info.h" |
12 #include "base/tracked.h" | 13 #include "base/tracked.h" |
13 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/sessions/session_service_factory.h" | 15 #include "chrome/browser/sessions/session_service_factory.h" |
15 #include "chrome/browser/sync/api/sync_error.h" | 16 #include "chrome/browser/sync/api/sync_error.h" |
16 #include "chrome/browser/sync/glue/synced_tab_delegate.h" | 17 #include "chrome/browser/sync/glue/synced_tab_delegate.h" |
17 #include "chrome/browser/sync/glue/synced_window_delegate.h" | 18 #include "chrome/browser/sync/glue/synced_window_delegate.h" |
18 #include "chrome/browser/sync/internal_api/read_node.h" | 19 #include "chrome/browser/sync/internal_api/read_node.h" |
19 #include "chrome/browser/sync/internal_api/read_transaction.h" | 20 #include "chrome/browser/sync/internal_api/read_transaction.h" |
20 #include "chrome/browser/sync/internal_api/write_node.h" | 21 #include "chrome/browser/sync/internal_api/write_node.h" |
21 #include "chrome/browser/sync/internal_api/write_transaction.h" | 22 #include "chrome/browser/sync/internal_api/write_transaction.h" |
22 #include "chrome/browser/sync/profile_sync_service.h" | 23 #include "chrome/browser/sync/profile_sync_service.h" |
23 #include "chrome/browser/sync/syncable/syncable.h" | 24 #include "chrome/browser/sync/syncable/syncable.h" |
24 #include "chrome/common/chrome_notification_types.h" | 25 #include "chrome/common/chrome_notification_types.h" |
25 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
26 #include "content/browser/tab_contents/navigation_entry.h" | 27 #include "content/browser/tab_contents/navigation_entry.h" |
27 #include "content/common/notification_details.h" | 28 #include "content/common/notification_details.h" |
28 #include "content/common/notification_service.h" | 29 #include "content/common/notification_service.h" |
| 30 #if defined(OS_LINUX) |
| 31 #include "base/linux_util.h" |
| 32 #elif defined(OS_MACOSX) |
| 33 #include "base/mac/mac_util.h" |
| 34 #elif defined(OS_WIN) |
| 35 #include "base/win/win_util.h" |
| 36 #endif |
29 | 37 |
30 namespace browser_sync { | 38 namespace browser_sync { |
31 | 39 |
32 namespace { | 40 namespace { |
33 static const char kNoSessionsFolderError[] = | 41 static const char kNoSessionsFolderError[] = |
34 "Server did not create the top-level sessions node. We " | 42 "Server did not create the top-level sessions node. We " |
35 "might be running against an out-of-date server."; | 43 "might be running against an out-of-date server."; |
36 | 44 |
37 // The maximum number of navigations in each direction we care to sync. | 45 // The maximum number of navigations in each direction we care to sync. |
38 static const int max_sync_navigation_count = 6; | 46 static const int max_sync_navigation_count = 6; |
39 } // namespace | 47 } // namespace |
40 | 48 |
| 49 std::string SessionModelAssociator::current_machine_name_ = ""; |
| 50 |
41 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service) | 51 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service) |
42 : tab_pool_(sync_service), | 52 : tab_pool_(sync_service), |
43 local_session_syncid_(sync_api::kInvalidId), | 53 local_session_syncid_(sync_api::kInvalidId), |
44 sync_service_(sync_service), | 54 sync_service_(sync_service), |
45 setup_for_test_(false), | 55 setup_for_test_(false), |
46 waiting_for_change_(false), | 56 waiting_for_change_(false), |
47 ALLOW_THIS_IN_INITIALIZER_LIST(test_method_factory_(this)) { | 57 ALLOW_THIS_IN_INITIALIZER_LIST(test_method_factory_(this)) { |
48 DCHECK(CalledOnValidThread()); | 58 DCHECK(CalledOnValidThread()); |
49 DCHECK(sync_service_); | 59 DCHECK(sync_service_); |
50 } | 60 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 126 } |
117 | 127 |
118 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) { | 128 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) { |
119 DCHECK(CalledOnValidThread()); | 129 DCHECK(CalledOnValidThread()); |
120 std::string local_tag = GetCurrentMachineTag(); | 130 std::string local_tag = GetCurrentMachineTag(); |
121 sync_pb::SessionSpecifics specifics; | 131 sync_pb::SessionSpecifics specifics; |
122 specifics.set_session_tag(local_tag); | 132 specifics.set_session_tag(local_tag); |
123 sync_pb::SessionHeader* header_s = specifics.mutable_header(); | 133 sync_pb::SessionHeader* header_s = specifics.mutable_header(); |
124 SyncedSession* current_session = | 134 SyncedSession* current_session = |
125 synced_session_tracker_.GetSession(local_tag); | 135 synced_session_tracker_.GetSession(local_tag); |
| 136 header_s->set_client_name(current_machine_name_); |
| 137 #if defined(OS_LINUX) |
| 138 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_LINUX); |
| 139 #elif defined(OS_MACOSX) |
| 140 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_MAC); |
| 141 #elif defined(OS_WIN) |
| 142 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_WIN); |
| 143 #elif defined(OS_CHROMEOS) |
| 144 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_CROS); |
| 145 #else |
| 146 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_OTHER); |
| 147 #endif |
126 | 148 |
127 size_t window_num = 0; | 149 size_t window_num = 0; |
128 std::set<SyncedWindowDelegate*> windows = | 150 std::set<SyncedWindowDelegate*> windows = |
129 SyncedWindowDelegate::GetSyncedWindowDelegates(); | 151 SyncedWindowDelegate::GetSyncedWindowDelegates(); |
130 current_session->windows.reserve(windows.size()); | 152 current_session->windows.reserve(windows.size()); |
131 for (std::set<SyncedWindowDelegate*>::const_iterator i = | 153 for (std::set<SyncedWindowDelegate*>::const_iterator i = |
132 windows.begin(); i != windows.end(); ++i) { | 154 windows.begin(); i != windows.end(); ++i) { |
133 // Make sure the window has tabs and a viewable window. The viewable window | 155 // Make sure the window has tabs and a viewable window. The viewable window |
134 // check is necessary because, for example, when a browser is closed the | 156 // check is necessary because, for example, when a browser is closed the |
135 // destructor is not necessarily run immediately. This means its possible | 157 // destructor is not necessarily run immediately. This means its possible |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 { | 442 { |
421 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 443 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
422 | 444 |
423 sync_api::ReadNode root(&trans); | 445 sync_api::ReadNode root(&trans); |
424 if (!root.InitByTagLookup(kSessionsTag)) { | 446 if (!root.InitByTagLookup(kSessionsTag)) { |
425 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); | 447 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); |
426 return false; | 448 return false; |
427 } | 449 } |
428 | 450 |
429 // Make sure we have a machine tag. | 451 // Make sure we have a machine tag. |
430 if (current_machine_tag_.empty()) | 452 if (current_machine_tag_.empty()) { |
431 InitializeCurrentMachineTag(&trans); | 453 InitializeCurrentMachineTag(&trans); |
| 454 InitializeCurrentMachineName(); |
| 455 } |
432 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); | 456 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); |
433 if (!UpdateAssociationsFromSyncModel(root, &trans)) { | 457 if (!UpdateAssociationsFromSyncModel(root, &trans)) { |
434 error->Reset(FROM_HERE, | 458 error->Reset(FROM_HERE, |
435 "Failed to update associations from sync", | 459 "Failed to update associations from sync", |
436 model_type()); | 460 model_type()); |
437 return false; | 461 return false; |
438 } | 462 } |
439 | 463 |
440 if (local_session_syncid_ == sync_api::kInvalidId) { | 464 if (local_session_syncid_ == sync_api::kInvalidId) { |
441 // The sync db didn't have a header node for us, we need to create one. | 465 // The sync db didn't have a header node for us, we need to create one. |
(...skipping 17 matching lines...) Expand all Loading... |
459 | 483 |
460 return true; | 484 return true; |
461 } | 485 } |
462 | 486 |
463 bool SessionModelAssociator::DisassociateModels(SyncError* error) { | 487 bool SessionModelAssociator::DisassociateModels(SyncError* error) { |
464 DCHECK(CalledOnValidThread()); | 488 DCHECK(CalledOnValidThread()); |
465 synced_session_tracker_.clear(); | 489 synced_session_tracker_.clear(); |
466 tab_map_.clear(); | 490 tab_map_.clear(); |
467 tab_pool_.clear(); | 491 tab_pool_.clear(); |
468 local_session_syncid_ = sync_api::kInvalidId; | 492 local_session_syncid_ = sync_api::kInvalidId; |
| 493 current_machine_tag_ = ""; |
469 | 494 |
470 // There is no local model stored with which to disassociate, just notify | 495 // There is no local model stored with which to disassociate, just notify |
471 // foreign session handlers. | 496 // foreign session handlers. |
472 NotificationService::current()->Notify( | 497 NotificationService::current()->Notify( |
473 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED, | 498 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED, |
474 NotificationService::AllSources(), | 499 NotificationService::AllSources(), |
475 NotificationService::NoDetails()); | 500 NotificationService::NoDetails()); |
476 return true; | 501 return true; |
477 } | 502 } |
478 | 503 |
479 void SessionModelAssociator::InitializeCurrentMachineTag( | 504 void SessionModelAssociator::InitializeCurrentMachineTag( |
480 sync_api::WriteTransaction* trans) { | 505 sync_api::WriteTransaction* trans) { |
481 DCHECK(CalledOnValidThread()); | 506 DCHECK(CalledOnValidThread()); |
482 syncable::Directory* dir = trans->GetWrappedWriteTrans()->directory(); | 507 syncable::Directory* dir = trans->GetWrappedWriteTrans()->directory(); |
483 | 508 |
484 // TODO(zea): We need a better way of creating a machine tag. The directory | 509 // TODO(zea): We need a better way of creating a machine tag. The directory |
485 // kernel's cache_guid changes every time syncing is turned on and off. This | 510 // kernel's cache_guid changes every time syncing is turned on and off. This |
486 // will result in session's associated with stale machine tags persisting on | 511 // will result in session's associated with stale machine tags persisting on |
487 // the server since that tag will not be reused. Eventually this should | 512 // the server since that tag will not be reused. |
488 // become some string identifiable to the user. (Home, Work, Laptop, etc.) | |
489 // See issue at http://crbug.com/59672 | 513 // See issue at http://crbug.com/59672 |
490 current_machine_tag_ = "session_sync"; | 514 current_machine_tag_ = "session_sync"; |
491 current_machine_tag_.append(dir->cache_guid()); | 515 current_machine_tag_.append(dir->cache_guid()); |
492 VLOG(1) << "Creating machine tag: " << current_machine_tag_; | 516 VLOG(1) << "Creating machine tag: " << current_machine_tag_; |
493 tab_pool_.set_machine_tag(current_machine_tag_); | 517 tab_pool_.set_machine_tag(current_machine_tag_); |
494 } | 518 } |
495 | 519 |
| 520 // Static |
| 521 void SessionModelAssociator::InitializeCurrentMachineName() { |
| 522 #if defined(OS_LINUX) |
| 523 current_machine_name_ = base::GetLinuxDistro(); |
| 524 #elif defined(OS_MACOSX) |
| 525 current_machine_name_ = base::mac::GetHardwareModelName(); |
| 526 #elif defined(OS_WIN) |
| 527 current_machine_name_ = base::win::GetComputerName(); |
| 528 #elif defined(OS_CHROMEOS) |
| 529 current_machine_name_ = "Chromebook"; |
| 530 #endif |
| 531 if (current_machine_name_ == "Unknown" || current_machine_name_.empty()) { |
| 532 current_machine_name_ = base::SysInfo::OperatingSystemName(); |
| 533 } |
| 534 } |
| 535 |
| 536 |
496 bool SessionModelAssociator::UpdateAssociationsFromSyncModel( | 537 bool SessionModelAssociator::UpdateAssociationsFromSyncModel( |
497 const sync_api::ReadNode& root, | 538 const sync_api::ReadNode& root, |
498 const sync_api::BaseTransaction* trans) { | 539 const sync_api::BaseTransaction* trans) { |
499 DCHECK(CalledOnValidThread()); | 540 DCHECK(CalledOnValidThread()); |
500 | 541 |
501 // Iterate through the nodes and associate any foreign sessions. | 542 // Iterate through the nodes and associate any foreign sessions. |
502 int64 id = root.GetFirstChildId(); | 543 int64 id = root.GetFirstChildId(); |
503 while (id != sync_api::kInvalidId) { | 544 while (id != sync_api::kInvalidId) { |
504 sync_api::ReadNode sync_node(trans); | 545 sync_api::ReadNode sync_node(trans); |
505 if (!sync_node.InitByIdLookup(id)) { | 546 if (!sync_node.InitByIdLookup(id)) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 if (specifics.has_header()) { | 595 if (specifics.has_header()) { |
555 // Read in the header data for this foreign session. | 596 // Read in the header data for this foreign session. |
556 // Header data contains window information and ordered tab id's for each | 597 // Header data contains window information and ordered tab id's for each |
557 // window. | 598 // window. |
558 | 599 |
559 // Load (or create) the SyncedSession object for this client. | 600 // Load (or create) the SyncedSession object for this client. |
560 SyncedSession* foreign_session = | 601 SyncedSession* foreign_session = |
561 synced_session_tracker_.GetSession(foreign_session_tag); | 602 synced_session_tracker_.GetSession(foreign_session_tag); |
562 | 603 |
563 const sync_pb::SessionHeader& header = specifics.header(); | 604 const sync_pb::SessionHeader& header = specifics.header(); |
| 605 PopulateSessionHeaderFromSpecifics(header, foreign_session); |
564 foreign_session->windows.reserve(header.window_size()); | 606 foreign_session->windows.reserve(header.window_size()); |
565 VLOG(1) << "Associating " << foreign_session_tag << " with " << | 607 VLOG(1) << "Associating " << foreign_session_tag << " with " << |
566 header.window_size() << " windows."; | 608 header.window_size() << " windows."; |
567 size_t i; | 609 size_t i; |
568 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) { | 610 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) { |
569 if (i >= foreign_session->windows.size()) { | 611 if (i >= foreign_session->windows.size()) { |
570 // This a new window, create it. | 612 // This a new window, create it. |
571 foreign_session->windows.push_back(new SessionWindow()); | 613 foreign_session->windows.push_back(new SessionWindow()); |
572 } | 614 } |
573 const sync_pb::SessionWindow& window_s = header.window(i); | 615 const sync_pb::SessionWindow& window_s = header.window(i); |
(...skipping 24 matching lines...) Expand all Loading... |
598 return true; | 640 return true; |
599 } | 641 } |
600 | 642 |
601 void SessionModelAssociator::DisassociateForeignSession( | 643 void SessionModelAssociator::DisassociateForeignSession( |
602 const std::string& foreign_session_tag) { | 644 const std::string& foreign_session_tag) { |
603 DCHECK(CalledOnValidThread()); | 645 DCHECK(CalledOnValidThread()); |
604 synced_session_tracker_.DeleteSession(foreign_session_tag); | 646 synced_session_tracker_.DeleteSession(foreign_session_tag); |
605 } | 647 } |
606 | 648 |
607 // Static | 649 // Static |
| 650 void SessionModelAssociator::PopulateSessionHeaderFromSpecifics( |
| 651 const sync_pb::SessionHeader& header_specifics, |
| 652 SyncedSession* session_header) { |
| 653 if (header_specifics.has_client_name()) { |
| 654 session_header->client_name = header_specifics.client_name(); |
| 655 } |
| 656 if (header_specifics.has_device_type()) { |
| 657 switch (header_specifics.device_type()) { |
| 658 case sync_pb::SessionHeader_DeviceType_TYPE_WIN: |
| 659 session_header->device_type = SyncedSession::TYPE_WIN; |
| 660 break; |
| 661 case sync_pb::SessionHeader_DeviceType_TYPE_MAC: |
| 662 session_header->device_type = SyncedSession::TYPE_MAC; |
| 663 break; |
| 664 case sync_pb::SessionHeader_DeviceType_TYPE_LINUX: |
| 665 session_header->device_type = SyncedSession::TYPE_LINUX; |
| 666 break; |
| 667 case sync_pb::SessionHeader_DeviceType_TYPE_CROS: |
| 668 session_header->device_type = SyncedSession::TYPE_CROS; |
| 669 break; |
| 670 case sync_pb::SessionHeader_DeviceType_TYPE_OTHER: |
| 671 // Intentionally fall-through |
| 672 default: |
| 673 session_header->device_type = SyncedSession::TYPE_OTHER; |
| 674 break; |
| 675 } |
| 676 } |
| 677 } |
| 678 |
| 679 // Static |
608 void SessionModelAssociator::PopulateSessionWindowFromSpecifics( | 680 void SessionModelAssociator::PopulateSessionWindowFromSpecifics( |
609 const std::string& session_tag, | 681 const std::string& session_tag, |
610 const sync_pb::SessionWindow& specifics, | 682 const sync_pb::SessionWindow& specifics, |
611 int64 mtime, | 683 int64 mtime, |
612 SessionWindow* session_window, | 684 SessionWindow* session_window, |
613 SyncedSessionTracker* tracker) { | 685 SyncedSessionTracker* tracker) { |
614 if (specifics.has_window_id()) | 686 if (specifics.has_window_id()) |
615 session_window->window_id.set_id(specifics.window_id()); | 687 session_window->window_id.set_id(specifics.window_id()); |
616 if (specifics.has_selected_tab_index()) | 688 if (specifics.has_selected_tab_index()) |
617 session_window->selected_tab_index = specifics.selected_tab_index(); | 689 session_window->selected_tab_index = specifics.selected_tab_index(); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 bool SessionModelAssociator::CryptoReadyIfNecessary() { | 1142 bool SessionModelAssociator::CryptoReadyIfNecessary() { |
1071 // We only access the cryptographer while holding a transaction. | 1143 // We only access the cryptographer while holding a transaction. |
1072 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 1144 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
1073 syncable::ModelTypeSet encrypted_types; | 1145 syncable::ModelTypeSet encrypted_types; |
1074 encrypted_types = sync_api::GetEncryptedTypes(&trans); | 1146 encrypted_types = sync_api::GetEncryptedTypes(&trans); |
1075 return encrypted_types.count(syncable::SESSIONS) == 0 || | 1147 return encrypted_types.count(syncable::SESSIONS) == 0 || |
1076 sync_service_->IsCryptographerReady(&trans); | 1148 sync_service_->IsCryptographerReady(&trans); |
1077 } | 1149 } |
1078 | 1150 |
1079 } // namespace browser_sync | 1151 } // namespace browser_sync |
OLD | NEW |