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