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

Unified Diff: components/browser_sync/profile_sync_service.cc

Issue 2663783002: [Sync] Split encryption state and logic out of PSS and SBHI. (Closed)
Patch Set: Self-review. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: components/browser_sync/profile_sync_service.cc
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 1acbeeedbccc9700d0a48562f588a4a64684efe1..2f050adc20575e9e135b53d271bab19afd530db9 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -118,26 +118,6 @@ namespace {
typedef GoogleServiceAuthError AuthError;
-// Events in ClearServerData flow to be recorded in histogram. Existing
-// constants should not be deleted or reordered. New ones shold be added at the
-// end, before CLEAR_SERVER_DATA_MAX.
-enum ClearServerDataEvents {
- // ClearServerData started after user switched to custom passphrase.
- CLEAR_SERVER_DATA_STARTED,
- // DataTypeManager reported that catchup configuration failed.
- CLEAR_SERVER_DATA_CATCHUP_FAILED,
- // ClearServerData flow restarted after browser restart.
- CLEAR_SERVER_DATA_RETRIED,
- // Success.
- CLEAR_SERVER_DATA_SUCCEEDED,
- // Client received RECET_LOCAL_SYNC_DATA after custom passphrase was enabled
- // on different client.
- CLEAR_SERVER_DATA_RESET_LOCAL_DATA_RECEIVED,
- CLEAR_SERVER_DATA_MAX
-};
-
-const char kClearServerDataEventsHistogramName[] = "Sync.ClearServerDataEvents";
-
const char kSyncUnrecoverableErrorHistogram[] = "Sync.UnrecoverableErrors";
const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
@@ -185,7 +165,6 @@ ProfileSyncService::ProfileSyncService(InitParams init_params)
init_params.debug_identifier),
OAuth2TokenService::Consumer("sync"),
last_auth_error_(AuthError::AuthErrorNone()),
- passphrase_required_reason_(syncer::REASON_PASSPHRASE_NOT_REQUIRED),
sync_service_url_(
syncer::GetSyncServiceURL(*base::CommandLine::ForCurrentProcess(),
init_params.channel)),
@@ -200,10 +179,6 @@ ProfileSyncService::ProfileSyncService(InitParams init_params)
local_sync_backend_folder_(init_params.local_sync_backend_folder),
unrecoverable_error_reason_(ERROR_REASON_UNSET),
expect_sync_configuration_aborted_(false),
- encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()),
- encrypt_everything_allowed_(true),
- encrypt_everything_(false),
- encryption_pending_(false),
configure_status_(DataTypeManager::UNKNOWN),
oauth2_token_service_(init_params.oauth2_token_service),
request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
@@ -373,10 +348,11 @@ void ProfileSyncService::StartSyncingWithServer() {
switches::kSyncClearDataOnPassphraseEncryption) &&
sync_prefs_.GetPassphraseEncryptionTransitionInProgress()) {
// We are restarting catchup configuration after browser restart.
- UMA_HISTOGRAM_ENUMERATION(kClearServerDataEventsHistogramName,
- CLEAR_SERVER_DATA_RETRIED, CLEAR_SERVER_DATA_MAX);
+ UMA_HISTOGRAM_ENUMERATION("Sync.ClearServerDataEvents",
+ syncer::CLEAR_SERVER_DATA_RETRIED,
+ syncer::CLEAR_SERVER_DATA_MAX);
- BeginConfigureCatchUpBeforeClear();
+ crypto_->BeginConfigureCatchUpBeforeClear();
return;
}
@@ -502,11 +478,6 @@ ProfileSyncService::MakeHttpPostProviderFactoryGetter() {
url_request_context_, network_time_update_callback_);
}
-std::unique_ptr<syncer::SyncEncryptionHandler::NigoriState>
-ProfileSyncService::MoveSavedNigoriState() {
- return std::move(saved_nigori_state_);
-}
-
syncer::WeakHandle<syncer::UnrecoverableErrorHandler>
ProfileSyncService::GetUnrecoverableErrorHandler() {
return syncer::MakeWeakHandle(sync_enabled_weak_factory_.GetWeakPtr());
@@ -775,14 +746,10 @@ void ProfileSyncService::ShutdownImpl(syncer::ShutdownReason reason) {
}
// Clear various state.
+ ResetCryptoState();
expect_sync_configuration_aborted_ = false;
is_auth_in_progress_ = false;
engine_initialized_ = false;
- cached_passphrase_.clear();
- encryption_pending_ = false;
- encrypt_everything_ = false;
- encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes();
- passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
access_token_.clear();
request_access_token_retry_timer_.Stop();
last_snapshot_ = syncer::SyncCycleSnapshot();
@@ -828,11 +795,6 @@ void ProfileSyncService::UpdateLastSyncedTime() {
sync_prefs_.SetLastSyncedTime(base::Time::Now());
}
-void ProfileSyncService::NotifyObservers() {
- for (auto& observer : observers_)
- observer.OnStateChanged();
-}
-
void ProfileSyncService::NotifySyncCycleCompleted() {
for (auto& observer : observers_)
observer.OnSyncCycleCompleted();
@@ -976,7 +938,7 @@ void ProfileSyncService::OnEngineInitialized(
// If we have a cached passphrase use it to decrypt/encrypt data now that the
// backend is initialized. We want to call this before notifying observers in
// case this operation affects the "passphrase required" status.
- ConsumeCachedPassphraseIfPossible();
+ crypto_->ConsumeCachedPassphraseIfPossible();
// The very first time the backend initializes is effectively the first time
// we can say we successfully "synced". LastSyncedTime will only be null in
@@ -990,6 +952,9 @@ void ProfileSyncService::OnEngineInitialized(
initial_types, debug_info_listener_, &data_type_controllers_, this,
engine_.get(), this));
+ crypto_->SetSyncEngine(engine_.get());
+ crypto_->SetDataTypeManager(data_type_manager_.get());
+
// Auto-start means IsFirstSetupComplete gets set automatically.
if (start_behavior_ == AUTO_START && !IsFirstSetupComplete()) {
// This will trigger a configure if it completes setup.
@@ -1139,86 +1104,6 @@ void ProfileSyncService::OnConnectionStatusChange(
}
}
-void ProfileSyncService::OnPassphraseRequired(
- syncer::PassphraseRequiredReason reason,
- const sync_pb::EncryptedData& pending_keys) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(engine_);
- DCHECK(engine_->IsNigoriEnabled());
-
- // TODO(lipalani) : add this check to other locations as well.
- if (HasUnrecoverableError()) {
- // When unrecoverable error is detected we post a task to shutdown the
- // engine. The task might not have executed yet.
- return;
- }
-
- DVLOG(1) << "Passphrase required with reason: "
- << syncer::PassphraseRequiredReasonToString(reason);
- passphrase_required_reason_ = reason;
-
- const syncer::ModelTypeSet types = GetPreferredDataTypes();
- if (data_type_manager_) {
- // Reconfigure without the encrypted types (excluded implicitly via the
- // failed datatypes handler).
- data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CRYPTO);
- }
-
- // Notify observers that the passphrase status may have changed.
- NotifyObservers();
-}
-
-void ProfileSyncService::OnPassphraseAccepted() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(1) << "Received OnPassphraseAccepted.";
-
- // If the pending keys were resolved via keystore, it's possible we never
- // consumed our cached passphrase. Clear it now.
- if (!cached_passphrase_.empty())
- cached_passphrase_.clear();
-
- // Reset passphrase_required_reason_ since we know we no longer require the
- // passphrase.
- passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
-
- // Make sure the data types that depend on the passphrase are started at
- // this time.
- const syncer::ModelTypeSet types = GetPreferredDataTypes();
- if (data_type_manager_) {
- // Re-enable any encrypted types if necessary.
- data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CRYPTO);
- }
-
- NotifyObservers();
-}
-
-void ProfileSyncService::OnEncryptedTypesChanged(
- syncer::ModelTypeSet encrypted_types,
- bool encrypt_everything) {
- DCHECK(thread_checker_.CalledOnValidThread());
- encrypted_types_ = encrypted_types;
- encrypt_everything_ = encrypt_everything;
- DCHECK(encrypt_everything_allowed_ || !encrypt_everything_);
- DVLOG(1) << "Encrypted types changed to "
- << syncer::ModelTypeSetToString(encrypted_types_)
- << " (encrypt everything is set to "
- << (encrypt_everything_ ? "true" : "false") << ")";
- DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
-
- NotifyObservers();
-}
-
-void ProfileSyncService::OnEncryptionComplete() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(1) << "Encryption complete";
- if (encryption_pending_ && encrypt_everything_) {
- encryption_pending_ = false;
- // This is to nudge the integration tests when encryption is
- // finished.
- NotifyObservers();
- }
-}
-
void ProfileSyncService::OnMigrationNeededForTypes(syncer::ModelTypeSet types) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(engine_initialized_);
@@ -1273,9 +1158,10 @@ void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
case syncer::RESET_LOCAL_SYNC_DATA:
ShutdownImpl(syncer::DISABLE_SYNC);
startup_controller_->TryStart();
- UMA_HISTOGRAM_ENUMERATION(kClearServerDataEventsHistogramName,
- CLEAR_SERVER_DATA_RESET_LOCAL_DATA_RECEIVED,
- CLEAR_SERVER_DATA_MAX);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Sync.ClearServerDataEvents",
+ syncer::CLEAR_SERVER_DATA_RESET_LOCAL_DATA_RECEIVED,
+ syncer::CLEAR_SERVER_DATA_MAX);
break;
default:
NOTREACHED();
@@ -1283,35 +1169,6 @@ void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
NotifyObservers();
}
-void ProfileSyncService::OnLocalSetPassphraseEncryption(
- const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!base::FeatureList::IsEnabled(
- switches::kSyncClearDataOnPassphraseEncryption))
- return;
-
- // At this point the user has set a custom passphrase and we have received the
- // updated nigori state. Time to cache the nigori state, and catch up the
- // active data types.
- UMA_HISTOGRAM_ENUMERATION(kClearServerDataEventsHistogramName,
- CLEAR_SERVER_DATA_STARTED, CLEAR_SERVER_DATA_MAX);
- sync_prefs_.SetNigoriSpecificsForPassphraseTransition(
- nigori_state.nigori_specifics);
- sync_prefs_.SetPassphraseEncryptionTransitionInProgress(true);
- BeginConfigureCatchUpBeforeClear();
-}
-
-void ProfileSyncService::BeginConfigureCatchUpBeforeClear() {
- DCHECK(data_type_manager_);
- DCHECK(!saved_nigori_state_);
- saved_nigori_state_ =
- base::MakeUnique<syncer::SyncEncryptionHandler::NigoriState>();
- sync_prefs_.GetNigoriSpecificsForPassphraseTransition(
- &saved_nigori_state_->nigori_specifics);
- const syncer::ModelTypeSet types = GetActiveDataTypes();
- data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CATCH_UP);
-}
-
void ProfileSyncService::ClearAndRestartSyncForPassphraseEncryption() {
DCHECK(thread_checker_.CalledOnValidThread());
engine_->ClearServerData(
@@ -1331,8 +1188,9 @@ void ProfileSyncService::OnClearServerDataDone() {
// nigori state.
ShutdownImpl(syncer::DISABLE_SYNC);
startup_controller_->TryStart();
- UMA_HISTOGRAM_ENUMERATION(kClearServerDataEventsHistogramName,
- CLEAR_SERVER_DATA_SUCCEEDED, CLEAR_SERVER_DATA_MAX);
+ UMA_HISTOGRAM_ENUMERATION("Sync.ClearServerDataEvents",
+ syncer::CLEAR_SERVER_DATA_SUCCEEDED,
+ syncer::CLEAR_SERVER_DATA_MAX);
}
void ProfileSyncService::OnConfigureDone(
@@ -1343,7 +1201,7 @@ void ProfileSyncService::OnConfigureDone(
// We should have cleared our cached passphrase before we get here (in
// OnEngineInitialized()).
- DCHECK(cached_passphrase_.empty());
+ DCHECK(crypto_->cached_passphrase().empty());
if (!sync_configure_start_time_.is_null()) {
if (configure_status_ == DataTypeManager::OK) {
@@ -1382,9 +1240,9 @@ void ProfileSyncService::OnConfigureDone(
if (configure_status_ != DataTypeManager::OK) {
if (result.was_catch_up_configure) {
// Record catchup configuration failure.
- UMA_HISTOGRAM_ENUMERATION(kClearServerDataEventsHistogramName,
- CLEAR_SERVER_DATA_CATCHUP_FAILED,
- CLEAR_SERVER_DATA_MAX);
+ UMA_HISTOGRAM_ENUMERATION("Sync.ClearServerDataEvents",
+ syncer::CLEAR_SERVER_DATA_CATCHUP_FAILED,
+ syncer::CLEAR_SERVER_DATA_MAX);
}
// Something catastrophic had happened. We should only have one
// error representing it.
@@ -1412,7 +1270,7 @@ void ProfileSyncService::OnConfigureDone(
// This must be done before we start syncing with the server to avoid
// sending unencrypted data up on a first time sync.
- if (encryption_pending_)
+ if (crypto_->encryption_pending())
engine_->EnableEncryptEverything();
NotifyObservers();
@@ -1598,7 +1456,8 @@ bool ProfileSyncService::HasUnrecoverableError() const {
bool ProfileSyncService::IsPassphraseRequired() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return passphrase_required_reason_ != syncer::REASON_PASSPHRASE_NOT_REQUIRED;
+ return crypto_->passphrase_required_reason() !=
+ syncer::REASON_PASSPHRASE_NOT_REQUIRED;
}
bool ProfileSyncService::IsPassphraseRequiredForDecryption() const {
@@ -1771,10 +1630,7 @@ syncer::ModelTypeSet ProfileSyncService::GetRegisteredDataTypes() const {
bool ProfileSyncService::IsUsingSecondaryPassphrase() const {
DCHECK(thread_checker_.CalledOnValidThread());
- syncer::PassphraseType passphrase_type = GetPassphraseType();
- return passphrase_type ==
- syncer::PassphraseType::FROZEN_IMPLICIT_PASSPHRASE ||
- passphrase_type == syncer::PassphraseType::CUSTOM_PASSPHRASE;
+ return crypto_->IsUsingSecondaryPassphrase();
}
std::string ProfileSyncService::GetCustomPassphraseKey() const {
@@ -1787,12 +1643,12 @@ std::string ProfileSyncService::GetCustomPassphraseKey() const {
syncer::PassphraseType ProfileSyncService::GetPassphraseType() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return engine_->GetPassphraseType();
+ return crypto_->GetPassphraseType();
}
base::Time ProfileSyncService::GetExplicitPassphraseTime() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return engine_->GetExplicitPassphraseTime();
+ return crypto_->GetExplicitPassphraseTime();
}
bool ProfileSyncService::IsCryptographerReady(
@@ -2001,32 +1857,6 @@ std::unique_ptr<base::Value> ProfileSyncService::GetTypeStatusMap() {
return std::move(result);
}
-void ProfileSyncService::ConsumeCachedPassphraseIfPossible() {
- // If no cached passphrase, or sync engine hasn't started up yet, just exit.
- // If the engine isn't running yet, OnEngineInitialized() will call this
- // method again after the engine starts up.
- if (cached_passphrase_.empty() || !IsEngineInitialized())
- return;
-
- // Engine is up and running, so we can consume the cached passphrase.
- std::string passphrase = cached_passphrase_;
- cached_passphrase_.clear();
-
- // If we need a passphrase to decrypt data, try the cached passphrase.
- if (passphrase_required_reason() == syncer::REASON_DECRYPTION) {
- if (SetDecryptionPassphrase(passphrase)) {
- DVLOG(1) << "Cached passphrase successfully decrypted pending keys";
- return;
- }
- }
-
- // If we get here, we don't have pending keys (or at least, the passphrase
- // doesn't decrypt them) - just try to re-encrypt using the encryption
- // passphrase.
- if (!IsUsingSecondaryPassphrase())
- SetEncryptionPassphrase(passphrase, IMPLICIT);
-}
-
void ProfileSyncService::RequestAccessToken() {
// Only one active request at a time.
if (access_token_request_ != nullptr)
@@ -2055,26 +1885,7 @@ void ProfileSyncService::RequestAccessToken() {
void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
PassphraseType type) {
DCHECK(thread_checker_.CalledOnValidThread());
- // This should only be called when the engine has been initialized.
- DCHECK(IsEngineInitialized());
- DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase()))
- << "Data is already encrypted using an explicit passphrase";
- DCHECK(!(type == EXPLICIT &&
- passphrase_required_reason_ == syncer::REASON_DECRYPTION))
- << "Can not set explicit passphrase when decryption is needed.";
-
- DVLOG(1) << "Setting " << (type == EXPLICIT ? "explicit" : "implicit")
- << " passphrase for encryption.";
- if (passphrase_required_reason_ == syncer::REASON_ENCRYPTION) {
- // REASON_ENCRYPTION implies that the cryptographer does not have pending
- // keys. Hence, as long as we're not trying to do an invalid passphrase
- // change (e.g. explicit -> explicit or explicit -> implicit), we know this
- // will succeed. If for some reason a new encryption key arrives via
- // sync later, the SBH will trigger another OnPassphraseRequired().
- passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
- NotifyObservers();
- }
- engine_->SetEncryptionPassphrase(passphrase, type == EXPLICIT);
+ crypto_->SetEncryptionPassphrase(passphrase, type == EXPLICIT);
}
bool ProfileSyncService::SetDecryptionPassphrase(
@@ -2082,7 +1893,7 @@ bool ProfileSyncService::SetDecryptionPassphrase(
DCHECK(thread_checker_.CalledOnValidThread());
if (IsPassphraseRequired()) {
DVLOG(1) << "Setting passphrase for decryption.";
- bool result = engine_->SetDecryptionPassphrase(passphrase);
+ bool result = crypto_->SetDecryptionPassphrase(passphrase);
UMA_HISTOGRAM_BOOLEAN("Sync.PassphraseDecryptionSucceeded", result);
return result;
} else {
@@ -2094,27 +1905,17 @@ bool ProfileSyncService::SetDecryptionPassphrase(
bool ProfileSyncService::IsEncryptEverythingAllowed() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return encrypt_everything_allowed_;
+ return crypto_->IsEncryptEverythingAllowed();
}
void ProfileSyncService::SetEncryptEverythingAllowed(bool allowed) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(allowed || !IsEngineInitialized() || !IsEncryptEverythingEnabled());
- encrypt_everything_allowed_ = allowed;
+ crypto_->SetEncryptEverythingAllowed(allowed);
}
void ProfileSyncService::EnableEncryptEverything() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(IsEncryptEverythingAllowed());
-
- // Tests override IsEngineInitialized() to always return true, so we
- // must check that instead of |engine_initialized_|.
- // TODO(akalin): Fix the above. :/
- DCHECK(IsEngineInitialized());
- // TODO(atwilson): Persist the encryption_pending_ flag to address the various
- // problems around cancelling encryption in the background (crbug.com/119649).
- if (!encrypt_everything_)
- encryption_pending_ = true;
+ crypto_->EnableEncryptEverything();
}
bool ProfileSyncService::encryption_pending() const {
@@ -2122,21 +1923,17 @@ bool ProfileSyncService::encryption_pending() const {
// We may be called during the setup process before we're
// initialized (via IsEncryptedDatatypeEnabled and
// IsPassphraseRequiredForDecryption).
- return encryption_pending_;
+ return crypto_->encryption_pending();
}
bool ProfileSyncService::IsEncryptEverythingEnabled() const {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(engine_initialized_);
- return encrypt_everything_ || encryption_pending_;
+ return crypto_->IsEncryptEverythingEnabled();
}
syncer::ModelTypeSet ProfileSyncService::GetEncryptedDataTypes() const {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
- // We may be called during the setup process before we're
- // initialized. In this case, we default to the sensitive types.
- return encrypted_types_;
+ return crypto_->GetEncryptedDataTypes();
}
void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) {
@@ -2154,11 +1951,11 @@ void ProfileSyncService::GoogleSigninSucceeded(const std::string& account_id,
const std::string& password) {
DCHECK(thread_checker_.CalledOnValidThread());
if (IsSyncRequested() && !password.empty()) {
- cached_passphrase_ = password;
+ crypto_->CachePassphrase(password);
// Try to consume the passphrase we just cached. If the sync engine
// is not running yet, the passphrase will remain cached until the
// engine starts up.
- ConsumeCachedPassphraseIfPossible();
+ crypto_->ConsumeCachedPassphraseIfPossible();
}
#if defined(OS_CHROMEOS)
RefreshSpareBootstrapToken(password);
@@ -2203,16 +2000,6 @@ void ProfileSyncService::OnGaiaAccountsInCookieUpdated(
engine_->OnCookieJarChanged(cookie_jar_mismatch, cookie_jar_empty);
}
-void ProfileSyncService::AddObserver(syncer::SyncServiceObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void ProfileSyncService::RemoveObserver(syncer::SyncServiceObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.RemoveObserver(observer);
-}
-
void ProfileSyncService::AddProtocolEventObserver(
ProtocolEventObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -2364,12 +2151,6 @@ void ProfileSyncService::GetAllNodes(
}
}
-bool ProfileSyncService::HasObserver(
- const syncer::SyncServiceObserver* observer) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return observers_.HasObserver(observer);
-}
-
base::WeakPtr<syncer::JsController> ProfileSyncService::GetJsController() {
DCHECK(thread_checker_.CalledOnValidThread());
return sync_js_controller_.AsWeakPtr();
@@ -2554,6 +2335,11 @@ base::MessageLoop* ProfileSyncService::GetSyncLoopForTest() const {
}
}
+syncer::SyncEncryptionHandler::Observer*
+ProfileSyncService::GetEncryptionObserverForTest() const {
+ return crypto_.get();
+}
+
void ProfileSyncService::RefreshTypesForTest(syncer::ModelTypeSet types) {
DCHECK(thread_checker_.CalledOnValidThread());
if (engine_initialized_)

Powered by Google App Engine
This is Rietveld 408576698