Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / remoting / host / native_messaging / log_message_handler.cc
blob4f8293347d9483796499f60c28a335520850ae02
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.
5 #include "remoting/host/native_messaging/log_message_handler.h"
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"
14 namespace remoting {
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 pointer to the LogMessageHandler instance.
20 base::LazyInstance<base::Lock>::Leaky g_log_message_handler_lock =
21 LAZY_INSTANCE_INITIALIZER;
23 // The singleton LogMessageHandler instance, or null if log messages are not
24 // being intercepted. It must be dereferenced and updated under the above lock.
25 LogMessageHandler* g_log_message_handler = nullptr;
26 } // namespace
28 LogMessageHandler::LogMessageHandler(
29 const Delegate& delegate)
30 : delegate_(delegate),
31 suppress_logging_(false),
32 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
33 weak_ptr_factory_(this) {
34 base::AutoLock lock(g_log_message_handler_lock.Get());
35 if (g_log_message_handler) {
36 LOG(FATAL) << "LogMessageHandler is already registered. Only one instance "
37 << "per process is allowed.";
39 previous_log_message_handler_ = logging::GetLogMessageHandler();
40 logging::SetLogMessageHandler(&LogMessageHandler::OnLogMessage);
41 g_log_message_handler = this;
44 LogMessageHandler::~LogMessageHandler() {
45 base::AutoLock lock(g_log_message_handler_lock.Get());
46 if (logging::GetLogMessageHandler() != &LogMessageHandler::OnLogMessage) {
47 LOG(FATAL) << "LogMessageHandler is not the top-most message handler. "
48 << "Cannot unregister.";
50 logging::SetLogMessageHandler(previous_log_message_handler_);
51 g_log_message_handler = nullptr;
54 // static
55 const char* LogMessageHandler::kDebugMessageTypeName = "_debug_log";
57 // static
58 bool LogMessageHandler::OnLogMessage(
59 logging::LogSeverity severity,
60 const char* file,
61 int line,
62 size_t message_start,
63 const std::string& str) {
64 base::AutoLock lock(g_log_message_handler_lock.Get());
65 if (g_log_message_handler) {
66 g_log_message_handler->PostLogMessageToCorrectThread(
67 severity, file, line, message_start, str);
69 return false;
72 void LogMessageHandler::PostLogMessageToCorrectThread(
73 logging::LogSeverity severity,
74 const char* file,
75 int line,
76 size_t message_start,
77 const std::string& str) {
78 // Don't process this message if we're already logging and on the caller
79 // thread. This guards against an infinite loop if any code called by this
80 // class logs something.
81 if (suppress_logging_ && caller_task_runner_->BelongsToCurrentThread()) {
82 return;
85 // This method is always called under the global lock, so post a task to
86 // handle the log message, even if we're already on the correct thread.
87 // This alows the lock to be released quickly.
89 // Note that this means that LOG(FATAL) messages will be lost because the
90 // process will exit before the message is sent to the client.
91 caller_task_runner_->PostTask(
92 FROM_HERE,
93 base::Bind(&LogMessageHandler::SendLogMessageToClient,
94 weak_ptr_factory_.GetWeakPtr(),
95 severity, file, line, message_start, str));
98 void LogMessageHandler::SendLogMessageToClient(
99 logging::LogSeverity severity,
100 const char* file,
101 int line,
102 size_t message_start,
103 const std::string& str) {
104 suppress_logging_ = true;
106 std::string severity_string = "log";
107 switch (severity) {
108 case logging::LOG_WARNING:
109 severity_string = "warn";
110 break;
111 case logging::LOG_FATAL:
112 case logging::LOG_ERROR:
113 severity_string = "error";
114 break;
117 std::string message = str.substr(message_start);
118 base::TrimWhitespaceASCII(message, base::TRIM_ALL, &message);
120 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue);
121 dictionary->SetString("type", kDebugMessageTypeName);
122 dictionary->SetString("severity", severity_string);
123 dictionary->SetString("message", message);
124 dictionary->SetString("file", file);
125 dictionary->SetInteger("line", line);
127 delegate_.Run(dictionary.Pass());
129 suppress_logging_ = false;
132 } // namespace remoting