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/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 Loading... |
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 Loading... |
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 registrar_.Remove( | |
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(); | 496 data_type_manager_.reset(); |
509 } | 497 } |
510 | 498 |
511 // Shutdown the migrator before the backend to ensure it doesn't pull a null | 499 // Shutdown the migrator before the backend to ensure it doesn't pull a null |
512 // snapshot. | 500 // snapshot. |
513 migrator_.reset(); | 501 migrator_.reset(); |
514 sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>()); | 502 sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>()); |
515 | 503 |
516 // Move aside the backend so nobody else tries to use it while we are | 504 // Move aside the backend so nobody else tries to use it while we are |
517 // shutting it down. | 505 // shutting it down. |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 break; | 981 break; |
994 case syncer::DISABLE_SYNC_ON_CLIENT: | 982 case syncer::DISABLE_SYNC_ON_CLIENT: |
995 OnStopSyncingPermanently(); | 983 OnStopSyncingPermanently(); |
996 break; | 984 break; |
997 default: | 985 default: |
998 NOTREACHED(); | 986 NOTREACHED(); |
999 } | 987 } |
1000 NotifyObservers(); | 988 NotifyObservers(); |
1001 } | 989 } |
1002 | 990 |
| 991 void ProfileSyncService::OnConfigureBlocked() { |
| 992 NotifyObservers(); |
| 993 } |
| 994 |
| 995 void ProfileSyncService::OnConfigureDone( |
| 996 const browser_sync::DataTypeManager::ConfigureResult& result) { |
| 997 // We should have cleared our cached passphrase before we get here (in |
| 998 // OnBackendInitialized()). |
| 999 DCHECK(cached_passphrase_.empty()); |
| 1000 |
| 1001 if (!sync_configure_start_time_.is_null()) { |
| 1002 if (result.status == DataTypeManager::OK || |
| 1003 result.status == DataTypeManager::PARTIAL_SUCCESS) { |
| 1004 base::Time sync_configure_stop_time = base::Time::Now(); |
| 1005 base::TimeDelta delta = sync_configure_stop_time - |
| 1006 sync_configure_start_time_; |
| 1007 if (is_first_time_sync_configure_) { |
| 1008 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceInitialConfigureTime", delta); |
| 1009 } else { |
| 1010 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceSubsequentConfigureTime", |
| 1011 delta); |
| 1012 } |
| 1013 } |
| 1014 sync_configure_start_time_ = base::Time(); |
| 1015 } |
| 1016 |
| 1017 // Notify listeners that configuration is done. |
| 1018 content::NotificationService::current()->Notify( |
| 1019 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE, |
| 1020 content::Source<ProfileSyncService>(this), |
| 1021 content::NotificationService::NoDetails()); |
| 1022 |
| 1023 configure_status_ = result.status; |
| 1024 DVLOG(1) << "PSS OnConfigureDone called with status: " << configure_status_; |
| 1025 // The possible status values: |
| 1026 // ABORT - Configuration was aborted. This is not an error, if |
| 1027 // initiated by user. |
| 1028 // OK - Everything succeeded. |
| 1029 // PARTIAL_SUCCESS - Some datatypes failed to start. |
| 1030 // Everything else is an UnrecoverableError. So treat it as such. |
| 1031 |
| 1032 // First handle the abort case. |
| 1033 if (configure_status_ == DataTypeManager::ABORTED && |
| 1034 expect_sync_configuration_aborted_) { |
| 1035 DVLOG(0) << "ProfileSyncService::Observe Sync Configure aborted"; |
| 1036 expect_sync_configuration_aborted_ = false; |
| 1037 return; |
| 1038 } |
| 1039 |
| 1040 // Handle unrecoverable error. |
| 1041 if (configure_status_ != DataTypeManager::OK && |
| 1042 configure_status_ != DataTypeManager::PARTIAL_SUCCESS) { |
| 1043 // Something catastrophic had happened. We should only have one |
| 1044 // error representing it. |
| 1045 DCHECK_EQ(result.failed_data_types.size(), |
| 1046 static_cast<unsigned int>(1)); |
| 1047 syncer::SyncError error = result.failed_data_types.front(); |
| 1048 DCHECK(error.IsSet()); |
| 1049 std::string message = |
| 1050 "Sync configuration failed with status " + |
| 1051 DataTypeManager::ConfigureStatusToString(configure_status_) + |
| 1052 " during " + syncer::ModelTypeToString(error.type()) + |
| 1053 ": " + error.message(); |
| 1054 LOG(ERROR) << "ProfileSyncService error: " |
| 1055 << message; |
| 1056 OnInternalUnrecoverableError(error.location(), |
| 1057 message, |
| 1058 true, |
| 1059 ERROR_REASON_CONFIGURATION_FAILURE); |
| 1060 return; |
| 1061 } |
| 1062 |
| 1063 // Now handle partial success and full success. |
| 1064 MessageLoop::current()->PostTask(FROM_HERE, |
| 1065 base::Bind(&ProfileSyncService::OnSyncConfigureDone, |
| 1066 weak_factory_.GetWeakPtr(), result)); |
| 1067 |
| 1068 // We should never get in a state where we have no encrypted datatypes |
| 1069 // enabled, and yet we still think we require a passphrase for decryption. |
| 1070 DCHECK(!(IsPassphraseRequiredForDecryption() && |
| 1071 !IsEncryptedDatatypeEnabled())); |
| 1072 |
| 1073 // This must be done before we start syncing with the server to avoid |
| 1074 // sending unencrypted data up on a first time sync. |
| 1075 if (encryption_pending_) |
| 1076 backend_->EnableEncryptEverything(); |
| 1077 NotifyObservers(); |
| 1078 |
| 1079 if (migrator_.get() && |
| 1080 migrator_->state() != browser_sync::BackendMigrator::IDLE) { |
| 1081 // Migration in progress. Let the migrator know we just finished |
| 1082 // configuring something. It will be up to the migrator to call |
| 1083 // StartSyncingWithServer() if migration is now finished. |
| 1084 migrator_->OnConfigureDone(result); |
| 1085 } else { |
| 1086 StartSyncingWithServer(); |
| 1087 } |
| 1088 } |
| 1089 |
| 1090 void ProfileSyncService::OnConfigureRetry() { |
| 1091 // We should have cleared our cached passphrase before we get here (in |
| 1092 // OnBackendInitialized()). |
| 1093 DCHECK(cached_passphrase_.empty()); |
| 1094 |
| 1095 OnSyncConfigureRetry(); |
| 1096 } |
| 1097 |
| 1098 void ProfileSyncService::OnConfigureStart() { |
| 1099 sync_configure_start_time_ = base::Time::Now(); |
| 1100 content::NotificationService::current()->Notify( |
| 1101 chrome::NOTIFICATION_SYNC_CONFIGURE_START, |
| 1102 content::Source<ProfileSyncService>(this), |
| 1103 content::NotificationService::NoDetails()); |
| 1104 NotifyObservers(); |
| 1105 } |
| 1106 |
1003 std::string ProfileSyncService::QuerySyncStatusSummary() { | 1107 std::string ProfileSyncService::QuerySyncStatusSummary() { |
1004 if (HasUnrecoverableError()) { | 1108 if (HasUnrecoverableError()) { |
1005 return "Unrecoverable error detected"; | 1109 return "Unrecoverable error detected"; |
1006 } else if (!backend_.get()) { | 1110 } else if (!backend_.get()) { |
1007 return "Syncing not enabled"; | 1111 return "Syncing not enabled"; |
1008 } else if (backend_.get() && !HasSyncSetupCompleted()) { | 1112 } else if (backend_.get() && !HasSyncSetupCompleted()) { |
1009 return "First time sync setup incomplete"; | 1113 return "First time sync setup incomplete"; |
1010 } else if (backend_.get() && HasSyncSetupCompleted() && | 1114 } else if (backend_.get() && HasSyncSetupCompleted() && |
1011 data_type_manager_.get() && | 1115 data_type_manager_.get() && |
1012 data_type_manager_->state() != DataTypeManager::CONFIGURED) { | 1116 data_type_manager_->state() != DataTypeManager::CONFIGURED) { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 // knows what it's doing. | 1329 // knows what it's doing. |
1226 return backend_.get(); | 1330 return backend_.get(); |
1227 } | 1331 } |
1228 | 1332 |
1229 void ProfileSyncService::ConfigureDataTypeManager() { | 1333 void ProfileSyncService::ConfigureDataTypeManager() { |
1230 bool restart = false; | 1334 bool restart = false; |
1231 if (!data_type_manager_.get()) { | 1335 if (!data_type_manager_.get()) { |
1232 restart = true; | 1336 restart = true; |
1233 data_type_manager_.reset( | 1337 data_type_manager_.reset( |
1234 factory_->CreateDataTypeManager(backend_.get(), | 1338 factory_->CreateDataTypeManager(backend_.get(), |
1235 &data_type_controllers_)); | 1339 &data_type_controllers_, |
1236 registrar_.Add(this, | 1340 this)); |
1237 chrome::NOTIFICATION_SYNC_CONFIGURE_START, | |
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 | 1341 |
1246 // We create the migrator at the same time. | 1342 // We create the migrator at the same time. |
1247 migrator_.reset( | 1343 migrator_.reset( |
1248 new browser_sync::BackendMigrator( | 1344 new browser_sync::BackendMigrator( |
1249 profile_->GetDebugName(), GetUserShare(), | 1345 profile_->GetDebugName(), GetUserShare(), |
1250 this, data_type_manager_.get(), | 1346 this, data_type_manager_.get(), |
1251 base::Bind(&ProfileSyncService::StartSyncingWithServer, | 1347 base::Bind(&ProfileSyncService::StartSyncingWithServer, |
1252 base::Unretained(this)))); | 1348 base::Unretained(this)))); |
1253 } | 1349 } |
1254 | 1350 |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 IsSyncTokenAvailable()) { | 1602 IsSyncTokenAvailable()) { |
1507 // Previously-configured sync has been re-enabled, so start sync now. | 1603 // Previously-configured sync has been re-enabled, so start sync now. |
1508 StartUp(); | 1604 StartUp(); |
1509 } | 1605 } |
1510 } | 1606 } |
1511 | 1607 |
1512 void ProfileSyncService::Observe(int type, | 1608 void ProfileSyncService::Observe(int type, |
1513 const content::NotificationSource& source, | 1609 const content::NotificationSource& source, |
1514 const content::NotificationDetails& details) { | 1610 const content::NotificationDetails& details) { |
1515 switch (type) { | 1611 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: { | 1612 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { |
1625 const GoogleServiceSigninSuccessDetails* successful = | 1613 const GoogleServiceSigninSuccessDetails* successful = |
1626 content::Details<const GoogleServiceSigninSuccessDetails>( | 1614 content::Details<const GoogleServiceSigninSuccessDetails>( |
1627 details).ptr(); | 1615 details).ptr(); |
1628 DCHECK(!successful->password.empty()); | 1616 DCHECK(!successful->password.empty()); |
1629 if (!sync_prefs_.IsStartSuppressed()) { | 1617 if (!sync_prefs_.IsStartSuppressed()) { |
1630 cached_passphrase_ = successful->password; | 1618 cached_passphrase_ = successful->password; |
1631 // Try to consume the passphrase we just cached. If the sync backend | 1619 // Try to consume the passphrase we just cached. If the sync backend |
1632 // is not running yet, the passphrase will remain cached until the | 1620 // is not running yet, the passphrase will remain cached until the |
1633 // backend starts up. | 1621 // backend starts up. |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine
d-behaviour-after-directly-calling-the-destru. | 1800 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine
d-behaviour-after-directly-calling-the-destru. |
1813 ProfileSyncService* old_this = this; | 1801 ProfileSyncService* old_this = this; |
1814 this->~ProfileSyncService(); | 1802 this->~ProfileSyncService(); |
1815 new(old_this) ProfileSyncService( | 1803 new(old_this) ProfileSyncService( |
1816 new ProfileSyncComponentsFactoryImpl(profile, | 1804 new ProfileSyncComponentsFactoryImpl(profile, |
1817 CommandLine::ForCurrentProcess()), | 1805 CommandLine::ForCurrentProcess()), |
1818 profile, | 1806 profile, |
1819 signin, | 1807 signin, |
1820 behavior); | 1808 behavior); |
1821 } | 1809 } |
OLD | NEW |