1 // Copyright 2014 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 "extensions/renderer/console.h"
7 #include "base/compiler_specific.h"
8 #include "base/debug/alias.h"
9 #include "base/lazy_instance.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
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"
17 #include "extensions/renderer/v8_helpers.h"
19 namespace extensions
{
22 using namespace v8_helpers
;
26 // Writes |message| to stack to show up in minidump, then crashes.
27 void CheckWithMinidump(const std::string
& message
) {
29 base::debug::Alias(&minidump
);
31 minidump
, arraysize(minidump
), "e::console: %s", message
.c_str());
32 CHECK(false) << message
;
35 typedef void (*LogMethod
)(content::RenderFrame
* render_frame
,
36 const std::string
& message
);
38 void BoundLogMethodCallback(const v8::FunctionCallbackInfo
<v8::Value
>& info
) {
40 for (int i
= 0; i
< info
.Length(); ++i
) {
43 message
+= *v8::String::Utf8Value(info
[i
]);
46 v8::Local
<v8::Context
> context
= info
.GetIsolate()->GetCallingContext();
47 if (context
.IsEmpty()) {
48 LOG(WARNING
) << "Could not log \"" << message
<< "\": no context given";
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,
60 void BindLogMethod(v8::Isolate
* isolate
,
61 v8::Local
<v8::Object
> target
,
62 const std::string
& name
,
63 LogMethod log_method
) {
64 v8::Local
<v8::FunctionTemplate
> tmpl
= v8::FunctionTemplate::New(
66 &BoundLogMethodCallback
,
67 v8::External::New(isolate
, reinterpret_cast<void*>(log_method
)));
68 v8::Local
<v8::Function
> function
;
69 if (!tmpl
->GetFunction(isolate
->GetCurrentContext()).ToLocal(&function
)) {
70 LOG(FATAL
) << "Could not create log function \"" << name
<< "\"";
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
<< "\"";
77 SetProperty(isolate
->GetCurrentContext(), target
, v8_name
,
83 void Debug(content::RenderFrame
* render_frame
, const std::string
& message
) {
84 AddMessage(render_frame
, content::CONSOLE_MESSAGE_LEVEL_DEBUG
, message
);
87 void Log(content::RenderFrame
* render_frame
, const std::string
& message
) {
88 AddMessage(render_frame
, content::CONSOLE_MESSAGE_LEVEL_LOG
, message
);
91 void Warn(content::RenderFrame
* render_frame
, const std::string
& message
) {
92 AddMessage(render_frame
, content::CONSOLE_MESSAGE_LEVEL_WARNING
, message
);
95 void Error(content::RenderFrame
* render_frame
, const std::string
& message
) {
96 AddMessage(render_frame
, content::CONSOLE_MESSAGE_LEVEL_ERROR
, message
);
99 void Fatal(content::RenderFrame
* render_frame
, const std::string
& message
) {
100 Error(render_frame
, message
);
101 CheckWithMinidump(message
);
104 void AddMessage(content::RenderFrame
* render_frame
,
105 content::ConsoleMessageLevel level
,
106 const std::string
& message
) {
108 LOG(WARNING
) << "Could not log \"" << message
109 << "\": no render frame found";
111 render_frame
->AddMessageToConsole(level
, message
);
115 v8::Local
<v8::Object
> AsV8Object(v8::Isolate
* isolate
) {
116 v8::EscapableHandleScope
handle_scope(isolate
);
117 v8::Local
<v8::Object
> console_object
= v8::Object::New(isolate
);
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
);
122 return handle_scope
.Escape(console_object
);
125 } // namespace console
126 } // namespace extensions