1 // Copyright (c) 2013 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.
5 #include "chrome/browser/extensions/extension_message_bubble_controller.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/extensions/extension_message_bubble.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_finder.h"
14 #include "chrome/common/url_constants.h"
15 #include "content/public/browser/user_metrics.h"
16 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "grit/components_strings.h"
19 #include "ui/base/l10n/l10n_util.h"
21 namespace extensions
{
23 ////////////////////////////////////////////////////////////////////////////////
24 // ExtensionMessageBubbleController::Delegate
26 ExtensionMessageBubbleController::Delegate::Delegate(Profile
* profile
)
30 ExtensionMessageBubbleController::Delegate::~Delegate() {
33 void ExtensionMessageBubbleController::Delegate::RestrictToSingleExtension(
34 const std::string
& extension_id
) {
35 NOTIMPLEMENTED(); // Derived classes that need this should implement.
38 base::string16
ExtensionMessageBubbleController::Delegate::GetLearnMoreLabel()
40 return l10n_util::GetStringUTF16(IDS_LEARN_MORE
);
43 bool ExtensionMessageBubbleController::Delegate::HasBubbleInfoBeenAcknowledged(
44 const std::string
& extension_id
) {
45 std::string pref_name
= get_acknowledged_flag_pref_name();
46 if (pref_name
.empty())
48 bool pref_state
= false;
49 extensions::ExtensionPrefs
* prefs
= extensions::ExtensionPrefs::Get(profile_
);
50 prefs
->ReadPrefAsBoolean(extension_id
, pref_name
, &pref_state
);
54 void ExtensionMessageBubbleController::Delegate::SetBubbleInfoBeenAcknowledged(
55 const std::string
& extension_id
,
57 std::string pref_name
= get_acknowledged_flag_pref_name();
58 if (pref_name
.empty())
60 extensions::ExtensionPrefs
* prefs
= extensions::ExtensionPrefs::Get(profile_
);
61 prefs
->UpdateExtensionPref(extension_id
,
63 value
? new base::FundamentalValue(value
) : NULL
);
66 Profile
* ExtensionMessageBubbleController::Delegate::profile() const {
71 ExtensionMessageBubbleController::Delegate::get_acknowledged_flag_pref_name()
73 return acknowledged_pref_name_
;
77 ExtensionMessageBubbleController::Delegate::set_acknowledged_flag_pref_name(
78 std::string pref_name
) {
79 acknowledged_pref_name_
= pref_name
;
82 ////////////////////////////////////////////////////////////////////////////////
83 // ExtensionMessageBubbleController
85 ExtensionMessageBubbleController::ExtensionMessageBubbleController(
86 Delegate
* delegate
, Profile
* profile
)
88 user_action_(ACTION_BOUNDARY
),
93 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() {
96 std::vector
<base::string16
>
97 ExtensionMessageBubbleController::GetExtensionList() {
98 ExtensionIdList
* list
= GetOrCreateExtensionList();
100 return std::vector
<base::string16
>();
102 ExtensionRegistry
* registry
= ExtensionRegistry::Get(profile_
);
103 std::vector
<base::string16
> return_value
;
104 for (ExtensionIdList::const_iterator it
= list
->begin();
105 it
!= list
->end(); ++it
) {
106 const Extension
* extension
=
107 registry
->GetExtensionById(*it
, ExtensionRegistry::EVERYTHING
);
109 return_value
.push_back(base::UTF8ToUTF16(extension
->name()));
111 return_value
.push_back(
112 base::ASCIIToUTF16(std::string("(unknown name) ") + *it
));
113 // TODO(finnur): Add this as a string to the grd, for next milestone.
119 const ExtensionIdList
& ExtensionMessageBubbleController::GetExtensionIdList() {
120 return *GetOrCreateExtensionList();
123 bool ExtensionMessageBubbleController::CloseOnDeactivate() { return false; }
125 void ExtensionMessageBubbleController::Show(ExtensionMessageBubble
* bubble
) {
126 // Wire up all the callbacks, to get notified what actions the user took.
127 base::Closure dismiss_button_callback
=
128 base::Bind(&ExtensionMessageBubbleController::OnBubbleDismiss
,
129 base::Unretained(this));
130 base::Closure action_button_callback
=
131 base::Bind(&ExtensionMessageBubbleController::OnBubbleAction
,
132 base::Unretained(this));
133 base::Closure link_callback
=
134 base::Bind(&ExtensionMessageBubbleController::OnLinkClicked
,
135 base::Unretained(this));
136 bubble
->OnActionButtonClicked(action_button_callback
);
137 bubble
->OnDismissButtonClicked(dismiss_button_callback
);
138 bubble
->OnLinkClicked(link_callback
);
143 void ExtensionMessageBubbleController::OnBubbleAction() {
144 DCHECK_EQ(ACTION_BOUNDARY
, user_action_
);
145 user_action_
= ACTION_EXECUTE
;
147 delegate_
->LogAction(ACTION_EXECUTE
);
148 delegate_
->PerformAction(*GetOrCreateExtensionList());
149 AcknowledgeExtensions();
150 delegate_
->OnClose();
153 void ExtensionMessageBubbleController::OnBubbleDismiss() {
154 // OnBubbleDismiss() can be called twice when we receive multiple
155 // "OnWidgetDestroying" notifications (this can at least happen when we close
156 // a window with a notification open). Handle this gracefully.
157 if (user_action_
!= ACTION_BOUNDARY
) {
158 DCHECK(user_action_
== ACTION_DISMISS
);
162 user_action_
= ACTION_DISMISS
;
164 delegate_
->LogAction(ACTION_DISMISS
);
165 AcknowledgeExtensions();
166 delegate_
->OnClose();
169 void ExtensionMessageBubbleController::OnLinkClicked() {
170 DCHECK_EQ(ACTION_BOUNDARY
, user_action_
);
171 user_action_
= ACTION_LEARN_MORE
;
173 delegate_
->LogAction(ACTION_LEARN_MORE
);
175 chrome::FindBrowserWithProfile(profile_
, chrome::GetActiveDesktop());
178 content::OpenURLParams(delegate_
->GetLearnMoreUrl(),
181 ui::PAGE_TRANSITION_LINK
,
184 AcknowledgeExtensions();
185 delegate_
->OnClose();
188 void ExtensionMessageBubbleController::AcknowledgeExtensions() {
189 ExtensionIdList
* list
= GetOrCreateExtensionList();
190 for (ExtensionIdList::const_iterator it
= list
->begin();
191 it
!= list
->end(); ++it
)
192 delegate_
->AcknowledgeExtension(*it
, user_action_
);
195 ExtensionIdList
* ExtensionMessageBubbleController::GetOrCreateExtensionList() {
197 scoped_ptr
<const ExtensionSet
> extension_set(
198 ExtensionRegistry::Get(profile_
)->GenerateInstalledExtensionsSet());
199 for (ExtensionSet::const_iterator it
= extension_set
->begin();
200 it
!= extension_set
->end(); ++it
) {
201 std::string id
= (*it
)->id();
202 if (!delegate_
->ShouldIncludeExtension(id
))
204 extension_list_
.push_back(id
);
207 delegate_
->LogExtensionCount(extension_list_
.size());
211 return &extension_list_
;
214 } // namespace extensions