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