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 bool TypedUrlDataTypeController::ReadyForStart() const {
     96   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     97   return !profile()->GetPrefs()->GetBoolean(
     98       prefs::kSavingBrowserHistoryDisabled);
     99 }
    100 
    101 void TypedUrlDataTypeController::SetBackend(history::HistoryBackend* backend) {
    102   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
    103   backend_ = backend;
    104 }
    105 
    106 void TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged() {
    107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    108   if (profile()->GetPrefs()->GetBoolean(
    109           prefs::kSavingBrowserHistoryDisabled)) {
    110     // We've turned off history persistence, so if we are running,
    111     // generate an unrecoverable error. This can be fixed by restarting
    112     // Chrome (on restart, typed urls will not be a registered type).
    113     if (state() != NOT_RUNNING && state() != STOPPING) {
    114       syncer::SyncError error(
    115           FROM_HERE,
    116           syncer::SyncError::DATATYPE_POLICY_ERROR,
    117           "History saving is now disabled by policy.",
    118           syncer::TYPED_URLS);
    119       DisableImpl(error);
    120     }
    121   }
    122 }
    123 
    124 bool TypedUrlDataTypeController::PostTaskOnBackendThread(
    125     const tracked_objects::Location& from_here,
    126     const base::Closure& task) {
    127   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    128   HistoryService* history = HistoryServiceFactory::GetForProfile(
    129       profile(), Profile::IMPLICIT_ACCESS);
    130   if (history) {
    131     history->ScheduleDBTask(
    132         scoped_ptr<history::HistoryDBTask>(
    133             new RunTaskOnHistoryThread(task, this)),
    134         &task_tracker_);
    135     return true;
    136   } else {
    137     // History must be disabled - don't start.
    138     LOG(WARNING) << "Cannot access history service - disabling typed url sync";
    139     return false;
    140   }
    141 }
    142 
    143 ProfileSyncComponentsFactory::SyncComponents
    144 TypedUrlDataTypeController::CreateSyncComponents() {
    145   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
    146   DCHECK_EQ(state(), ASSOCIATING);
    147   DCHECK(backend_);
    148   return profile_sync_factory()->CreateTypedUrlSyncComponents(
    149       profile_sync_service(),
    150       backend_,
    151       this);
    152 }
    153 
    154 void TypedUrlDataTypeController::DisconnectProcessor(
    155     sync_driver::ChangeProcessor* processor) {
    156   static_cast<TypedUrlChangeProcessor*>(processor)->Disconnect();
    157 }
    158 
    159 TypedUrlDataTypeController::~TypedUrlDataTypeController() {}
    160 
    161 }  // namespace browser_sync
    162