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
ChromeSystemResources(StateWriter * state_writer)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
~ChromeSystemResources()28 ChromeSystemResources::~ChromeSystemResources() {
29 DCHECK(non_thread_safe_.CalledOnValidThread());
30 CHECK_EQ(created_on_loop_, MessageLoop::current());
31 StopScheduler();
32 }
33
current_time()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
StartScheduler()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
StopScheduler()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
ScheduleWithDelay(invalidation::TimeDelta delay,invalidation::Closure * task)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
ScheduleImmediately(invalidation::Closure * task)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).
ScheduleOnListenerThread(invalidation::Closure * task)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.
IsRunningOnInternalThread()89 bool ChromeSystemResources::IsRunningOnInternalThread() {
90 DCHECK(non_thread_safe_.CalledOnValidThread());
91 CHECK_EQ(created_on_loop_, MessageLoop::current());
92 return false;
93 }
94
Log(LogLevel level,const char * file,int line,const char * format,...)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
RunAndDeleteStorageCallback(invalidation::StorageCallback * callback)124 void ChromeSystemResources::RunAndDeleteStorageCallback(
125 invalidation::StorageCallback* callback) {
126 callback->Run(true);
127 delete callback;
128 }
129
WriteState(const invalidation::string & state,invalidation::StorageCallback * callback)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
MakeTaskToPost(invalidation::Closure * task)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
RunPostedTask(invalidation::Closure * task)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