Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: chrome/browser/ui/webui/extensions/extension_error_handler.cc

Issue 23624002: Add UI for RuntimeErrors in the ErrorConsole (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@dc_ec_merge
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "chrome/browser/ui/webui/extensions/extension_error_handler.h" 5 #include "chrome/browser/ui/webui/extensions/extension_error_handler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h" 15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/extensions/extension.h"
18 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_ui.h" 19 #include "content/public/browser/web_ui.h"
20 #include "content/public/browser/web_ui_data_source.h" 20 #include "content/public/browser/web_ui_data_source.h"
21 #include "extensions/browser/extension_error.h" 21 #include "extensions/browser/extension_error.h"
22 #include "extensions/browser/manifest_highlighter.h" 22 #include "extensions/browser/file_highlighter.h"
23 #include "extensions/common/constants.h"
23 #include "grit/generated_resources.h" 24 #include "grit/generated_resources.h"
24 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
25 26
26 namespace extensions { 27 namespace extensions {
27 28
28 namespace { 29 namespace {
29 30
30 // Keys for objects passed to and from extension error UI. 31 // Keys for objects passed to and from extension error UI.
31 const char kFileTypeKey[] = "fileType"; 32 const char kFileTypeKey[] = "fileType";
32 const char kManifestFileType[] = "manifest"; 33 const char kManifestFileType[] = "manifest";
33 const char kPathSuffixKey[] = "pathSuffix"; 34 const char kPathSuffixKey[] = "pathSuffix";
35 const char kSourceFileType[] = "source";
34 const char kTitleKey[] = "title"; 36 const char kTitleKey[] = "title";
35 37
36 const char kBeforeHighlightKey[] = "beforeHighlight";
37 const char kHighlightKey[] = "highlight";
38 const char kAfterHighlightKey[] = "afterHighlight";
39
40 // Populate a DictionaryValue with the highlighted portions for the callback to
41 // ExtensionErrorOverlay, given the components.
42 void HighlightDictionary(base::DictionaryValue* dict,
43 const ManifestHighlighter& highlighter) {
44 std::string before_feature = highlighter.GetBeforeFeature();
45 if (!before_feature.empty())
46 dict->SetString(kBeforeHighlightKey, base::UTF8ToUTF16(before_feature));
47
48 std::string feature = highlighter.GetFeature();
49 if (!feature.empty())
50 dict->SetString(kHighlightKey, base::UTF8ToUTF16(feature));
51
52 std::string after_feature = highlighter.GetAfterFeature();
53 if (!after_feature.empty())
54 dict->SetString(kAfterHighlightKey, base::UTF8ToUTF16(after_feature));
55 }
56
57 } // namespace 38 } // namespace
58 39
59 ExtensionErrorHandler::ExtensionErrorHandler(Profile* profile) 40 ExtensionErrorHandler::ExtensionErrorHandler(Profile* profile)
60 : profile_(profile) { 41 : profile_(profile) {
61 } 42 }
62 43
63 ExtensionErrorHandler::~ExtensionErrorHandler() { 44 ExtensionErrorHandler::~ExtensionErrorHandler() {
64 } 45 }
65 46
66 void ExtensionErrorHandler::GetLocalizedValues( 47 void ExtensionErrorHandler::GetLocalizedValues(
67 content::WebUIDataSource* source) { 48 content::WebUIDataSource* source) {
68 source->AddString( 49 source->AddString(
69 "extensionErrorsManifestErrors", 50 "extensionErrorsManifestErrors",
70 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_MANIFEST_ERRORS)); 51 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_MANIFEST_ERRORS));
71 source->AddString( 52 source->AddString(
53 "extensionErrorsRuntimeErrors",
54 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_RUNTIME_ERRORS));
55 source->AddString(
72 "extensionErrorsShowMore", 56 "extensionErrorsShowMore",
73 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_SHOW_MORE)); 57 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_SHOW_MORE));
74 source->AddString( 58 source->AddString(
75 "extensionErrorsShowFewer", 59 "extensionErrorsShowFewer",
76 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_SHOW_FEWER)); 60 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERRORS_SHOW_FEWER));
77 source->AddString( 61 source->AddString(
78 "extensionErrorViewSource", 62 "extensionErrorViewSource",
79 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERROR_VIEW_SOURCE)); 63 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERROR_VIEW_SOURCE));
64 source->AddString(
65 "extensionErrorContext",
66 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERROR_CONTEXT));
67 source->AddString(
68 "extensionErrorStackTrace",
69 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERROR_STACK_TRACE));
70 source->AddString(
71 "extensionErrorAnonymousFunction",
72 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ERROR_ANONYMOUS_FUNCTION));
80 } 73 }
81 74
82 void ExtensionErrorHandler::RegisterMessages() { 75 void ExtensionErrorHandler::RegisterMessages() {
83 web_ui()->RegisterMessageCallback( 76 web_ui()->RegisterMessageCallback(
84 "extensionErrorRequestFileSource", 77 "extensionErrorRequestFileSource",
85 base::Bind(&ExtensionErrorHandler::HandleRequestFileSource, 78 base::Bind(&ExtensionErrorHandler::HandleRequestFileSource,
86 base::Unretained(this))); 79 base::Unretained(this)));
87 } 80 }
88 81
89 void ExtensionErrorHandler::HandleRequestFileSource( 82 void ExtensionErrorHandler::HandleRequestFileSource(
90 const base::ListValue* args) { 83 const base::ListValue* args) {
91 // There should only be one argument, a dictionary. Use this instead of a list 84 // There should only be one argument, a dictionary. Use this instead of a list
92 // because it's more descriptive, harder to accidentally break with minor 85 // because it's more descriptive, harder to accidentally break with minor
93 // modifications, and supports optional arguments more easily. 86 // modifications, and supports optional arguments more easily.
94 CHECK_EQ(1u, args->GetSize()); 87 CHECK_EQ(1u, args->GetSize());
95 88
96 const base::DictionaryValue* dict = NULL; 89 const base::DictionaryValue* dict = NULL;
97 90
98 // Four required arguments: extension_id, path_suffix, error_message, and 91 // Three required arguments: extension_id, path_suffix, and error_message.
99 // file_type.
100 std::string extension_id; 92 std::string extension_id;
101 base::FilePath::StringType path_suffix; 93 base::FilePath::StringType path_suffix;
102 base::string16 error_message; 94 base::string16 error_message;
103 std::string file_type;
104 95
105 if (!args->GetDictionary(0, &dict) || 96 if (!args->GetDictionary(0, &dict) ||
106 !dict->GetString(kFileTypeKey, &file_type) ||
107 !dict->GetString(kPathSuffixKey, &path_suffix) || 97 !dict->GetString(kPathSuffixKey, &path_suffix) ||
108 !dict->GetString(ExtensionError::kExtensionIdKey, &extension_id) || 98 !dict->GetString(ExtensionError::kExtensionIdKey, &extension_id) ||
109 !dict->GetString(ExtensionError::kMessageKey, &error_message)) { 99 !dict->GetString(ExtensionError::kMessageKey, &error_message)) {
110 NOTREACHED(); 100 NOTREACHED();
111 return; 101 return;
112 } 102 }
113 103
114 const Extension* extension = 104 const Extension* extension =
115 ExtensionSystem::Get(Profile::FromWebUI(web_ui()))-> 105 ExtensionSystem::Get(Profile::FromWebUI(web_ui()))->
116 extension_service()->GetExtensionById(extension_id, 106 extension_service()->GetExtensionById(extension_id,
117 true /* include disabled */ ); 107 true /* include disabled */ );
118 base::FilePath path = extension->path().Append(path_suffix); 108 base::FilePath path = extension->path().Append(path_suffix);
Finnur 2013/09/09 09:15:56 In the event of a compromised caller (sending in v
Devlin 2013/09/09 16:56:03 It's possible that, if the caller is compromised,
Finnur 2013/09/09 18:05:43 The person controlling a compromised renderer does
Devlin 2013/09/09 18:26:14 Thanks for the explanation :) Fixed in 23875013.
119 109
120 // Setting the title and the error message is the same for all file types. 110 // Setting the title and the error message is the same for all file types.
121 scoped_ptr<base::DictionaryValue> results(new base::DictionaryValue); 111 scoped_ptr<base::DictionaryValue> results(new base::DictionaryValue);
122 results->SetString(kTitleKey, 112 results->SetString(kTitleKey,
123 base::UTF8ToUTF16(extension->name()) + 113 base::UTF8ToUTF16(extension->name()) +
124 base::ASCIIToUTF16(": ") + 114 base::ASCIIToUTF16(": ") +
125 path.BaseName().LossyDisplayName()); 115 path.BaseName().LossyDisplayName());
126 results->SetString(ExtensionError::kMessageKey, error_message); 116 results->SetString(ExtensionError::kMessageKey, error_message);
127 117
128 base::Closure closure; 118 base::Closure closure;
129 std::string* contents = NULL; 119 std::string* contents = NULL;
130 120
131 if (file_type == kManifestFileType) { 121 if (path_suffix == kManifestFilename) {
132 std::string manifest_key; 122 std::string manifest_key;
133 if (!dict->GetString(ManifestError::kManifestKeyKey, &manifest_key)) { 123 if (!dict->GetString(ManifestError::kManifestKeyKey, &manifest_key)) {
134 NOTREACHED(); 124 NOTREACHED();
135 return; 125 return;
136 } 126 }
137 127
138 // A "specific" location is optional. 128 // A "specific" location is optional.
139 std::string specific; 129 std::string specific;
140 dict->GetString(ManifestError::kManifestSpecificKey, &specific); 130 dict->GetString(ManifestError::kManifestSpecificKey, &specific);
141 131
142 contents = new std::string; // Owned by GetManifestFileCallback( ) 132 contents = new std::string; // Owned by GetManifestFileCallback( )
Finnur 2013/09/09 09:15:56 It looks like this leaks as I don't really see thi
Devlin 2013/09/09 16:56:03 |contents| is base::Owned by the callback. This m
Finnur 2013/09/09 18:05:43 Thanks, I overlooked that.
143 closure = base::Bind(&ExtensionErrorHandler::GetManifestFileCallback, 133 closure = base::Bind(&ExtensionErrorHandler::GetManifestFileCallback,
144 base::Unretained(this), 134 base::Unretained(this),
145 base::Owned(results.release()), 135 base::Owned(results.release()),
146 manifest_key, 136 manifest_key,
147 specific, 137 specific,
148 base::Owned(contents)); 138 base::Owned(contents));
149 } else { 139 } else {
150 // currently, only manifest file types supported. 140 int line_number = 0;
151 NOTREACHED(); 141 dict->GetInteger(RuntimeError::kLineNumberKey, &line_number);
152 return; 142
143 contents = new std::string; // Owned by GetSourceFileCallback()
Finnur 2013/09/09 09:15:56 Same problem here: GetSourceFileCallback passes th
Devlin 2013/09/09 16:56:03 See above :)
144 closure = base::Bind(&ExtensionErrorHandler::GetSourceFileCallback,
145 base::Unretained(this),
146 base::Owned(results.release()),
147 line_number,
148 base::Owned(contents));
153 } 149 }
154 150
155 content::BrowserThread::PostBlockingPoolTaskAndReply( 151 content::BrowserThread::PostBlockingPoolTaskAndReply(
156 FROM_HERE, 152 FROM_HERE,
157 base::Bind(base::IgnoreResult(&base::ReadFileToString), 153 base::Bind(base::IgnoreResult(&base::ReadFileToString),
158 path, 154 path,
159 contents), 155 contents),
160 closure); 156 closure);
161 } 157 }
162 158
163 void ExtensionErrorHandler::GetManifestFileCallback( 159 void ExtensionErrorHandler::GetManifestFileCallback(
164 base::DictionaryValue* results, 160 base::DictionaryValue* results,
165 const std::string& key, 161 const std::string& key,
166 const std::string& specific, 162 const std::string& specific,
167 std::string* contents) { 163 std::string* contents) {
168 ManifestHighlighter highlighter(*contents, key, specific); 164 ManifestHighlighter highlighter(*contents, key, specific);
169 HighlightDictionary(results, highlighter); 165 highlighter.SetHighlightedRegions(results);
170 web_ui()->CallJavascriptFunction( 166 web_ui()->CallJavascriptFunction(
171 "extensions.ExtensionErrorOverlay.requestFileSourceResponse", *results); 167 "extensions.ExtensionErrorOverlay.requestFileSourceResponse", *results);
172 } 168 }
169
170 void ExtensionErrorHandler::GetSourceFileCallback(
171 base::DictionaryValue* results,
172 int line_number,
173 std::string* contents) {
174 SourceHighlighter highlighter(*contents, line_number);
175 highlighter.SetHighlightedRegions(results);
176 web_ui()->CallJavascriptFunction(
177 "extensions.ExtensionErrorOverlay.requestFileSourceResponse", *results);
178 }
173 179
174 } // namespace extensions 180 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698