| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/system/network/auto_connect_notifier.h" |
| |
| #include "ash/public/cpp/network_icon_image_source.h" |
| #include "ash/public/cpp/notification_utils.h" |
| #include "ash/strings/grit/ash_strings.h" |
| #include "base/logging.h" |
| #include "base/strings/string16.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chromeos/network/network_connection_handler.h" |
| #include "chromeos/network/network_state.h" |
| #include "chromeos/network/network_state_handler.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/image/canvas_image_source.h" |
| #include "ui/gfx/image/image.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/public/cpp/message_center_constants.h" |
| #include "ui/message_center/public/cpp/notification.h" |
| #include "ui/message_center/public/cpp/notification_types.h" |
| #include "ui/message_center/public/cpp/notifier_id.h" |
| #include "url/gurl.h" |
| |
| using chromeos::NetworkHandler; |
| |
| namespace ash { |
| |
| namespace { |
| |
| // Timeout used for connecting to a managed network. When an auto-connection is |
| // initiated, we expect the connection to occur within this amount of time. If |
| // a timeout occurs, we assume that no auto-connection occurred and do not show |
| // a notification. |
| constexpr const base::TimeDelta kNetworkConnectionTimeout = |
| base::TimeDelta::FromSeconds(3); |
| |
| const char kNotifierAutoConnect[] = "ash.auto-connect"; |
| |
| } // namespace |
| |
| // static |
| const char AutoConnectNotifier::kAutoConnectNotificationId[] = |
| "cros_auto_connect_notifier_ids.connected_to_network"; |
| |
| AutoConnectNotifier::AutoConnectNotifier() |
| : timer_(std::make_unique<base::OneShotTimer>()) { |
| // NetworkHandler may not be initialized in tests. |
| if (NetworkHandler::IsInitialized()) { |
| auto* network_handler = NetworkHandler::Get(); |
| network_handler->network_connection_handler()->AddObserver(this); |
| network_handler->network_state_handler()->AddObserver(this, FROM_HERE); |
| // AutoConnectHandler may not be initialized in tests with NetworkHandler. |
| if (network_handler->auto_connect_handler()) |
| network_handler->auto_connect_handler()->AddObserver(this); |
| } |
| } |
| |
| AutoConnectNotifier::~AutoConnectNotifier() { |
| // NetworkHandler may not be initialized in tests. |
| if (NetworkHandler::IsInitialized()) { |
| auto* network_handler = NetworkHandler::Get(); |
| // AutoConnectHandler may not be initialized in tests with NetworkHandler. |
| if (network_handler->auto_connect_handler()) |
| network_handler->auto_connect_handler()->RemoveObserver(this); |
| network_handler->network_state_handler()->RemoveObserver(this, FROM_HERE); |
| network_handler->network_connection_handler()->RemoveObserver(this); |
| } |
| } |
| |
| void AutoConnectNotifier::ConnectToNetworkRequested( |
| const std::string& /* service_path */) { |
| has_user_explicitly_requested_connection_ = true; |
| } |
| |
| void AutoConnectNotifier::NetworkConnectionStateChanged( |
| const chromeos::NetworkState* network) { |
| // No notification should be shown unless an auto-connection is underway. |
| if (!timer_->IsRunning()) |
| return; |
| |
| // The notification is only shown when a connection has succeeded; if |
| // |network| is not connected, there is nothing to do. |
| if (!network->IsConnectedState()) |
| return; |
| |
| // An auto-connected network has connected successfully. Display a |
| // notification alerting the user that this has occurred. |
| DisplayNotification(); |
| has_user_explicitly_requested_connection_ = false; |
| } |
| |
| void AutoConnectNotifier::OnAutoConnectedInitiated(int auto_connect_reasons) { |
| // If the user has not explicitly requested a connection to another network, |
| // the notification does not need to be shown. |
| if (!has_user_explicitly_requested_connection_) |
| return; |
| |
| // The notification should only be shown if a network is joined due to a |
| // policy or certificate. Other reasons (e.g., joining a network due to login) |
| // do not require that a notification be shown. |
| const int kManagedNetworkReasonsBitmask = |
| chromeos::AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED | |
| chromeos::AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED; |
| if (!(auto_connect_reasons & kManagedNetworkReasonsBitmask)) |
| return; |
| |
| // If a potential connection is already underway, reset the timeout and |
| // continue waiting. |
| if (timer_->IsRunning()) { |
| timer_->Reset(); |
| return; |
| } |
| |
| // Auto-connection has been requested, so start a timer. If a network connects |
| // successfully before the timer expires, auto-connection has succeeded, so a |
| // notification should be shown. If no connection occurs before the timer |
| // fires, we assume that auto-connect attempted to search for networks to |
| // join but did not succeed in joining one (in that case, no notification |
| // should be shown). |
| timer_->Start(FROM_HERE, kNetworkConnectionTimeout, base::DoNothing()); |
| } |
| |
| void AutoConnectNotifier::DisplayNotification() { |
| auto notification = ash::CreateSystemNotification( |
| message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, |
| kAutoConnectNotificationId, |
| l10n_util::GetStringUTF16(IDS_ASH_NETWORK_AUTOCONNECT_NOTIFICATION_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_NETWORK_AUTOCONNECT_NOTIFICATION_MESSAGE), |
| base::string16() /* display_source */, GURL() /* origin_url */, |
| message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierAutoConnect), |
| {} /* optional_fields */, |
| base::MakeRefCounted<message_center::NotificationDelegate>(), |
| gfx::VectorIcon() /* small_image */, |
| message_center::SystemNotificationWarningLevel::NORMAL); |
| |
| notification->set_small_image(gfx::Image(network_icon::GetImageForWifiNetwork( |
| notification->accent_color(), |
| gfx::Size(message_center::kSmallImageSizeMD, |
| message_center::kSmallImageSizeMD)))); |
| |
| message_center::MessageCenter* message_center = |
| message_center::MessageCenter::Get(); |
| if (message_center->FindVisibleNotificationById(kAutoConnectNotificationId)) |
| message_center->RemoveNotification(kAutoConnectNotificationId, false); |
| message_center->AddNotification(std::move(notification)); |
| } |
| |
| } // namespace ash |