| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/browser/extension_error.h" | 5 #include "extensions/browser/extension_error.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" | |
| 8 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/values.h" | 9 #include "base/values.h" |
| 11 #include "extensions/common/constants.h" | 10 #include "extensions/common/constants.h" |
| 12 #include "url/gurl.h" | 11 #include "url/gurl.h" |
| 13 | 12 |
| 14 using base::string16; | 13 using base::string16; |
| 15 | 14 |
| 16 namespace extensions { | 15 namespace extensions { |
| 17 | 16 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 return ExtensionError::PrintForTest() + | 89 return ExtensionError::PrintForTest() + |
| 91 "\n Type: ManifestError"; | 90 "\n Type: ManifestError"; |
| 92 } | 91 } |
| 93 | 92 |
| 94 bool ManifestError::IsEqualImpl(const ExtensionError* rhs) const { | 93 bool ManifestError::IsEqualImpl(const ExtensionError* rhs) const { |
| 95 // If two manifest errors have the same extension id and message (which are | 94 // If two manifest errors have the same extension id and message (which are |
| 96 // both checked in ExtensionError::IsEqual), then they are equal. | 95 // both checked in ExtensionError::IsEqual), then they are equal. |
| 97 return true; | 96 return true; |
| 98 } | 97 } |
| 99 | 98 |
| 100 RuntimeError::StackFrame::StackFrame() : line_number(-1), column_number(-1) { | |
| 101 } | |
| 102 | |
| 103 RuntimeError::StackFrame::StackFrame(size_t frame_line, | |
| 104 size_t frame_column, | |
| 105 const string16& frame_url, | |
| 106 const string16& frame_function) | |
| 107 : line_number(frame_line), | |
| 108 column_number(frame_column), | |
| 109 url(frame_url), | |
| 110 function(frame_function) { | |
| 111 } | |
| 112 | |
| 113 RuntimeError::StackFrame::~StackFrame() { | |
| 114 } | |
| 115 | |
| 116 bool RuntimeError::StackFrame::operator==( | |
| 117 const RuntimeError::StackFrame& rhs) const { | |
| 118 return line_number == rhs.line_number && | |
| 119 column_number == rhs.column_number && | |
| 120 url == rhs.url && | |
| 121 function == rhs.function; | |
| 122 } | |
| 123 RuntimeError::RuntimeError(bool from_incognito, | 99 RuntimeError::RuntimeError(bool from_incognito, |
| 124 const string16& source, | 100 const string16& source, |
| 125 const string16& message, | 101 const string16& message, |
| 126 logging::LogSeverity level, | 102 const StackTrace& stack_trace, |
| 127 const string16& details) | 103 const GURL& context_url, |
| 104 logging::LogSeverity level) |
| 128 : ExtensionError(ExtensionError::RUNTIME_ERROR, | 105 : ExtensionError(ExtensionError::RUNTIME_ERROR, |
| 129 std::string(), // We don't know the id yet. | 106 GURL(source).host(), |
| 130 from_incognito, | 107 from_incognito, |
| 131 level, | 108 level, |
| 132 source, | 109 source, |
| 133 message) { | 110 message), |
| 134 ParseDetails(details); | 111 context_url_(context_url), |
| 135 DetermineExtensionID(); | 112 stack_trace_(stack_trace) { |
| 113 CleanUpInit(); |
| 136 } | 114 } |
| 137 | 115 |
| 138 RuntimeError::~RuntimeError() { | 116 RuntimeError::~RuntimeError() { |
| 139 } | 117 } |
| 140 | 118 |
| 141 std::string RuntimeError::PrintForTest() const { | 119 std::string RuntimeError::PrintForTest() const { |
| 142 std::string result = ExtensionError::PrintForTest() + | 120 std::string result = ExtensionError::PrintForTest() + |
| 143 "\n Type: RuntimeError" | 121 "\n Type: RuntimeError" |
| 144 "\n Context: " + base::UTF16ToUTF8(execution_context_url_) + | 122 "\n Context: " + context_url_.spec() + |
| 145 "\n Stack Trace: "; | 123 "\n Stack Trace: "; |
| 146 for (StackTrace::const_iterator iter = stack_trace_.begin(); | 124 for (StackTrace::const_iterator iter = stack_trace_.begin(); |
| 147 iter != stack_trace_.end(); ++iter) { | 125 iter != stack_trace_.end(); ++iter) { |
| 148 result += "\n {" | 126 result += "\n {" |
| 149 "\n Line: " + base::IntToString(iter->line_number) + | 127 "\n Line: " + base::IntToString(iter->line_number) + |
| 150 "\n Column: " + base::IntToString(iter->column_number) + | 128 "\n Column: " + base::IntToString(iter->column_number) + |
| 151 "\n URL: " + base::UTF16ToUTF8(iter->url) + | 129 "\n URL: " + base::UTF16ToUTF8(iter->source) + |
| 152 "\n Function: " + base::UTF16ToUTF8(iter->function) + | 130 "\n Function: " + base::UTF16ToUTF8(iter->function) + |
| 153 "\n }"; | 131 "\n }"; |
| 154 } | 132 } |
| 155 return result; | 133 return result; |
| 156 } | 134 } |
| 157 | 135 |
| 158 bool RuntimeError::IsEqualImpl(const ExtensionError* rhs) const { | 136 bool RuntimeError::IsEqualImpl(const ExtensionError* rhs) const { |
| 159 const RuntimeError* error = static_cast<const RuntimeError*>(rhs); | 137 const RuntimeError* error = static_cast<const RuntimeError*>(rhs); |
| 160 | 138 |
| 161 // Only look at the first frame of a stack trace to save time and group | 139 // Only look at the first frame of a stack trace to save time and group |
| 162 // nearly-identical errors. The most recent error is kept, so there's no risk | 140 // nearly-identical errors. The most recent error is kept, so there's no risk |
| 163 // of displaying an old and inaccurate stack trace. | 141 // of displaying an old and inaccurate stack trace. |
| 164 return level_ == level_ && | 142 return level_ == level_ && |
| 165 source_ == source_ && | 143 source_ == source_ && |
| 166 execution_context_url_ == error->execution_context_url_ && | 144 context_url_ == error->context_url_ && |
| 167 stack_trace_.size() == error->stack_trace_.size() && | 145 stack_trace_.size() == error->stack_trace_.size() && |
| 168 (stack_trace_.empty() || stack_trace_[0] == error->stack_trace_[0]); | 146 (stack_trace_.empty() || stack_trace_[0] == error->stack_trace_[0]); |
| 169 } | 147 } |
| 170 | 148 |
| 171 void RuntimeError::ParseDetails(const string16& details) { | 149 void RuntimeError::CleanUpInit() { |
| 172 scoped_ptr<base::Value> value( | 150 // If the error came from a generated background page, the "context" is empty |
| 173 base::JSONReader::Read(base::UTF16ToUTF8(details))); | 151 // because there's no visible URL. We should set context to be the generated |
| 174 const base::DictionaryValue* details_value; | 152 // background page in this case. |
| 175 const base::ListValue* trace_value = NULL; | 153 GURL source_url = GURL(source_); |
| 176 | 154 if (context_url_.is_empty() && |
| 177 // The |details| value should contain an execution context url and a stack | 155 source_url.path() == |
| 178 // trace. | 156 std::string("/") + kGeneratedBackgroundPageFilename) { |
| 179 if (!value.get() || | 157 context_url_ = source_url; |
| 180 !value->GetAsDictionary(&details_value) || | |
| 181 !details_value->GetString(kExecutionContextURLKey, | |
| 182 &execution_context_url_) || | |
| 183 !details_value->GetList(kStackTraceKey, &trace_value)) { | |
| 184 NOTREACHED(); | |
| 185 return; | |
| 186 } | 158 } |
| 187 | 159 |
| 188 int line = 0; | 160 // In some instances (due to the fact that we're reusing error reporting from |
| 189 int column = 0; | 161 // other systems), the source won't match up with the final entry in the stack |
| 190 string16 url; | 162 // trace. (For instance, in a browser action error, the source is the page - |
| 191 | 163 // sometimes the background page - but the error is thrown from the script.) |
| 192 for (size_t i = 0; i < trace_value->GetSize(); ++i) { | 164 // Make the source match the stack trace, since that is more likely the cause |
| 193 const base::DictionaryValue* frame_value = NULL; | 165 // of the error. |
| 194 CHECK(trace_value->GetDictionary(i, &frame_value)); | 166 if (!stack_trace_.empty() && source_ != stack_trace_[0].source) |
| 195 | 167 source_ = stack_trace_[0].source; |
| 196 frame_value->GetInteger(kLineNumberKey, &line); | |
| 197 frame_value->GetInteger(kColumnNumberKey, &column); | |
| 198 frame_value->GetString(kURLKey, &url); | |
| 199 | |
| 200 string16 function; | |
| 201 frame_value->GetString(kFunctionNameKey, &function); // This can be empty. | |
| 202 stack_trace_.push_back(StackFrame(line, column, url, function)); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 void RuntimeError::DetermineExtensionID() { | |
| 207 if (!GetExtensionIDFromGURL(GURL(source_), &extension_id_)) | |
| 208 GetExtensionIDFromGURL(GURL(execution_context_url_), &extension_id_); | |
| 209 } | 168 } |
| 210 | 169 |
| 211 } // namespace extensions | 170 } // namespace extensions |
| OLD | NEW |