1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// found in the LICENSE file.
4558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/extensions/error_console/error_console.h"
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <vector>
8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/bind.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/bind_helpers.h"
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/lazy_instance.h"
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/prefs/pref_service.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/stl_util.h"
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
16558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/profiles/profile.h"
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/chrome_version_info.h"
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/extensions/features/feature_channel.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/common/pref_names.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h"
21558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/public/browser/notification_details.h"
22558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/public/browser/notification_service.h"
23558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/public/browser/notification_source.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_registry.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "extensions/common/constants.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h"
31558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochnamespace extensions {
33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The key into the Extension prefs for an Extension's specific reporting
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// settings.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kStoreExtensionErrorsPref[] = "store_extension_errors";
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// This is the default mask for which errors to report. That is, if an extension
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// does not have specific preference set, this will be used instead.
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst int kDefaultMask = 0;
43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kAppsDeveloperToolsExtensionId[] =
45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "ohmmkhmmmpcnpikjeljgnaoabkaalbgc";
46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid ErrorConsole::Observer::OnErrorConsoleDestroyed() {
50558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
51558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochErrorConsole::ErrorConsole(Profile* profile)
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch     : enabled_(false),
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       default_mask_(kDefaultMask),
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       profile_(profile),
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       prefs_(NULL),
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       registry_observer_(this) {
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pref_registrar_.Init(profile_->GetPrefs());
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode,
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                      base::Bind(&ErrorConsole::OnPrefChanged,
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                 base::Unretained(this)));
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  registry_observer_.Add(ExtensionRegistry::Get(profile_));
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CheckEnabled();
66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
68558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochErrorConsole::~ErrorConsole() {
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// static
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochErrorConsole* ErrorConsole::Get(Profile* profile) {
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return ExtensionSystem::Get(profile)->error_console();
75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ErrorConsole::SetReportingForExtension(const std::string& extension_id,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            ExtensionError::Type type,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool enabled) {
80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int mask = default_mask_;
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // This call can fail if the preference isn't set, but we don't really care
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // if it does, because we just use the default mask instead.
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &mask);
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (enabled)
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    mask |= 1 << type;
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    mask &= ~(1 << type);
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs_->UpdateExtensionPref(extension_id,
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                              kStoreExtensionErrorsPref,
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              new base::FundamentalValue(mask));
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ErrorConsole::SetReportingAllForExtension(
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const std::string& extension_id, bool enabled) {
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int mask = 0;
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (enabled)
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    mask = (1 << ExtensionError::NUM_ERROR_TYPES) - 1;
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs_->UpdateExtensionPref(extension_id,
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                              kStoreExtensionErrorsPref,
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              new base::FundamentalValue(mask));
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool ErrorConsole::IsReportingEnabledForExtension(
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const std::string& extension_id) const {
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetMaskForExtension(extension_id) != 0;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ErrorConsole::UseDefaultReportingForExtension(
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& extension_id) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs_->UpdateExtensionPref(extension_id, kStoreExtensionErrorsPref, NULL);
130558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
131558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!enabled_ || !crx_file::id_util::IdIsValid(error->extension_id()))
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int mask = GetMaskForExtension(error->extension_id());
1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!(mask & (1 << error->type())))
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ExtensionError* weak_error = errors_.AddError(error.Pass());
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(weak_error));
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const ErrorList& ErrorConsole::GetErrorsForExtension(
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& extension_id) const {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return errors_.GetErrorsForExtension(extension_id);
148558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
149558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid ErrorConsole::AddObserver(Observer* observer) {
151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  observers_.AddObserver(observer);
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid ErrorConsole::RemoveObserver(Observer* observer) {
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  observers_.RemoveObserver(observer);
158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool ErrorConsole::IsEnabledForChromeExtensionsPage() const {
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode) &&
162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch         (FeatureSwitch::error_console()->IsEnabled() ||
163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV);
164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool ErrorConsole::IsEnabledForAppsDeveloperTools() const {
167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return ExtensionRegistry::Get(profile_)->enabled_extensions()
168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      .Contains(kAppsDeveloperToolsExtensionId);
169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ErrorConsole::CheckEnabled() {
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool should_be_enabled = IsEnabledForChromeExtensionsPage() ||
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           IsEnabledForAppsDeveloperTools();
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (should_be_enabled && !enabled_)
175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    Enable();
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!should_be_enabled && enabled_)
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    Disable();
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ErrorConsole::Enable() {
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  enabled_ = true;
182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // We postpone the initialization of |prefs_| until now because they can be
1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // NULL in unit_tests. Any unit tests that enable the error console should
1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // also create an ExtensionPrefs object.
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs_ = ExtensionPrefs::Get(profile_);
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  notification_registrar_.Add(
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      this,
190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      chrome::NOTIFICATION_PROFILE_DESTROYED,
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      content::NotificationService::AllBrowserContextsAndSources());
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const ExtensionSet& extensions =
194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ExtensionRegistry::Get(profile_)->enabled_extensions();
195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (ExtensionSet::const_iterator iter = extensions.begin();
196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       iter != extensions.end();
197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++iter) {
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    AddManifestErrorsForExtension(iter->get());
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void ErrorConsole::Disable() {
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  notification_registrar_.RemoveAll();
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  errors_.RemoveAllErrors();
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  enabled_ = false;
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ErrorConsole::OnPrefChanged() {
209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CheckEnabled();
210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ErrorConsole::OnExtensionUnloaded(content::BrowserContext* browser_context,
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                       const Extension* extension,
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                       UnloadedExtensionInfo::Reason reason) {
215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CheckEnabled();
216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ErrorConsole::OnExtensionLoaded(content::BrowserContext* browser_context,
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     const Extension* extension) {
220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CheckEnabled();
221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ErrorConsole::OnExtensionInstalled(
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    content::BrowserContext* browser_context,
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update) {
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // We don't want to have manifest errors from previous installs. We want
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // to keep runtime errors, though, because extensions are reloaded on a
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // refresh of chrome:extensions, and we don't want to wipe our history
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // whenever that happens.
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  errors_.RemoveErrorsForExtensionOfType(extension->id(),
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         ExtensionError::MANIFEST_ERROR);
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddManifestErrorsForExtension(extension);
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ErrorConsole::OnExtensionUninstalled(
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    content::BrowserContext* browser_context,
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extensions::UninstallReason reason) {
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  errors_.Remove(extension->id());
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) {
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const std::vector<InstallWarning>& warnings =
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->install_warnings();
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (std::vector<InstallWarning>::const_iterator iter = warnings.begin();
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)       iter != warnings.end(); ++iter) {
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ReportError(scoped_ptr<ExtensionError>(new ManifestError(
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        extension->id(),
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::UTF8ToUTF16(iter->message),
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::UTF8ToUTF16(iter->key),
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::UTF8ToUTF16(iter->specific))));
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
256558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid ErrorConsole::Observe(int type,
257558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                           const content::NotificationSource& source,
258558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                           const content::NotificationDetails& details) {
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Profile* profile = content::Source<Profile>(source).ptr();
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If incognito profile which we are associated with is destroyed, also
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // destroy all incognito errors.
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile))
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    errors_.RemoveIncognitoErrors();
265558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
266558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint ErrorConsole::GetMaskForExtension(const std::string& extension_id) const {
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Registered preferences take priority over everything else.
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int pref = 0;
2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &pref))
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return pref;
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // If the extension is unpacked, we report all error types by default.
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const Extension* extension =
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ExtensionRegistry::Get(profile_)->GetExtensionById(
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          extension_id, ExtensionRegistry::EVERYTHING);
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (extension && extension->location() == Manifest::UNPACKED)
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return (1 << ExtensionError::NUM_ERROR_TYPES) - 1;
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Otherwise, use the default mask.
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return default_mask_;
2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
284558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}  // namespace extensions
285