bookmark_data_type_controller.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/histogram.h" 6#include "base/logging.h" 7#include "base/time.h" 8#include "chrome/browser/bookmarks/bookmark_model.h" 9#include "chrome/browser/chrome_thread.h" 10#include "chrome/browser/profile.h" 11#include "chrome/browser/sync/glue/bookmark_change_processor.h" 12#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" 13#include "chrome/browser/sync/glue/bookmark_model_associator.h" 14#include "chrome/browser/sync/profile_sync_service.h" 15#include "chrome/browser/sync/profile_sync_factory.h" 16#include "chrome/common/notification_details.h" 17#include "chrome/common/notification_source.h" 18#include "chrome/common/notification_type.h" 19 20namespace browser_sync { 21 22BookmarkDataTypeController::BookmarkDataTypeController( 23 ProfileSyncFactory* profile_sync_factory, 24 Profile* profile, 25 ProfileSyncService* sync_service) 26 : profile_sync_factory_(profile_sync_factory), 27 profile_(profile), 28 sync_service_(sync_service), 29 state_(NOT_RUNNING) { 30 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 31 DCHECK(profile_sync_factory); 32 DCHECK(profile); 33 DCHECK(sync_service); 34} 35 36BookmarkDataTypeController::~BookmarkDataTypeController() { 37 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 38} 39 40void BookmarkDataTypeController::Start(StartCallback* start_callback) { 41 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 42 DCHECK(start_callback); 43 if (state_ != NOT_RUNNING) { 44 start_callback->Run(BUSY); 45 delete start_callback; 46 return; 47 } 48 49 start_callback_.reset(start_callback); 50 51 if (!enabled()) { 52 FinishStart(NOT_ENABLED); 53 return; 54 } 55 56 state_ = MODEL_STARTING; 57 58 // If the bookmarks model is loaded, continue with association. 59 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); 60 if (bookmark_model && bookmark_model->IsLoaded()) { 61 Associate(); 62 return; 63 } 64 65 // Add an observer and continue when the bookmarks model is loaded. 66 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED, 67 Source<Profile>(sync_service_->profile())); 68} 69 70void BookmarkDataTypeController::Stop() { 71 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 72 // If Stop() is called while Start() is waiting for the bookmark 73 // model to load, abort the start. 74 if (state_ == MODEL_STARTING) 75 FinishStart(ABORTED); 76 77 registrar_.RemoveAll(); 78 if (change_processor_ != NULL) 79 sync_service_->DeactivateDataType(this, change_processor_.get()); 80 81 if (model_associator_ != NULL) 82 model_associator_->DisassociateModels(); 83 84 change_processor_.reset(); 85 model_associator_.reset(); 86 87 state_ = NOT_RUNNING; 88} 89 90void BookmarkDataTypeController::OnUnrecoverableError( 91 const tracked_objects::Location& from_here, const std::string& message) { 92 // The ProfileSyncService will invoke our Stop() method in response to this. 93 UMA_HISTOGRAM_COUNTS("Sync.BookmarkRunFailures", 1); 94 sync_service_->OnUnrecoverableError(from_here, message); 95} 96 97void BookmarkDataTypeController::Observe(NotificationType type, 98 const NotificationSource& source, 99 const NotificationDetails& details) { 100 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 101 DCHECK_EQ(NotificationType::BOOKMARK_MODEL_LOADED, type.value); 102 registrar_.RemoveAll(); 103 Associate(); 104} 105 106void BookmarkDataTypeController::Associate() { 107 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 108 DCHECK_EQ(state_, MODEL_STARTING); 109 state_ = ASSOCIATING; 110 111 ProfileSyncFactory::SyncComponents sync_components = 112 profile_sync_factory_->CreateBookmarkSyncComponents(sync_service_, this); 113 model_associator_.reset(sync_components.model_associator); 114 change_processor_.reset(sync_components.change_processor); 115 116 bool sync_has_nodes = false; 117 if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) { 118 StartFailed(UNRECOVERABLE_ERROR); 119 return; 120 } 121 122 base::TimeTicks start_time = base::TimeTicks::Now(); 123 bool merge_success = model_associator_->AssociateModels(); 124 UMA_HISTOGRAM_TIMES("Sync.BookmarkAssociationTime", 125 base::TimeTicks::Now() - start_time); 126 if (!merge_success) { 127 StartFailed(ASSOCIATION_FAILED); 128 return; 129 } 130 131 sync_service_->ActivateDataType(this, change_processor_.get()); 132 state_ = RUNNING; 133 FinishStart(!sync_has_nodes ? OK_FIRST_RUN : OK); 134} 135 136void BookmarkDataTypeController::FinishStart(StartResult result) { 137 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 138 start_callback_->Run(result); 139 start_callback_.reset(); 140} 141 142void BookmarkDataTypeController::StartFailed(StartResult result) { 143 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 144 model_associator_.reset(); 145 change_processor_.reset(); 146 state_ = NOT_RUNNING; 147 start_callback_->Run(result); 148 start_callback_.reset(); 149 UMA_HISTOGRAM_ENUMERATION("Sync.BookmarkStartFailures", 150 result, 151 MAX_START_RESULT); 152} 153 154} // namespace browser_sync 155