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_view.h"
14 #include "content/public/renderer/render_view_visitor.h"
15 #include "extensions/renderer/dispatcher.h"
16 #include "extensions/renderer/extension_helper.h"
17 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
18 #include "third_party/WebKit/public/web/WebFrame.h"
19 #include "third_party/WebKit/public/web/WebView.h"
21 namespace extensions
{
26 // Finds the RenderView associated with a context. Note: there will be multiple
27 // contexts in each RenderView.
28 class ByContextFinder
: public content::RenderViewVisitor
{
30 static content::RenderView
* Find(v8::Handle
<v8::Context
> context
) {
31 ByContextFinder
finder(context
);
32 content::RenderView::ForEach(&finder
);
37 explicit ByContextFinder(v8::Handle
<v8::Context
> context
)
38 : context_(context
), found_(NULL
) {}
40 virtual bool Visit(content::RenderView
* render_view
) OVERRIDE
{
41 ExtensionHelper
* helper
= ExtensionHelper::Get(render_view
);
43 helper
->dispatcher()->script_context_set().GetByV8Context(context_
)) {
49 v8::Handle
<v8::Context
> context_
;
50 content::RenderView
* found_
;
52 DISALLOW_COPY_AND_ASSIGN(ByContextFinder
);
55 // Writes |message| to stack to show up in minidump, then crashes.
56 void CheckWithMinidump(const std::string
& message
) {
58 base::debug::Alias(&minidump
);
60 minidump
, arraysize(minidump
), "e::console: %s", message
.c_str());
61 CHECK(false) << message
;
64 typedef void (*LogMethod
)(v8::Handle
<v8::Context
> context
,
65 const std::string
& message
);
67 void BoundLogMethodCallback(const v8::FunctionCallbackInfo
<v8::Value
>& info
) {
68 LogMethod log_method
=
69 reinterpret_cast<LogMethod
>(info
.Data().As
<v8::External
>()->Value());
71 for (int i
= 0; i
< info
.Length(); ++i
) {
74 message
+= *v8::String::Utf8Value(info
[i
]);
76 (*log_method
)(info
.GetIsolate()->GetCallingContext(), message
);
79 void BindLogMethod(v8::Isolate
* isolate
,
80 v8::Local
<v8::Object
> target
,
81 const std::string
& name
,
82 LogMethod log_method
) {
83 v8::Local
<v8::FunctionTemplate
> tmpl
= v8::FunctionTemplate::New(
85 &BoundLogMethodCallback
,
86 v8::External::New(isolate
, reinterpret_cast<void*>(log_method
)));
87 target
->Set(v8::String::NewFromUtf8(isolate
, name
.c_str()),
93 void Debug(content::RenderView
* render_view
, const std::string
& message
) {
94 AddMessage(render_view
, content::CONSOLE_MESSAGE_LEVEL_DEBUG
, message
);
97 void Log(content::RenderView
* render_view
, const std::string
& message
) {
98 AddMessage(render_view
, content::CONSOLE_MESSAGE_LEVEL_LOG
, message
);
101 void Warn(content::RenderView
* render_view
, const std::string
& message
) {
102 AddMessage(render_view
, content::CONSOLE_MESSAGE_LEVEL_WARNING
, message
);
105 void Error(content::RenderView
* render_view
, const std::string
& message
) {
106 AddMessage(render_view
, content::CONSOLE_MESSAGE_LEVEL_ERROR
, message
);
109 void Fatal(content::RenderView
* render_view
, const std::string
& message
) {
110 Error(render_view
, message
);
111 CheckWithMinidump(message
);
114 void AddMessage(content::RenderView
* render_view
,
115 content::ConsoleMessageLevel level
,
116 const std::string
& message
) {
117 blink::WebView
* web_view
= render_view
->GetWebView();
118 if (!web_view
|| !web_view
->mainFrame())
120 blink::WebConsoleMessage::Level target_level
=
121 blink::WebConsoleMessage::LevelLog
;
123 case content::CONSOLE_MESSAGE_LEVEL_DEBUG
:
124 target_level
= blink::WebConsoleMessage::LevelDebug
;
126 case content::CONSOLE_MESSAGE_LEVEL_LOG
:
127 target_level
= blink::WebConsoleMessage::LevelLog
;
129 case content::CONSOLE_MESSAGE_LEVEL_WARNING
:
130 target_level
= blink::WebConsoleMessage::LevelWarning
;
132 case content::CONSOLE_MESSAGE_LEVEL_ERROR
:
133 target_level
= blink::WebConsoleMessage::LevelError
;
136 web_view
->mainFrame()->addMessageToConsole(
137 blink::WebConsoleMessage(target_level
, base::UTF8ToUTF16(message
)));
140 void Debug(v8::Handle
<v8::Context
> context
, const std::string
& message
) {
141 AddMessage(context
, content::CONSOLE_MESSAGE_LEVEL_DEBUG
, message
);
144 void Log(v8::Handle
<v8::Context
> context
, const std::string
& message
) {
145 AddMessage(context
, content::CONSOLE_MESSAGE_LEVEL_LOG
, message
);
148 void Warn(v8::Handle
<v8::Context
> context
, const std::string
& message
) {
149 AddMessage(context
, content::CONSOLE_MESSAGE_LEVEL_WARNING
, message
);
152 void Error(v8::Handle
<v8::Context
> context
, const std::string
& message
) {
153 AddMessage(context
, content::CONSOLE_MESSAGE_LEVEL_ERROR
, message
);
156 void Fatal(v8::Handle
<v8::Context
> context
, const std::string
& message
) {
157 Error(context
, message
);
158 CheckWithMinidump(message
);
161 void AddMessage(v8::Handle
<v8::Context
> context
,
162 content::ConsoleMessageLevel level
,
163 const std::string
& message
) {
164 if (context
.IsEmpty()) {
165 LOG(WARNING
) << "Could not log \"" << message
<< "\": no context given";
168 content::RenderView
* render_view
= ByContextFinder::Find(context
);
170 LOG(WARNING
) << "Could not log \"" << message
<< "\": no render view found";
173 AddMessage(render_view
, level
, message
);
176 v8::Local
<v8::Object
> AsV8Object() {
177 v8::Isolate
* isolate
= v8::Isolate::GetCurrent();
178 v8::EscapableHandleScope
handle_scope(isolate
);
179 v8::Local
<v8::Object
> console_object
= v8::Object::New(isolate
);
180 BindLogMethod(isolate
, console_object
, "debug", &Debug
);
181 BindLogMethod(isolate
, console_object
, "log", &Log
);
182 BindLogMethod(isolate
, console_object
, "warn", &Warn
);
183 BindLogMethod(isolate
, console_object
, "error", &Error
);
184 return handle_scope
.Escape(console_object
);
187 } // namespace console
188 } // namespace extensions