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 |