1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/sync/glue/password_data_type_controller.h" 6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/password_manager/password_store.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/password_change_processor.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/password_model_associator.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_service.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_factory.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPasswordDataTypeController::PasswordDataTypeController( 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileSyncFactory* profile_sync_factory, 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileSyncService* sync_service) 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : profile_sync_factory_(profile_sync_factory), 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_(profile), 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_(sync_service), 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state_(NOT_RUNNING), 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_(false), 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_complete_(false, false), 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen datatype_stopped_(false, false) { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(profile_sync_factory); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(profile); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(sync_service); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPasswordDataTypeController::~PasswordDataTypeController() { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::Start(StartCallback* start_callback) { 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(start_callback); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ != NOT_RUNNING) { 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen start_callback->Run(BUSY, FROM_HERE); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete start_callback; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen password_store_ = profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS); 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!password_store_.get()) { 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "PasswordStore not initialized, password datatype controller" 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " aborting."; 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen state_ = NOT_RUNNING; 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen start_callback->Run(ABORTED, FROM_HERE); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete start_callback; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_callback_.reset(start_callback); 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_ = false; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_state(ASSOCIATING); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_->ScheduleTask( 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &PasswordDataTypeController::StartImpl)); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// distinguishing chrome shutdown from sync shutdown, we should be able to avoid 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// this (http://crbug.com/55662). Further, all this functionality should be 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// abstracted to a higher layer, where we could ensure all datatypes are doing 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// the same thing (http://crbug.com/76232). 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::Stop() { 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If Stop() is called while Start() is waiting for association to 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // complete, we need to abort the association and wait for the PASSWORD 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // thread to finish the StartImpl() task. 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (state_ == ASSOCIATING) { 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::AutoLock lock(abort_association_lock_); 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_ = true; 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (model_associator_.get()) 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->AbortAssociation(); 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Wait for the model association to abort. 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_complete_.Wait(); 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartDoneImpl(ABORTED, STOPPING); 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If Stop() is called while Start() is waiting for another service to load, 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // abort the start. 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (state_ == MODEL_STARTING) 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartDoneImpl(ABORTED, STOPPING); 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!start_callback_.get()); 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (change_processor_ != NULL) 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->DeactivateDataType(this, change_processor_.get()); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_state(NOT_RUNNING); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(password_store_.get()); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_->ScheduleTask( 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &PasswordDataTypeController::StopImpl)); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen datatype_stopped_.Wait(); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PasswordDataTypeController::enabled() { 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsensyncable::ModelType PasswordDataTypeController::type() const { 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return syncable::PASSWORDS; 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbrowser_sync::ModelSafeGroup PasswordDataTypeController::model_safe_group() 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const { 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return browser_sync::GROUP_PASSWORD; 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string PasswordDataTypeController::name() const { 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // For logging only. 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return "password"; 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDataTypeController::State PasswordDataTypeController::state() const { 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return state_; 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::StartImpl() { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No additional services need to be started before we can proceed 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with model association. 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::AutoLock lock(abort_association_lock_); 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (abort_association_) { 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_complete_.Signal(); 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileSyncFactory::SyncComponents sync_components = 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_sync_factory_->CreatePasswordSyncComponents( 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_service_, 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen password_store_.get(), 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this); 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_.reset(sync_components.model_associator); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_processor_.reset(sync_components.change_processor); 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!model_associator_->CryptoReadyIfNecessary()) { 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartFailed(NEEDS_CRYPTO); 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool sync_has_nodes = false; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartFailed(UNRECOVERABLE_ERROR); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks start_time = base::TimeTicks::Now(); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool merge_success = model_associator_->AssociateModels(); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("Sync.PasswordAssociationTime", 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks::Now() - start_time); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!merge_success) { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartFailed(ASSOCIATION_FAILED); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->ActivateDataType(this, change_processor_.get()); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::StartDone( 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DataTypeController::StartResult result, 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DataTypeController::State new_state) { 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen abort_association_complete_.Signal(); 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::AutoLock lock(abort_association_lock_); 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!abort_association_) { 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod( 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &PasswordDataTypeController::StartDoneImpl, 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result, 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_state)); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::StartDoneImpl( 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DataTypeController::StartResult result, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DataTypeController::State new_state) { 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_state(new_state); 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen start_callback_->Run(result, FROM_HERE); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_callback_.reset(); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::StopImpl() { 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (model_associator_ != NULL) 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_associator_->DisassociateModels(); 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_processor_.reset(); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_.reset(); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen datatype_stopped_.Signal(); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::StartFailed(StartResult result) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_processor_.reset(); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_.reset(); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartDone(result, NOT_RUNNING); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::OnUnrecoverableError( 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const tracked_objects::Location& from_here, const std::string& message) { 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &PasswordDataTypeController::OnUnrecoverableErrorImpl, 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch from_here, message)); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordDataTypeController::OnUnrecoverableErrorImpl( 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const tracked_objects::Location& from_here, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& message) { 222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_service_->OnUnrecoverableError(from_here, message); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 227