blob: d9a52ee7735054064d19f9fd275506e51356916e [file] [log] [blame]
// Copyright 2014 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 "base/compiler_specific.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/portal_detector/network_portal_detector.h"
#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
#include "components/captive_portal/captive_portal_testing_utils.h"
#include "content/public/test/test_utils.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_observer.h"
using base::MessageLoop;
using message_center::MessageCenter;
using message_center::MessageCenterObserver;
namespace chromeos {
namespace {
const char* kNotificationId =
NetworkPortalNotificationController::kNotificationId;
const char* kNotificationMetric =
NetworkPortalNotificationController::kNotificationMetric;
const char* kUserActionMetric =
NetworkPortalNotificationController::kUserActionMetric;
const char kTestUser[] = "test-user@gmail.com";
const char kWifiServicePath[] = "/service/wifi";
const char kWifiGuid[] = "wifi";
void ErrorCallbackFunction(const std::string& error_name,
const std::string& error_message) {
CHECK(false) << "Shill Error: " << error_name << " : " << error_message;
}
void SetConnected(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Connect(
dbus::ObjectPath(service_path),
base::Bind(&base::DoNothing),
base::Bind(&ErrorCallbackFunction));
base::RunLoop().RunUntilIdle();
}
class TestObserver : public MessageCenterObserver {
public:
TestObserver() : run_loop_(new base::RunLoop()) {
MessageCenter::Get()->AddObserver(this);
}
virtual ~TestObserver() {
MessageCenter::Get()->RemoveObserver(this);
}
void WaitAndReset() {
run_loop_->Run();
run_loop_.reset(new base::RunLoop());
}
virtual void OnNotificationDisplayed(
const std::string& notification_id,
const message_center::DisplaySource source)
OVERRIDE {
if (notification_id == kNotificationId)
MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
}
virtual void OnNotificationRemoved(const std::string& notification_id,
bool by_user) OVERRIDE {
if (notification_id == kNotificationId && by_user)
MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
}
private:
scoped_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
} // namespace
class NetworkPortalDetectorImplBrowserTest
: public LoginManagerTest,
public captive_portal::CaptivePortalDetectorTestBase {
public:
NetworkPortalDetectorImplBrowserTest()
: LoginManagerTest(false), network_portal_detector_(NULL) {}
virtual ~NetworkPortalDetectorImplBrowserTest() {}
virtual void SetUpOnMainThread() OVERRIDE {
LoginManagerTest::SetUpOnMainThread();
ShillServiceClient::TestInterface* service_test =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
service_test->ClearServices();
service_test->AddService(kWifiServicePath,
kWifiGuid,
"wifi",
shill::kTypeEthernet,
shill::kStateIdle,
true /* add_to_visible */);
DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
dbus::ObjectPath(kWifiServicePath),
shill::kStateProperty,
base::StringValue(shill::kStatePortal),
base::Bind(&base::DoNothing),
base::Bind(&ErrorCallbackFunction));
network_portal_detector_ = new NetworkPortalDetectorImpl(
g_browser_process->system_request_context());
NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
network_portal_detector_->Enable(false /* start_detection */);
set_detector(network_portal_detector_->captive_portal_detector_.get());
PortalDetectorStrategy::set_delay_till_next_attempt_for_testing(
base::TimeDelta());
base::RunLoop().RunUntilIdle();
}
void RestartDetection() {
network_portal_detector_->StopDetection();
network_portal_detector_->StartDetection();
base::RunLoop().RunUntilIdle();
}
PortalDetectorStrategy* strategy() {
return network_portal_detector_->strategy_.get();
}
MessageCenter* message_center() { return MessageCenter::Get(); }
private:
NetworkPortalDetectorImpl* network_portal_detector_;
DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorImplBrowserTest);
};
IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
PRE_InSessionDetection) {
RegisterUser(kTestUser);
StartupUtils::MarkOobeCompleted();
ASSERT_EQ(PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN, strategy()->Id());
}
IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
InSessionDetection) {
typedef NetworkPortalNotificationController Controller;
TestObserver observer;
EnumHistogramChecker ui_checker(
kNotificationMetric, Controller::NOTIFICATION_METRIC_COUNT, NULL);
EnumHistogramChecker action_checker(
kUserActionMetric, Controller::USER_ACTION_METRIC_COUNT, NULL);
LoginUser(kTestUser);
content::RunAllPendingInMessageLoop();
// User connects to wifi.
SetConnected(kWifiServicePath);
ASSERT_EQ(PortalDetectorStrategy::STRATEGY_ID_SESSION, strategy()->Id());
// No notification until portal detection is completed.
ASSERT_FALSE(message_center()->FindVisibleNotificationById(kNotificationId));
RestartDetection();
CompleteURLFetch(net::OK, 200, NULL);
// Check that wifi is marked as behind the portal and that notification
// is displayed.
ASSERT_TRUE(message_center()->FindVisibleNotificationById(kNotificationId));
ASSERT_EQ(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
NetworkPortalDetector::Get()->GetCaptivePortalState(kWifiGuid).status);
// Wait until notification is displayed.
observer.WaitAndReset();
ASSERT_TRUE(
ui_checker.Expect(Controller::NOTIFICATION_METRIC_DISPLAYED, 1)->Check());
ASSERT_TRUE(action_checker.Check());
// User explicitly closes the notification.
message_center()->RemoveNotification(kNotificationId, true);
// Wait until notification is closed.
observer.WaitAndReset();
ASSERT_TRUE(ui_checker.Check());
ASSERT_TRUE(
action_checker.Expect(Controller::USER_ACTION_METRIC_CLOSED, 1)->Check());
}
} // namespace chromeos