| 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 |