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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync/glue/typed_url_data_type_controller.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/metrics/histogram.h" 10 #include "base/prefs/pref_service.h" 11 #include "chrome/browser/chrome_notification_types.h" 12 #include "chrome/browser/history/history_db_task.h" 13 #include "chrome/browser/history/history_service.h" 14 #include "chrome/browser/history/history_service_factory.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/sync/glue/typed_url_change_processor.h" 17 #include "chrome/browser/sync/profile_sync_components_factory.h" 18 #include "chrome/browser/sync/profile_sync_service.h" 19 #include "chrome/common/pref_names.h" 20 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/notification_details.h" 22 23 namespace browser_sync { 24 25 using content::BrowserThread; 26 27 namespace { 28 29 // The history service exposes a special non-standard task API which calls back 30 // once a task has been dispatched, so we have to build a special wrapper around 31 // the tasks we want to run. 32 class RunTaskOnHistoryThread : public history::HistoryDBTask { 33 public: 34 explicit RunTaskOnHistoryThread(const base::Closure& task, 35 TypedUrlDataTypeController* dtc) 36 : task_(new base::Closure(task)), 37 dtc_(dtc) { 38 } 39 40 virtual bool RunOnDBThread(history::HistoryBackend* backend, 41 history::HistoryDatabase* db) OVERRIDE { 42 // Set the backend, then release our reference before executing the task. 43 dtc_->SetBackend(backend); 44 dtc_ = NULL; 45 46 // Invoke the task, then free it immediately so we don't keep a reference 47 // around all the way until DoneRunOnMainThread() is invoked back on the 48 // main thread - we want to release references as soon as possible to avoid 49 // keeping them around too long during shutdown. 50 task_->Run(); 51 task_.reset(); 52 return true; 53 } 54 55 virtual void DoneRunOnMainThread() OVERRIDE {} 56 57 protected: 58 virtual ~RunTaskOnHistoryThread() {} 59 60 scoped_ptr<base::Closure> task_; 61 scoped_refptr<TypedUrlDataTypeController> dtc_; 62 }; 63 64 } // namespace 65 66 TypedUrlDataTypeController::TypedUrlDataTypeController( 67 ProfileSyncComponentsFactory* profile_sync_factory, 68 Profile* profile, 69 ProfileSyncService* sync_service) 70 : NonFrontendDataTypeController(profile_sync_factory, 71 profile, 72 sync_service), 73 backend_(NULL) { 74 pref_registrar_.Init(profile->GetPrefs()); 75 pref_registrar_.Add( 76 prefs::kSavingBrowserHistoryDisabled, 77 base::Bind( 78 &TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged, 79 base::Unretained(this))); 80 } 81 82 syncer::ModelType TypedUrlDataTypeController::type() const { 83 return syncer::TYPED_URLS; 84 } 85 86 syncer::ModelSafeGroup TypedUrlDataTypeController::model_safe_group() 87 const { 88 return syncer::GROUP_HISTORY; 89 } 90 91 void TypedUrlDataTypeController::SetBackend(history::HistoryBackend* backend) { 92 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 backend_ = backend; 94 } 95 96 void TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged() { 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 98 if (profile()->GetPrefs()->GetBoolean( 99 prefs::kSavingBrowserHistoryDisabled)) { 100 // We've turned off history persistence, so if we are running, 101 // generate an unrecoverable error. This can be fixed by restarting 102 // Chrome (on restart, typed urls will not be a registered type). 103 if (state() != NOT_RUNNING && state() != STOPPING) { 104 profile_sync_service()->DisableBrokenDatatype( 105 syncer::TYPED_URLS, 106 FROM_HERE, 107 "History saving is now disabled by policy."); 108 } 109 } 110 } 111 112 bool TypedUrlDataTypeController::PostTaskOnBackendThread( 113 const tracked_objects::Location& from_here, 114 const base::Closure& task) { 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 116 HistoryService* history = HistoryServiceFactory::GetForProfile( 117 profile(), Profile::IMPLICIT_ACCESS); 118 if (history) { 119 history->ScheduleDBTask(new RunTaskOnHistoryThread(task, this), 120 &cancelable_consumer_); 121 return true; 122 } else { 123 // History must be disabled - don't start. 124 LOG(WARNING) << "Cannot access history service - disabling typed url sync"; 125 return false; 126 } 127 } 128 129 ProfileSyncComponentsFactory::SyncComponents 130 TypedUrlDataTypeController::CreateSyncComponents() { 131 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 132 DCHECK_EQ(state(), ASSOCIATING); 133 DCHECK(backend_); 134 return profile_sync_factory()->CreateTypedUrlSyncComponents( 135 profile_sync_service(), 136 backend_, 137 this); 138 } 139 140 void TypedUrlDataTypeController::DisconnectProcessor( 141 ChangeProcessor* processor) { 142 static_cast<TypedUrlChangeProcessor*>(processor)->Disconnect(); 143 } 144 145 TypedUrlDataTypeController::~TypedUrlDataTypeController() {} 146 147 } // namespace browser_sync 148