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