[email protected] | f55c90ee6 | 2014-04-12 00:50:03 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | f55c90ee6 | 2014-04-12 00:50:03 | [diff] [blame] | 5 | #include "extensions/renderer/console.h" |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 6 | |
| 7 | #include "base/compiler_specific.h" |
[email protected] | 95ee77da | 2013-03-19 21:11:11 | [diff] [blame] | 8 | #include "base/debug/alias.h" |
| 9 | #include "base/lazy_instance.h" |
[email protected] | a19a16d8 | 2013-06-11 17:45:12 | [diff] [blame] | 10 | #include "base/strings/string_util.h" |
| 11 | #include "base/strings/stringprintf.h" |
[email protected] | abfd149 | 2013-06-07 21:23:26 | [diff] [blame] | 12 | #include "base/strings/utf_string_conversions.h" |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 13 | #include "content/public/renderer/render_frame.h" |
| 14 | #include "extensions/renderer/extension_frame_helper.h" |
| 15 | #include "extensions/renderer/script_context.h" |
| 16 | #include "extensions/renderer/script_context_set.h" |
bashi | facd48b8 | 2015-06-30 05:44:20 | [diff] [blame^] | 17 | #include "extensions/renderer/v8_helpers.h" |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 18 | |
| 19 | namespace extensions { |
| 20 | namespace console { |
| 21 | |
bashi | facd48b8 | 2015-06-30 05:44:20 | [diff] [blame^] | 22 | using namespace v8_helpers; |
| 23 | |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 24 | namespace { |
| 25 | |
[email protected] | 95ee77da | 2013-03-19 21:11:11 | [diff] [blame] | 26 | // Writes |message| to stack to show up in minidump, then crashes. |
| 27 | void CheckWithMinidump(const std::string& message) { |
[email protected] | 662c48b | 2013-07-12 03:50:52 | [diff] [blame] | 28 | char minidump[1024]; |
[email protected] | 95ee77da | 2013-03-19 21:11:11 | [diff] [blame] | 29 | base::debug::Alias(&minidump); |
[email protected] | f55c90ee6 | 2014-04-12 00:50:03 | [diff] [blame] | 30 | base::snprintf( |
| 31 | minidump, arraysize(minidump), "e::console: %s", message.c_str()); |
[email protected] | 95ee77da | 2013-03-19 21:11:11 | [diff] [blame] | 32 | CHECK(false) << message; |
| 33 | } |
| 34 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 35 | typedef void (*LogMethod)(content::RenderFrame* render_frame, |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 36 | const std::string& message); |
| 37 | |
| 38 | void BoundLogMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 39 | std::string message; |
| 40 | for (int i = 0; i < info.Length(); ++i) { |
| 41 | if (i > 0) |
| 42 | message += " "; |
[email protected] | 95c6b301 | 2013-12-02 14:30:31 | [diff] [blame] | 43 | message += *v8::String::Utf8Value(info[i]); |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 44 | } |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 45 | |
| 46 | v8::Local<v8::Context> context = info.GetIsolate()->GetCallingContext(); |
| 47 | if (context.IsEmpty()) { |
| 48 | LOG(WARNING) << "Could not log \"" << message << "\": no context given"; |
| 49 | return; |
| 50 | } |
| 51 | |
| 52 | ScriptContext* script_context = |
| 53 | ScriptContextSet::GetContextByV8Context(context); |
| 54 | LogMethod log_method = |
| 55 | reinterpret_cast<LogMethod>(info.Data().As<v8::External>()->Value()); |
| 56 | (*log_method)(script_context ? script_context->GetRenderFrame() : nullptr, |
| 57 | message); |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 58 | } |
| 59 | |
[email protected] | 69c8792 | 2013-11-18 16:47:51 | [diff] [blame] | 60 | void BindLogMethod(v8::Isolate* isolate, |
| 61 | v8::Local<v8::Object> target, |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 62 | const std::string& name, |
| 63 | LogMethod log_method) { |
| 64 | v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New( |
[email protected] | ef4e7bfb0 | 2013-12-09 09:56:06 | [diff] [blame] | 65 | isolate, |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 66 | &BoundLogMethodCallback, |
[email protected] | 69c8792 | 2013-11-18 16:47:51 | [diff] [blame] | 67 | v8::External::New(isolate, reinterpret_cast<void*>(log_method))); |
bashi | facd48b8 | 2015-06-30 05:44:20 | [diff] [blame^] | 68 | v8::Local<v8::Function> function; |
| 69 | if (!tmpl->GetFunction(isolate->GetCurrentContext()).ToLocal(&function)) { |
| 70 | LOG(FATAL) << "Could not create log function \"" << name << "\""; |
| 71 | return; |
| 72 | } |
| 73 | v8::Local<v8::String> v8_name = ToV8StringUnsafe(isolate, name); |
| 74 | if (!SetProperty(isolate->GetCurrentContext(), target, v8_name, function)) { |
| 75 | LOG(WARNING) << "Could not bind log method \"" << name << "\""; |
| 76 | } |
| 77 | SetProperty(isolate->GetCurrentContext(), target, v8_name, |
[email protected] | 9c47471e | 2013-11-28 14:41:21 | [diff] [blame] | 78 | tmpl->GetFunction()); |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 79 | } |
| 80 | |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 81 | } // namespace |
| 82 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 83 | void Debug(content::RenderFrame* render_frame, const std::string& message) { |
| 84 | AddMessage(render_frame, content::CONSOLE_MESSAGE_LEVEL_DEBUG, message); |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 85 | } |
| 86 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 87 | void Log(content::RenderFrame* render_frame, const std::string& message) { |
| 88 | AddMessage(render_frame, content::CONSOLE_MESSAGE_LEVEL_LOG, message); |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 89 | } |
| 90 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 91 | void Warn(content::RenderFrame* render_frame, const std::string& message) { |
| 92 | AddMessage(render_frame, content::CONSOLE_MESSAGE_LEVEL_WARNING, message); |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 93 | } |
| 94 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 95 | void Error(content::RenderFrame* render_frame, const std::string& message) { |
| 96 | AddMessage(render_frame, content::CONSOLE_MESSAGE_LEVEL_ERROR, message); |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 97 | } |
| 98 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 99 | void Fatal(content::RenderFrame* render_frame, const std::string& message) { |
| 100 | Error(render_frame, message); |
[email protected] | 95ee77da | 2013-03-19 21:11:11 | [diff] [blame] | 101 | CheckWithMinidump(message); |
| 102 | } |
| 103 | |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 104 | void AddMessage(content::RenderFrame* render_frame, |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 105 | content::ConsoleMessageLevel level, |
| 106 | const std::string& message) { |
rdevlin.cronin | b2cec91 | 2015-06-24 20:36:01 | [diff] [blame] | 107 | if (!render_frame) { |
| 108 | LOG(WARNING) << "Could not log \"" << message |
| 109 | << "\": no render frame found"; |
| 110 | } else { |
| 111 | render_frame->AddMessageToConsole(level, message); |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 112 | } |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 113 | } |
| 114 | |
kalman | fb6f10ac | 2014-11-06 23:55:35 | [diff] [blame] | 115 | v8::Local<v8::Object> AsV8Object(v8::Isolate* isolate) { |
[email protected] | 95c6b301 | 2013-12-02 14:30:31 | [diff] [blame] | 116 | v8::EscapableHandleScope handle_scope(isolate); |
[email protected] | 505ffde | 2013-12-19 15:47:13 | [diff] [blame] | 117 | v8::Local<v8::Object> console_object = v8::Object::New(isolate); |
[email protected] | 69c8792 | 2013-11-18 16:47:51 | [diff] [blame] | 118 | BindLogMethod(isolate, console_object, "debug", &Debug); |
| 119 | BindLogMethod(isolate, console_object, "log", &Log); |
| 120 | BindLogMethod(isolate, console_object, "warn", &Warn); |
| 121 | BindLogMethod(isolate, console_object, "error", &Error); |
[email protected] | 95c6b301 | 2013-12-02 14:30:31 | [diff] [blame] | 122 | return handle_scope.Escape(console_object); |
[email protected] | 7205a9c | 2013-08-03 03:15:00 | [diff] [blame] | 123 | } |
| 124 | |
[email protected] | d266361 | 2013-03-17 09:25:56 | [diff] [blame] | 125 | } // namespace console |
| 126 | } // namespace extensions |