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/extensions_render_frame_observer.h"
7 #include "base/strings/string_split.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "content/public/renderer/render_frame.h"
10 #include "extensions/common/extension_messages.h"
11 #include "extensions/common/stack_frame.h"
12 #include "third_party/WebKit/public/web/WebLocalFrame.h"
14 namespace extensions
{
18 // The delimiter for a stack trace provided by WebKit.
19 const char kStackFrameDelimiter
[] = "\n at ";
21 // Get a stack trace from a WebKit console message.
22 // There are three possible scenarios:
23 // 1. WebKit gives us a stack trace in |stack_trace|.
24 // 2. The stack trace is embedded in the error |message| by an internal
25 // script. This will be more useful than |stack_trace|, since |stack_trace|
26 // will include the internal bindings trace, instead of a developer's code.
27 // 3. No stack trace is included. In this case, we should mock one up from
28 // the given line number and source.
29 // |message| will be populated with the error message only (i.e., will not
30 // include any stack trace).
31 StackTrace
GetStackTraceFromMessage(
32 base::string16
* message
,
33 const base::string16
& source
,
34 const base::string16
& stack_trace
,
37 std::vector
<base::string16
> pieces
;
40 if (message
->find(base::UTF8ToUTF16(kStackFrameDelimiter
)) !=
41 base::string16::npos
) {
42 base::SplitStringUsingSubstr(*message
,
43 base::UTF8ToUTF16(kStackFrameDelimiter
),
47 } else if (!stack_trace
.empty()) {
48 base::SplitStringUsingSubstr(stack_trace
,
49 base::UTF8ToUTF16(kStackFrameDelimiter
),
53 // If we got a stack trace, parse each frame from the text.
54 if (index
< pieces
.size()) {
55 for (; index
< pieces
.size(); ++index
) {
56 scoped_ptr
<StackFrame
> frame
= StackFrame::CreateFromText(pieces
[index
]);
58 result
.push_back(*frame
);
62 if (result
.empty()) { // If we don't have a stack trace, mock one up.
64 StackFrame(line_number
,
67 base::string16() /* no function name */ ));
75 ExtensionsRenderFrameObserver::ExtensionsRenderFrameObserver(
76 content::RenderFrame
* render_frame
)
77 : content::RenderFrameObserver(render_frame
) {
80 ExtensionsRenderFrameObserver::~ExtensionsRenderFrameObserver() {
83 void ExtensionsRenderFrameObserver::DetailedConsoleMessageAdded(
84 const base::string16
& message
,
85 const base::string16
& source
,
86 const base::string16
& stack_trace_string
,
88 int32 severity_level
) {
89 base::string16 trimmed_message
= message
;
90 StackTrace stack_trace
= GetStackTraceFromMessage(
95 Send(new ExtensionHostMsg_DetailedConsoleMessageAdded(
96 routing_id(), trimmed_message
, source
, stack_trace
, severity_level
));
99 } // namespace extensions