blob: 9d8944cedbc505f812d6205154bfada96f4fbb5c [file] [log] [blame]
// 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 "chrome/browser/extensions/error_console/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 "chrome/common/extensions/extension.h"
#include "extensions/common/constants.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(extensions::kExtensionScheme)) {
*extension_id = url.host();
return true;
}
return false;
}
} // namespace
ExtensionError::ExtensionError(Type type,
bool from_incognito,
const string16& source,
const string16& message)
: type_(type),
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(bool from_incognito,
const string16& source,
const string16& message,
size_t line_number)
: ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR,
from_incognito,
source,
message),
line_number_(line_number) {
}
ManifestParsingError::~ManifestParsingError() {
}
std::string ManifestParsingError::PrintForTest() const {
return ExtensionError::PrintForTest() +
"\n Type: ManifestParsingError" +
"\n Line: " + base::IntToString(line_number_);
}
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,
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