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

Side by Side Diff: chrome/browser/sync/glue/session_model_associator.cc

Issue 7740055: Set user-visible machine names and devices types for synced sessions. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fix tests Created 9 years, 3 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 | Annotate | Revision Log
OLDNEW
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"
14 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sessions/session_service_factory.h" 16 #include "chrome/browser/sessions/session_service_factory.h"
15 #include "chrome/browser/sync/api/sync_error.h" 17 #include "chrome/browser/sync/api/sync_error.h"
18 #include "chrome/browser/sync/glue/synced_session.h"
16 #include "chrome/browser/sync/glue/synced_tab_delegate.h" 19 #include "chrome/browser/sync/glue/synced_tab_delegate.h"
17 #include "chrome/browser/sync/glue/synced_window_delegate.h" 20 #include "chrome/browser/sync/glue/synced_window_delegate.h"
18 #include "chrome/browser/sync/internal_api/read_node.h" 21 #include "chrome/browser/sync/internal_api/read_node.h"
19 #include "chrome/browser/sync/internal_api/read_transaction.h" 22 #include "chrome/browser/sync/internal_api/read_transaction.h"
20 #include "chrome/browser/sync/internal_api/write_node.h" 23 #include "chrome/browser/sync/internal_api/write_node.h"
21 #include "chrome/browser/sync/internal_api/write_transaction.h" 24 #include "chrome/browser/sync/internal_api/write_transaction.h"
22 #include "chrome/browser/sync/profile_sync_service.h" 25 #include "chrome/browser/sync/profile_sync_service.h"
23 #include "chrome/browser/sync/syncable/syncable.h" 26 #include "chrome/browser/sync/syncable/syncable.h"
24 #include "chrome/common/chrome_notification_types.h" 27 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/url_constants.h" 28 #include "chrome/common/url_constants.h"
26 #include "content/browser/tab_contents/navigation_entry.h" 29 #include "content/browser/tab_contents/navigation_entry.h"
27 #include "content/common/notification_details.h" 30 #include "content/common/notification_details.h"
28 #include "content/common/notification_service.h" 31 #include "content/common/notification_service.h"
32 #if defined(OS_LINUX)
33 #include "base/linux_util.h"
34 #elif defined(OS_WIN)
35 #include <windows.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;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 } 124 }
117 125
118 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) { 126 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) {
119 DCHECK(CalledOnValidThread()); 127 DCHECK(CalledOnValidThread());
120 std::string local_tag = GetCurrentMachineTag(); 128 std::string local_tag = GetCurrentMachineTag();
121 sync_pb::SessionSpecifics specifics; 129 sync_pb::SessionSpecifics specifics;
122 specifics.set_session_tag(local_tag); 130 specifics.set_session_tag(local_tag);
123 sync_pb::SessionHeader* header_s = specifics.mutable_header(); 131 sync_pb::SessionHeader* header_s = specifics.mutable_header();
124 SyncedSession* current_session = 132 SyncedSession* current_session =
125 synced_session_tracker_.GetSession(local_tag); 133 synced_session_tracker_.GetSession(local_tag);
134 header_s->set_client_name(current_session_name_);
135 #if defined(OS_LINUX)
136 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_LINUX);
137 #elif defined(OS_MACOSX)
138 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_MAC);
139 #elif defined(OS_WIN)
140 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_WIN);
141 #elif defined(OS_CHROMEOS)
142 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_CROS);
143 #else
144 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_OTHER);
145 #endif
126 146
127 size_t window_num = 0; 147 size_t window_num = 0;
128 std::set<SyncedWindowDelegate*> windows = 148 std::set<SyncedWindowDelegate*> windows =
129 SyncedWindowDelegate::GetSyncedWindowDelegates(); 149 SyncedWindowDelegate::GetSyncedWindowDelegates();
130 current_session->windows.reserve(windows.size()); 150 current_session->windows.reserve(windows.size());
131 for (std::set<SyncedWindowDelegate*>::const_iterator i = 151 for (std::set<SyncedWindowDelegate*>::const_iterator i =
132 windows.begin(); i != windows.end(); ++i) { 152 windows.begin(); i != windows.end(); ++i) {
133 // Make sure the window has tabs and a viewable window. The viewable window 153 // 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 154 // check is necessary because, for example, when a browser is closed the
135 // destructor is not necessarily run immediately. This means its possible 155 // destructor is not necessarily run immediately. This means its possible
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 { 440 {
421 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 441 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
422 442
423 sync_api::ReadNode root(&trans); 443 sync_api::ReadNode root(&trans);
424 if (!root.InitByTagLookup(kSessionsTag)) { 444 if (!root.InitByTagLookup(kSessionsTag)) {
425 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); 445 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type());
426 return false; 446 return false;
427 } 447 }
428 448
429 // Make sure we have a machine tag. 449 // Make sure we have a machine tag.
430 if (current_machine_tag_.empty()) 450 if (current_machine_tag_.empty()) {
431 InitializeCurrentMachineTag(&trans); 451 InitializeCurrentMachineTag(&trans);
452 // The session name is retrieved asynchronously so it might not come back
453 // for the writing of the session. However, we write to the session often
454 // enough (on every navigation) that we'll pick it up quickly.
455 InitializeCurrentSessionName();
456 }
432 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_); 457 synced_session_tracker_.SetLocalSessionTag(current_machine_tag_);
433 if (!UpdateAssociationsFromSyncModel(root, &trans)) { 458 if (!UpdateAssociationsFromSyncModel(root, &trans)) {
434 error->Reset(FROM_HERE, 459 error->Reset(FROM_HERE,
435 "Failed to update associations from sync", 460 "Failed to update associations from sync",
436 model_type()); 461 model_type());
437 return false; 462 return false;
438 } 463 }
439 464
440 if (local_session_syncid_ == sync_api::kInvalidId) { 465 if (local_session_syncid_ == sync_api::kInvalidId) {
441 // The sync db didn't have a header node for us, we need to create one. 466 // The sync db didn't have a header node for us, we need to create one.
(...skipping 17 matching lines...) Expand all
459 484
460 return true; 485 return true;
461 } 486 }
462 487
463 bool SessionModelAssociator::DisassociateModels(SyncError* error) { 488 bool SessionModelAssociator::DisassociateModels(SyncError* error) {
464 DCHECK(CalledOnValidThread()); 489 DCHECK(CalledOnValidThread());
465 synced_session_tracker_.clear(); 490 synced_session_tracker_.clear();
466 tab_map_.clear(); 491 tab_map_.clear();
467 tab_pool_.clear(); 492 tab_pool_.clear();
468 local_session_syncid_ = sync_api::kInvalidId; 493 local_session_syncid_ = sync_api::kInvalidId;
494 current_machine_tag_ = "";
495 current_session_name_ = "";
469 496
470 // There is no local model stored with which to disassociate, just notify 497 // There is no local model stored with which to disassociate, just notify
471 // foreign session handlers. 498 // foreign session handlers.
472 NotificationService::current()->Notify( 499 NotificationService::current()->Notify(
473 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED, 500 chrome::NOTIFICATION_FOREIGN_SESSION_DISABLED,
474 NotificationService::AllSources(), 501 NotificationService::AllSources(),
475 NotificationService::NoDetails()); 502 NotificationService::NoDetails());
476 return true; 503 return true;
477 } 504 }
478 505
479 void SessionModelAssociator::InitializeCurrentMachineTag( 506 void SessionModelAssociator::InitializeCurrentMachineTag(
480 sync_api::WriteTransaction* trans) { 507 sync_api::WriteTransaction* trans) {
481 DCHECK(CalledOnValidThread()); 508 DCHECK(CalledOnValidThread());
482 syncable::Directory* dir = trans->GetWrappedWriteTrans()->directory(); 509 syncable::Directory* dir = trans->GetWrappedWriteTrans()->directory();
483
484 // 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
486 // 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
488 // become some string identifiable to the user. (Home, Work, Laptop, etc.)
489 // See issue at http://crbug.com/59672
490 current_machine_tag_ = "session_sync"; 510 current_machine_tag_ = "session_sync";
491 current_machine_tag_.append(dir->cache_guid()); 511 current_machine_tag_.append(dir->cache_guid());
492 VLOG(1) << "Creating machine tag: " << current_machine_tag_; 512 VLOG(1) << "Creating machine tag: " << current_machine_tag_;
493 tab_pool_.set_machine_tag(current_machine_tag_); 513 tab_pool_.set_machine_tag(current_machine_tag_);
494 } 514 }
495 515
516 void SessionModelAssociator::OnSessionNameInitialized(const std::string name) {
517 DCHECK(CalledOnValidThread());
518 // Only use the default machine name if it hasn't already been set.
519 if (current_session_name_.empty()) {
520 current_session_name_ = name;
521 }
522 }
523
524 // Task which runs on the file thread because it runs system calls which can
525 // block while retrieving sytem information.
526 class GetSessionNameTask : public Task {
527 public:
528 explicit GetSessionNameTask(
529 const WeakHandle<SessionModelAssociator> associator) :
530 associator_(associator) {}
531
532 virtual void Run() {
533 #if defined(OS_LINUX)
534 std::string session_name = base::GetLinuxDistro();
535 #elif defined(OS_MACOSX)
536 std::string session_name = SessionModelAssociator::GetHardwareModelName();
537 #elif defined(OS_WIN)
538 std::string session_name = SessionModelAssociator::GetComputerName();
539 #else
540 std::string session_name;
541 #endif
542 if (session_name == "Unknown" || session_name.empty()) {
543 session_name = base::SysInfo::OperatingSystemName();
544 }
545 associator_.Call(FROM_HERE,
546 &SessionModelAssociator::OnSessionNameInitialized,
547 session_name);
548 }
549 const WeakHandle<SessionModelAssociator> associator_;
550
551 DISALLOW_COPY_AND_ASSIGN(GetSessionNameTask);
552 };
553
554 void SessionModelAssociator::InitializeCurrentSessionName() {
555 DCHECK(CalledOnValidThread());
556 if (setup_for_test_) {
557 OnSessionNameInitialized("TestSessionName");
558 } else {
559 #if defined(OS_CHROMEOS)
560 OnSessionNameInitialized("Chromebook");
561 #else
562 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
563 new GetSessionNameTask(MakeWeakHandle(AsWeakPtr())));
564 #endif
565 }
566 }
567
496 bool SessionModelAssociator::UpdateAssociationsFromSyncModel( 568 bool SessionModelAssociator::UpdateAssociationsFromSyncModel(
497 const sync_api::ReadNode& root, 569 const sync_api::ReadNode& root,
498 const sync_api::BaseTransaction* trans) { 570 const sync_api::BaseTransaction* trans) {
499 DCHECK(CalledOnValidThread()); 571 DCHECK(CalledOnValidThread());
500 572
501 // Iterate through the nodes and associate any foreign sessions. 573 // Iterate through the nodes and associate any foreign sessions.
502 int64 id = root.GetFirstChildId(); 574 int64 id = root.GetFirstChildId();
503 while (id != sync_api::kInvalidId) { 575 while (id != sync_api::kInvalidId) {
504 sync_api::ReadNode sync_node(trans); 576 sync_api::ReadNode sync_node(trans);
505 if (!sync_node.InitByIdLookup(id)) { 577 if (!sync_node.InitByIdLookup(id)) {
506 LOG(ERROR) << "Failed to fetch sync node for id " << id; 578 LOG(ERROR) << "Failed to fetch sync node for id " << id;
507 return false; 579 return false;
508 } 580 }
509 581
510 const sync_pb::SessionSpecifics& specifics = 582 const sync_pb::SessionSpecifics& specifics =
511 sync_node.GetSessionSpecifics(); 583 sync_node.GetSessionSpecifics();
512 const int64 modification_time = sync_node.GetModificationTime(); 584 const int64 modification_time = sync_node.GetModificationTime();
513 if (specifics.session_tag() != GetCurrentMachineTag()) { 585 if (specifics.session_tag() != GetCurrentMachineTag()) {
514 if (!AssociateForeignSpecifics(specifics, modification_time)) { 586 if (!AssociateForeignSpecifics(specifics, modification_time)) {
515 return false; 587 return false;
516 } 588 }
517 } else if (id != local_session_syncid_) { 589 } else if (id != local_session_syncid_) {
518 // This is previously stored local session information. 590 // This is previously stored local session information.
519 if (specifics.has_header()) { 591 if (specifics.has_header()) {
520 if (sync_api::kInvalidId != local_session_syncid_) 592 if (sync_api::kInvalidId != local_session_syncid_)
521 return false; 593 return false;
522 594
523 // This is our previous header node, reuse it. 595 // This is our previous header node, reuse it.
524 local_session_syncid_ = id; 596 local_session_syncid_ = id;
597 if (specifics.header().has_client_name()) {
598 current_session_name_ = specifics.header().client_name();
599 }
525 } else { 600 } else {
526 if (!specifics.has_tab()) 601 if (!specifics.has_tab())
527 return false; 602 return false;
528 603
529 // This is a tab node. We want to track these to reuse them in our free 604 // This is a tab node. We want to track these to reuse them in our free
530 // tab node pool. They will be overwritten eventually, so need to do 605 // tab node pool. They will be overwritten eventually, so need to do
531 // anything else. 606 // anything else.
532 tab_pool_.AddTabNode(id); 607 tab_pool_.AddTabNode(id);
533 } 608 }
534 } 609 }
(...skipping 19 matching lines...) Expand all
554 if (specifics.has_header()) { 629 if (specifics.has_header()) {
555 // Read in the header data for this foreign session. 630 // Read in the header data for this foreign session.
556 // Header data contains window information and ordered tab id's for each 631 // Header data contains window information and ordered tab id's for each
557 // window. 632 // window.
558 633
559 // Load (or create) the SyncedSession object for this client. 634 // Load (or create) the SyncedSession object for this client.
560 SyncedSession* foreign_session = 635 SyncedSession* foreign_session =
561 synced_session_tracker_.GetSession(foreign_session_tag); 636 synced_session_tracker_.GetSession(foreign_session_tag);
562 637
563 const sync_pb::SessionHeader& header = specifics.header(); 638 const sync_pb::SessionHeader& header = specifics.header();
639 PopulateSessionHeaderFromSpecifics(header, foreign_session);
564 foreign_session->windows.reserve(header.window_size()); 640 foreign_session->windows.reserve(header.window_size());
565 VLOG(1) << "Associating " << foreign_session_tag << " with " << 641 VLOG(1) << "Associating " << foreign_session_tag << " with " <<
566 header.window_size() << " windows."; 642 header.window_size() << " windows.";
567 size_t i; 643 size_t i;
568 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) { 644 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) {
569 if (i >= foreign_session->windows.size()) { 645 if (i >= foreign_session->windows.size()) {
570 // This a new window, create it. 646 // This a new window, create it.
571 foreign_session->windows.push_back(new SessionWindow()); 647 foreign_session->windows.push_back(new SessionWindow());
572 } 648 }
573 const sync_pb::SessionWindow& window_s = header.window(i); 649 const sync_pb::SessionWindow& window_s = header.window(i);
(...skipping 24 matching lines...) Expand all
598 return true; 674 return true;
599 } 675 }
600 676
601 void SessionModelAssociator::DisassociateForeignSession( 677 void SessionModelAssociator::DisassociateForeignSession(
602 const std::string& foreign_session_tag) { 678 const std::string& foreign_session_tag) {
603 DCHECK(CalledOnValidThread()); 679 DCHECK(CalledOnValidThread());
604 synced_session_tracker_.DeleteSession(foreign_session_tag); 680 synced_session_tracker_.DeleteSession(foreign_session_tag);
605 } 681 }
606 682
607 // Static 683 // Static
684 void SessionModelAssociator::PopulateSessionHeaderFromSpecifics(
685 const sync_pb::SessionHeader& header_specifics,
686 SyncedSession* session_header) {
687 if (header_specifics.has_client_name()) {
688 session_header->session_name = header_specifics.client_name();
689 }
690 if (header_specifics.has_device_type()) {
691 switch (header_specifics.device_type()) {
692 case sync_pb::SessionHeader_DeviceType_TYPE_WIN:
693 session_header->device_type = SyncedSession::TYPE_WIN;
694 break;
695 case sync_pb::SessionHeader_DeviceType_TYPE_MAC:
696 session_header->device_type = SyncedSession::TYPE_MACOSX;
697 break;
698 case sync_pb::SessionHeader_DeviceType_TYPE_LINUX:
699 session_header->device_type = SyncedSession::TYPE_LINUX;
700 break;
701 case sync_pb::SessionHeader_DeviceType_TYPE_CROS:
702 session_header->device_type = SyncedSession::TYPE_CHROMEOS;
703 break;
704 case sync_pb::SessionHeader_DeviceType_TYPE_OTHER:
705 // Intentionally fall-through
706 default:
707 session_header->device_type = SyncedSession::TYPE_OTHER;
708 break;
709 }
710 }
711 }
712
713 // Static
608 void SessionModelAssociator::PopulateSessionWindowFromSpecifics( 714 void SessionModelAssociator::PopulateSessionWindowFromSpecifics(
609 const std::string& session_tag, 715 const std::string& session_tag,
610 const sync_pb::SessionWindow& specifics, 716 const sync_pb::SessionWindow& specifics,
611 int64 mtime, 717 int64 mtime,
612 SessionWindow* session_window, 718 SessionWindow* session_window,
613 SyncedSessionTracker* tracker) { 719 SyncedSessionTracker* tracker) {
614 if (specifics.has_window_id()) 720 if (specifics.has_window_id())
615 session_window->window_id.set_id(specifics.window_id()); 721 session_window->window_id.set_id(specifics.window_id());
616 if (specifics.has_selected_tab_index()) 722 if (specifics.has_selected_tab_index())
617 session_window->selected_tab_index = specifics.selected_tab_index(); 723 session_window->selected_tab_index = specifics.selected_tab_index();
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 1175
1070 bool SessionModelAssociator::CryptoReadyIfNecessary() { 1176 bool SessionModelAssociator::CryptoReadyIfNecessary() {
1071 // We only access the cryptographer while holding a transaction. 1177 // We only access the cryptographer while holding a transaction.
1072 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 1178 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1073 syncable::ModelTypeSet encrypted_types; 1179 syncable::ModelTypeSet encrypted_types;
1074 encrypted_types = sync_api::GetEncryptedTypes(&trans); 1180 encrypted_types = sync_api::GetEncryptedTypes(&trans);
1075 return encrypted_types.count(syncable::SESSIONS) == 0 || 1181 return encrypted_types.count(syncable::SESSIONS) == 0 ||
1076 sync_service_->IsCryptographerReady(&trans); 1182 sync_service_->IsCryptographerReady(&trans);
1077 } 1183 }
1078 1184
1185 #if defined(OS_WIN)
1186 // Static
1187 // TODO(nzea): This isn't safe to call on the UI-thread. Move it out to a util
1188 // or object that lives on the FILE thread.
1189 std::string SessionModelAssociator::GetComputerName() {
1190 char computer_name[MAX_COMPUTERNAME_LENGTH + 1];
1191 DWORD size = sizeof(computer_name);
1192 if (GetComputerNameA(computer_name, &size)) {
1193 return computer_name;
1194 }
1195 return std::string();
1196 }
1197 #endif
1198
1079 } // namespace browser_sync 1199 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/session_model_associator.h ('k') | chrome/browser/sync/glue/session_model_associator_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698