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/dev_mode_bubble_controller.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/metrics/histogram.h"
      9 #include "chrome/browser/extensions/extension_action_manager.h"
     10 #include "chrome/browser/extensions/extension_message_bubble.h"
     11 #include "chrome/browser/extensions/extension_service.h"
     12 #include "chrome/browser/extensions/extension_toolbar_model.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/ui/browser.h"
     15 #include "chrome/common/chrome_version_info.h"
     16 #include "chrome/common/url_constants.h"
     17 #include "extensions/browser/extension_prefs.h"
     18 #include "extensions/browser/extension_system.h"
     19 #include "extensions/common/feature_switch.h"
     20 #include "grit/chromium_strings.h"
     21 #include "grit/generated_resources.h"
     22 #include "ui/base/l10n/l10n_util.h"
     23 
     24 namespace extensions {
     25 
     26 namespace {
     27 
     28 base::LazyInstance<std::set<Profile*> > g_shown_for_profiles =
     29     LAZY_INSTANCE_INITIALIZER;
     30 
     31 ////////////////////////////////////////////////////////////////////////////////
     32 // DevModeBubbleDelegate
     33 
     34 class DevModeBubbleDelegate
     35     : public ExtensionMessageBubbleController::Delegate {
     36  public:
     37   explicit DevModeBubbleDelegate(Profile* profile);
     38   virtual ~DevModeBubbleDelegate();
     39 
     40   // ExtensionMessageBubbleController::Delegate methods.
     41   virtual bool ShouldIncludeExtension(const std::string& extension_id) OVERRIDE;
     42   virtual void AcknowledgeExtension(
     43       const std::string& extension_id,
     44       ExtensionMessageBubbleController::BubbleAction user_action) OVERRIDE;
     45   virtual void PerformAction(const ExtensionIdList& list) OVERRIDE;
     46   virtual void OnClose() OVERRIDE;
     47   virtual base::string16 GetTitle() const OVERRIDE;
     48   virtual base::string16 GetMessageBody(
     49       bool anchored_to_browser_action) const OVERRIDE;
     50   virtual base::string16 GetOverflowText(
     51       const base::string16& overflow_count) const OVERRIDE;
     52   virtual base::string16 GetLearnMoreLabel() const OVERRIDE;
     53   virtual GURL GetLearnMoreUrl() const OVERRIDE;
     54   virtual base::string16 GetActionButtonLabel() const OVERRIDE;
     55   virtual base::string16 GetDismissButtonLabel() const OVERRIDE;
     56   virtual bool ShouldShowExtensionList() const OVERRIDE;
     57   virtual void LogExtensionCount(size_t count) OVERRIDE;
     58   virtual void LogAction(
     59       ExtensionMessageBubbleController::BubbleAction action) OVERRIDE;
     60 
     61  private:
     62   // The associated profile (weak).
     63   Profile* profile_;
     64 
     65   // Our extension service. Weak, not owned by us.
     66   ExtensionService* service_;
     67 
     68   DISALLOW_COPY_AND_ASSIGN(DevModeBubbleDelegate);
     69 };
     70 
     71 DevModeBubbleDelegate::DevModeBubbleDelegate(Profile* profile)
     72     : profile_(profile),
     73       service_(ExtensionSystem::Get(profile)->extension_service()) {}
     74 
     75 DevModeBubbleDelegate::~DevModeBubbleDelegate() {
     76 }
     77 
     78 bool DevModeBubbleDelegate::ShouldIncludeExtension(
     79     const std::string& extension_id) {
     80   const Extension* extension = service_->GetExtensionById(extension_id, false);
     81   if (!extension)
     82     return false;
     83   return DevModeBubbleController::IsDevModeExtension(extension);
     84 }
     85 
     86 void DevModeBubbleDelegate::AcknowledgeExtension(
     87     const std::string& extension_id,
     88     ExtensionMessageBubbleController::BubbleAction user_action) {
     89 }
     90 
     91 void DevModeBubbleDelegate::PerformAction(const ExtensionIdList& list) {
     92   for (size_t i = 0; i < list.size(); ++i)
     93     service_->DisableExtension(list[i], Extension::DISABLE_USER_ACTION);
     94 }
     95 
     96 void DevModeBubbleDelegate::OnClose() {
     97   ExtensionToolbarModel* toolbar_model = ExtensionToolbarModel::Get(profile_);
     98   if (toolbar_model)
     99     toolbar_model->StopHighlighting();
    100 }
    101 
    102 base::string16 DevModeBubbleDelegate::GetTitle() const {
    103   return l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE_DEVELOPER_MODE_TITLE);
    104 }
    105 
    106 base::string16 DevModeBubbleDelegate::GetMessageBody(
    107     bool anchored_to_browser_action) const {
    108   return l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE_DEVELOPER_MODE_BODY);
    109 }
    110 
    111 base::string16 DevModeBubbleDelegate::GetOverflowText(
    112     const base::string16& overflow_count) const {
    113   return l10n_util::GetStringFUTF16(
    114             IDS_EXTENSIONS_DISABLED_AND_N_MORE,
    115             overflow_count);
    116 }
    117 
    118 base::string16 DevModeBubbleDelegate::GetLearnMoreLabel() const {
    119   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
    120 }
    121 
    122 GURL DevModeBubbleDelegate::GetLearnMoreUrl() const {
    123   return GURL(chrome::kChromeUIExtensionsURL);
    124 }
    125 
    126 base::string16 DevModeBubbleDelegate::GetActionButtonLabel() const {
    127   return l10n_util::GetStringUTF16(IDS_DISABLE);
    128 }
    129 
    130 base::string16 DevModeBubbleDelegate::GetDismissButtonLabel() const {
    131   return l10n_util::GetStringUTF16(IDS_CANCEL);
    132 }
    133 
    134 bool DevModeBubbleDelegate::ShouldShowExtensionList() const {
    135   return false;
    136 }
    137 
    138 void DevModeBubbleDelegate::LogExtensionCount(size_t count) {
    139   UMA_HISTOGRAM_COUNTS_100(
    140       "ExtensionBubble.ExtensionsInDevModeCount", count);
    141 }
    142 
    143 void DevModeBubbleDelegate::LogAction(
    144     ExtensionMessageBubbleController::BubbleAction action) {
    145   UMA_HISTOGRAM_ENUMERATION(
    146       "ExtensionBubble.DevModeUserSelection",
    147       action, ExtensionMessageBubbleController::ACTION_BOUNDARY);
    148 }
    149 
    150 }  // namespace
    151 
    152 ////////////////////////////////////////////////////////////////////////////////
    153 // DevModeBubbleController
    154 
    155 // static
    156 void DevModeBubbleController::ClearProfileListForTesting() {
    157   g_shown_for_profiles.Get().clear();
    158 }
    159 
    160 // static
    161 bool DevModeBubbleController::IsDevModeExtension(
    162     const Extension* extension) {
    163   if (!FeatureSwitch::force_dev_mode_highlighting()->IsEnabled()) {
    164     if (chrome::VersionInfo::GetChannel() < chrome::VersionInfo::CHANNEL_BETA)
    165       return false;
    166   }
    167   return extension->location() == Manifest::UNPACKED ||
    168          extension->location() == Manifest::COMMAND_LINE;
    169 }
    170 
    171 DevModeBubbleController::DevModeBubbleController(Profile* profile)
    172     : ExtensionMessageBubbleController(new DevModeBubbleDelegate(profile),
    173                                        profile),
    174       profile_(profile) {}
    175 
    176 DevModeBubbleController::~DevModeBubbleController() {
    177 }
    178 
    179 bool DevModeBubbleController::ShouldShow() {
    180   return !g_shown_for_profiles.Get().count(profile_->GetOriginalProfile()) &&
    181       !GetExtensionList().empty();
    182 }
    183 
    184 void DevModeBubbleController::Show(ExtensionMessageBubble* bubble) {
    185   g_shown_for_profiles.Get().insert(profile_->GetOriginalProfile());
    186   ExtensionMessageBubbleController::Show(bubble);
    187 }
    188 
    189 }  // namespace extensions
    190