diff options
author | rdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-10 15:30:49 +0000 |
---|---|---|
committer | rdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-10 15:30:49 +0000 |
commit | 921237d0684838c8b39a189dad1a5736836bd951 (patch) | |
tree | c1e5141d43b32cb25a2e0ef542dd9b2c7d3a6881 /extensions | |
parent | ae298148693d2183a662e76cf2854fe2ccea42ab (diff) | |
download | chromium_src-921237d0684838c8b39a189dad1a5736836bd951.zip chromium_src-921237d0684838c8b39a189dad1a5736836bd951.tar.gz chromium_src-921237d0684838c8b39a189dad1a5736836bd951.tar.bz2 |
Resubmit 21609003: Move ExtensionError to extensions/, add error limits
Added in a fix for the memory leak.
Move ExtensionError class to extensions/browser/, since it doesn't need to be in chrome/.
Limit the number of errors stored per extension to 100.
Store errors in a map, keyed by Extension ID, since that is how we will likely be accessing them.
BUG=21734
Review URL: https://chromiumcodereview.appspot.com/22647007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216871 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/browser/extension_error.cc | 172 | ||||
-rw-r--r-- | extensions/browser/extension_error.h | 121 |
2 files changed, 293 insertions, 0 deletions
diff --git a/extensions/browser/extension_error.cc b/extensions/browser/extension_error.cc new file mode 100644 index 0000000..8b6196c --- /dev/null +++ b/extensions/browser/extension_error.cc @@ -0,0 +1,172 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/browser/extension_error.h" + +#include "base/json/json_reader.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "extensions/common/constants.h" +#include "url/gurl.h" + +using base::string16; + +namespace extensions { + +namespace { + +const char kLineNumberKey[] = "lineNumber"; +const char kColumnNumberKey[] = "columnNumber"; +const char kURLKey[] = "url"; +const char kFunctionNameKey[] = "functionName"; +const char kExecutionContextURLKey[] = "executionContextURL"; +const char kStackTraceKey[] = "stackTrace"; + +// Try to retrieve an extension ID from a |url|. On success, returns true and +// populates |extension_id| with the ID. On failure, returns false and leaves +// extension_id untouched. +bool GetExtensionIDFromGURL(const GURL& url, std::string* extension_id) { + if (url.SchemeIs(kExtensionScheme)) { + *extension_id = url.host(); + return true; + } + return false; +} + +} // namespace + +ExtensionError::ExtensionError(Type type, + const std::string& extension_id, + bool from_incognito, + const string16& source, + const string16& message) + : type_(type), + extension_id_(extension_id), + from_incognito_(from_incognito), + source_(source), + message_(message) { +} + +ExtensionError::~ExtensionError() { +} + +std::string ExtensionError::PrintForTest() const { + return std::string("Extension Error:") + + "\n OTR: " + std::string(from_incognito_ ? "true" : "false") + + "\n Source: " + base::UTF16ToUTF8(source_) + + "\n Message: " + base::UTF16ToUTF8(message_) + + "\n ID: " + extension_id_; +} + +ManifestParsingError::ManifestParsingError(const std::string& extension_id, + const string16& message) + : ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR, + extension_id, + false, // extensions can't be installed while incognito. + base::FilePath(kManifestFilename).AsUTF16Unsafe(), + message) { +} + +ManifestParsingError::~ManifestParsingError() { +} + +std::string ManifestParsingError::PrintForTest() const { + return ExtensionError::PrintForTest() + + "\n Type: ManifestParsingError"; +} + +JavascriptRuntimeError::StackFrame::StackFrame() : line_number(-1), + column_number(-1) { +} + +JavascriptRuntimeError::StackFrame::StackFrame(size_t frame_line, + size_t frame_column, + const string16& frame_url, + const string16& frame_function) + : line_number(frame_line), + column_number(frame_column), + url(frame_url), + function(frame_function) { +} + +JavascriptRuntimeError::StackFrame::~StackFrame() { +} + +JavascriptRuntimeError::JavascriptRuntimeError(bool from_incognito, + const string16& source, + const string16& message, + logging::LogSeverity level, + const string16& details) + : ExtensionError(ExtensionError::JAVASCRIPT_RUNTIME_ERROR, + std::string(), // We don't know the id yet. + from_incognito, + source, + message), + level_(level) { + ParseDetails(details); + DetermineExtensionID(); +} + +JavascriptRuntimeError::~JavascriptRuntimeError() { +} + +std::string JavascriptRuntimeError::PrintForTest() const { + std::string result = ExtensionError::PrintForTest() + + "\n Type: JavascriptRuntimeError" + "\n Context: " + base::UTF16ToUTF8(execution_context_url_) + + "\n Stack Trace: "; + for (StackTrace::const_iterator iter = stack_trace_.begin(); + iter != stack_trace_.end(); ++iter) { + result += "\n {" + "\n Line: " + base::IntToString(iter->line_number) + + "\n Column: " + base::IntToString(iter->column_number) + + "\n URL: " + base::UTF16ToUTF8(iter->url) + + "\n Function: " + base::UTF16ToUTF8(iter->function) + + "\n }"; + } + return result; +} + +void JavascriptRuntimeError::ParseDetails(const string16& details) { + scoped_ptr<base::Value> value( + base::JSONReader::Read(base::UTF16ToUTF8(details))); + const base::DictionaryValue* details_value; + const base::ListValue* trace_value = NULL; + + // The |details| value should contain an execution context url and a stack + // trace. + if (!value.get() || + !value->GetAsDictionary(&details_value) || + !details_value->GetString(kExecutionContextURLKey, + &execution_context_url_) || + !details_value->GetList(kStackTraceKey, &trace_value)) { + NOTREACHED(); + return; + } + + int line = 0; + int column = 0; + string16 url; + + for (size_t i = 0; i < trace_value->GetSize(); ++i) { + const base::DictionaryValue* frame_value = NULL; + CHECK(trace_value->GetDictionary(i, &frame_value)); + + frame_value->GetInteger(kLineNumberKey, &line); + frame_value->GetInteger(kColumnNumberKey, &column); + frame_value->GetString(kURLKey, &url); + + string16 function; + frame_value->GetString(kFunctionNameKey, &function); // This can be empty. + stack_trace_.push_back(StackFrame(line, column, url, function)); + } +} + +void JavascriptRuntimeError::DetermineExtensionID() { + if (!GetExtensionIDFromGURL(GURL(source_), &extension_id_)) + GetExtensionIDFromGURL(GURL(execution_context_url_), &extension_id_); +} + +} // namespace extensions diff --git a/extensions/browser/extension_error.h b/extensions/browser/extension_error.h new file mode 100644 index 0000000..1cd4a7b --- /dev/null +++ b/extensions/browser/extension_error.h @@ -0,0 +1,121 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_BROWSER_EXTENSION_ERROR_H_ +#define EXTENSIONS_BROWSER_EXTENSION_ERROR_H_ + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/strings/string16.h" + +namespace extensions { + +class ExtensionError { + public: + enum Type { + MANIFEST_PARSING_ERROR, + JAVASCRIPT_RUNTIME_ERROR + }; + + virtual ~ExtensionError(); + + virtual std::string PrintForTest() const; + + Type type() const { return type_; } + const base::string16& source() const { return source_; } + const base::string16& message() const { return message_; } + const std::string& extension_id() const { return extension_id_; } + bool from_incognito() const { return from_incognito_; } + + protected: + ExtensionError(Type type, + const std::string& extension_id, + bool from_incognito, + const base::string16& source, + const base::string16& message); + + // Which type of error this is. + Type type_; + // The ID of the extension which caused the error. + std::string extension_id_; + // Whether or not the error was caused while incognito. + bool from_incognito_; + // The source for the error; this can be a script, web page, or manifest file. + // This is stored as a string (rather than a url) since it can be a Chrome + // script file (e.g., event_bindings.js). + base::string16 source_; + // The error message itself. + base::string16 message_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionError); +}; + +class ManifestParsingError : public ExtensionError { + public: + ManifestParsingError(const std::string& extension_id, + const base::string16& message); + virtual ~ManifestParsingError(); + + virtual std::string PrintForTest() const OVERRIDE; + private: + DISALLOW_COPY_AND_ASSIGN(ManifestParsingError); +}; + +class JavascriptRuntimeError : public ExtensionError { + public: + struct StackFrame { + size_t line_number; + size_t column_number; + // This is stored as a string (rather than a url) since it can be a + // Chrome script file (e.g., event_bindings.js). + base::string16 url; + base::string16 function; // optional + + // STL-Required constructor + StackFrame(); + + StackFrame(size_t frame_line, + size_t frame_column, + const base::string16& frame_url, + const base::string16& frame_function /* can be empty */); + + ~StackFrame(); + }; + typedef std::vector<StackFrame> StackTrace; + + JavascriptRuntimeError(bool from_incognito, + const base::string16& source, + const base::string16& message, + logging::LogSeverity level, + const base::string16& details); + virtual ~JavascriptRuntimeError(); + + virtual std::string PrintForTest() const OVERRIDE; + + logging::LogSeverity level() const { return level_; } + const base::string16& execution_context_url() const { + return execution_context_url_; + } + const StackTrace& stack_trace() const { return stack_trace_; } + private: + // Parse the JSON |details| passed to the error. This includes a stack trace + // and an execution context url. + void ParseDetails(const base::string16& details); + // Try to determine the ID of the extension. This may be obtained through the + // reported source, or through the execution context url. + void DetermineExtensionID(); + + logging::LogSeverity level_; + base::string16 execution_context_url_; + StackTrace stack_trace_; + + DISALLOW_COPY_AND_ASSIGN(JavascriptRuntimeError); +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_EXTENSION_ERROR_H_ |