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