Chromium Code Reviews| 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" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/common/chrome_version_info.h" | |
| 19 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 20 #include "content/public/browser/notification_details.h" | 21 #include "content/public/browser/notification_details.h" |
| 21 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
| 22 #include "content/public/browser/notification_source.h" | 23 #include "content/public/browser/notification_source.h" |
| 24 #include "extensions/browser/extension_registry.h" | |
| 23 #include "extensions/browser/extension_system.h" | 25 #include "extensions/browser/extension_system.h" |
| 24 #include "extensions/common/constants.h" | 26 #include "extensions/common/constants.h" |
| 25 #include "extensions/common/extension.h" | 27 #include "extensions/common/extension.h" |
| 26 #include "extensions/common/extension_set.h" | 28 #include "extensions/common/extension_set.h" |
| 27 #include "extensions/common/feature_switch.h" | 29 #include "extensions/common/feature_switch.h" |
| 28 | 30 |
| 29 namespace extensions { | 31 namespace extensions { |
| 30 | 32 |
| 31 namespace { | 33 namespace { |
| 34 | |
| 32 // The key into the Extension prefs for an Extension's specific reporting | 35 // The key into the Extension prefs for an Extension's specific reporting |
| 33 // settings. | 36 // settings. |
| 34 const char kStoreExtensionErrorsPref[] = "store_extension_errors"; | 37 const char kStoreExtensionErrorsPref[] = "store_extension_errors"; |
| 35 | 38 |
| 36 // The default mask (for the time being) is to report everything. | 39 // The default mask (for the time being) is to report everything. |
| 37 const int32 kDefaultMask = (1 << ExtensionError::MANIFEST_ERROR) | | 40 const int32 kDefaultMask = (1 << ExtensionError::MANIFEST_ERROR) | |
| 38 (1 << ExtensionError::RUNTIME_ERROR); | 41 (1 << ExtensionError::RUNTIME_ERROR); |
| 39 } | 42 |
| 43 const char kAppsDeveloperToolsExtensionId[] = | |
| 44 "ohmmkhmmmpcnpikjeljgnaoabkaalbgc"; | |
| 45 | |
| 46 } // namespace | |
| 40 | 47 |
| 41 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { | 48 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { |
| 42 } | 49 } |
| 43 | 50 |
| 44 ErrorConsole::ErrorConsole(Profile* profile, | 51 ErrorConsole::ErrorConsole(Profile* profile, |
| 45 ExtensionService* extension_service) | 52 ExtensionService* extension_service) |
| 46 : enabled_(false), default_mask_(kDefaultMask), profile_(profile) { | 53 : should_record_(false), default_mask_(kDefaultMask), profile_(profile) { |
|
not at google - send to devlin
2014/03/28 22:05:32
I thnk that enabled_ was better, sorry.
Devlin
2014/03/31 18:39:31
Haha okay, done.
| |
| 47 // TODO(rdevlin.cronin): Remove once crbug.com/159265 is fixed. | 54 // TODO(rdevlin.cronin): Remove once crbug.com/159265 is fixed. |
| 48 #if !defined(ENABLE_EXTENSIONS) | 55 #if !defined(ENABLE_EXTENSIONS) |
| 49 return; | 56 return; |
| 50 #endif | 57 #endif |
| 51 | 58 |
| 52 // If we don't have the necessary FeatureSwitch enabled, then return | |
| 53 // immediately. Since we never register for any notifications, this ensures | |
| 54 // the ErrorConsole will never be enabled. | |
| 55 if (!FeatureSwitch::error_console()->IsEnabled()) | |
| 56 return; | |
| 57 | |
| 58 pref_registrar_.Init(profile_->GetPrefs()); | 59 pref_registrar_.Init(profile_->GetPrefs()); |
| 59 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode, | 60 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode, |
| 60 base::Bind(&ErrorConsole::OnPrefChanged, | 61 base::Bind(&ErrorConsole::OnPrefChanged, |
| 61 base::Unretained(this))); | 62 base::Unretained(this))); |
| 62 | 63 |
| 63 if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode)) | 64 if (IsEnabledForChromeExtensionsPage() || IsEnabledForAppsDeveloperTools()) |
| 64 Enable(extension_service); | 65 Enable(extension_service); |
| 65 } | 66 } |
| 66 | 67 |
| 67 ErrorConsole::~ErrorConsole() { | 68 ErrorConsole::~ErrorConsole() { |
| 68 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); | 69 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); |
| 69 } | 70 } |
| 70 | 71 |
| 71 // static | 72 // static |
| 72 ErrorConsole* ErrorConsole::Get(Profile* profile) { | 73 ErrorConsole* ErrorConsole::Get(Profile* profile) { |
| 73 return ExtensionSystem::Get(profile)->error_console(); | 74 return ExtensionSystem::Get(profile)->error_console(); |
| 74 } | 75 } |
| 75 | 76 |
| 76 void ErrorConsole::SetReportingForExtension(const std::string& extension_id, | 77 void ErrorConsole::SetReportingForExtension(const std::string& extension_id, |
| 77 ExtensionError::Type type, | 78 ExtensionError::Type type, |
| 78 bool enabled) { | 79 bool enabled) { |
| 79 DCHECK(thread_checker_.CalledOnValidThread()); | 80 DCHECK(thread_checker_.CalledOnValidThread()); |
| 80 if (!enabled_ || !Extension::IdIsValid(extension_id)) | 81 if (!should_record_ || !Extension::IdIsValid(extension_id)) |
| 81 return; | 82 return; |
| 82 | 83 |
| 83 ErrorPreferenceMap::iterator pref = pref_map_.find(extension_id); | 84 ErrorPreferenceMap::iterator pref = pref_map_.find(extension_id); |
| 84 | 85 |
| 85 if (pref == pref_map_.end()) { | 86 if (pref == pref_map_.end()) { |
| 86 pref = pref_map_.insert( | 87 pref = pref_map_.insert( |
| 87 std::pair<std::string, int32>(extension_id, default_mask_)).first; | 88 std::pair<std::string, int32>(extension_id, default_mask_)).first; |
| 88 } | 89 } |
| 89 | 90 |
| 90 pref->second = | 91 pref->second = |
| 91 enabled ? pref->second | (1 << type) : pref->second &~(1 << type); | 92 enabled ? pref->second | (1 << type) : pref->second &~(1 << type); |
| 92 | 93 |
| 93 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( | 94 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( |
| 94 extension_id, | 95 extension_id, |
| 95 kStoreExtensionErrorsPref, | 96 kStoreExtensionErrorsPref, |
| 96 base::Value::CreateIntegerValue(pref->second)); | 97 base::Value::CreateIntegerValue(pref->second)); |
| 97 } | 98 } |
| 98 | 99 |
| 99 void ErrorConsole::UseDefaultReportingForExtension( | 100 void ErrorConsole::UseDefaultReportingForExtension( |
| 100 const std::string& extension_id) { | 101 const std::string& extension_id) { |
| 101 DCHECK(thread_checker_.CalledOnValidThread()); | 102 DCHECK(thread_checker_.CalledOnValidThread()); |
| 102 if (!enabled_ || !Extension::IdIsValid(extension_id)) | 103 if (!should_record_ || !Extension::IdIsValid(extension_id)) |
| 103 return; | 104 return; |
| 104 | 105 |
| 105 pref_map_.erase(extension_id); | 106 pref_map_.erase(extension_id); |
| 106 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( | 107 ExtensionPrefs::Get(profile_)->UpdateExtensionPref( |
| 107 extension_id, | 108 extension_id, |
| 108 kStoreExtensionErrorsPref, | 109 kStoreExtensionErrorsPref, |
| 109 NULL); | 110 NULL); |
| 110 } | 111 } |
| 111 | 112 |
| 112 void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) { | 113 void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) { |
| 113 DCHECK(thread_checker_.CalledOnValidThread()); | 114 DCHECK(thread_checker_.CalledOnValidThread()); |
| 114 if (!enabled_ || !Extension::IdIsValid(error->extension_id())) | 115 if (!should_record_ || !Extension::IdIsValid(error->extension_id())) |
| 115 return; | 116 return; |
| 116 | 117 |
| 117 ErrorPreferenceMap::const_iterator pref = | 118 ErrorPreferenceMap::const_iterator pref = |
| 118 pref_map_.find(error->extension_id()); | 119 pref_map_.find(error->extension_id()); |
| 119 // Check the mask to see if we report the error. If we don't have a specific | 120 // Check the mask to see if we report the error. If we don't have a specific |
| 120 // entry, use the default mask. | 121 // entry, use the default mask. |
| 121 if ((pref == pref_map_.end() && | 122 if ((pref == pref_map_.end() && |
| 122 ((default_mask_ & (1 << error->type())) == 0)) || | 123 ((default_mask_ & (1 << error->type())) == 0)) || |
| 123 (pref != pref_map_.end() && (pref->second & (1 << error->type())) == 0)) { | 124 (pref != pref_map_.end() && (pref->second & (1 << error->type())) == 0)) { |
| 124 return; | 125 return; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 137 DCHECK(thread_checker_.CalledOnValidThread()); | 138 DCHECK(thread_checker_.CalledOnValidThread()); |
| 138 observers_.AddObserver(observer); | 139 observers_.AddObserver(observer); |
| 139 } | 140 } |
| 140 | 141 |
| 141 void ErrorConsole::RemoveObserver(Observer* observer) { | 142 void ErrorConsole::RemoveObserver(Observer* observer) { |
| 142 DCHECK(thread_checker_.CalledOnValidThread()); | 143 DCHECK(thread_checker_.CalledOnValidThread()); |
| 143 observers_.RemoveObserver(observer); | 144 observers_.RemoveObserver(observer); |
| 144 } | 145 } |
| 145 | 146 |
| 146 void ErrorConsole::OnPrefChanged() { | 147 void ErrorConsole::OnPrefChanged() { |
| 147 bool developer_mode = | 148 bool should_be_enabled = IsEnabledForChromeExtensionsPage() || |
| 148 profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode); | 149 IsEnabledForAppsDeveloperTools(); |
| 149 | 150 |
| 150 if (developer_mode && !enabled_) | 151 if (should_be_enabled && !should_record_) |
| 151 Enable(ExtensionSystem::Get(profile_)->extension_service()); | 152 Enable(ExtensionSystem::Get(profile_)->extension_service()); |
| 152 else if (!developer_mode && enabled_) | 153 else if (!should_be_enabled && should_record_) |
| 153 Disable(); | 154 Disable(); |
| 154 } | 155 } |
| 155 | 156 |
| 157 bool ErrorConsole::IsEnabledForChromeExtensionsPage() const { | |
| 158 return profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode) && | |
| 159 (FeatureSwitch::error_console()->IsEnabled() || | |
| 160 chrome::VersionInfo::GetChannel() <= | |
| 161 chrome::VersionInfo::CHANNEL_DEV); | |
| 162 } | |
| 163 | |
| 164 bool ErrorConsole::IsEnabledForAppsDeveloperTools() const { | |
| 165 return ExtensionRegistry::Get(profile_)->GetExtensionById( | |
| 166 kAppsDeveloperToolsExtensionId, ExtensionRegistry::EVERYTHING) != NULL; | |
|
not at google - send to devlin
2014/03/28 22:05:32
Yes I think we had better only do this while the A
Devlin
2014/03/31 18:39:31
ErrorConsole can't directly have dependencies - it
| |
| 167 } | |
| 168 | |
| 156 void ErrorConsole::Enable(ExtensionService* extension_service) { | 169 void ErrorConsole::Enable(ExtensionService* extension_service) { |
| 157 enabled_ = true; | 170 should_record_ = true; |
| 158 | 171 |
| 159 notification_registrar_.Add( | 172 notification_registrar_.Add( |
| 160 this, | 173 this, |
| 161 chrome::NOTIFICATION_PROFILE_DESTROYED, | 174 chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 162 content::NotificationService::AllBrowserContextsAndSources()); | 175 content::NotificationService::AllBrowserContextsAndSources()); |
| 163 notification_registrar_.Add( | 176 notification_registrar_.Add( |
| 164 this, | 177 this, |
| 165 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | 178 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 166 content::Source<Profile>(profile_)); | 179 content::Source<Profile>(profile_)); |
| 167 notification_registrar_.Add( | 180 notification_registrar_.Add( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 181 pref_map_[iter->get()->id()] = mask; | 194 pref_map_[iter->get()->id()] = mask; |
| 182 } | 195 } |
| 183 AddManifestErrorsForExtension(iter->get()); | 196 AddManifestErrorsForExtension(iter->get()); |
| 184 } | 197 } |
| 185 } | 198 } |
| 186 } | 199 } |
| 187 | 200 |
| 188 void ErrorConsole::Disable() { | 201 void ErrorConsole::Disable() { |
| 189 notification_registrar_.RemoveAll(); | 202 notification_registrar_.RemoveAll(); |
| 190 errors_.RemoveAllErrors(); | 203 errors_.RemoveAllErrors(); |
| 191 enabled_ = false; | 204 should_record_ = false; |
| 192 } | 205 } |
| 193 | 206 |
| 194 void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) { | 207 void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) { |
| 195 const std::vector<InstallWarning>& warnings = | 208 const std::vector<InstallWarning>& warnings = |
| 196 extension->install_warnings(); | 209 extension->install_warnings(); |
| 197 for (std::vector<InstallWarning>::const_iterator iter = warnings.begin(); | 210 for (std::vector<InstallWarning>::const_iterator iter = warnings.begin(); |
| 198 iter != warnings.end(); ++iter) { | 211 iter != warnings.end(); ++iter) { |
| 199 ReportError(scoped_ptr<ExtensionError>(new ManifestError( | 212 ReportError(scoped_ptr<ExtensionError>(new ManifestError( |
| 200 extension->id(), | 213 extension->id(), |
| 201 base::UTF8ToUTF16(iter->message), | 214 base::UTF8ToUTF16(iter->message), |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 | 247 |
| 235 AddManifestErrorsForExtension(info->extension); | 248 AddManifestErrorsForExtension(info->extension); |
| 236 break; | 249 break; |
| 237 } | 250 } |
| 238 default: | 251 default: |
| 239 NOTREACHED(); | 252 NOTREACHED(); |
| 240 } | 253 } |
| 241 } | 254 } |
| 242 | 255 |
| 243 } // namespace extensions | 256 } // namespace extensions |
| OLD | NEW |