Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / settings_api_bubble_controller.cc
1 // Copyright (c) 2014 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/settings_api_bubble_controller.h"
6
7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_toolbar_model.h"
10 #include "chrome/browser/extensions/settings_api_helpers.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/startup/startup_browser_creator.h"
13 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/grit/chromium_strings.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "extensions/browser/extension_prefs.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/extension_system.h"
20 #include "grit/components_strings.h"
21 #include "ui/base/l10n/l10n_util.h"
22
23 namespace extensions {
24
25 namespace {
26
27 ////////////////////////////////////////////////////////////////////////////////
28 // SettingsApiBubbleDelegate
29
30 class SettingsApiBubbleDelegate
31     : public ExtensionMessageBubbleController::Delegate {
32  public:
33   explicit SettingsApiBubbleDelegate(ExtensionService* service,
34                                      Profile* profile,
35                                      SettingsApiOverrideType type);
36   virtual ~SettingsApiBubbleDelegate();
37
38   // ExtensionMessageBubbleController::Delegate methods.
39   virtual bool ShouldIncludeExtension(const std::string& extension_id) OVERRIDE;
40   virtual void AcknowledgeExtension(
41       const std::string& extension_id,
42       ExtensionMessageBubbleController::BubbleAction user_action) OVERRIDE;
43   virtual void PerformAction(const ExtensionIdList& list) OVERRIDE;
44   virtual void OnClose() OVERRIDE;
45   virtual base::string16 GetTitle() const OVERRIDE;
46   virtual base::string16 GetMessageBody(
47       bool anchored_to_browser_action) const OVERRIDE;
48   virtual base::string16 GetOverflowText(
49       const base::string16& overflow_count) const OVERRIDE;
50   virtual base::string16 GetLearnMoreLabel() const OVERRIDE;
51   virtual GURL GetLearnMoreUrl() const OVERRIDE;
52   virtual base::string16 GetActionButtonLabel() const OVERRIDE;
53   virtual base::string16 GetDismissButtonLabel() const OVERRIDE;
54   virtual bool ShouldShowExtensionList() const OVERRIDE;
55   virtual void LogExtensionCount(size_t count) OVERRIDE;
56   virtual void LogAction(
57       ExtensionMessageBubbleController::BubbleAction action) OVERRIDE;
58
59  private:
60   // Our extension service. Weak, not owned by us.
61   ExtensionService* service_;
62
63   // A weak pointer to the profile we are associated with. Not owned by us.
64   Profile* profile_;
65
66   // The type of settings override this bubble will report on. This can be, for
67   // example, a bubble to notify the user that the search engine has been
68   // changed by an extension (or homepage/startup pages/etc).
69   SettingsApiOverrideType type_;
70
71   // The ID of the extension we are showing the bubble for.
72   std::string extension_id_;
73
74   DISALLOW_COPY_AND_ASSIGN(SettingsApiBubbleDelegate);
75 };
76
77 SettingsApiBubbleDelegate::SettingsApiBubbleDelegate(
78     ExtensionService* service,
79     Profile* profile,
80     SettingsApiOverrideType type)
81     : service_(service), profile_(profile), type_(type) {}
82
83 SettingsApiBubbleDelegate::~SettingsApiBubbleDelegate() {}
84
85 bool SettingsApiBubbleDelegate::ShouldIncludeExtension(
86     const std::string& extension_id) {
87   ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
88   const Extension* extension =
89       registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
90   if (!extension)
91     return false;  // The extension provided is no longer enabled.
92
93   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
94   if (prefs->HasSettingsApiBubbleBeenAcknowledged(extension_id))
95     return false;
96
97   const Extension* override = NULL;
98   switch (type_) {
99     case extensions::BUBBLE_TYPE_HOME_PAGE:
100       override = extensions::GetExtensionOverridingHomepage(profile_);
101       break;
102     case extensions::BUBBLE_TYPE_STARTUP_PAGES:
103       override = extensions::GetExtensionOverridingStartupPages(profile_);
104       break;
105     case extensions::BUBBLE_TYPE_SEARCH_ENGINE:
106       override = extensions::GetExtensionOverridingSearchEngine(profile_);
107       break;
108   }
109
110   if (!override || override->id() != extension->id())
111     return false;
112
113   extension_id_ = extension_id;
114   return true;
115 }
116
117 void SettingsApiBubbleDelegate::AcknowledgeExtension(
118     const std::string& extension_id,
119     ExtensionMessageBubbleController::BubbleAction user_action) {
120   if (user_action != ExtensionMessageBubbleController::ACTION_EXECUTE) {
121     ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
122     prefs->SetSettingsApiBubbleBeenAcknowledged(extension_id, true);
123   }
124 }
125
126 void SettingsApiBubbleDelegate::PerformAction(const ExtensionIdList& list) {
127   for (size_t i = 0; i < list.size(); ++i) {
128     service_->DisableExtension(list[i], Extension::DISABLE_USER_ACTION);
129   }
130 }
131
132 void SettingsApiBubbleDelegate::OnClose() {
133   ExtensionToolbarModel* toolbar_model = ExtensionToolbarModel::Get(profile_);
134   if (toolbar_model)
135     toolbar_model->StopHighlighting();
136 }
137
138 base::string16 SettingsApiBubbleDelegate::GetTitle() const {
139   switch (type_) {
140     case BUBBLE_TYPE_HOME_PAGE:
141       return l10n_util::GetStringUTF16(
142           IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE);
143     case BUBBLE_TYPE_STARTUP_PAGES:
144       return l10n_util::GetStringUTF16(
145           IDS_EXTENSIONS_SETTINGS_API_TITLE_STARTUP_PAGES_BUBBLE);
146     case BUBBLE_TYPE_SEARCH_ENGINE:
147       return l10n_util::GetStringUTF16(
148           IDS_EXTENSIONS_SETTINGS_API_TITLE_SEARCH_ENGINE_BUBBLE);
149   }
150   NOTREACHED();
151   return base::string16();
152 }
153
154 base::string16 SettingsApiBubbleDelegate::GetMessageBody(
155     bool anchored_to_browser_action) const {
156   ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
157   const Extension* extension =
158       registry->GetExtensionById(extension_id_, ExtensionRegistry::ENABLED);
159   const SettingsOverrides* settings =
160       extension ? SettingsOverrides::Get(extension) : NULL;
161   if (!extension || !settings) {
162     NOTREACHED();
163     return base::string16();
164   }
165
166   bool home_change = settings->homepage != NULL;
167   bool startup_change = !settings->startup_pages.empty();
168   bool search_change = settings->search_engine != NULL;
169
170   base::string16 body;
171   switch (type_) {
172     case BUBBLE_TYPE_HOME_PAGE:
173       body = l10n_util::GetStringUTF16(
174           IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_HOME_PAGE);
175       if (startup_change && search_change) {
176         body += l10n_util::GetStringUTF16(
177             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_SEARCH);
178       } else if (startup_change) {
179         body += l10n_util::GetStringUTF16(
180             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES);
181       } else if (search_change) {
182         body += l10n_util::GetStringUTF16(
183             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE);
184       }
185       break;
186     case BUBBLE_TYPE_STARTUP_PAGES:
187       body = l10n_util::GetStringUTF16(
188           IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_START_PAGES);
189       if (home_change && search_change) {
190         body += l10n_util::GetStringUTF16(
191             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_AND_SEARCH);
192       } else if (home_change) {
193         body += l10n_util::GetStringUTF16(
194             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_PAGE);
195       } else if (search_change) {
196         body += l10n_util::GetStringUTF16(
197             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE);
198       }
199       break;
200     case BUBBLE_TYPE_SEARCH_ENGINE:
201       body = l10n_util::GetStringUTF16(
202           IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_SEARCH_ENGINE);
203       if (startup_change && home_change) {
204         body += l10n_util::GetStringUTF16(
205             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_HOME);
206       } else if (startup_change) {
207         body += l10n_util::GetStringUTF16(
208             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES);
209       } else if (home_change) {
210         body += l10n_util::GetStringUTF16(
211             IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_PAGE);
212       }
213       break;
214   }
215   if (!body.empty())
216     body += l10n_util::GetStringUTF16(
217             IDS_EXTENSIONS_SETTINGS_API_THIRD_LINE_CONFIRMATION);
218   return body;
219 }
220
221 base::string16 SettingsApiBubbleDelegate::GetOverflowText(
222     const base::string16& overflow_count) const {
223   // Does not have more than one extension in the list at a time.
224   NOTREACHED();
225   return base::string16();
226 }
227
228 base::string16 SettingsApiBubbleDelegate::GetLearnMoreLabel() const {
229   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
230 }
231
232 GURL SettingsApiBubbleDelegate::GetLearnMoreUrl() const {
233   return GURL(chrome::kExtensionControlledSettingLearnMoreURL);
234 }
235
236 base::string16 SettingsApiBubbleDelegate::GetActionButtonLabel() const {
237   return l10n_util::GetStringUTF16(IDS_EXTENSION_CONTROLLED_RESTORE_SETTINGS);
238 }
239
240 base::string16 SettingsApiBubbleDelegate::GetDismissButtonLabel() const {
241   return l10n_util::GetStringUTF16(IDS_EXTENSION_CONTROLLED_KEEP_CHANGES);
242 }
243
244 bool SettingsApiBubbleDelegate::ShouldShowExtensionList() const {
245   return false;
246 }
247
248 void SettingsApiBubbleDelegate::LogExtensionCount(size_t count) {
249 }
250
251 void SettingsApiBubbleDelegate::LogAction(
252     ExtensionMessageBubbleController::BubbleAction action) {
253   switch (type_) {
254     case BUBBLE_TYPE_HOME_PAGE:
255       UMA_HISTOGRAM_ENUMERATION(
256           "ExtensionOverrideBubble.SettingsApiUserSelectionHomePage",
257           action,
258           ExtensionMessageBubbleController::ACTION_BOUNDARY);
259       break;
260     case BUBBLE_TYPE_STARTUP_PAGES:
261       UMA_HISTOGRAM_ENUMERATION(
262           "ExtensionOverrideBubble.SettingsApiUserSelectionStartupPage",
263           action,
264           ExtensionMessageBubbleController::ACTION_BOUNDARY);
265       break;
266     case BUBBLE_TYPE_SEARCH_ENGINE:
267       UMA_HISTOGRAM_ENUMERATION(
268           "ExtensionOverrideBubble.SettingsApiUserSelectionSearchEngine",
269           action,
270           ExtensionMessageBubbleController::ACTION_BOUNDARY);
271       break;
272   }
273 }
274
275 }  // namespace
276
277 ////////////////////////////////////////////////////////////////////////////////
278 // SettingsApiBubbleController
279
280 SettingsApiBubbleController::SettingsApiBubbleController(
281     Profile* profile,
282     SettingsApiOverrideType type)
283     : ExtensionMessageBubbleController(
284           new SettingsApiBubbleDelegate(
285               ExtensionSystem::Get(profile)->extension_service(),
286               profile,
287               type),
288           profile),
289       profile_(profile),
290       type_(type) {}
291
292 SettingsApiBubbleController::~SettingsApiBubbleController() {}
293
294 bool SettingsApiBubbleController::ShouldShow(const std::string& extension_id) {
295   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
296   if (prefs->HasSettingsApiBubbleBeenAcknowledged(extension_id))
297     return false;
298
299   if (!delegate()->ShouldIncludeExtension(extension_id))
300     return false;
301
302   // If the browser is showing the 'Chrome crashed' infobar, it won't be showing
303   // the startup pages, so there's no point in showing the bubble now.
304   if (type_ == BUBBLE_TYPE_STARTUP_PAGES)
305     return profile_->GetLastSessionExitType() != Profile::EXIT_CRASHED;
306
307   return true;
308 }
309
310 bool SettingsApiBubbleController::CloseOnDeactivate() {
311   // Startup bubbles tend to get lost in the focus storm that happens on
312   // startup. Other types should dismiss on focus loss.
313   return type_ != BUBBLE_TYPE_STARTUP_PAGES;
314 }
315
316 }  // namespace extensions