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