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 34using message_center::Notification; 35 36namespace chromeos { 37 38namespace { 39 40bool IsPortalNotificationEnabled() { 41 return !CommandLine::ForCurrentProcess()->HasSwitch( 42 switches::kDisableNetworkPortalNotification); 43} 44 45 46void CloseNotification() { 47 message_center::MessageCenter::Get()->RemoveNotification( 48 NetworkPortalNotificationController::kNotificationId, false); 49} 50 51class 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 70void NetworkPortalNotificationControllerDelegate::Display() { 71 UMA_HISTOGRAM_ENUMERATION( 72 NetworkPortalNotificationController::kNotificationMetric, 73 NetworkPortalNotificationController::NOTIFICATION_METRIC_DISPLAYED, 74 NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT); 75} 76 77void NetworkPortalNotificationControllerDelegate::Error() { 78 UMA_HISTOGRAM_ENUMERATION( 79 NetworkPortalNotificationController::kNotificationMetric, 80 NetworkPortalNotificationController::NOTIFICATION_METRIC_ERROR, 81 NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT); 82} 83 84void 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 97void 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 118const char NetworkPortalNotificationController::kNotificationId[] = 119 "chrome://net/network_portal_detector"; 120 121// static 122const char NetworkPortalNotificationController::kNotificationMetric[] = 123 "CaptivePortal.Notification.Status"; 124 125// static 126const char NetworkPortalNotificationController::kUserActionMetric[] = 127 "CaptivePortal.Notification.UserAction"; 128 129NetworkPortalNotificationController::NetworkPortalNotificationController() {} 130 131NetworkPortalNotificationController::~NetworkPortalNotificationController() {} 132 133void 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