Home | History | Annotate | Download | only in extensions
      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 
     26 ExtensionMessageBubbleController::Delegate::Delegate() {
     27 }
     28 
     29 ExtensionMessageBubbleController::Delegate::~Delegate() {
     30 }
     31 
     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 
     40 ExtensionMessageBubbleController::ExtensionMessageBubbleController(
     41     Delegate* delegate, Profile* profile)
     42     : profile_(profile),
     43       user_action_(ACTION_BOUNDARY),
     44       delegate_(delegate),
     45       initialized_(false) {
     46 }
     47 
     48 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() {
     49 }
     50 
     51 std::vector<base::string16>
     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 
     74 const ExtensionIdList& ExtensionMessageBubbleController::GetExtensionIdList() {
     75   return *GetOrCreateExtensionList();
     76 }
     77 
     78 bool ExtensionMessageBubbleController::CloseOnDeactivate() { return false; }
     79 
     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 
     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 
    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 
    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 
    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 
    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