OLD | NEW |
| (Empty) |
1 // Copyright 2013 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. | |
4 | |
5 #include "chrome/browser/extensions/error_console/extension_error.h" | |
6 | |
7 #include "base/json/json_reader.h" | |
8 #include "base/strings/string_number_conversions.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "base/values.h" | |
11 #include "chrome/common/extensions/extension.h" | |
12 #include "extensions/common/constants.h" | |
13 | |
14 using base::string16; | |
15 | |
16 namespace extensions { | |
17 | |
18 namespace { | |
19 | |
20 const char kLineNumberKey[] = "lineNumber"; | |
21 const char kColumnNumberKey[] = "columnNumber"; | |
22 const char kURLKey[] = "url"; | |
23 const char kFunctionNameKey[] = "functionName"; | |
24 const char kExecutionContextURLKey[] = "executionContextURL"; | |
25 const char kStackTraceKey[] = "stackTrace"; | |
26 | |
27 // Try to retrieve an extension ID from a |url|. On success, returns true and | |
28 // populates |extension_id| with the ID. On failure, returns false and leaves | |
29 // extension_id untouched. | |
30 bool GetExtensionIDFromGURL(const GURL& url, std::string* extension_id) { | |
31 if (url.SchemeIs(extensions::kExtensionScheme)) { | |
32 *extension_id = url.host(); | |
33 return true; | |
34 } | |
35 return false; | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 ExtensionError::ExtensionError(Type type, | |
41 bool from_incognito, | |
42 const string16& source, | |
43 const string16& message) | |
44 : type_(type), | |
45 from_incognito_(from_incognito), | |
46 source_(source), | |
47 message_(message) { | |
48 } | |
49 | |
50 ExtensionError::~ExtensionError() { | |
51 } | |
52 | |
53 std::string ExtensionError::PrintForTest() const { | |
54 return std::string("Extension Error:") + | |
55 "\n OTR: " + std::string(from_incognito_ ? "true" : "false") + | |
56 "\n Source: " + base::UTF16ToUTF8(source_) + | |
57 "\n Message: " + base::UTF16ToUTF8(message_) + | |
58 "\n ID: " + extension_id_; | |
59 } | |
60 | |
61 ManifestParsingError::ManifestParsingError(bool from_incognito, | |
62 const string16& source, | |
63 const string16& message, | |
64 size_t line_number) | |
65 : ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR, | |
66 from_incognito, | |
67 source, | |
68 message), | |
69 line_number_(line_number) { | |
70 } | |
71 | |
72 ManifestParsingError::~ManifestParsingError() { | |
73 } | |
74 | |
75 std::string ManifestParsingError::PrintForTest() const { | |
76 return ExtensionError::PrintForTest() + | |
77 "\n Type: ManifestParsingError" + | |
78 "\n Line: " + base::IntToString(line_number_); | |
79 } | |
80 | |
81 JavascriptRuntimeError::StackFrame::StackFrame() : line_number(-1), | |
82 column_number(-1) { | |
83 } | |
84 | |
85 JavascriptRuntimeError::StackFrame::StackFrame(size_t frame_line, | |
86 size_t frame_column, | |
87 const string16& frame_url, | |
88 const string16& frame_function) | |
89 : line_number(frame_line), | |
90 column_number(frame_column), | |
91 url(frame_url), | |
92 function(frame_function) { | |
93 } | |
94 | |
95 JavascriptRuntimeError::StackFrame::~StackFrame() { | |
96 } | |
97 | |
98 JavascriptRuntimeError::JavascriptRuntimeError(bool from_incognito, | |
99 const string16& source, | |
100 const string16& message, | |
101 logging::LogSeverity level, | |
102 const string16& details) | |
103 : ExtensionError(ExtensionError::JAVASCRIPT_RUNTIME_ERROR, | |
104 from_incognito, | |
105 source, | |
106 message), | |
107 level_(level) { | |
108 ParseDetails(details); | |
109 DetermineExtensionID(); | |
110 } | |
111 | |
112 JavascriptRuntimeError::~JavascriptRuntimeError() { | |
113 } | |
114 | |
115 std::string JavascriptRuntimeError::PrintForTest() const { | |
116 std::string result = ExtensionError::PrintForTest() + | |
117 "\n Type: JavascriptRuntimeError" | |
118 "\n Context: " + base::UTF16ToUTF8(execution_context_url_) + | |
119 "\n Stack Trace: "; | |
120 for (StackTrace::const_iterator iter = stack_trace_.begin(); | |
121 iter != stack_trace_.end(); ++iter) { | |
122 result += "\n {" | |
123 "\n Line: " + base::IntToString(iter->line_number) + | |
124 "\n Column: " + base::IntToString(iter->column_number) + | |
125 "\n URL: " + base::UTF16ToUTF8(iter->url) + | |
126 "\n Function: " + base::UTF16ToUTF8(iter->function) + | |
127 "\n }"; | |
128 } | |
129 return result; | |
130 } | |
131 | |
132 void JavascriptRuntimeError::ParseDetails(const string16& details) { | |
133 scoped_ptr<base::Value> value( | |
134 base::JSONReader::Read(base::UTF16ToUTF8(details))); | |
135 const base::DictionaryValue* details_value; | |
136 const base::ListValue* trace_value = NULL; | |
137 | |
138 // The |details| value should contain an execution context url and a stack | |
139 // trace. | |
140 if (!value.get() || | |
141 !value->GetAsDictionary(&details_value) || | |
142 !details_value->GetString(kExecutionContextURLKey, | |
143 &execution_context_url_) || | |
144 !details_value->GetList(kStackTraceKey, &trace_value)) { | |
145 NOTREACHED(); | |
146 return; | |
147 } | |
148 | |
149 int line = 0; | |
150 int column = 0; | |
151 string16 url; | |
152 | |
153 for (size_t i = 0; i < trace_value->GetSize(); ++i) { | |
154 const base::DictionaryValue* frame_value = NULL; | |
155 CHECK(trace_value->GetDictionary(i, &frame_value)); | |
156 | |
157 frame_value->GetInteger(kLineNumberKey, &line); | |
158 frame_value->GetInteger(kColumnNumberKey, &column); | |
159 frame_value->GetString(kURLKey, &url); | |
160 | |
161 string16 function; | |
162 frame_value->GetString(kFunctionNameKey, &function); // This can be empty. | |
163 stack_trace_.push_back(StackFrame(line, column, url, function)); | |
164 } | |
165 } | |
166 | |
167 void JavascriptRuntimeError::DetermineExtensionID() { | |
168 if (!GetExtensionIDFromGURL(GURL(source_), &extension_id_)) | |
169 GetExtensionIDFromGURL(GURL(execution_context_url_), &extension_id_); | |
170 } | |
171 | |
172 } // namespace extensions | |
OLD | NEW |