network_portal_notification_controller.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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