• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/extension_message_bubble_controller.h"
6 
7 #include "base/bind.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_registry.h"
17 #include "grit/chromium_strings.h"
18 #include "grit/generated_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
20 
21 namespace extensions {
22 
23 ////////////////////////////////////////////////////////////////////////////////
24 // ExtensionMessageBubbleController::Delegate
25 
Delegate()26 ExtensionMessageBubbleController::Delegate::Delegate() {
27 }
28 
~Delegate()29 ExtensionMessageBubbleController::Delegate::~Delegate() {
30 }
31 
RestrictToSingleExtension(const std::string & extension_id)32 void ExtensionMessageBubbleController::Delegate::RestrictToSingleExtension(
33     const std::string& extension_id) {
34   NOTIMPLEMENTED();  // Derived classes that need this should implement.
35 }
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 // ExtensionMessageBubbleController
39 
ExtensionMessageBubbleController(Delegate * delegate,Profile * profile)40 ExtensionMessageBubbleController::ExtensionMessageBubbleController(
41     Delegate* delegate, Profile* profile)
42     : profile_(profile),
43       user_action_(ACTION_BOUNDARY),
44       delegate_(delegate),
45       initialized_(false) {
46 }
47 
~ExtensionMessageBubbleController()48 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() {
49 }
50 
51 std::vector<base::string16>
GetExtensionList()52 ExtensionMessageBubbleController::GetExtensionList() {
53   ExtensionIdList* list = GetOrCreateExtensionList();
54   if (list->empty())
55     return std::vector<base::string16>();
56 
57   ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
58   std::vector<base::string16> return_value;
59   for (ExtensionIdList::const_iterator it = list->begin();
60        it != list->end(); ++it) {
61     const Extension* extension =
62         registry->GetExtensionById(*it, ExtensionRegistry::EVERYTHING);
63     if (extension) {
64       return_value.push_back(base::UTF8ToUTF16(extension->name()));
65     } else {
66       return_value.push_back(
67           base::ASCIIToUTF16(std::string("(unknown name) ") + *it));
68       // TODO(finnur): Add this as a string to the grd, for next milestone.
69     }
70   }
71   return return_value;
72 }
73 
GetExtensionIdList()74 const ExtensionIdList& ExtensionMessageBubbleController::GetExtensionIdList() {
75   return *GetOrCreateExtensionList();
76 }
77 
CloseOnDeactivate()78 bool ExtensionMessageBubbleController::CloseOnDeactivate() { return false; }
79 
Show(ExtensionMessageBubble * bubble)80 void ExtensionMessageBubbleController::Show(ExtensionMessageBubble* bubble) {
81   // Wire up all the callbacks, to get notified what actions the user took.
82   base::Closure dismiss_button_callback =
83       base::Bind(&ExtensionMessageBubbleController::OnBubbleDismiss,
84       base::Unretained(this));
85   base::Closure action_button_callback =
86       base::Bind(&ExtensionMessageBubbleController::OnBubbleAction,
87       base::Unretained(this));
88   base::Closure link_callback =
89       base::Bind(&ExtensionMessageBubbleController::OnLinkClicked,
90       base::Unretained(this));
91   bubble->OnActionButtonClicked(action_button_callback);
92   bubble->OnDismissButtonClicked(dismiss_button_callback);
93   bubble->OnLinkClicked(link_callback);
94 
95   bubble->Show();
96 }
97 
OnBubbleAction()98 void ExtensionMessageBubbleController::OnBubbleAction() {
99   DCHECK_EQ(ACTION_BOUNDARY, user_action_);
100   user_action_ = ACTION_EXECUTE;
101 
102   delegate_->LogAction(ACTION_EXECUTE);
103   delegate_->PerformAction(*GetOrCreateExtensionList());
104   AcknowledgeExtensions();
105   delegate_->OnClose();
106 }
107 
OnBubbleDismiss()108 void ExtensionMessageBubbleController::OnBubbleDismiss() {
109   // OnBubbleDismiss() can be called twice when we receive multiple
110   // "OnWidgetDestroying" notifications (this can at least happen when we close
111   // a window with a notification open). Handle this gracefully.
112   if (user_action_ != ACTION_BOUNDARY) {
113     DCHECK(user_action_ == ACTION_DISMISS);
114     return;
115   }
116 
117   user_action_ = ACTION_DISMISS;
118 
119   delegate_->LogAction(ACTION_DISMISS);
120   AcknowledgeExtensions();
121   delegate_->OnClose();
122 }
123 
OnLinkClicked()124 void ExtensionMessageBubbleController::OnLinkClicked() {
125   DCHECK_EQ(ACTION_BOUNDARY, user_action_);
126   user_action_ = ACTION_LEARN_MORE;
127 
128   delegate_->LogAction(ACTION_LEARN_MORE);
129   Browser* browser =
130       chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop());
131   if (browser) {
132     browser->OpenURL(
133         content::OpenURLParams(delegate_->GetLearnMoreUrl(),
134                                content::Referrer(),
135                                NEW_FOREGROUND_TAB,
136                                content::PAGE_TRANSITION_LINK,
137                                false));
138   }
139   AcknowledgeExtensions();
140   delegate_->OnClose();
141 }
142 
AcknowledgeExtensions()143 void ExtensionMessageBubbleController::AcknowledgeExtensions() {
144   ExtensionIdList* list = GetOrCreateExtensionList();
145   for (ExtensionIdList::const_iterator it = list->begin();
146        it != list->end(); ++it)
147     delegate_->AcknowledgeExtension(*it, user_action_);
148 }
149 
GetOrCreateExtensionList()150 ExtensionIdList* ExtensionMessageBubbleController::GetOrCreateExtensionList() {
151   if (!initialized_) {
152     scoped_ptr<const ExtensionSet> extension_set(
153         ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet());
154     for (ExtensionSet::const_iterator it = extension_set->begin();
155          it != extension_set->end(); ++it) {
156       std::string id = (*it)->id();
157       if (!delegate_->ShouldIncludeExtension(id))
158         continue;
159       extension_list_.push_back(id);
160     }
161 
162     delegate_->LogExtensionCount(extension_list_.size());
163     initialized_ = true;
164   }
165 
166   return &extension_list_;
167 }
168 
169 }  // namespace extensions
170