[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 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 | |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 5 | #include "extensions/browser/extension_error.h" |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 6 | |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 7 | #include "base/strings/string_number_conversions.h" |
| 8 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 9 | #include "extensions/common/constants.h" |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 10 | #include "url/gurl.h" |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 11 | |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 12 | namespace extensions { |
| 13 | |
[email protected] | fa5fed3 | 2013-09-05 21:56:22 | [diff] [blame] | 14 | //////////////////////////////////////////////////////////////////////////////// |
| 15 | // ExtensionError |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 16 | |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 17 | ExtensionError::ExtensionError(Type type, |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 18 | const std::string& extension_id, |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 19 | bool from_incognito, |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 20 | logging::LogSeverity level, |
[email protected] | 0d163dc | 2013-12-20 23:48:36 | [diff] [blame] | 21 | const base::string16& source, |
| 22 | const base::string16& message) |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 23 | : type_(type), |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 24 | extension_id_(extension_id), |
rdevlin.cronin | c799f9f | 2015-03-21 00:56:30 | [diff] [blame] | 25 | id_(0), |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 26 | from_incognito_(from_incognito), |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 27 | level_(level), |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 28 | source_(source), |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 29 | message_(message), |
| 30 | occurrences_(1u) { |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 31 | } |
| 32 | |
| 33 | ExtensionError::~ExtensionError() { |
| 34 | } |
| 35 | |
wittman | b3ee048 | 2015-06-24 17:47:40 | [diff] [blame] | 36 | std::string ExtensionError::GetDebugString() const { |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 37 | return std::string("Extension Error:") + |
| 38 | "\n OTR: " + std::string(from_incognito_ ? "true" : "false") + |
[email protected] | 50af608 | 2013-09-10 02:05:19 | [diff] [blame] | 39 | "\n Level: " + base::IntToString(static_cast<int>(level_)) + |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 40 | "\n Source: " + base::UTF16ToUTF8(source_) + |
| 41 | "\n Message: " + base::UTF16ToUTF8(message_) + |
| 42 | "\n ID: " + extension_id_; |
| 43 | } |
| 44 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 45 | bool ExtensionError::IsEqual(const ExtensionError* rhs) const { |
| 46 | // We don't check |source_| or |level_| here, since they are constant for |
| 47 | // manifest errors. Check them in RuntimeError::IsEqualImpl() instead. |
| 48 | return type_ == rhs->type_ && |
| 49 | extension_id_ == rhs->extension_id_ && |
| 50 | message_ == rhs->message_ && |
| 51 | IsEqualImpl(rhs); |
| 52 | } |
| 53 | |
[email protected] | fa5fed3 | 2013-09-05 21:56:22 | [diff] [blame] | 54 | //////////////////////////////////////////////////////////////////////////////// |
| 55 | // ManifestError |
| 56 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 57 | ManifestError::ManifestError(const std::string& extension_id, |
[email protected] | 0d163dc | 2013-12-20 23:48:36 | [diff] [blame] | 58 | const base::string16& message, |
| 59 | const base::string16& manifest_key, |
| 60 | const base::string16& manifest_specific) |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 61 | : ExtensionError(ExtensionError::MANIFEST_ERROR, |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 62 | extension_id, |
| 63 | false, // extensions can't be installed while incognito. |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 64 | logging::LOG_WARNING, // All manifest errors are warnings. |
[email protected] | 921237d06 | 2013-08-10 15:30:49 | [diff] [blame] | 65 | base::FilePath(kManifestFilename).AsUTF16Unsafe(), |
[email protected] | b191e2d3 | 2013-09-03 21:08:30 | [diff] [blame] | 66 | message), |
| 67 | manifest_key_(manifest_key), |
| 68 | manifest_specific_(manifest_specific) { |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 69 | } |
| 70 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 71 | ManifestError::~ManifestError() { |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 72 | } |
| 73 | |
wittman | b3ee048 | 2015-06-24 17:47:40 | [diff] [blame] | 74 | std::string ManifestError::GetDebugString() const { |
| 75 | return ExtensionError::GetDebugString() + |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 76 | "\n Type: ManifestError"; |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 77 | } |
| 78 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 79 | bool ManifestError::IsEqualImpl(const ExtensionError* rhs) const { |
| 80 | // If two manifest errors have the same extension id and message (which are |
| 81 | // both checked in ExtensionError::IsEqual), then they are equal. |
| 82 | return true; |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 83 | } |
| 84 | |
[email protected] | 2fb9bd2 | 2013-09-07 00:08:08 | [diff] [blame] | 85 | //////////////////////////////////////////////////////////////////////////////// |
| 86 | // RuntimeError |
| 87 | |
[email protected] | a0ed268 | 2013-09-06 08:41:07 | [diff] [blame] | 88 | RuntimeError::RuntimeError(const std::string& extension_id, |
| 89 | bool from_incognito, |
[email protected] | 0d163dc | 2013-12-20 23:48:36 | [diff] [blame] | 90 | const base::string16& source, |
| 91 | const base::string16& message, |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 92 | const StackTrace& stack_trace, |
| 93 | const GURL& context_url, |
[email protected] | c934c38 | 2013-11-01 00:36:01 | [diff] [blame] | 94 | logging::LogSeverity level, |
rdevlin.cronin | 86f5b70 | 2015-06-24 18:49:17 | [diff] [blame] | 95 | int render_frame_id, |
[email protected] | c934c38 | 2013-11-01 00:36:01 | [diff] [blame] | 96 | int render_process_id) |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 97 | : ExtensionError(ExtensionError::RUNTIME_ERROR, |
[email protected] | a0ed268 | 2013-09-06 08:41:07 | [diff] [blame] | 98 | !extension_id.empty() ? extension_id : GURL(source).host(), |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 99 | from_incognito, |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 100 | level, |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 101 | source, |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 102 | message), |
| 103 | context_url_(context_url), |
[email protected] | c934c38 | 2013-11-01 00:36:01 | [diff] [blame] | 104 | stack_trace_(stack_trace), |
rdevlin.cronin | 86f5b70 | 2015-06-24 18:49:17 | [diff] [blame] | 105 | render_frame_id_(render_frame_id), |
[email protected] | c934c38 | 2013-11-01 00:36:01 | [diff] [blame] | 106 | render_process_id_(render_process_id) { |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 107 | CleanUpInit(); |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 108 | } |
| 109 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 110 | RuntimeError::~RuntimeError() { |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 111 | } |
| 112 | |
wittman | b3ee048 | 2015-06-24 17:47:40 | [diff] [blame] | 113 | std::string RuntimeError::GetDebugString() const { |
| 114 | std::string result = ExtensionError::GetDebugString() + |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 115 | "\n Type: RuntimeError" |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 116 | "\n Context: " + context_url_.spec() + |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 117 | "\n Stack Trace: "; |
| 118 | for (StackTrace::const_iterator iter = stack_trace_.begin(); |
| 119 | iter != stack_trace_.end(); ++iter) { |
ricea | c700927 | 2015-09-25 18:45:13 | [diff] [blame] | 120 | // The "NL" comments are to force clang-format to choose the right layout. |
| 121 | result += "\n {"; |
| 122 | result += |
| 123 | "\n Line: " + base::SizeTToString(iter->line_number) + // NL |
| 124 | "\n Column: " + base::SizeTToString(iter->column_number) + // NL |
| 125 | "\n URL: " + base::UTF16ToUTF8(iter->source) + // NL |
| 126 | "\n Function: " + base::UTF16ToUTF8(iter->function) + // NL |
| 127 | "\n }"; // NL |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 128 | } |
| 129 | return result; |
| 130 | } |
| 131 | |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 132 | bool RuntimeError::IsEqualImpl(const ExtensionError* rhs) const { |
| 133 | const RuntimeError* error = static_cast<const RuntimeError*>(rhs); |
| 134 | |
| 135 | // Only look at the first frame of a stack trace to save time and group |
| 136 | // nearly-identical errors. The most recent error is kept, so there's no risk |
| 137 | // of displaying an old and inaccurate stack trace. |
[email protected] | 010ff507 | 2013-09-10 08:36:50 | [diff] [blame] | 138 | return level_ == error->level_ && |
| 139 | source_ == error->source_ && |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 140 | context_url_ == error->context_url_ && |
[email protected] | d466f78 | 2013-08-28 21:59:23 | [diff] [blame] | 141 | stack_trace_.size() == error->stack_trace_.size() && |
| 142 | (stack_trace_.empty() || stack_trace_[0] == error->stack_trace_[0]); |
| 143 | } |
| 144 | |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 145 | void RuntimeError::CleanUpInit() { |
| 146 | // If the error came from a generated background page, the "context" is empty |
| 147 | // because there's no visible URL. We should set context to be the generated |
| 148 | // background page in this case. |
| 149 | GURL source_url = GURL(source_); |
| 150 | if (context_url_.is_empty() && |
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame^] | 151 | source_url.path_piece() == |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 152 | std::string("/") + kGeneratedBackgroundPageFilename) { |
| 153 | context_url_ = source_url; |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 154 | } |
| 155 | |
[email protected] | 88b50b6 | 2013-09-01 23:05:06 | [diff] [blame] | 156 | // In some instances (due to the fact that we're reusing error reporting from |
| 157 | // other systems), the source won't match up with the final entry in the stack |
| 158 | // trace. (For instance, in a browser action error, the source is the page - |
| 159 | // sometimes the background page - but the error is thrown from the script.) |
| 160 | // Make the source match the stack trace, since that is more likely the cause |
| 161 | // of the error. |
| 162 | if (!stack_trace_.empty() && source_ != stack_trace_[0].source) |
| 163 | source_ = stack_trace_[0].source; |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 164 | } |
| 165 | |
wittman | b3ee048 | 2015-06-24 17:47:40 | [diff] [blame] | 166 | //////////////////////////////////////////////////////////////////////////////// |
| 167 | // InternalError |
| 168 | |
| 169 | InternalError::InternalError(const std::string& extension_id, |
| 170 | const base::string16& message, |
| 171 | logging::LogSeverity level) |
| 172 | : ExtensionError(ExtensionError::INTERNAL_ERROR, |
| 173 | extension_id, |
| 174 | false, // not incognito. |
| 175 | level, |
| 176 | base::string16(), |
| 177 | message) { |
| 178 | } |
| 179 | |
| 180 | InternalError::~InternalError() { |
| 181 | } |
| 182 | |
| 183 | std::string InternalError::GetDebugString() const { |
| 184 | return ExtensionError::GetDebugString() + |
| 185 | "\n Type: InternalError"; |
| 186 | } |
| 187 | |
| 188 | bool InternalError::IsEqualImpl(const ExtensionError* rhs) const { |
| 189 | // ExtensionError logic is sufficient for comparison. |
| 190 | return true; |
| 191 | } |
| 192 | |
[email protected] | 1b66fdb | 2013-07-26 09:57:28 | [diff] [blame] | 193 | } // namespace extensions |