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 18namespace sync_notifier { 19 20ChromeSystemResources::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 28ChromeSystemResources::~ChromeSystemResources() { 29 DCHECK(non_thread_safe_.CalledOnValidThread()); 30 CHECK_EQ(created_on_loop_, MessageLoop::current()); 31 StopScheduler(); 32} 33 34invalidation::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 40void 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 47void 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 54void 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 67void 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). 80void 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. 89bool ChromeSystemResources::IsRunningOnInternalThread() { 90 DCHECK(non_thread_safe_.CalledOnValidThread()); 91 CHECK_EQ(created_on_loop_, MessageLoop::current()); 92 return false; 93} 94 95void 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 124void ChromeSystemResources::RunAndDeleteStorageCallback( 125 invalidation::StorageCallback* callback) { 126 callback->Run(true); 127 delete callback; 128} 129 130void 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 146Task* 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 162void 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