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

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: Set device_type for SessionHeader 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/tracked.h" 12 #include "base/tracked.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sessions/session_service_factory.h" 14 #include "chrome/browser/sessions/session_service_factory.h"
15 #include "chrome/browser/sync/api/sync_error.h" 15 #include "chrome/browser/sync/api/sync_error.h"
16 #include "chrome/browser/sync/glue/synced_tab_delegate.h" 16 #include "chrome/browser/sync/glue/synced_tab_delegate.h"
17 #include "chrome/browser/sync/glue/synced_window_delegate.h" 17 #include "chrome/browser/sync/glue/synced_window_delegate.h"
18 #include "chrome/browser/sync/internal_api/read_node.h" 18 #include "chrome/browser/sync/internal_api/read_node.h"
19 #include "chrome/browser/sync/internal_api/read_transaction.h" 19 #include "chrome/browser/sync/internal_api/read_transaction.h"
20 #include "chrome/browser/sync/internal_api/write_node.h" 20 #include "chrome/browser/sync/internal_api/write_node.h"
21 #include "chrome/browser/sync/internal_api/write_transaction.h" 21 #include "chrome/browser/sync/internal_api/write_transaction.h"
22 #include "chrome/browser/sync/profile_sync_service.h" 22 #include "chrome/browser/sync/profile_sync_service.h"
23 #include "chrome/browser/sync/syncable/syncable.h" 23 #include "chrome/browser/sync/syncable/syncable.h"
24 #include "chrome/common/chrome_notification_types.h" 24 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
26 #include "content/browser/tab_contents/navigation_entry.h" 26 #include "content/browser/tab_contents/navigation_entry.h"
27 #include "content/common/notification_details.h" 27 #include "content/common/notification_details.h"
28 #include "content/common/notification_service.h" 28 #include "content/common/notification_service.h"
29 #if defined(OS_LINUX)
30 #include "base/linux_util.h"
31 #elif defined(OS_MACOSX)
32 #include <sys/sysctl.h> // sysctlbyname()
33 #include "base/sys_info.h"
34 #include "base/string_util.h"
35 #elif defined(OS_WIN)
36 #include <windows.h>
37 #endif
29 38
30 namespace browser_sync { 39 namespace browser_sync {
31 40
32 namespace { 41 namespace {
33 static const char kNoSessionsFolderError[] = 42 static const char kNoSessionsFolderError[] =
34 "Server did not create the top-level sessions node. We " 43 "Server did not create the top-level sessions node. We "
35 "might be running against an out-of-date server."; 44 "might be running against an out-of-date server.";
36 45
37 // The maximum number of navigations in each direction we care to sync. 46 // The maximum number of navigations in each direction we care to sync.
38 static const int max_sync_navigation_count = 6; 47 static const int max_sync_navigation_count = 6;
39 } // namespace 48 } // namespace
40 49
50 std::string SessionModelAssociator::current_machine_name_ = "";
Nicolas Zea 2011/08/30 21:29:58 You can remove this line (default value for a stri
Yaron 2011/08/31 03:26:12 But since it's static, I need to have a concrete i
Nicolas Zea 2011/08/31 18:23:00 Woops, I didn't read this properly. Yeah, this def
Yaron 2011/08/31 23:23:21 Done.
51
41 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service) 52 SessionModelAssociator::SessionModelAssociator(ProfileSyncService* sync_service)
42 : tab_pool_(sync_service), 53 : tab_pool_(sync_service),
43 local_session_syncid_(sync_api::kInvalidId), 54 local_session_syncid_(sync_api::kInvalidId),
44 sync_service_(sync_service), 55 sync_service_(sync_service),
45 setup_for_test_(false), 56 setup_for_test_(false),
46 waiting_for_change_(false), 57 waiting_for_change_(false),
47 ALLOW_THIS_IN_INITIALIZER_LIST(test_method_factory_(this)) { 58 ALLOW_THIS_IN_INITIALIZER_LIST(test_method_factory_(this)) {
48 DCHECK(CalledOnValidThread()); 59 DCHECK(CalledOnValidThread());
49 DCHECK(sync_service_); 60 DCHECK(sync_service_);
50 } 61 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 } 127 }
117 128
118 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) { 129 void SessionModelAssociator::ReassociateWindows(bool reload_tabs) {
119 DCHECK(CalledOnValidThread()); 130 DCHECK(CalledOnValidThread());
120 std::string local_tag = GetCurrentMachineTag(); 131 std::string local_tag = GetCurrentMachineTag();
121 sync_pb::SessionSpecifics specifics; 132 sync_pb::SessionSpecifics specifics;
122 specifics.set_session_tag(local_tag); 133 specifics.set_session_tag(local_tag);
123 sync_pb::SessionHeader* header_s = specifics.mutable_header(); 134 sync_pb::SessionHeader* header_s = specifics.mutable_header();
124 SyncedSession* current_session = 135 SyncedSession* current_session =
125 synced_session_tracker_.GetSession(local_tag); 136 synced_session_tracker_.GetSession(local_tag);
137 header_s->set_client_name(current_machine_name_);
138 #if defined(OS_LINUX)
139 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_LINUX);
140 #elif defined(OS_MACOSX)
141 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_MAC);
142 #elif defined(OS_WIN)
143 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_WIN);
144 #elif defined(OS_CHROMEOS)
145 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_CROS);
146 #else
147 header_s->set_device_type(sync_pb::SessionHeader_DeviceType_TYPE_OTHER);
148 #endif
126 149
127 size_t window_num = 0; 150 size_t window_num = 0;
128 std::set<SyncedWindowDelegate*> windows = 151 std::set<SyncedWindowDelegate*> windows =
129 SyncedWindowDelegate::GetSyncedWindowDelegates(); 152 SyncedWindowDelegate::GetSyncedWindowDelegates();
130 current_session->windows.reserve(windows.size()); 153 current_session->windows.reserve(windows.size());
131 for (std::set<SyncedWindowDelegate*>::const_iterator i = 154 for (std::set<SyncedWindowDelegate*>::const_iterator i =
132 windows.begin(); i != windows.end(); ++i) { 155 windows.begin(); i != windows.end(); ++i) {
133 // Make sure the window has tabs and a viewable window. The viewable window 156 // 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 157 // check is necessary because, for example, when a browser is closed the
135 // destructor is not necessarily run immediately. This means its possible 158 // destructor is not necessarily run immediately. This means its possible
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 { 443 {
421 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 444 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
422 445
423 sync_api::ReadNode root(&trans); 446 sync_api::ReadNode root(&trans);
424 if (!root.InitByTagLookup(kSessionsTag)) { 447 if (!root.InitByTagLookup(kSessionsTag)) {
425 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type()); 448 error->Reset(FROM_HERE, kNoSessionsFolderError, model_type());
426 return false; 449 return false;
427 } 450 }
428 451
429 // Make sure we have a machine tag. 452 // Make sure we have a machine tag.
430 if (current_machine_tag_.empty()) 453 if (current_machine_tag_.empty()) {
431 InitializeCurrentMachineTag(&trans); 454 InitializeCurrentMachineTag(&trans);
455 InitializeCurrentMachineName();
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 16 matching lines...) Expand all
458 VLOG(1) << "Session models associated."; 483 VLOG(1) << "Session models associated.";
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;
Nicolas Zea 2011/08/30 21:29:58 Should probably clear current_machine_name and cur
Yaron 2011/08/31 03:26:12 I cleared current_machine_tag_ but not current_mac
Nicolas Zea 2011/08/31 18:23:00 See above comment.
Yaron 2011/08/31 23:23:21 Done.
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
Nicolas Zea 2011/08/30 21:29:58 This TODO no longer applies.
Yaron 2011/08/31 03:26:12 Well not entirely. The last bit of being human-rea
Nicolas Zea 2011/08/31 18:23:00 Tim and I have chatted about this before and we're
Yaron 2011/08/31 23:23:21 Done.
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. Eventually this should
488 // become some string identifiable to the user. (Home, Work, Laptop, etc.) 513 // become some string identifiable to the user. (Home, Work, Laptop, etc.)
489 // See issue at http://crbug.com/59672 514 // See issue at http://crbug.com/59672
490 current_machine_tag_ = "session_sync"; 515 current_machine_tag_ = "session_sync";
491 current_machine_tag_.append(dir->cache_guid()); 516 current_machine_tag_.append(dir->cache_guid());
492 VLOG(1) << "Creating machine tag: " << current_machine_tag_; 517 VLOG(1) << "Creating machine tag: " << current_machine_tag_;
493 tab_pool_.set_machine_tag(current_machine_tag_); 518 tab_pool_.set_machine_tag(current_machine_tag_);
494 } 519 }
495 520
521 // Static
522 void SessionModelAssociator::InitializeCurrentMachineName() {
523 #if defined(OS_LINUX)
524 current_machine_name_ = base::GetLinuxDistro();
Nicolas Zea 2011/08/30 21:29:58 should probably check for the "Unknown" case and r
Yaron 2011/08/31 03:26:12 Done
525 #elif defined(OS_MACOSX)
526 char modelBuffer[256];
527 size_t length = sizeof(modelBuffer);
528 if (!sysctlbyname("hw.model", modelBuffer, &length, NULL, 0)) {
Nicolas Zea 2011/08/30 21:29:58 I'm not familiar with these API's, so my main conc
Yaron 2011/08/31 03:26:12 Split off GetComputerName to win_util and GetHardw
529 for (size_t i = 0; i < length; i++) {
530 if (IsAsciiDigit(modelBuffer[i])) {
531 current_machine_name_ = std::string(modelBuffer, 0, i);
532 return;
533 }
534 }
535 // If we didn't find a number in the string, Just use Mac OS X.
Nicolas Zea 2011/08/30 21:29:58 Why not just use the full string?
Yaron 2011/08/31 03:26:12 Hmm. I suppose that could be better
536 current_machine_name_ = base::SysInfo::OperatingSystemName();
537 } else {
538 // Can't read hardware model. Just use Mac OS X.
539 current_machine_name_ = base::SysInfo::OperatingSystemName();
540 }
541 #elif defined(OS_WIN)
542 char computer_name[MAX_COMPUTERNAME_LENGTH + 1];
543 DWORD size = sizeof(computer_name);
544 if (GetComputerNameA(computer_name, &size)) {
545 current_machine_name_ = computer_name;
546 } else {
547 current_machine_name_ = "Windows";
548 }
549 #elif defined(OS_CHROMEOS)
550 current_machine_name_ = "Chromebook";
551 #endif
Nicolas Zea 2011/08/30 21:29:58 else "Unknown OS"
Yaron 2011/08/31 03:26:12 I added a catch-all case instead (because it also
552 }
553
554
496 bool SessionModelAssociator::UpdateAssociationsFromSyncModel( 555 bool SessionModelAssociator::UpdateAssociationsFromSyncModel(
497 const sync_api::ReadNode& root, 556 const sync_api::ReadNode& root,
498 const sync_api::BaseTransaction* trans) { 557 const sync_api::BaseTransaction* trans) {
499 DCHECK(CalledOnValidThread()); 558 DCHECK(CalledOnValidThread());
500 559
501 // Iterate through the nodes and associate any foreign sessions. 560 // Iterate through the nodes and associate any foreign sessions.
502 int64 id = root.GetFirstChildId(); 561 int64 id = root.GetFirstChildId();
503 while (id != sync_api::kInvalidId) { 562 while (id != sync_api::kInvalidId) {
504 sync_api::ReadNode sync_node(trans); 563 sync_api::ReadNode sync_node(trans);
505 if (!sync_node.InitByIdLookup(id)) { 564 if (!sync_node.InitByIdLookup(id)) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (specifics.has_header()) { 613 if (specifics.has_header()) {
555 // Read in the header data for this foreign session. 614 // Read in the header data for this foreign session.
556 // Header data contains window information and ordered tab id's for each 615 // Header data contains window information and ordered tab id's for each
557 // window. 616 // window.
558 617
559 // Load (or create) the SyncedSession object for this client. 618 // Load (or create) the SyncedSession object for this client.
560 SyncedSession* foreign_session = 619 SyncedSession* foreign_session =
561 synced_session_tracker_.GetSession(foreign_session_tag); 620 synced_session_tracker_.GetSession(foreign_session_tag);
562 621
563 const sync_pb::SessionHeader& header = specifics.header(); 622 const sync_pb::SessionHeader& header = specifics.header();
623 PopulateSessionHeaderFromSpecifics(header, foreign_session);
564 foreign_session->windows.reserve(header.window_size()); 624 foreign_session->windows.reserve(header.window_size());
565 VLOG(1) << "Associating " << foreign_session_tag << " with " << 625 VLOG(1) << "Associating " << foreign_session_tag << " with " <<
566 header.window_size() << " windows."; 626 header.window_size() << " windows.";
567 size_t i; 627 size_t i;
568 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) { 628 for (i = 0; i < static_cast<size_t>(header.window_size()); ++i) {
569 if (i >= foreign_session->windows.size()) { 629 if (i >= foreign_session->windows.size()) {
570 // This a new window, create it. 630 // This a new window, create it.
571 foreign_session->windows.push_back(new SessionWindow()); 631 foreign_session->windows.push_back(new SessionWindow());
572 } 632 }
573 const sync_pb::SessionWindow& window_s = header.window(i); 633 const sync_pb::SessionWindow& window_s = header.window(i);
(...skipping 24 matching lines...) Expand all
598 return true; 658 return true;
599 } 659 }
600 660
601 void SessionModelAssociator::DisassociateForeignSession( 661 void SessionModelAssociator::DisassociateForeignSession(
602 const std::string& foreign_session_tag) { 662 const std::string& foreign_session_tag) {
603 DCHECK(CalledOnValidThread()); 663 DCHECK(CalledOnValidThread());
604 synced_session_tracker_.DeleteSession(foreign_session_tag); 664 synced_session_tracker_.DeleteSession(foreign_session_tag);
605 } 665 }
606 666
607 // Static 667 // Static
668 void SessionModelAssociator::PopulateSessionHeaderFromSpecifics(
669 const sync_pb::SessionHeader& header_specifics,
670 SyncedSession* session_header) {
671 if (header_specifics.has_client_name()) {
672 session_header->client_name = header_specifics.client_name();
673 }
674 if (header_specifics.has_device_type()) {
675 switch (header_specifics.device_type()) {
676 case sync_pb::SessionHeader_DeviceType_TYPE_WIN:
677 session_header->device_type = SyncedSession::TYPE_WIN;
678 break;
679 case sync_pb::SessionHeader_DeviceType_TYPE_MAC:
680 session_header->device_type = SyncedSession::TYPE_MAC;
681 break;
682 case sync_pb::SessionHeader_DeviceType_TYPE_LINUX:
683 session_header->device_type = SyncedSession::TYPE_LINUX;
684 break;
685 case sync_pb::SessionHeader_DeviceType_TYPE_CROS:
686 session_header->device_type = SyncedSession::TYPE_CROS;
687 break;
688 case sync_pb::SessionHeader_DeviceType_TYPE_OTHER:
689 // Intentionally fall-through
690 default:
691 session_header->device_type = SyncedSession::TYPE_OTHER;
692 break;
693 }
694 }
695 }
696
697 // Static
608 void SessionModelAssociator::PopulateSessionWindowFromSpecifics( 698 void SessionModelAssociator::PopulateSessionWindowFromSpecifics(
609 const std::string& session_tag, 699 const std::string& session_tag,
610 const sync_pb::SessionWindow& specifics, 700 const sync_pb::SessionWindow& specifics,
611 int64 mtime, 701 int64 mtime,
612 SessionWindow* session_window, 702 SessionWindow* session_window,
613 SyncedSessionTracker* tracker) { 703 SyncedSessionTracker* tracker) {
614 if (specifics.has_window_id()) 704 if (specifics.has_window_id())
615 session_window->window_id.set_id(specifics.window_id()); 705 session_window->window_id.set_id(specifics.window_id());
616 if (specifics.has_selected_tab_index()) 706 if (specifics.has_selected_tab_index())
617 session_window->selected_tab_index = specifics.selected_tab_index(); 707 session_window->selected_tab_index = specifics.selected_tab_index();
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 bool SessionModelAssociator::CryptoReadyIfNecessary() { 1160 bool SessionModelAssociator::CryptoReadyIfNecessary() {
1071 // We only access the cryptographer while holding a transaction. 1161 // We only access the cryptographer while holding a transaction.
1072 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 1162 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1073 syncable::ModelTypeSet encrypted_types; 1163 syncable::ModelTypeSet encrypted_types;
1074 encrypted_types = sync_api::GetEncryptedTypes(&trans); 1164 encrypted_types = sync_api::GetEncryptedTypes(&trans);
1075 return encrypted_types.count(syncable::SESSIONS) == 0 || 1165 return encrypted_types.count(syncable::SESSIONS) == 0 ||
1076 sync_service_->IsCryptographerReady(&trans); 1166 sync_service_->IsCryptographerReady(&trans);
1077 } 1167 }
1078 1168
1079 } // namespace browser_sync 1169 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698