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