summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-10 15:30:49 +0000
committerrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-10 15:30:49 +0000
commit921237d0684838c8b39a189dad1a5736836bd951 (patch)
treec1e5141d43b32cb25a2e0ef542dd9b2c7d3a6881 /extensions
parentae298148693d2183a662e76cf2854fe2ccea42ab (diff)
downloadchromium_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.cc172
-rw-r--r--extensions/browser/extension_error.h121
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_