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