Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / extension_message_bubble_controller.cc
blob3fe6dc527d2ac5babb19cabd19047266e9ebbecf
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"
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/extensions/extension_message_bubble.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_finder.h"
16 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
17 #include "chrome/common/url_constants.h"
18 #include "content/public/browser/user_metrics.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/browser/extension_system.h"
22 #include "grit/components_strings.h"
23 #include "ui/base/l10n/l10n_util.h"
25 namespace extensions {
27 namespace {
28 // How many extensions to show in the bubble (max).
29 const int kMaxExtensionsToShow = 7;
31 // Whether or not to ignore the learn more link navigation for testing.
32 bool g_should_ignore_learn_more_for_testing = false;
35 ////////////////////////////////////////////////////////////////////////////////
36 // ExtensionMessageBubbleController::Delegate
38 ExtensionMessageBubbleController::Delegate::Delegate(Profile* profile)
39 : profile_(profile),
40 service_(ExtensionSystem::Get(profile)->extension_service()),
41 registry_(ExtensionRegistry::Get(profile)) {
44 ExtensionMessageBubbleController::Delegate::~Delegate() {
47 void ExtensionMessageBubbleController::Delegate::RestrictToSingleExtension(
48 const std::string& extension_id) {
49 NOTIMPLEMENTED(); // Derived classes that need this should implement.
52 base::string16 ExtensionMessageBubbleController::Delegate::GetLearnMoreLabel()
53 const {
54 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
57 bool ExtensionMessageBubbleController::Delegate::HasBubbleInfoBeenAcknowledged(
58 const std::string& extension_id) {
59 std::string pref_name = get_acknowledged_flag_pref_name();
60 if (pref_name.empty())
61 return false;
62 bool pref_state = false;
63 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
64 prefs->ReadPrefAsBoolean(extension_id, pref_name, &pref_state);
65 return pref_state;
68 void ExtensionMessageBubbleController::Delegate::SetBubbleInfoBeenAcknowledged(
69 const std::string& extension_id,
70 bool value) {
71 std::string pref_name = get_acknowledged_flag_pref_name();
72 if (pref_name.empty())
73 return;
74 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
75 prefs->UpdateExtensionPref(extension_id,
76 pref_name,
77 value ? new base::FundamentalValue(value) : NULL);
80 std::string
81 ExtensionMessageBubbleController::Delegate::get_acknowledged_flag_pref_name()
82 const {
83 return acknowledged_pref_name_;
86 void
87 ExtensionMessageBubbleController::Delegate::set_acknowledged_flag_pref_name(
88 std::string pref_name) {
89 acknowledged_pref_name_ = pref_name;
92 ////////////////////////////////////////////////////////////////////////////////
93 // ExtensionMessageBubbleController
95 ExtensionMessageBubbleController::ExtensionMessageBubbleController(
96 Delegate* delegate,
97 Browser* browser)
98 : browser_(browser),
99 user_action_(ACTION_BOUNDARY),
100 delegate_(delegate),
101 initialized_(false),
102 did_highlight_(false) {
105 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() {
108 Profile* ExtensionMessageBubbleController::profile() {
109 return browser_->profile();
112 std::vector<base::string16>
113 ExtensionMessageBubbleController::GetExtensionList() {
114 ExtensionIdList* list = GetOrCreateExtensionList();
115 if (list->empty())
116 return std::vector<base::string16>();
118 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
119 std::vector<base::string16> return_value;
120 for (ExtensionIdList::const_iterator it = list->begin();
121 it != list->end(); ++it) {
122 const Extension* extension =
123 registry->GetExtensionById(*it, ExtensionRegistry::EVERYTHING);
124 if (extension) {
125 return_value.push_back(base::UTF8ToUTF16(extension->name()));
126 } else {
127 return_value.push_back(
128 base::ASCIIToUTF16(std::string("(unknown name) ") + *it));
129 // TODO(finnur): Add this as a string to the grd, for next milestone.
132 return return_value;
135 base::string16 ExtensionMessageBubbleController::GetExtensionListForDisplay() {
136 if (!delegate_->ShouldShowExtensionList())
137 return base::string16();
139 std::vector<base::string16> extension_list = GetExtensionList();
140 if (extension_list.size() > kMaxExtensionsToShow) {
141 int old_size = extension_list.size();
142 extension_list.erase(extension_list.begin() + kMaxExtensionsToShow,
143 extension_list.end());
144 extension_list.push_back(delegate_->GetOverflowText(base::IntToString16(
145 old_size - kMaxExtensionsToShow)));
147 const base::char16 bullet_point = 0x2022;
148 base::string16 prefix = bullet_point + base::ASCIIToUTF16(" ");
149 for (base::string16& str : extension_list)
150 str.insert(0, prefix);
151 return base::JoinString(extension_list, base::ASCIIToUTF16("\n"));
154 const ExtensionIdList& ExtensionMessageBubbleController::GetExtensionIdList() {
155 return *GetOrCreateExtensionList();
158 bool ExtensionMessageBubbleController::CloseOnDeactivate() { return false; }
160 void ExtensionMessageBubbleController::HighlightExtensionsIfNecessary() {
161 if (delegate_->ShouldHighlightExtensions() && !did_highlight_) {
162 did_highlight_ = true;
163 const ExtensionIdList& extension_ids = GetExtensionIdList();
164 DCHECK(!extension_ids.empty());
165 ToolbarActionsModel::Get(profile())->HighlightActions(
166 extension_ids, ToolbarActionsModel::HIGHLIGHT_WARNING);
170 void ExtensionMessageBubbleController::Show(ExtensionMessageBubble* bubble) {
171 bubble->Show();
174 void ExtensionMessageBubbleController::OnBubbleAction() {
175 DCHECK_EQ(ACTION_BOUNDARY, user_action_);
176 user_action_ = ACTION_EXECUTE;
178 delegate_->LogAction(ACTION_EXECUTE);
179 delegate_->PerformAction(*GetOrCreateExtensionList());
181 OnClose();
184 void ExtensionMessageBubbleController::OnBubbleDismiss() {
185 // OnBubbleDismiss() can be called twice when we receive multiple
186 // "OnWidgetDestroying" notifications (this can at least happen when we close
187 // a window with a notification open). Handle this gracefully.
188 if (user_action_ != ACTION_BOUNDARY) {
189 DCHECK(user_action_ == ACTION_DISMISS);
190 return;
193 user_action_ = ACTION_DISMISS;
195 delegate_->LogAction(ACTION_DISMISS);
197 OnClose();
200 void ExtensionMessageBubbleController::OnLinkClicked() {
201 DCHECK_EQ(ACTION_BOUNDARY, user_action_);
202 user_action_ = ACTION_LEARN_MORE;
204 delegate_->LogAction(ACTION_LEARN_MORE);
205 if (!g_should_ignore_learn_more_for_testing) {
206 browser_->OpenURL(
207 content::OpenURLParams(delegate_->GetLearnMoreUrl(),
208 content::Referrer(),
209 NEW_FOREGROUND_TAB,
210 ui::PAGE_TRANSITION_LINK,
211 false));
213 OnClose();
216 // static
217 void ExtensionMessageBubbleController::set_should_ignore_learn_more_for_testing(
218 bool should_ignore) {
219 g_should_ignore_learn_more_for_testing = should_ignore;
222 void ExtensionMessageBubbleController::AcknowledgeExtensions() {
223 ExtensionIdList* list = GetOrCreateExtensionList();
224 for (ExtensionIdList::const_iterator it = list->begin();
225 it != list->end(); ++it)
226 delegate_->AcknowledgeExtension(*it, user_action_);
229 ExtensionIdList* ExtensionMessageBubbleController::GetOrCreateExtensionList() {
230 if (!initialized_) {
231 scoped_ptr<const ExtensionSet> extension_set(
232 ExtensionRegistry::Get(profile())->GenerateInstalledExtensionsSet());
233 for (ExtensionSet::const_iterator it = extension_set->begin();
234 it != extension_set->end(); ++it) {
235 std::string id = (*it)->id();
236 if (!delegate_->ShouldIncludeExtension(id))
237 continue;
238 extension_list_.push_back(id);
241 delegate_->LogExtensionCount(extension_list_.size());
242 initialized_ = true;
245 return &extension_list_;
248 void ExtensionMessageBubbleController::OnClose() {
249 AcknowledgeExtensions();
250 if (did_highlight_)
251 ToolbarActionsModel::Get(profile())->StopHighlighting();
254 } // namespace extensions