1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_warning_badge_service.h"
6
7#include "base/stl_util.h"
8#include "chrome/app/chrome_command_ids.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser_commands.h"
11#include "chrome/browser/ui/global_error/global_error.h"
12#include "chrome/browser/ui/global_error/global_error_service.h"
13#include "chrome/browser/ui/global_error/global_error_service_factory.h"
14#include "chrome/grit/generated_resources.h"
15#include "extensions/browser/extension_system.h"
16#include "ui/base/l10n/l10n_util.h"
17
18namespace extensions {
19
20namespace {
21// Non-modal GlobalError implementation that warns the user if extensions
22// created warnings or errors. If the user clicks on the wrench menu, the user
23// is redirected to chrome://extensions to inspect the errors.
24class ErrorBadge : public GlobalError {
25 public:
26  explicit ErrorBadge(ExtensionWarningBadgeService* badge_service);
27  virtual ~ErrorBadge();
28
29  // Implementation for GlobalError:
30  virtual bool HasMenuItem() OVERRIDE;
31  virtual int MenuItemCommandID() OVERRIDE;
32  virtual base::string16 MenuItemLabel() OVERRIDE;
33  virtual void ExecuteMenuItem(Browser* browser) OVERRIDE;
34
35  virtual bool HasBubbleView() OVERRIDE;
36  virtual bool HasShownBubbleView() OVERRIDE;
37  virtual void ShowBubbleView(Browser* browser) OVERRIDE;
38  virtual GlobalErrorBubbleViewBase* GetBubbleView() OVERRIDE;
39
40  static int GetMenuItemCommandID();
41
42 private:
43  ExtensionWarningBadgeService* badge_service_;
44
45  DISALLOW_COPY_AND_ASSIGN(ErrorBadge);
46};
47
48ErrorBadge::ErrorBadge(ExtensionWarningBadgeService* badge_service)
49    : badge_service_(badge_service) {}
50
51ErrorBadge::~ErrorBadge() {}
52
53bool ErrorBadge::HasMenuItem() {
54  return true;
55}
56
57int ErrorBadge::MenuItemCommandID() {
58  return GetMenuItemCommandID();
59}
60
61base::string16 ErrorBadge::MenuItemLabel() {
62  return l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_WRENCH_MENU_ITEM);
63}
64
65void ErrorBadge::ExecuteMenuItem(Browser* browser) {
66  // Suppress all current warnings in the extension service from triggering
67  // a badge on the wrench menu in the future of this session.
68  badge_service_->SuppressCurrentWarnings();
69
70  chrome::ExecuteCommand(browser, IDC_MANAGE_EXTENSIONS);
71}
72
73bool ErrorBadge::HasBubbleView() { return false; }
74
75bool ErrorBadge::HasShownBubbleView() { return false; }
76
77void ErrorBadge::ShowBubbleView(Browser* browser) { NOTREACHED(); }
78
79GlobalErrorBubbleViewBase* ErrorBadge::GetBubbleView() {
80  return NULL;
81}
82
83// static
84int ErrorBadge::GetMenuItemCommandID() {
85  return IDC_EXTENSION_ERRORS;
86}
87
88}  // namespace
89
90
91ExtensionWarningBadgeService::ExtensionWarningBadgeService(Profile* profile)
92    : profile_(profile) {
93  DCHECK(CalledOnValidThread());
94}
95
96ExtensionWarningBadgeService::~ExtensionWarningBadgeService() {}
97
98void ExtensionWarningBadgeService::SuppressCurrentWarnings() {
99  DCHECK(CalledOnValidThread());
100  size_t old_size = suppressed_warnings_.size();
101
102  const WarningSet& warnings = GetCurrentWarnings();
103  suppressed_warnings_.insert(warnings.begin(), warnings.end());
104
105  if (old_size != suppressed_warnings_.size())
106    UpdateBadgeStatus();
107}
108
109const WarningSet& ExtensionWarningBadgeService::GetCurrentWarnings() const {
110  return ExtensionSystem::Get(profile_)->warning_service()->warnings();
111}
112
113void ExtensionWarningBadgeService::ExtensionWarningsChanged() {
114  DCHECK(CalledOnValidThread());
115  UpdateBadgeStatus();
116}
117
118void ExtensionWarningBadgeService::UpdateBadgeStatus() {
119  const std::set<Warning>& warnings = GetCurrentWarnings();
120  bool non_suppressed_warnings_exist = false;
121  for (std::set<Warning>::const_iterator i = warnings.begin();
122       i != warnings.end(); ++i) {
123    if (!ContainsKey(suppressed_warnings_, *i)) {
124      non_suppressed_warnings_exist = true;
125      break;
126    }
127  }
128  ShowBadge(non_suppressed_warnings_exist);
129}
130
131void ExtensionWarningBadgeService::ShowBadge(bool show) {
132  GlobalErrorService* service =
133      GlobalErrorServiceFactory::GetForProfile(profile_);
134  GlobalError* error = service->GetGlobalErrorByMenuItemCommandID(
135      ErrorBadge::GetMenuItemCommandID());
136
137  // Activate or hide the warning badge in case the current state is incorrect.
138  if (error && !show) {
139    service->RemoveGlobalError(error);
140    delete error;
141  } else if (!error && show) {
142    service->AddGlobalError(new ErrorBadge(this));
143  }
144}
145
146}  // namespace extensions
147