Home | History | Annotate | Download | only in net
      1 // Copyright 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/chromeos/net/network_portal_notification_controller.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/system/system_notifier.h"
      9 #include "ash/system/tray/system_tray_notifier.h"
     10 #include "base/basictypes.h"
     11 #include "base/command_line.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/metrics/histogram.h"
     16 #include "base/strings/string16.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "chrome/browser/chromeos/mobile/mobile_activator.h"
     19 #include "chrome/browser/profiles/profile_manager.h"
     20 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
     21 #include "chrome/browser/ui/singleton_tabs.h"
     22 #include "chrome/grit/generated_resources.h"
     23 #include "chrome/grit/theme_resources.h"
     24 #include "chromeos/chromeos_switches.h"
     25 #include "chromeos/network/network_state.h"
     26 #include "components/captive_portal/captive_portal_detector.h"
     27 #include "ui/base/l10n/l10n_util.h"
     28 #include "ui/base/resource/resource_bundle.h"
     29 #include "ui/message_center/message_center.h"
     30 #include "ui/message_center/notification.h"
     31 #include "ui/message_center/notification_types.h"
     32 #include "ui/message_center/notifier_settings.h"
     33 
     34 using message_center::Notification;
     35 
     36 namespace chromeos {
     37 
     38 namespace {
     39 
     40 bool IsPortalNotificationEnabled() {
     41   return !CommandLine::ForCurrentProcess()->HasSwitch(
     42       switches::kDisableNetworkPortalNotification);
     43 }
     44 
     45 
     46 void CloseNotification() {
     47   message_center::MessageCenter::Get()->RemoveNotification(
     48       NetworkPortalNotificationController::kNotificationId, false);
     49 }
     50 
     51 class NetworkPortalNotificationControllerDelegate
     52     : public message_center::NotificationDelegate {
     53  public:
     54   NetworkPortalNotificationControllerDelegate(): clicked_(false) {}
     55 
     56   // Overridden from message_center::NotificationDelegate:
     57   virtual void Display() OVERRIDE;
     58   virtual void Error() OVERRIDE;
     59   virtual void Close(bool by_user) OVERRIDE;
     60   virtual void Click() OVERRIDE;
     61 
     62  private:
     63   virtual ~NetworkPortalNotificationControllerDelegate() {}
     64 
     65   bool clicked_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(NetworkPortalNotificationControllerDelegate);
     68 };
     69 
     70 void NetworkPortalNotificationControllerDelegate::Display() {
     71   UMA_HISTOGRAM_ENUMERATION(
     72       NetworkPortalNotificationController::kNotificationMetric,
     73       NetworkPortalNotificationController::NOTIFICATION_METRIC_DISPLAYED,
     74       NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT);
     75 }
     76 
     77 void NetworkPortalNotificationControllerDelegate::Error() {
     78   UMA_HISTOGRAM_ENUMERATION(
     79       NetworkPortalNotificationController::kNotificationMetric,
     80       NetworkPortalNotificationController::NOTIFICATION_METRIC_ERROR,
     81       NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT);
     82 }
     83 
     84 void NetworkPortalNotificationControllerDelegate::Close(bool by_user) {
     85   if (clicked_)
     86     return;
     87   NetworkPortalNotificationController::UserActionMetric metric =
     88       by_user
     89       ? NetworkPortalNotificationController::USER_ACTION_METRIC_CLOSED
     90       : NetworkPortalNotificationController::USER_ACTION_METRIC_IGNORED;
     91   UMA_HISTOGRAM_ENUMERATION(
     92       NetworkPortalNotificationController::kUserActionMetric,
     93       metric,
     94       NetworkPortalNotificationController::USER_ACTION_METRIC_COUNT);
     95 }
     96 
     97 void NetworkPortalNotificationControllerDelegate::Click() {
     98   clicked_ = true;
     99   UMA_HISTOGRAM_ENUMERATION(
    100       NetworkPortalNotificationController::kUserActionMetric,
    101       NetworkPortalNotificationController::USER_ACTION_METRIC_CLICKED,
    102       NetworkPortalNotificationController::USER_ACTION_METRIC_COUNT);
    103 
    104   Profile* profile = ProfileManager::GetActiveUserProfile();
    105   if (!profile)
    106     return;
    107   chrome::ScopedTabbedBrowserDisplayer displayer(profile,
    108                                                  chrome::HOST_DESKTOP_TYPE_ASH);
    109   GURL url(captive_portal::CaptivePortalDetector::kDefaultURL);
    110   chrome::ShowSingletonTab(displayer.browser(), url);
    111 
    112   CloseNotification();
    113 }
    114 
    115 }  // namespace
    116 
    117 // static
    118 const char NetworkPortalNotificationController::kNotificationId[] =
    119     "chrome://net/network_portal_detector";
    120 
    121 // static
    122 const char NetworkPortalNotificationController::kNotificationMetric[] =
    123     "CaptivePortal.Notification.Status";
    124 
    125 // static
    126 const char NetworkPortalNotificationController::kUserActionMetric[] =
    127     "CaptivePortal.Notification.UserAction";
    128 
    129 NetworkPortalNotificationController::NetworkPortalNotificationController() {}
    130 
    131 NetworkPortalNotificationController::~NetworkPortalNotificationController() {}
    132 
    133 void NetworkPortalNotificationController::OnPortalDetectionCompleted(
    134     const NetworkState* network,
    135     const NetworkPortalDetector::CaptivePortalState& state) {
    136   if (!IsPortalNotificationEnabled())
    137     return;
    138 
    139   if (!network ||
    140       state.status != NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL) {
    141     last_network_path_.clear();
    142     CloseNotification();
    143     return;
    144   }
    145 
    146   // Don't do anything if we're currently activating the device.
    147   if (MobileActivator::GetInstance()->RunningActivation())
    148     return;
    149 
    150   // Don't do anything if notification for |network| already was
    151   // displayed.
    152   if (network->path() == last_network_path_)
    153     return;
    154   last_network_path_ = network->path();
    155 
    156   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
    157   gfx::Image& icon = bundle.GetImageNamed(IDR_PORTAL_DETECTION_ALERT);
    158   message_center::NotifierId notifier_id(
    159       message_center::NotifierId::SYSTEM_COMPONENT,
    160       ash::system_notifier::kNotifierNetworkPortalDetector);
    161 
    162   scoped_ptr<Notification> notification(new Notification(
    163       message_center::NOTIFICATION_TYPE_SIMPLE,
    164       kNotificationId,
    165       l10n_util::GetStringUTF16(IDS_PORTAL_DETECTION_NOTIFICATION_TITLE),
    166       l10n_util::GetStringFUTF16(IDS_PORTAL_DETECTION_NOTIFICATION_MESSAGE,
    167                                  base::UTF8ToUTF16(network->name())),
    168       icon,
    169       base::string16() /* display_source */,
    170       notifier_id,
    171       message_center::RichNotificationData(),
    172       new NetworkPortalNotificationControllerDelegate()));
    173   notification->SetSystemPriority();
    174 
    175   if (ash::Shell::HasInstance()) {
    176     ash::Shell::GetInstance()
    177         ->system_tray_notifier()
    178         ->NotifyOnCaptivePortalDetected(network->path());
    179   }
    180 
    181   message_center::MessageCenter::Get()->AddNotification(notification.Pass());
    182 }
    183 
    184 }  // namespace chromeos
    185