blob: 77a7d075087f8dcef62312d13699bebc57264e9d [file] [log] [blame]
// Copyright 2017 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 "components/blocked_content/popup_opener_tab_helper.h"
#include <utility>
#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/tick_clock.h"
#include "components/blocked_content/popup_tracker.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/ukm/content/source_url_recorder.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "ui/base/scoped_visibility_tracker.h"
namespace blocked_content {
// static
void PopupOpenerTabHelper::CreateForWebContents(
content::WebContents* contents,
const base::TickClock* tick_clock,
HostContentSettingsMap* settings_map) {
DCHECK(contents);
if (!FromWebContents(contents)) {
contents->SetUserData(UserDataKey(),
base::WrapUnique(new PopupOpenerTabHelper(
contents, tick_clock, settings_map)));
}
}
PopupOpenerTabHelper::~PopupOpenerTabHelper() {
DCHECK(visibility_tracker_);
base::TimeDelta total_visible_time =
visibility_tracker_->GetForegroundDuration();
if (did_tab_under()) {
UMA_HISTOGRAM_LONG_TIMES(
"Tab.TabUnder.VisibleTime",
total_visible_time - visible_time_before_tab_under_.value());
UMA_HISTOGRAM_LONG_TIMES("Tab.TabUnder.VisibleTimeBefore",
visible_time_before_tab_under_.value());
}
UMA_HISTOGRAM_LONG_TIMES("Tab.VisibleTime", total_visible_time);
}
void PopupOpenerTabHelper::OnOpenedPopup(PopupTracker* popup_tracker) {
has_opened_popup_since_last_user_gesture_ = true;
MaybeLogPagePopupContentSettings();
last_popup_open_time_ = tick_clock_->NowTicks();
}
void PopupOpenerTabHelper::OnDidTabUnder() {
// The tab already did a tab-under.
if (did_tab_under())
return;
// Tab-under requires a popup, so this better not be null.
DCHECK(!last_popup_open_time_.is_null());
UMA_HISTOGRAM_LONG_TIMES("Tab.TabUnder.PopupToTabUnderTime",
tick_clock_->NowTicks() - last_popup_open_time_);
visible_time_before_tab_under_ = visibility_tracker_->GetForegroundDuration();
}
PopupOpenerTabHelper::PopupOpenerTabHelper(content::WebContents* web_contents,
const base::TickClock* tick_clock,
HostContentSettingsMap* settings_map)
: content::WebContentsObserver(web_contents),
tick_clock_(tick_clock),
settings_map_(settings_map) {
visibility_tracker_ = std::make_unique<ui::ScopedVisibilityTracker>(
tick_clock_,
web_contents->GetVisibility() != content::Visibility::HIDDEN);
}
void PopupOpenerTabHelper::OnVisibilityChanged(content::Visibility visibility) {
// TODO(csharrison): Consider handling OCCLUDED tabs the same way as HIDDEN
// tabs.
if (visibility == content::Visibility::HIDDEN)
visibility_tracker_->OnHidden();
else
visibility_tracker_->OnShown();
}
void PopupOpenerTabHelper::DidGetUserInteraction(
const blink::WebInputEvent& event) {
has_opened_popup_since_last_user_gesture_ = false;
}
void PopupOpenerTabHelper::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
// Treat browser-initiated navigations as user interactions.
if (!navigation_handle->IsRendererInitiated())
has_opened_popup_since_last_user_gesture_ = false;
}
void PopupOpenerTabHelper::MaybeLogPagePopupContentSettings() {
// If the user has opened a popup, record the page popup settings ukm.
const GURL& url = web_contents()->GetLastCommittedURL();
if (!url.is_valid())
return;
const ukm::SourceId source_id =
ukm::GetSourceIdForWebContentsDocument(web_contents());
// Do not record duplicate Popup.Page events for popups opened in succession
// from the same opener.
if (source_id != last_opener_source_id_) {
bool user_allows_popups = settings_map_->GetContentSetting(
url, url, ContentSettingsType::POPUPS,
std::string()) == CONTENT_SETTING_ALLOW;
ukm::builders::Popup_Page(source_id)
.SetAllowed(user_allows_popups)
.Record(ukm::UkmRecorder::Get());
last_opener_source_id_ = source_id;
}
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(PopupOpenerTabHelper)
} // namespace blocked_content