Home | History | Annotate | Download | only in notifier
      1 // Copyright (c) 2010 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/notifier/chrome_system_resources.h"
      6 
      7 #include <cstdlib>
      8 #include <cstring>
      9 #include <string>
     10 
     11 #include "base/logging.h"
     12 #include "base/message_loop.h"
     13 #include "base/stl_util-inl.h"
     14 #include "base/string_util.h"
     15 #include "base/stringprintf.h"
     16 #include "chrome/browser/sync/notifier/invalidation_util.h"
     17 
     18 namespace sync_notifier {
     19 
     20 ChromeSystemResources::ChromeSystemResources(StateWriter* state_writer)
     21     : state_writer_(state_writer),
     22       created_on_loop_(MessageLoop::current()) {
     23   DCHECK(non_thread_safe_.CalledOnValidThread());
     24   CHECK(created_on_loop_);
     25   DCHECK(state_writer_);
     26 }
     27 
     28 ChromeSystemResources::~ChromeSystemResources() {
     29   DCHECK(non_thread_safe_.CalledOnValidThread());
     30   CHECK_EQ(created_on_loop_, MessageLoop::current());
     31   StopScheduler();
     32 }
     33 
     34 invalidation::Time ChromeSystemResources::current_time() {
     35   DCHECK(non_thread_safe_.CalledOnValidThread());
     36   CHECK_EQ(created_on_loop_, MessageLoop::current());
     37   return base::Time::Now();
     38 }
     39 
     40 void ChromeSystemResources::StartScheduler() {
     41   DCHECK(non_thread_safe_.CalledOnValidThread());
     42   CHECK_EQ(created_on_loop_, MessageLoop::current());
     43   scoped_runnable_method_factory_.reset(
     44       new ScopedRunnableMethodFactory<ChromeSystemResources>(this));
     45 }
     46 
     47 void ChromeSystemResources::StopScheduler() {
     48   DCHECK(non_thread_safe_.CalledOnValidThread());
     49   CHECK_EQ(created_on_loop_, MessageLoop::current());
     50   scoped_runnable_method_factory_.reset();
     51   STLDeleteElements(&posted_tasks_);
     52 }
     53 
     54 void ChromeSystemResources::ScheduleWithDelay(
     55     invalidation::TimeDelta delay,
     56     invalidation::Closure* task) {
     57   DCHECK(non_thread_safe_.CalledOnValidThread());
     58   CHECK_EQ(created_on_loop_, MessageLoop::current());
     59   Task* task_to_post = MakeTaskToPost(task);
     60   if (!task_to_post) {
     61     return;
     62   }
     63   MessageLoop::current()->PostDelayedTask(
     64       FROM_HERE, task_to_post, delay.InMillisecondsRoundedUp());
     65 }
     66 
     67 void ChromeSystemResources::ScheduleImmediately(
     68     invalidation::Closure* task) {
     69   DCHECK(non_thread_safe_.CalledOnValidThread());
     70   CHECK_EQ(created_on_loop_, MessageLoop::current());
     71   Task* task_to_post = MakeTaskToPost(task);
     72   if (!task_to_post) {
     73     return;
     74   }
     75   MessageLoop::current()->PostTask(FROM_HERE, task_to_post);
     76 }
     77 
     78 // The listener thread is just our current thread (i.e., the
     79 // notifications thread).
     80 void ChromeSystemResources::ScheduleOnListenerThread(
     81     invalidation::Closure* task) {
     82   DCHECK(non_thread_safe_.CalledOnValidThread());
     83   CHECK_EQ(created_on_loop_, MessageLoop::current());
     84   ScheduleImmediately(task);
     85 }
     86 
     87 // 'Internal thread' means 'not the listener thread'.  Since the
     88 // listener thread is the notifications thread, always return false.
     89 bool ChromeSystemResources::IsRunningOnInternalThread() {
     90   DCHECK(non_thread_safe_.CalledOnValidThread());
     91   CHECK_EQ(created_on_loop_, MessageLoop::current());
     92   return false;
     93 }
     94 
     95 void ChromeSystemResources::Log(
     96     LogLevel level, const char* file, int line,
     97     const char* format, ...) {
     98   DCHECK(non_thread_safe_.CalledOnValidThread());
     99   logging::LogSeverity log_severity = logging::LOG_INFO;
    100   switch (level) {
    101     case INFO_LEVEL:
    102       log_severity = logging::LOG_INFO;
    103       break;
    104     case WARNING_LEVEL:
    105       log_severity = logging::LOG_WARNING;
    106       break;
    107     case SEVERE_LEVEL:
    108       log_severity = logging::LOG_ERROR;
    109       break;
    110   }
    111   // We treat LOG(INFO) as VLOG(1).
    112   if ((log_severity >= logging::GetMinLogLevel()) &&
    113       ((log_severity != logging::LOG_INFO) ||
    114        (1 <= logging::GetVlogLevelHelper(file, ::strlen(file))))) {
    115     va_list ap;
    116     va_start(ap, format);
    117     std::string result;
    118     base::StringAppendV(&result, format, ap);
    119     logging::LogMessage(file, line, log_severity).stream() << result;
    120     va_end(ap);
    121   }
    122 }
    123 
    124 void ChromeSystemResources::RunAndDeleteStorageCallback(
    125     invalidation::StorageCallback* callback) {
    126   callback->Run(true);
    127   delete callback;
    128 }
    129 
    130 void ChromeSystemResources::WriteState(
    131     const invalidation::string& state,
    132     invalidation::StorageCallback* callback) {
    133   CHECK(state_writer_);
    134   state_writer_->WriteState(state);
    135   // According to the cache invalidation API folks, we can do this as
    136   // long as we make sure to clear the persistent state that we start
    137   // up the cache invalidation client with.  However, we musn't do it
    138   // right away, as we may be called under a lock that the callback
    139   // uses.
    140   ScheduleImmediately(
    141       invalidation::NewPermanentCallback(
    142           this, &ChromeSystemResources::RunAndDeleteStorageCallback,
    143           callback));
    144 }
    145 
    146 Task* ChromeSystemResources::MakeTaskToPost(
    147     invalidation::Closure* task) {
    148   DCHECK(non_thread_safe_.CalledOnValidThread());
    149   DCHECK(invalidation::IsCallbackRepeatable(task));
    150   CHECK_EQ(created_on_loop_, MessageLoop::current());
    151   if (!scoped_runnable_method_factory_.get()) {
    152     delete task;
    153     return NULL;
    154   }
    155   posted_tasks_.insert(task);
    156   Task* task_to_post =
    157       scoped_runnable_method_factory_->NewRunnableMethod(
    158           &ChromeSystemResources::RunPostedTask, task);
    159   return task_to_post;
    160 }
    161 
    162 void ChromeSystemResources::RunPostedTask(invalidation::Closure* task) {
    163   DCHECK(non_thread_safe_.CalledOnValidThread());
    164   CHECK_EQ(created_on_loop_, MessageLoop::current());
    165   RunAndDeleteClosure(task);
    166   posted_tasks_.erase(task);
    167 }
    168 
    169 }  // namespace sync_notifier
    170