| 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" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 return true; | 33 return true; |
| 34 } | 34 } |
| 35 return false; | 35 return false; |
| 36 } | 36 } |
| 37 | 37 |
| 38 } // namespace | 38 } // namespace |
| 39 | 39 |
| 40 ExtensionError::ExtensionError(Type type, | 40 ExtensionError::ExtensionError(Type type, |
| 41 const std::string& extension_id, | 41 const std::string& extension_id, |
| 42 bool from_incognito, | 42 bool from_incognito, |
| 43 logging::LogSeverity level, |
| 43 const string16& source, | 44 const string16& source, |
| 44 const string16& message) | 45 const string16& message) |
| 45 : type_(type), | 46 : type_(type), |
| 46 extension_id_(extension_id), | 47 extension_id_(extension_id), |
| 47 from_incognito_(from_incognito), | 48 from_incognito_(from_incognito), |
| 49 level_(level), |
| 48 source_(source), | 50 source_(source), |
| 49 message_(message) { | 51 message_(message), |
| 52 occurrences_(1u) { |
| 50 } | 53 } |
| 51 | 54 |
| 52 ExtensionError::~ExtensionError() { | 55 ExtensionError::~ExtensionError() { |
| 53 } | 56 } |
| 54 | 57 |
| 55 std::string ExtensionError::PrintForTest() const { | 58 std::string ExtensionError::PrintForTest() const { |
| 56 return std::string("Extension Error:") + | 59 return std::string("Extension Error:") + |
| 57 "\n OTR: " + std::string(from_incognito_ ? "true" : "false") + | 60 "\n OTR: " + std::string(from_incognito_ ? "true" : "false") + |
| 61 "\n Level: " + base::IntToString(static_cast<int>(level_)); |
| 58 "\n Source: " + base::UTF16ToUTF8(source_) + | 62 "\n Source: " + base::UTF16ToUTF8(source_) + |
| 59 "\n Message: " + base::UTF16ToUTF8(message_) + | 63 "\n Message: " + base::UTF16ToUTF8(message_) + |
| 60 "\n ID: " + extension_id_; | 64 "\n ID: " + extension_id_; |
| 61 } | 65 } |
| 62 | 66 |
| 63 ManifestParsingError::ManifestParsingError(const std::string& extension_id, | 67 bool ExtensionError::IsEqual(const ExtensionError* rhs) const { |
| 64 const string16& message) | 68 // We don't check |source_| or |level_| here, since they are constant for |
| 65 : ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR, | 69 // manifest errors. Check them in RuntimeError::IsEqualImpl() instead. |
| 70 return type_ == rhs->type_ && |
| 71 extension_id_ == rhs->extension_id_ && |
| 72 message_ == rhs->message_ && |
| 73 IsEqualImpl(rhs); |
| 74 } |
| 75 |
| 76 ManifestError::ManifestError(const std::string& extension_id, |
| 77 const string16& message) |
| 78 : ExtensionError(ExtensionError::MANIFEST_ERROR, |
| 66 extension_id, | 79 extension_id, |
| 67 false, // extensions can't be installed while incognito. | 80 false, // extensions can't be installed while incognito. |
| 81 logging::LOG_WARNING, // All manifest errors are warnings. |
| 68 base::FilePath(kManifestFilename).AsUTF16Unsafe(), | 82 base::FilePath(kManifestFilename).AsUTF16Unsafe(), |
| 69 message) { | 83 message) { |
| 70 } | 84 } |
| 71 | 85 |
| 72 ManifestParsingError::~ManifestParsingError() { | 86 ManifestError::~ManifestError() { |
| 73 } | 87 } |
| 74 | 88 |
| 75 std::string ManifestParsingError::PrintForTest() const { | 89 std::string ManifestError::PrintForTest() const { |
| 76 return ExtensionError::PrintForTest() + | 90 return ExtensionError::PrintForTest() + |
| 77 "\n Type: ManifestParsingError"; | 91 "\n Type: ManifestError"; |
| 78 } | 92 } |
| 79 | 93 |
| 80 JavascriptRuntimeError::StackFrame::StackFrame() : line_number(-1), | 94 bool ManifestError::IsEqualImpl(const ExtensionError* rhs) const { |
| 81 column_number(-1) { | 95 // If two manifest errors have the same extension id and message (which are |
| 96 // both checked in ExtensionError::IsEqual), then they are equal. |
| 97 return true; |
| 82 } | 98 } |
| 83 | 99 |
| 84 JavascriptRuntimeError::StackFrame::StackFrame(size_t frame_line, | 100 RuntimeError::StackFrame::StackFrame() : line_number(-1), column_number(-1) { |
| 85 size_t frame_column, | 101 } |
| 86 const string16& frame_url, | 102 |
| 87 const string16& frame_function) | 103 RuntimeError::StackFrame::StackFrame(size_t frame_line, |
| 104 size_t frame_column, |
| 105 const string16& frame_url, |
| 106 const string16& frame_function) |
| 88 : line_number(frame_line), | 107 : line_number(frame_line), |
| 89 column_number(frame_column), | 108 column_number(frame_column), |
| 90 url(frame_url), | 109 url(frame_url), |
| 91 function(frame_function) { | 110 function(frame_function) { |
| 92 } | 111 } |
| 93 | 112 |
| 94 JavascriptRuntimeError::StackFrame::~StackFrame() { | 113 RuntimeError::StackFrame::~StackFrame() { |
| 95 } | 114 } |
| 96 | 115 |
| 97 JavascriptRuntimeError::JavascriptRuntimeError(bool from_incognito, | 116 bool RuntimeError::StackFrame::operator==( |
| 98 const string16& source, | 117 const RuntimeError::StackFrame& rhs) const { |
| 99 const string16& message, | 118 return line_number == rhs.line_number && |
| 100 logging::LogSeverity level, | 119 column_number == rhs.column_number && |
| 101 const string16& details) | 120 url == rhs.url && |
| 102 : ExtensionError(ExtensionError::JAVASCRIPT_RUNTIME_ERROR, | 121 function == rhs.function; |
| 122 } |
| 123 RuntimeError::RuntimeError(bool from_incognito, |
| 124 const string16& source, |
| 125 const string16& message, |
| 126 logging::LogSeverity level, |
| 127 const string16& details) |
| 128 : ExtensionError(ExtensionError::RUNTIME_ERROR, |
| 103 std::string(), // We don't know the id yet. | 129 std::string(), // We don't know the id yet. |
| 104 from_incognito, | 130 from_incognito, |
| 131 level, |
| 105 source, | 132 source, |
| 106 message), | 133 message) { |
| 107 level_(level) { | |
| 108 ParseDetails(details); | 134 ParseDetails(details); |
| 109 DetermineExtensionID(); | 135 DetermineExtensionID(); |
| 110 } | 136 } |
| 111 | 137 |
| 112 JavascriptRuntimeError::~JavascriptRuntimeError() { | 138 RuntimeError::~RuntimeError() { |
| 113 } | 139 } |
| 114 | 140 |
| 115 std::string JavascriptRuntimeError::PrintForTest() const { | 141 std::string RuntimeError::PrintForTest() const { |
| 116 std::string result = ExtensionError::PrintForTest() + | 142 std::string result = ExtensionError::PrintForTest() + |
| 117 "\n Type: JavascriptRuntimeError" | 143 "\n Type: RuntimeError" |
| 118 "\n Context: " + base::UTF16ToUTF8(execution_context_url_) + | 144 "\n Context: " + base::UTF16ToUTF8(execution_context_url_) + |
| 119 "\n Stack Trace: "; | 145 "\n Stack Trace: "; |
| 120 for (StackTrace::const_iterator iter = stack_trace_.begin(); | 146 for (StackTrace::const_iterator iter = stack_trace_.begin(); |
| 121 iter != stack_trace_.end(); ++iter) { | 147 iter != stack_trace_.end(); ++iter) { |
| 122 result += "\n {" | 148 result += "\n {" |
| 123 "\n Line: " + base::IntToString(iter->line_number) + | 149 "\n Line: " + base::IntToString(iter->line_number) + |
| 124 "\n Column: " + base::IntToString(iter->column_number) + | 150 "\n Column: " + base::IntToString(iter->column_number) + |
| 125 "\n URL: " + base::UTF16ToUTF8(iter->url) + | 151 "\n URL: " + base::UTF16ToUTF8(iter->url) + |
| 126 "\n Function: " + base::UTF16ToUTF8(iter->function) + | 152 "\n Function: " + base::UTF16ToUTF8(iter->function) + |
| 127 "\n }"; | 153 "\n }"; |
| 128 } | 154 } |
| 129 return result; | 155 return result; |
| 130 } | 156 } |
| 131 | 157 |
| 132 void JavascriptRuntimeError::ParseDetails(const string16& details) { | 158 bool RuntimeError::IsEqualImpl(const ExtensionError* rhs) const { |
| 159 const RuntimeError* error = static_cast<const RuntimeError*>(rhs); |
| 160 |
| 161 // 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 |
| 163 // of displaying an old and inaccurate stack trace. |
| 164 return level_ == level_ && |
| 165 source_ == source_ && |
| 166 execution_context_url_ == error->execution_context_url_ && |
| 167 stack_trace_.size() == error->stack_trace_.size() && |
| 168 (stack_trace_.empty() || stack_trace_[0] == error->stack_trace_[0]); |
| 169 } |
| 170 |
| 171 void RuntimeError::ParseDetails(const string16& details) { |
| 133 scoped_ptr<base::Value> value( | 172 scoped_ptr<base::Value> value( |
| 134 base::JSONReader::Read(base::UTF16ToUTF8(details))); | 173 base::JSONReader::Read(base::UTF16ToUTF8(details))); |
| 135 const base::DictionaryValue* details_value; | 174 const base::DictionaryValue* details_value; |
| 136 const base::ListValue* trace_value = NULL; | 175 const base::ListValue* trace_value = NULL; |
| 137 | 176 |
| 138 // The |details| value should contain an execution context url and a stack | 177 // The |details| value should contain an execution context url and a stack |
| 139 // trace. | 178 // trace. |
| 140 if (!value.get() || | 179 if (!value.get() || |
| 141 !value->GetAsDictionary(&details_value) || | 180 !value->GetAsDictionary(&details_value) || |
| 142 !details_value->GetString(kExecutionContextURLKey, | 181 !details_value->GetString(kExecutionContextURLKey, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 157 frame_value->GetInteger(kLineNumberKey, &line); | 196 frame_value->GetInteger(kLineNumberKey, &line); |
| 158 frame_value->GetInteger(kColumnNumberKey, &column); | 197 frame_value->GetInteger(kColumnNumberKey, &column); |
| 159 frame_value->GetString(kURLKey, &url); | 198 frame_value->GetString(kURLKey, &url); |
| 160 | 199 |
| 161 string16 function; | 200 string16 function; |
| 162 frame_value->GetString(kFunctionNameKey, &function); // This can be empty. | 201 frame_value->GetString(kFunctionNameKey, &function); // This can be empty. |
| 163 stack_trace_.push_back(StackFrame(line, column, url, function)); | 202 stack_trace_.push_back(StackFrame(line, column, url, function)); |
| 164 } | 203 } |
| 165 } | 204 } |
| 166 | 205 |
| 167 void JavascriptRuntimeError::DetermineExtensionID() { | 206 void RuntimeError::DetermineExtensionID() { |
| 168 if (!GetExtensionIDFromGURL(GURL(source_), &extension_id_)) | 207 if (!GetExtensionIDFromGURL(GURL(source_), &extension_id_)) |
| 169 GetExtensionIDFromGURL(GURL(execution_context_url_), &extension_id_); | 208 GetExtensionIDFromGURL(GURL(execution_context_url_), &extension_id_); |
| 170 } | 209 } |
| 171 | 210 |
| 172 } // namespace extensions | 211 } // namespace extensions |
| OLD | NEW |