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 "chrome/browser/extensions/error_console/error_console.h" | 5 #include "chrome/browser/extensions/error_console/error_console.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "extensions/common/feature_switch.h" | 30 #include "extensions/common/feature_switch.h" |
31 | 31 |
32 namespace extensions { | 32 namespace extensions { |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
36 // The key into the Extension prefs for an Extension's specific reporting | 36 // The key into the Extension prefs for an Extension's specific reporting |
37 // settings. | 37 // settings. |
38 const char kStoreExtensionErrorsPref[] = "store_extension_errors"; | 38 const char kStoreExtensionErrorsPref[] = "store_extension_errors"; |
39 | 39 |
40 // The default mask (for the time being) is to report everything. | 40 // This is the default mask for which errors to report. That is, if an extension |
41 const int32 kDefaultMask = (1 << ExtensionError::MANIFEST_ERROR) | | 41 // does not have specific preference set, this will be used instead. |
42 (1 << ExtensionError::RUNTIME_ERROR); | 42 const int kDefaultMask = 0; |
43 | 43 |
44 const char kAppsDeveloperToolsExtensionId[] = | 44 const char kAppsDeveloperToolsExtensionId[] = |
45 "ohmmkhmmmpcnpikjeljgnaoabkaalbgc"; | 45 "ohmmkhmmmpcnpikjeljgnaoabkaalbgc"; |
46 | 46 |
47 } // namespace | 47 } // namespace |
48 | 48 |
49 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { | 49 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { |
50 } | 50 } |
51 | 51 |
52 ErrorConsole::ErrorConsole(Profile* profile) | 52 ErrorConsole::ErrorConsole(Profile* profile) |
53 : enabled_(false), | 53 : enabled_(false), |
54 default_mask_(kDefaultMask), | 54 default_mask_(kDefaultMask), |
55 profile_(profile), | 55 profile_(profile), |
| 56 prefs_(NULL), |
56 registry_observer_(this) { | 57 registry_observer_(this) { |
57 // TODO(rdevlin.cronin): Remove once crbug.com/159265 is fixed. | 58 // TODO(rdevlin.cronin): Remove once crbug.com/159265 is fixed. |
58 #if !defined(ENABLE_EXTENSIONS) | 59 #if !defined(ENABLE_EXTENSIONS) |
59 return; | 60 return; |
60 #endif | 61 #endif |
61 | 62 |
62 pref_registrar_.Init(profile_->GetPrefs()); | 63 pref_registrar_.Init(profile_->GetPrefs()); |
63 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode, | 64 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode, |
64 base::Bind(&ErrorConsole::OnPrefChanged, | 65 base::Bind(&ErrorConsole::OnPrefChanged, |
65 base::Unretained(this))); | 66 base::Unretained(this))); |
(...skipping 12 matching lines...) Expand all Loading... |
78 return ExtensionSystem::Get(profile)->error_console(); | 79 return ExtensionSystem::Get(profile)->error_console(); |
79 } | 80 } |
80 | 81 |
81 void ErrorConsole::SetReportingForExtension(const std::string& extension_id, | 82 void ErrorConsole::SetReportingForExtension(const std::string& extension_id, |
82 ExtensionError::Type type, | 83 ExtensionError::Type type, |
83 bool enabled) { | 84 bool enabled) { |
84 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
85 if (!enabled_ || !Extension::IdIsValid(extension_id)) | 86 if (!enabled_ || !Extension::IdIsValid(extension_id)) |
86 return; | 87 return; |
87 | 88 |
88 ErrorPreferenceMap::iterator pref = pref_map_.find(extension_id); | 89 int mask = default_mask_; |
| 90 // This call can fail if the preference isn't set, but we don't really care |
| 91 // if it does, because we just use the default mask instead. |
| 92 prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &mask); |
89 | 93 |
90 if (pref == pref_map_.end()) { | 94 if (enabled) |
91 pref = pref_map_.insert( | 95 mask |= 1 << type; |
92 std::pair<std::string, int32>(extension_id, default_mask_)).first; | 96 else |
93 } | 97 mask &= ~(1 << type); |
94 | 98 |
95 pref->second = | 99 prefs_->UpdateExtensionPref(extension_id, |
96 enabled ? pref->second | (1 << type) : pref->second &~(1 << type); | 100 kStoreExtensionErrorsPref, |
| 101 base::Value::CreateIntegerValue(mask)); |
| 102 } |
97 | 103 |
98 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( | 104 void ErrorConsole::SetReportingAllForExtension( |
99 extension_id, | 105 const std::string& extension_id, bool enabled) { |
100 kStoreExtensionErrorsPref, | 106 DCHECK(thread_checker_.CalledOnValidThread()); |
101 base::Value::CreateIntegerValue(pref->second)); | 107 if (!enabled_ || !Extension::IdIsValid(extension_id)) |
| 108 return; |
| 109 |
| 110 int mask = 0; |
| 111 if (enabled) |
| 112 mask = (1 << ExtensionError::NUM_ERROR_TYPES) - 1; |
| 113 |
| 114 prefs_->UpdateExtensionPref(extension_id, |
| 115 kStoreExtensionErrorsPref, |
| 116 base::Value::CreateIntegerValue(mask)); |
| 117 } |
| 118 |
| 119 bool ErrorConsole::IsReportingEnabledForExtension( |
| 120 const std::string& extension_id) const { |
| 121 DCHECK(thread_checker_.CalledOnValidThread()); |
| 122 if (!enabled_ || !Extension::IdIsValid(extension_id)) |
| 123 return false; |
| 124 |
| 125 int mask = default_mask_; |
| 126 // This call can fail if the preference isn't set, but we don't really care |
| 127 // if it does, because we just use the default mask instead. |
| 128 prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &mask); |
| 129 return mask != 0; |
102 } | 130 } |
103 | 131 |
104 void ErrorConsole::UseDefaultReportingForExtension( | 132 void ErrorConsole::UseDefaultReportingForExtension( |
105 const std::string& extension_id) { | 133 const std::string& extension_id) { |
106 DCHECK(thread_checker_.CalledOnValidThread()); | 134 DCHECK(thread_checker_.CalledOnValidThread()); |
107 if (!enabled_ || !Extension::IdIsValid(extension_id)) | 135 if (!enabled_ || !Extension::IdIsValid(extension_id)) |
108 return; | 136 return; |
109 | 137 |
110 pref_map_.erase(extension_id); | 138 prefs_->UpdateExtensionPref(extension_id, kStoreExtensionErrorsPref, NULL); |
111 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( | |
112 extension_id, | |
113 kStoreExtensionErrorsPref, | |
114 NULL); | |
115 } | 139 } |
116 | 140 |
117 void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) { | 141 void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) { |
118 DCHECK(thread_checker_.CalledOnValidThread()); | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
119 if (!enabled_ || !Extension::IdIsValid(error->extension_id())) | 143 if (!enabled_ || |
120 return; | 144 !Extension::IdIsValid(error->extension_id()) || |
121 | 145 !ShouldReportErrorForExtension(error->extension_id(), error->type())) { |
122 ErrorPreferenceMap::const_iterator pref = | |
123 pref_map_.find(error->extension_id()); | |
124 // Check the mask to see if we report the error. If we don't have a specific | |
125 // entry, use the default mask. | |
126 if ((pref == pref_map_.end() && | |
127 ((default_mask_ & (1 << error->type())) == 0)) || | |
128 (pref != pref_map_.end() && (pref->second & (1 << error->type())) == 0)) { | |
129 return; | 146 return; |
130 } | 147 } |
131 | 148 |
132 const ExtensionError* weak_error = errors_.AddError(error.Pass()); | 149 const ExtensionError* weak_error = errors_.AddError(error.Pass()); |
133 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(weak_error)); | 150 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(weak_error)); |
134 } | 151 } |
135 | 152 |
136 const ErrorList& ErrorConsole::GetErrorsForExtension( | 153 const ErrorList& ErrorConsole::GetErrorsForExtension( |
137 const std::string& extension_id) const { | 154 const std::string& extension_id) const { |
138 return errors_.GetErrorsForExtension(extension_id); | 155 return errors_.GetErrorsForExtension(extension_id); |
(...skipping 25 matching lines...) Expand all Loading... |
164 IsEnabledForAppsDeveloperTools(); | 181 IsEnabledForAppsDeveloperTools(); |
165 if (should_be_enabled && !enabled_) | 182 if (should_be_enabled && !enabled_) |
166 Enable(); | 183 Enable(); |
167 if (!should_be_enabled && enabled_) | 184 if (!should_be_enabled && enabled_) |
168 Disable(); | 185 Disable(); |
169 } | 186 } |
170 | 187 |
171 void ErrorConsole::Enable() { | 188 void ErrorConsole::Enable() { |
172 enabled_ = true; | 189 enabled_ = true; |
173 | 190 |
| 191 // We postpone the initialization of |prefs_| until now because they can be |
| 192 // NULL in unit_tests. Any unit tests that enable the error console should |
| 193 // also create an ExtensionPrefs object. |
| 194 prefs_ = ExtensionPrefs::Get(profile_); |
| 195 |
174 notification_registrar_.Add( | 196 notification_registrar_.Add( |
175 this, | 197 this, |
176 chrome::NOTIFICATION_PROFILE_DESTROYED, | 198 chrome::NOTIFICATION_PROFILE_DESTROYED, |
177 content::NotificationService::AllBrowserContextsAndSources()); | 199 content::NotificationService::AllBrowserContextsAndSources()); |
178 notification_registrar_.Add( | 200 notification_registrar_.Add( |
179 this, | 201 this, |
180 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | 202 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
181 content::Source<Profile>(profile_)); | 203 content::Source<Profile>(profile_)); |
182 notification_registrar_.Add( | 204 notification_registrar_.Add( |
183 this, | 205 this, |
184 chrome::NOTIFICATION_EXTENSION_INSTALLED, | 206 chrome::NOTIFICATION_EXTENSION_INSTALLED, |
185 content::Source<Profile>(profile_)); | 207 content::Source<Profile>(profile_)); |
186 | 208 |
187 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); | |
188 const ExtensionSet& extensions = | 209 const ExtensionSet& extensions = |
189 ExtensionRegistry::Get(profile_)->enabled_extensions(); | 210 ExtensionRegistry::Get(profile_)->enabled_extensions(); |
190 for (ExtensionSet::const_iterator iter = extensions.begin(); | 211 for (ExtensionSet::const_iterator iter = extensions.begin(); |
191 iter != extensions.end(); | 212 iter != extensions.end(); |
192 ++iter) { | 213 ++iter) { |
193 int mask = 0; | |
194 if (prefs->ReadPrefAsInteger(iter->get()->id(), | |
195 kStoreExtensionErrorsPref, | |
196 &mask)) { | |
197 pref_map_[iter->get()->id()] = mask; | |
198 } | |
199 AddManifestErrorsForExtension(iter->get()); | 214 AddManifestErrorsForExtension(iter->get()); |
200 } | 215 } |
201 } | 216 } |
202 | 217 |
203 void ErrorConsole::Disable() { | 218 void ErrorConsole::Disable() { |
204 notification_registrar_.RemoveAll(); | 219 notification_registrar_.RemoveAll(); |
205 errors_.RemoveAllErrors(); | 220 errors_.RemoveAllErrors(); |
206 enabled_ = false; | 221 enabled_ = false; |
207 } | 222 } |
208 | 223 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 ExtensionError::MANIFEST_ERROR); | 277 ExtensionError::MANIFEST_ERROR); |
263 | 278 |
264 AddManifestErrorsForExtension(info->extension); | 279 AddManifestErrorsForExtension(info->extension); |
265 break; | 280 break; |
266 } | 281 } |
267 default: | 282 default: |
268 NOTREACHED(); | 283 NOTREACHED(); |
269 } | 284 } |
270 } | 285 } |
271 | 286 |
| 287 bool ErrorConsole::ShouldReportErrorForExtension( |
| 288 const std::string& extension_id, ExtensionError::Type type) const { |
| 289 // Registered preferences take priority over everything else. |
| 290 int pref = 0; |
| 291 if (prefs_->ReadPrefAsInteger( |
| 292 extension_id, kStoreExtensionErrorsPref, &pref)) { |
| 293 return (pref & (1 << type)) != 0; |
| 294 } |
| 295 |
| 296 // If the default mask says to report the error, do so. |
| 297 if ((default_mask_ & (1 << type)) != 0) |
| 298 return true; |
| 299 |
| 300 // One last check: If the extension is unpacked, we report all errors by |
| 301 // default. |
| 302 const Extension* extension = |
| 303 ExtensionRegistry::Get(profile_)->GetExtensionById( |
| 304 extension_id, ExtensionRegistry::EVERYTHING); |
| 305 if (extension && extension->location() == Manifest::UNPACKED) |
| 306 return true; |
| 307 |
| 308 return false; |
| 309 } |
| 310 |
272 } // namespace extensions | 311 } // namespace extensions |
OLD | NEW |