Roll src/third_party/skia 054eef2:51985e3
[chromium-blink-merge.git] / extensions / browser / extension_error.cc
blob605efbbbd281aa4b64792fb9dbdeb2ac24f8210b
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.
5 #include "extensions/browser/extension_error.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "extensions/common/constants.h"
11 #include "url/gurl.h"
13 using base::DictionaryValue;
15 namespace extensions {
17 ////////////////////////////////////////////////////////////////////////////////
18 // ExtensionError
20 // Static JSON keys.
21 const char ExtensionError::kExtensionIdKey[] = "extensionId";
22 const char ExtensionError::kFromIncognitoKey[] = "fromIncognito";
23 const char ExtensionError::kLevelKey[] = "level";
24 const char ExtensionError::kMessageKey[] = "message";
25 const char ExtensionError::kSourceKey[] = "source";
26 const char ExtensionError::kTypeKey[] = "type";
28 ExtensionError::ExtensionError(Type type,
29 const std::string& extension_id,
30 bool from_incognito,
31 logging::LogSeverity level,
32 const base::string16& source,
33 const base::string16& message)
34 : type_(type),
35 extension_id_(extension_id),
36 id_(0),
37 from_incognito_(from_incognito),
38 level_(level),
39 source_(source),
40 message_(message),
41 occurrences_(1u) {
44 ExtensionError::~ExtensionError() {
47 scoped_ptr<DictionaryValue> ExtensionError::ToValue() const {
48 // TODO(rdevlin.cronin): Use ValueBuilder when it's moved from
49 // chrome/common/extensions.
50 scoped_ptr<DictionaryValue> value(new DictionaryValue);
51 value->SetInteger(kTypeKey, static_cast<int>(type_));
52 value->SetString(kExtensionIdKey, extension_id_);
53 value->SetBoolean(kFromIncognitoKey, from_incognito_);
54 value->SetInteger(kLevelKey, static_cast<int>(level_));
55 value->SetString(kSourceKey, source_);
56 value->SetString(kMessageKey, message_);
58 return value.Pass();
61 std::string ExtensionError::PrintForTest() const {
62 return std::string("Extension Error:") +
63 "\n OTR: " + std::string(from_incognito_ ? "true" : "false") +
64 "\n Level: " + base::IntToString(static_cast<int>(level_)) +
65 "\n Source: " + base::UTF16ToUTF8(source_) +
66 "\n Message: " + base::UTF16ToUTF8(message_) +
67 "\n ID: " + extension_id_;
70 bool ExtensionError::IsEqual(const ExtensionError* rhs) const {
71 // We don't check |source_| or |level_| here, since they are constant for
72 // manifest errors. Check them in RuntimeError::IsEqualImpl() instead.
73 return type_ == rhs->type_ &&
74 extension_id_ == rhs->extension_id_ &&
75 message_ == rhs->message_ &&
76 IsEqualImpl(rhs);
79 ////////////////////////////////////////////////////////////////////////////////
80 // ManifestError
82 // Static JSON keys.
83 const char ManifestError::kManifestKeyKey[] = "manifestKey";
84 const char ManifestError::kManifestSpecificKey[] = "manifestSpecific";
86 ManifestError::ManifestError(const std::string& extension_id,
87 const base::string16& message,
88 const base::string16& manifest_key,
89 const base::string16& manifest_specific)
90 : ExtensionError(ExtensionError::MANIFEST_ERROR,
91 extension_id,
92 false, // extensions can't be installed while incognito.
93 logging::LOG_WARNING, // All manifest errors are warnings.
94 base::FilePath(kManifestFilename).AsUTF16Unsafe(),
95 message),
96 manifest_key_(manifest_key),
97 manifest_specific_(manifest_specific) {
100 ManifestError::~ManifestError() {
103 scoped_ptr<DictionaryValue> ManifestError::ToValue() const {
104 scoped_ptr<DictionaryValue> value = ExtensionError::ToValue();
105 if (!manifest_key_.empty())
106 value->SetString(kManifestKeyKey, manifest_key_);
107 if (!manifest_specific_.empty())
108 value->SetString(kManifestSpecificKey, manifest_specific_);
109 return value.Pass();
112 std::string ManifestError::PrintForTest() const {
113 return ExtensionError::PrintForTest() +
114 "\n Type: ManifestError";
117 bool ManifestError::IsEqualImpl(const ExtensionError* rhs) const {
118 // If two manifest errors have the same extension id and message (which are
119 // both checked in ExtensionError::IsEqual), then they are equal.
120 return true;
123 ////////////////////////////////////////////////////////////////////////////////
124 // RuntimeError
126 // Static JSON keys.
127 const char RuntimeError::kColumnNumberKey[] = "columnNumber";
128 const char RuntimeError::kContextUrlKey[] = "contextUrl";
129 const char RuntimeError::kFunctionNameKey[] = "functionName";
130 const char RuntimeError::kLineNumberKey[] = "lineNumber";
131 const char RuntimeError::kStackTraceKey[] = "stackTrace";
132 const char RuntimeError::kUrlKey[] = "url";
133 const char RuntimeError::kRenderProcessIdKey[] = "renderProcessId";
134 const char RuntimeError::kRenderViewIdKey[] = "renderViewId";
136 RuntimeError::RuntimeError(const std::string& extension_id,
137 bool from_incognito,
138 const base::string16& source,
139 const base::string16& message,
140 const StackTrace& stack_trace,
141 const GURL& context_url,
142 logging::LogSeverity level,
143 int render_view_id,
144 int render_process_id)
145 : ExtensionError(ExtensionError::RUNTIME_ERROR,
146 !extension_id.empty() ? extension_id : GURL(source).host(),
147 from_incognito,
148 level,
149 source,
150 message),
151 context_url_(context_url),
152 stack_trace_(stack_trace),
153 render_view_id_(render_view_id),
154 render_process_id_(render_process_id) {
155 CleanUpInit();
158 RuntimeError::~RuntimeError() {
161 scoped_ptr<DictionaryValue> RuntimeError::ToValue() const {
162 // The items which are to be written into value are also described in
163 // chrome/browser/resources/extensions/extension_error_overlay.js in @typedef
164 // for RuntimeError and StackTrace. Please update them whenever you add or
165 // remove any keys here.
166 scoped_ptr<DictionaryValue> value = ExtensionError::ToValue();
167 value->SetString(kContextUrlKey, context_url_.spec());
168 value->SetInteger(kRenderViewIdKey, render_view_id_);
169 value->SetInteger(kRenderProcessIdKey, render_process_id_);
171 base::ListValue* trace_value = new base::ListValue;
172 for (StackTrace::const_iterator iter = stack_trace_.begin();
173 iter != stack_trace_.end(); ++iter) {
174 DictionaryValue* frame_value = new DictionaryValue;
175 frame_value->SetInteger(kLineNumberKey, iter->line_number);
176 frame_value->SetInteger(kColumnNumberKey, iter->column_number);
177 frame_value->SetString(kUrlKey, iter->source);
178 frame_value->SetString(kFunctionNameKey, iter->function);
179 trace_value->Append(frame_value);
182 value->Set(kStackTraceKey, trace_value);
184 return value.Pass();
187 std::string RuntimeError::PrintForTest() const {
188 std::string result = ExtensionError::PrintForTest() +
189 "\n Type: RuntimeError"
190 "\n Context: " + context_url_.spec() +
191 "\n Stack Trace: ";
192 for (StackTrace::const_iterator iter = stack_trace_.begin();
193 iter != stack_trace_.end(); ++iter) {
194 result += "\n {"
195 "\n Line: " + base::IntToString(iter->line_number) +
196 "\n Column: " + base::IntToString(iter->column_number) +
197 "\n URL: " + base::UTF16ToUTF8(iter->source) +
198 "\n Function: " + base::UTF16ToUTF8(iter->function) +
199 "\n }";
201 return result;
204 bool RuntimeError::IsEqualImpl(const ExtensionError* rhs) const {
205 const RuntimeError* error = static_cast<const RuntimeError*>(rhs);
207 // Only look at the first frame of a stack trace to save time and group
208 // nearly-identical errors. The most recent error is kept, so there's no risk
209 // of displaying an old and inaccurate stack trace.
210 return level_ == error->level_ &&
211 source_ == error->source_ &&
212 context_url_ == error->context_url_ &&
213 stack_trace_.size() == error->stack_trace_.size() &&
214 (stack_trace_.empty() || stack_trace_[0] == error->stack_trace_[0]);
217 void RuntimeError::CleanUpInit() {
218 // If the error came from a generated background page, the "context" is empty
219 // because there's no visible URL. We should set context to be the generated
220 // background page in this case.
221 GURL source_url = GURL(source_);
222 if (context_url_.is_empty() &&
223 source_url.path() ==
224 std::string("/") + kGeneratedBackgroundPageFilename) {
225 context_url_ = source_url;
228 // In some instances (due to the fact that we're reusing error reporting from
229 // other systems), the source won't match up with the final entry in the stack
230 // trace. (For instance, in a browser action error, the source is the page -
231 // sometimes the background page - but the error is thrown from the script.)
232 // Make the source match the stack trace, since that is more likely the cause
233 // of the error.
234 if (!stack_trace_.empty() && source_ != stack_trace_[0].source)
235 source_ = stack_trace_[0].source;
238 } // namespace extensions