OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "remoting/host/native_messaging/log_message_handler.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/lazy_instance.h" | |
9 #include "base/strings/string_util.h" | |
10 #include "base/synchronization/lock.h" | |
11 #include "base/thread_task_runner_handle.h" | |
12 #include "base/tracked_objects.h" | |
13 | |
14 namespace remoting { | |
15 | |
16 namespace { | |
17 // Log message handler registration and deregistration is not thread-safe. | |
18 // This lock must be held in order to set or restore a log message handler, | |
19 // and when accessing the weak pointer to the LogMessageHandler instance. | |
Sergey Ulanov
2015/08/17 23:06:24
update the comment - it's not weak anymore.
Jamie
2015/08/18 00:05:20
Done.
| |
20 base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; | |
Sergey Ulanov
2015/08/17 23:06:25
nit: maybe rename this to g_log_message_handler_lo
Jamie
2015/08/18 00:05:20
Done.
| |
21 | |
22 // The singleton LogMessageHandler instance, or null if log messages are | |
23 // not being intercepted. It must be dereferenced and updated under a lock. | |
Sergey Ulanov
2015/08/17 23:06:25
s/a lock/the lock/
Jamie
2015/08/18 00:05:20
Done.
| |
24 LogMessageHandler* g_log_message_handler = nullptr; | |
25 } // namespace | |
26 | |
27 LogMessageHandler::LogMessageHandler( | |
28 const Delegate& delegate) | |
29 : delegate_(delegate), | |
30 suppress_logging_(false), | |
31 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
32 weak_ptr_factory_(this) { | |
33 base::AutoLock lock(g_lock.Get()); | |
34 if (g_log_message_handler) { | |
35 LOG(FATAL) << "LogMessageHandler is already registered. Only one instance " | |
36 << "per process is allowed."; | |
37 } | |
38 previous_log_message_handler_ = logging::GetLogMessageHandler(); | |
39 logging::SetLogMessageHandler(&LogMessageHandler::OnLogMessage); | |
40 g_log_message_handler = this; | |
41 } | |
42 | |
43 LogMessageHandler::~LogMessageHandler() { | |
44 base::AutoLock lock(g_lock.Get()); | |
45 if (logging::GetLogMessageHandler() != &LogMessageHandler::OnLogMessage) { | |
46 LOG(FATAL) << "LogMessageHandler is not the top-most message handler. " | |
47 << "Cannot unregister."; | |
48 } | |
49 logging::SetLogMessageHandler(previous_log_message_handler_); | |
50 g_log_message_handler = nullptr; | |
51 } | |
52 | |
53 // static | |
54 bool LogMessageHandler::OnLogMessage( | |
55 logging::LogSeverity severity, | |
56 const char* file, | |
57 int line, | |
58 size_t message_start, | |
59 const std::string& str) { | |
60 base::AutoLock lock(g_lock.Get()); | |
61 if (g_log_message_handler) { | |
62 g_log_message_handler->PostLogMessageToCorrectThread( | |
63 severity, file, line, message_start, str); | |
64 } | |
65 return false; | |
66 } | |
67 | |
68 void LogMessageHandler::PostLogMessageToCorrectThread( | |
69 logging::LogSeverity severity, | |
70 const char* file, | |
71 int line, | |
72 size_t message_start, | |
73 const std::string& str) { | |
74 // Don't process this message if we're already logging and on the caller | |
75 // thread. This guards against an infinite loop if any code called by this | |
76 // class logs something. | |
77 if (suppress_logging_ && caller_task_runner_->BelongsToCurrentThread()) { | |
78 return; | |
79 } | |
80 | |
81 // This method is always called under the global lock, so post a task to | |
82 // handle the log message, even if we're already on the correct thread. | |
83 // This alows the lock to be released quickly. | |
84 // | |
85 // Note that this means that LOG(FATAL) messages will be lost because the | |
86 // process will exit before the message is sent to the client. | |
87 caller_task_runner_->PostTask( | |
88 FROM_HERE, | |
89 base::Bind(&LogMessageHandler::SendLogMessageToClient, | |
90 weak_ptr_factory_.GetWeakPtr(), | |
91 severity, file, line, message_start, str)); | |
92 } | |
93 | |
94 void LogMessageHandler::SendLogMessageToClient( | |
95 logging::LogSeverity severity, | |
96 const char* file, | |
97 int line, | |
98 size_t message_start, | |
99 const std::string& str) { | |
100 suppress_logging_ = true; | |
101 | |
102 std::string severity_string = "log"; | |
103 switch (severity) { | |
104 case logging::LOG_WARNING: | |
105 severity_string = "warn"; | |
106 break; | |
107 case logging::LOG_FATAL: | |
108 case logging::LOG_ERROR: | |
109 severity_string = "error"; | |
110 break; | |
111 } | |
112 | |
113 std::string message = str.substr(message_start); | |
114 base::TrimWhitespaceASCII(message, base::TRIM_ALL, &message); | |
115 | |
116 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue); | |
117 dictionary->SetString("type", "_debug_log"); | |
118 dictionary->SetString("severity", severity_string); | |
119 dictionary->SetString("message", message); | |
120 dictionary->SetString("file", file); | |
121 dictionary->SetInteger("line", line); | |
122 | |
123 delegate_.Run(dictionary.Pass()); | |
124 | |
125 suppress_logging_ = false; | |
126 } | |
127 | |
128 } // namespace remoting | |
OLD | NEW |