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/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