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

Side by Side Diff: chrome/browser/sync/profile_sync_service.cc

Issue 10834351: [sync] Divorce DataTypeManager from NotificationService notifications by creating a new DataTypeMa… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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) 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/profile_sync_service.h" 5 #include "chrome/browser/sync/profile_sync_service.h"
6 6
7 #include <cstddef> 7 #include <cstddef>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 #include "chrome/browser/ui/browser_window.h" 46 #include "chrome/browser/ui/browser_window.h"
47 #include "chrome/browser/ui/global_error/global_error_service.h" 47 #include "chrome/browser/ui/global_error/global_error_service.h"
48 #include "chrome/browser/ui/global_error/global_error_service_factory.h" 48 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
49 #include "chrome/common/chrome_notification_types.h" 49 #include "chrome/common/chrome_notification_types.h"
50 #include "chrome/common/chrome_switches.h" 50 #include "chrome/common/chrome_switches.h"
51 #include "chrome/common/chrome_version_info.h" 51 #include "chrome/common/chrome_version_info.h"
52 #include "chrome/common/net/gaia/gaia_constants.h" 52 #include "chrome/common/net/gaia/gaia_constants.h"
53 #include "chrome/common/time_format.h" 53 #include "chrome/common/time_format.h"
54 #include "chrome/common/url_constants.h" 54 #include "chrome/common/url_constants.h"
55 #include "content/public/browser/notification_details.h" 55 #include "content/public/browser/notification_details.h"
56 #include "content/public/browser/notification_service.h"
56 #include "content/public/browser/notification_source.h" 57 #include "content/public/browser/notification_source.h"
57 #include "grit/generated_resources.h" 58 #include "grit/generated_resources.h"
58 #include "net/cookies/cookie_monster.h" 59 #include "net/cookies/cookie_monster.h"
59 #include "sync/api/sync_error.h" 60 #include "sync/api/sync_error.h"
60 #include "sync/internal_api/public/configure_reason.h" 61 #include "sync/internal_api/public/configure_reason.h"
61 #include "sync/internal_api/public/sync_encryption_handler.h" 62 #include "sync/internal_api/public/sync_encryption_handler.h"
62 #include "sync/internal_api/public/util/experiments.h" 63 #include "sync/internal_api/public/util/experiments.h"
63 #include "sync/internal_api/public/util/sync_string_conversions.h" 64 #include "sync/internal_api/public/util/sync_string_conversions.h"
64 #include "sync/js/js_arg_list.h" 65 #include "sync/js/js_arg_list.h"
65 #include "sync/js/js_event_details.h" 66 #include "sync/js/js_event_details.h"
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 // change from a native model. In that case, it will get applied to the sync 486 // change from a native model. In that case, it will get applied to the sync
486 // database (which doesn't get destroyed until we destroy the backend below) 487 // database (which doesn't get destroyed until we destroy the backend below)
487 // as an unsynced change. That will be persisted, and committed on restart. 488 // as an unsynced change. That will be persisted, and committed on restart.
488 if (data_type_manager_.get()) { 489 if (data_type_manager_.get()) {
489 if (data_type_manager_->state() != DataTypeManager::STOPPED) { 490 if (data_type_manager_->state() != DataTypeManager::STOPPED) {
490 // When aborting as part of shutdown, we should expect an aborted sync 491 // When aborting as part of shutdown, we should expect an aborted sync
491 // configure result, else we'll dcheck when we try to read the sync error. 492 // configure result, else we'll dcheck when we try to read the sync error.
492 expect_sync_configuration_aborted_ = true; 493 expect_sync_configuration_aborted_ = true;
493 data_type_manager_->Stop(); 494 data_type_manager_->Stop();
494 } 495 }
495 496 if (data_type_manager_->HasObserver(this))
tim (not reviewing) 2012/08/16 18:25:20 I think if data_type_manager_.get(), then this if
Raghu Simha 2012/08/17 01:56:42 Moot. We no longer add / remove observers from her
496 registrar_.Remove( 497 data_type_manager_->RemoveObserver(this);
497 this,
498 chrome::NOTIFICATION_SYNC_CONFIGURE_START,
499 content::Source<DataTypeManager>(data_type_manager_.get()));
500 registrar_.Remove(
501 this,
502 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
503 content::Source<DataTypeManager>(data_type_manager_.get()));
504 registrar_.Remove(
505 this,
506 chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED,
507 content::Source<DataTypeManager>(data_type_manager_.get()));
508 data_type_manager_.reset(); 498 data_type_manager_.reset();
509 } 499 }
510 500
511 // Shutdown the migrator before the backend to ensure it doesn't pull a null 501 // Shutdown the migrator before the backend to ensure it doesn't pull a null
512 // snapshot. 502 // snapshot.
513 migrator_.reset(); 503 migrator_.reset();
514 sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>()); 504 sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>());
515 505
516 // Move aside the backend so nobody else tries to use it while we are 506 // Move aside the backend so nobody else tries to use it while we are
517 // shutting it down. 507 // shutting it down.
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 break; 983 break;
994 case syncer::DISABLE_SYNC_ON_CLIENT: 984 case syncer::DISABLE_SYNC_ON_CLIENT:
995 OnStopSyncingPermanently(); 985 OnStopSyncingPermanently();
996 break; 986 break;
997 default: 987 default:
998 NOTREACHED(); 988 NOTREACHED();
999 } 989 }
1000 NotifyObservers(); 990 NotifyObservers();
1001 } 991 }
1002 992
993 void ProfileSyncService::OnConfigureBlocked() {
994 DCHECK(DataTypeManager::CONFIGURE_BLOCKED ==
995 data_type_manager_->last_configure_result().status);
996 NotifyObservers();
997 }
998
999 void ProfileSyncService::OnConfigureDone() {
1000 // We should have cleared our cached passphrase before we get here (in
1001 // OnBackendInitialized()).
1002 DCHECK(cached_passphrase_.empty());
1003
1004 // Update start / stop times and do UMA logging if required.
1005 UpdateConfigureTimes();
1006
1007 // Notify listeners that configuration is done.
1008 content::NotificationService::current()->Notify(
tim (not reviewing) 2012/08/16 18:25:20 I just realized, another nice part about this new
Raghu Simha 2012/08/17 01:56:42 True. I realised that while debugging and liked th
1009 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
1010 content::Source<ProfileSyncService>(this),
1011 content::NotificationService::NoDetails());
1012
1013 const DataTypeManager::ConfigureResult result =
1014 data_type_manager_->last_configure_result();
1015 configure_status_ = result.status;
1016 DVLOG(1) << "PSS OnConfigureDone called with status: "
1017 << configure_status_;
1018 // The possible status values:
1019 // ABORT - Configuration was aborted. This is not an error, if
1020 // initiated by user.
1021 // OK - Everything succeeded.
1022 // PARTIAL_SUCCESS - Some datatypes failed to start.
1023 // Everything else is an UnrecoverableError. So treat it as such.
1024
1025 // First handle the abort case.
1026 if (configure_status_ == DataTypeManager::ABORTED &&
1027 expect_sync_configuration_aborted_) {
1028 DVLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
1029 expect_sync_configuration_aborted_ = false;
1030 return;
1031 }
1032
1033 // Handle unrecoverable error.
1034 if (configure_status_ != DataTypeManager::OK &&
1035 configure_status_ != DataTypeManager::PARTIAL_SUCCESS) {
1036 // Something catastrophic had happened. We should only have one
1037 // error representing it.
1038 DCHECK_EQ(result.failed_data_types.size(),
1039 static_cast<unsigned int>(1));
1040 syncer::SyncError error = result.failed_data_types.front();
1041 DCHECK(error.IsSet());
1042 std::string message =
1043 "Sync configuration failed with status " +
1044 DataTypeManager::ConfigureStatusToString(configure_status_) +
1045 " during " + syncer::ModelTypeToString(error.type()) +
1046 ": " + error.message();
1047 LOG(ERROR) << "ProfileSyncService error: "
1048 << message;
1049 OnInternalUnrecoverableError(error.location(),
1050 message,
1051 true,
1052 ERROR_REASON_CONFIGURATION_FAILURE);
1053 return;
1054 }
1055
1056 // Now handle partial success and full success.
1057 MessageLoop::current()->PostTask(FROM_HERE,
1058 base::Bind(&ProfileSyncService::OnSyncConfigureDone,
1059 weak_factory_.GetWeakPtr(), result));
1060
1061 // We should never get in a state where we have no encrypted datatypes
1062 // enabled, and yet we still think we require a passphrase for decryption.
1063 DCHECK(!(IsPassphraseRequiredForDecryption() &&
1064 !IsEncryptedDatatypeEnabled()));
1065
1066 // This must be done before we start syncing with the server to avoid
1067 // sending unencrypted data up on a first time sync.
1068 if (encryption_pending_)
1069 backend_->EnableEncryptEverything();
1070 NotifyObservers();
1071
1072 if (migrator_.get() &&
1073 migrator_->state() != browser_sync::BackendMigrator::IDLE) {
1074 // Migration in progress. Let the migrator know we just finished
1075 // configuring something. It will be up to the migrator to call
1076 // StartSyncingWithServer() if migration is now finished.
1077 migrator_->OnConfigureDone(result);
1078 } else {
1079 StartSyncingWithServer();
1080 }
1081 }
1082
1083 void ProfileSyncService::OnConfigureRetry() {
1084 // We should have cleared our cached passphrase before we get here (in
1085 // OnBackendInitialized()).
1086 DCHECK(cached_passphrase_.empty());
1087
1088 DCHECK(DataTypeManager::RETRY ==
1089 data_type_manager_->last_configure_result().status);
1090
1091 // Update start / stop times and do UMA logging if required.
1092 UpdateConfigureTimes();
1093
1094 OnSyncConfigureRetry();
1095 }
1096
1097 void ProfileSyncService::OnConfigureStart() {
1098 sync_configure_start_time_ = base::Time::Now();
1099 content::NotificationService::current()->Notify(
1100 chrome::NOTIFICATION_SYNC_CONFIGURE_START,
1101 content::Source<ProfileSyncService>(this),
1102 content::NotificationService::NoDetails());
1103 NotifyObservers();
1104 }
1105
1106 void ProfileSyncService::UpdateConfigureTimes() {
1107 const DataTypeManager::ConfigureResult result =
1108 data_type_manager_->last_configure_result();
1109 if (!sync_configure_start_time_.is_null()) {
1110 if (result.status == DataTypeManager::OK ||
1111 result.status == DataTypeManager::PARTIAL_SUCCESS) {
1112 base::Time sync_configure_stop_time = base::Time::Now();
1113 base::TimeDelta delta = sync_configure_stop_time -
1114 sync_configure_start_time_;
1115 if (is_first_time_sync_configure_) {
1116 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceInitialConfigureTime", delta);
1117 } else {
1118 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceSubsequentConfigureTime",
1119 delta);
1120 }
1121 }
1122 sync_configure_start_time_ = base::Time();
1123 }
1124 }
1125
1003 std::string ProfileSyncService::QuerySyncStatusSummary() { 1126 std::string ProfileSyncService::QuerySyncStatusSummary() {
1004 if (HasUnrecoverableError()) { 1127 if (HasUnrecoverableError()) {
1005 return "Unrecoverable error detected"; 1128 return "Unrecoverable error detected";
1006 } else if (!backend_.get()) { 1129 } else if (!backend_.get()) {
1007 return "Syncing not enabled"; 1130 return "Syncing not enabled";
1008 } else if (backend_.get() && !HasSyncSetupCompleted()) { 1131 } else if (backend_.get() && !HasSyncSetupCompleted()) {
1009 return "First time sync setup incomplete"; 1132 return "First time sync setup incomplete";
1010 } else if (backend_.get() && HasSyncSetupCompleted() && 1133 } else if (backend_.get() && HasSyncSetupCompleted() &&
1011 data_type_manager_.get() && 1134 data_type_manager_.get() &&
1012 data_type_manager_->state() != DataTypeManager::CONFIGURED) { 1135 data_type_manager_->state() != DataTypeManager::CONFIGURED) {
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 return backend_.get(); 1349 return backend_.get();
1227 } 1350 }
1228 1351
1229 void ProfileSyncService::ConfigureDataTypeManager() { 1352 void ProfileSyncService::ConfigureDataTypeManager() {
1230 bool restart = false; 1353 bool restart = false;
1231 if (!data_type_manager_.get()) { 1354 if (!data_type_manager_.get()) {
1232 restart = true; 1355 restart = true;
1233 data_type_manager_.reset( 1356 data_type_manager_.reset(
1234 factory_->CreateDataTypeManager(backend_.get(), 1357 factory_->CreateDataTypeManager(backend_.get(),
1235 &data_type_controllers_)); 1358 &data_type_controllers_));
1236 registrar_.Add(this, 1359 if (!data_type_manager_->HasObserver(this))
1237 chrome::NOTIFICATION_SYNC_CONFIGURE_START, 1360 data_type_manager_->AddObserver(this);
1238 content::Source<DataTypeManager>(data_type_manager_.get()));
1239 registrar_.Add(this,
1240 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
1241 content::Source<DataTypeManager>(data_type_manager_.get()));
1242 registrar_.Add(this,
1243 chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED,
1244 content::Source<DataTypeManager>(data_type_manager_.get()));
1245 1361
1246 // We create the migrator at the same time. 1362 // We create the migrator at the same time.
1247 migrator_.reset( 1363 migrator_.reset(
1248 new browser_sync::BackendMigrator( 1364 new browser_sync::BackendMigrator(
1249 profile_->GetDebugName(), GetUserShare(), 1365 profile_->GetDebugName(), GetUserShare(),
1250 this, data_type_manager_.get(), 1366 this, data_type_manager_.get(),
1251 base::Bind(&ProfileSyncService::StartSyncingWithServer, 1367 base::Bind(&ProfileSyncService::StartSyncingWithServer,
1252 base::Unretained(this)))); 1368 base::Unretained(this))));
1253 } 1369 }
1254 1370
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 IsSyncTokenAvailable()) { 1622 IsSyncTokenAvailable()) {
1507 // Previously-configured sync has been re-enabled, so start sync now. 1623 // Previously-configured sync has been re-enabled, so start sync now.
1508 StartUp(); 1624 StartUp();
1509 } 1625 }
1510 } 1626 }
1511 1627
1512 void ProfileSyncService::Observe(int type, 1628 void ProfileSyncService::Observe(int type,
1513 const content::NotificationSource& source, 1629 const content::NotificationSource& source,
1514 const content::NotificationDetails& details) { 1630 const content::NotificationDetails& details) {
1515 switch (type) { 1631 switch (type) {
1516 case chrome::NOTIFICATION_SYNC_CONFIGURE_START:
1517 sync_configure_start_time_ = base::Time::Now();
1518 // no break
1519 case chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED:
1520 NotifyObservers();
1521 break;
1522 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: {
1523 // We should have cleared our cached passphrase before we get here (in
1524 // OnBackendInitialized()).
1525 DCHECK(cached_passphrase_.empty());
1526
1527 DataTypeManager::ConfigureResult* result =
1528 content::Details<DataTypeManager::ConfigureResult>(details).ptr();
1529
1530 if (!sync_configure_start_time_.is_null()) {
1531 if (result->status == DataTypeManager::OK ||
1532 result->status == DataTypeManager::PARTIAL_SUCCESS) {
1533 base::Time sync_configure_stop_time = base::Time::Now();
1534 base::TimeDelta delta = sync_configure_stop_time -
1535 sync_configure_start_time_;
1536 if (is_first_time_sync_configure_) {
1537 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceInitialConfigureTime", delta);
1538 } else {
1539 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceSubsequentConfigureTime",
1540 delta);
1541 }
1542 }
1543
1544 sync_configure_start_time_ = base::Time();
1545 }
1546
1547 configure_status_ = result->status;
1548 DVLOG(1) << "PSS SYNC_CONFIGURE_DONE called with status: "
1549 << configure_status_;
1550
1551 // The possible status values:
1552 // ABORT - Configuration was aborted. This is not an error, if
1553 // initiated by user.
1554 // RETRY - Configure failed but we are retrying.
1555 // OK - Everything succeeded.
1556 // PARTIAL_SUCCESS - Some datatypes failed to start.
1557 // Everything else is an UnrecoverableError. So treat it as such.
1558
1559 // First handle the abort case.
1560 if (configure_status_ == DataTypeManager::ABORTED &&
1561 expect_sync_configuration_aborted_) {
1562 DVLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
1563 expect_sync_configuration_aborted_ = false;
1564 return;
1565 }
1566
1567 // Handle retry case.
1568 if (configure_status_ == DataTypeManager::RETRY) {
1569 OnSyncConfigureRetry();
1570 return;
1571 }
1572
1573 // Handle unrecoverable error.
1574 if (configure_status_ != DataTypeManager::OK &&
1575 configure_status_ != DataTypeManager::PARTIAL_SUCCESS) {
1576 // Something catastrophic had happened. We should only have one
1577 // error representing it.
1578 DCHECK_EQ(result->failed_data_types.size(),
1579 static_cast<unsigned int>(1));
1580 syncer::SyncError error = result->failed_data_types.front();
1581 DCHECK(error.IsSet());
1582 std::string message =
1583 "Sync configuration failed with status " +
1584 DataTypeManager::ConfigureStatusToString(configure_status_) +
1585 " during " + syncer::ModelTypeToString(error.type()) +
1586 ": " + error.message();
1587 LOG(ERROR) << "ProfileSyncService error: "
1588 << message;
1589 OnInternalUnrecoverableError(error.location(),
1590 message,
1591 true,
1592 ERROR_REASON_CONFIGURATION_FAILURE);
1593 return;
1594 }
1595
1596 // Now handle partial success and full success.
1597 MessageLoop::current()->PostTask(FROM_HERE,
1598 base::Bind(&ProfileSyncService::OnSyncConfigureDone,
1599 weak_factory_.GetWeakPtr(), *result));
1600
1601 // We should never get in a state where we have no encrypted datatypes
1602 // enabled, and yet we still think we require a passphrase for decryption.
1603 DCHECK(!(IsPassphraseRequiredForDecryption() &&
1604 !IsEncryptedDatatypeEnabled()));
1605
1606 // This must be done before we start syncing with the server to avoid
1607 // sending unencrypted data up on a first time sync.
1608 if (encryption_pending_)
1609 backend_->EnableEncryptEverything();
1610 NotifyObservers();
1611
1612 if (migrator_.get() &&
1613 migrator_->state() != browser_sync::BackendMigrator::IDLE) {
1614 // Migration in progress. Let the migrator know we just finished
1615 // configuring something. It will be up to the migrator to call
1616 // StartSyncingWithServer() if migration is now finished.
1617 migrator_->OnConfigureDone(*result);
1618 } else {
1619 StartSyncingWithServer();
1620 }
1621
1622 break;
1623 }
1624 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { 1632 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
1625 const GoogleServiceSigninSuccessDetails* successful = 1633 const GoogleServiceSigninSuccessDetails* successful =
1626 content::Details<const GoogleServiceSigninSuccessDetails>( 1634 content::Details<const GoogleServiceSigninSuccessDetails>(
1627 details).ptr(); 1635 details).ptr();
1628 DCHECK(!successful->password.empty()); 1636 DCHECK(!successful->password.empty());
1629 if (!sync_prefs_.IsStartSuppressed()) { 1637 if (!sync_prefs_.IsStartSuppressed()) {
1630 cached_passphrase_ = successful->password; 1638 cached_passphrase_ = successful->password;
1631 // Try to consume the passphrase we just cached. If the sync backend 1639 // Try to consume the passphrase we just cached. If the sync backend
1632 // is not running yet, the passphrase will remain cached until the 1640 // is not running yet, the passphrase will remain cached until the
1633 // backend starts up. 1641 // backend starts up.
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine d-behaviour-after-directly-calling-the-destru. 1820 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine d-behaviour-after-directly-calling-the-destru.
1813 ProfileSyncService* old_this = this; 1821 ProfileSyncService* old_this = this;
1814 this->~ProfileSyncService(); 1822 this->~ProfileSyncService();
1815 new(old_this) ProfileSyncService( 1823 new(old_this) ProfileSyncService(
1816 new ProfileSyncComponentsFactoryImpl(profile, 1824 new ProfileSyncComponentsFactoryImpl(profile,
1817 CommandLine::ForCurrentProcess()), 1825 CommandLine::ForCurrentProcess()),
1818 profile, 1826 profile,
1819 signin, 1827 signin,
1820 behavior); 1828 behavior);
1821 } 1829 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698