blob: be17162e087dca12bf8027646552612a1c7e3e03 [file] [log] [blame]
// Copyright 2015 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 "chrome/browser/ssl/captive_portal_metrics_recorder.h"
#include <vector>
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/captive_portal/captive_portal_service.h"
#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
namespace {
// Events for UMA. Do not reorder or change!
enum SSLInterstitialCauseCaptivePortal {
CAPTIVE_PORTAL_ALL,
CAPTIVE_PORTAL_DETECTION_ENABLED,
CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
CAPTIVE_PORTAL_PROBE_COMPLETED,
CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
CAPTIVE_PORTAL_NO_RESPONSE,
CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
CAPTIVE_PORTAL_DETECTED,
CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
UNUSED_CAPTIVE_PORTAL_EVENT,
};
void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal", event,
UNUSED_CAPTIVE_PORTAL_EVENT);
}
} // namespace
CaptivePortalMetricsRecorder::CaptivePortalMetricsRecorder(
content::WebContents* web_contents,
bool overridable)
: overridable_(overridable),
captive_portal_detection_enabled_(false),
captive_portal_probe_completed_(false),
captive_portal_no_response_(false),
captive_portal_detected_(false) {
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
captive_portal_detection_enabled_ =
CaptivePortalServiceFactory::GetForProfile(profile)->enabled();
registrar_.Add(this, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
content::Source<Profile>(profile));
}
CaptivePortalMetricsRecorder::~CaptivePortalMetricsRecorder() {}
void CaptivePortalMetricsRecorder::RecordCaptivePortalUMAStatistics() const {
RecordCaptivePortalEventStats(CAPTIVE_PORTAL_ALL);
if (captive_portal_detection_enabled_)
RecordCaptivePortalEventStats(
overridable_ ? CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE
: CAPTIVE_PORTAL_DETECTION_ENABLED);
if (captive_portal_probe_completed_)
RecordCaptivePortalEventStats(
overridable_ ? CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE
: CAPTIVE_PORTAL_PROBE_COMPLETED);
// Log only one of portal detected and no response results.
if (captive_portal_detected_)
RecordCaptivePortalEventStats(overridable_
? CAPTIVE_PORTAL_DETECTED_OVERRIDABLE
: CAPTIVE_PORTAL_DETECTED);
else if (captive_portal_no_response_)
RecordCaptivePortalEventStats(overridable_
? CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE
: CAPTIVE_PORTAL_NO_RESPONSE);
}
void CaptivePortalMetricsRecorder::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, type);
// When detection is disabled, captive portal service always sends
// RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
if (!captive_portal_detection_enabled_)
return;
captive_portal_probe_completed_ = true;
CaptivePortalService::Results* results =
content::Details<CaptivePortalService::Results>(details).ptr();
// If a captive portal was detected at any point when the interstitial was
// displayed, assume that the interstitial was caused by a captive portal.
// Example scenario:
// 1- Interstitial displayed and captive portal detected, setting the flag.
// 2- Captive portal detection automatically opens portal login page.
// 3- User logs in on the portal login page.
// A notification will be received here for RESULT_INTERNET_CONNECTED. Make
// sure we don't clear the captive protal flag, since the interstitial was
// potentially caused by the captive portal.
captive_portal_detected_ =
captive_portal_detected_ ||
(results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
// Also keep track of non-HTTP portals and error cases.
captive_portal_no_response_ =
captive_portal_no_response_ ||
(results->result == captive_portal::RESULT_NO_RESPONSE);
}