Commit 2163df73 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Display Cutout] Add UKM metrics

Add a Layout.DisplayCutout.StateChanged UKM event that
is recorded when display cutout state changes.

BUG=825890

Change-Id: I7b134117ea847505e62f3690d0ac45ab02db8e1f
Reviewed-on: https://chromium-review.googlesource.com/1117638Reviewed-by: default avatarRobert Kaplow (slow) <rkaplow@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575717}
parent 6f2f737f
......@@ -693,6 +693,7 @@ jumbo_source_set("browser") {
"devtools/target_registry.cc",
"devtools/target_registry.h",
"discardable_shared_memory_manager.cc",
"display_cutout/display_cutout_constants.h",
"dom_storage/dom_storage_area.cc",
"dom_storage/dom_storage_area.h",
"dom_storage/dom_storage_context_impl.cc",
......
file://chrome/android/java/src/org/chromium/chrome/browser/display_cutout/OWNERS
# COMPONENT: Blink>Layout
// 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.
#ifndef CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
#define CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
namespace content {
// Contains the reasons why a |RenderFrameHost| does not have control over a
// the Display Cutout. This enum is used in metrics so the order should not
// be changed.
enum DisplayCutoutIgnoredReason {
// The frame was not ignored.
kAllowed = 0,
// The frame was ignored because it was not the current active fullscreen
// frame.
kFrameNotCurrentFullscreen,
// The frame was ignored because the WebContents was not fullscreen.
kWebContentsNotFullscreen,
};
// Contains flags as to which safe areas are present and greater than zero. This
// enum is used in metrics so the order should not be changed.
enum DisplayCutoutSafeArea {
kEmpty = 0,
kTop = 1 << 0,
kLeft = 1 << 1,
kBottom = 1 << 2,
kRight = 1 << 3,
};
} // namespace content
#endif // CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
......@@ -42,6 +42,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/display_cutout/display_cutout_constants.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/mhtml_generation_manager.h"
......@@ -134,6 +135,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
......@@ -423,6 +425,8 @@ class WebContentsImpl::DisplayCutoutHostImpl
// WebContentsObservers about the new value.
if (current_rfh_ == rfh)
NotifyObservers(value);
MaybeQueueUKMEvent(rfh);
}
// WebContentsObserver override.
......@@ -478,9 +482,44 @@ class WebContentsImpl::DisplayCutoutHostImpl
if (current_rfh_)
SendSafeAreaToFrame(current_rfh_, insets);
// If we have a pending UKM event on the top of the stack that is |kAllowed|
// and we have a |current_rfh_| then we should update that UKM event as it
// was recorded before we received the safe area.
if (!pending_ukm_events_.empty() && current_rfh_) {
PendingUKMEvent& last_entry = pending_ukm_events_.back();
if (last_entry.ignored_reason == DisplayCutoutIgnoredReason::kAllowed)
last_entry.safe_areas_present = GetSafeAreasPresentUKMValue();
}
}
// Record any pending UKM events when we start a main frame navigation.
void DidStartNavigation(NavigationHandle* navigation_handle) override {
// If the navigation is not in the main frame or if we are a same document
// navigation then we should stop now.
if (!navigation_handle->IsInMainFrame() ||
navigation_handle->IsSameDocument()) {
return;
}
RecordPendingUKMEvents();
}
void WebContentsDestroyed() override {
// Record any pending UKM events that we are waiting to record.
RecordPendingUKMEvents();
}
private:
// Stores the data for a pending UKM event.
struct PendingUKMEvent {
bool is_main_frame;
blink::mojom::ViewportFit applied_value;
blink::mojom::ViewportFit supplied_value;
int ignored_reason;
int safe_areas_present = 0;
};
// Set the current |RenderFrameHost| that should have control over the
// viewport fit value and we should set safe area insets on.
void SetCurrentRenderFrameHost(RenderFrameHost* rfh) {
......@@ -491,14 +530,19 @@ class WebContentsImpl::DisplayCutoutHostImpl
if (current_rfh_)
SendSafeAreaToFrame(current_rfh_, gfx::Insets());
// Update the |current_rfh_| with the new frame.
current_rfh_ = rfh;
// If the new RenderFrameHost is nullptr we should stop here and notify
// observers that the new viewport fit is kAuto (the default).
current_rfh_ = rfh;
if (!rfh) {
NotifyObservers(blink::mojom::ViewportFit::kAuto);
return;
}
// Record a UKM event for the new frame.
MaybeQueueUKMEvent(current_rfh_);
// Send the current safe area to the new frame.
SendSafeAreaToFrame(rfh, insets_);
......@@ -538,6 +582,68 @@ class WebContentsImpl::DisplayCutoutHostImpl
return static_cast<WebContentsImpl*>(web_contents());
}
// Builds and records a Layout.DisplayCutout.StateChanged UKM event for the
// provided |frame|. The event will be added to the list of pending events.
void MaybeQueueUKMEvent(RenderFrameHost* frame) {
if (!frame)
return;
// Get the current applied ViewportFit and the ViewportFit value supplied by
// |frame|. If the |supplied_value| is kAuto then we will not record the
// event since it is the default.
blink::mojom::ViewportFit supplied_value = GetValueOrDefault(frame);
if (supplied_value == blink::mojom::ViewportFit::kAuto)
return;
blink::mojom::ViewportFit applied_value = GetValueOrDefault(current_rfh_);
// Set the reason why this frame is not the current frame.
int ignored_reason = DisplayCutoutIgnoredReason::kAllowed;
if (current_rfh_ != frame) {
ignored_reason =
current_rfh_ == nullptr
? DisplayCutoutIgnoredReason::kWebContentsNotFullscreen
: DisplayCutoutIgnoredReason::kFrameNotCurrentFullscreen;
}
// Adds the UKM event to the list of pending events.
PendingUKMEvent pending_event;
pending_event.is_main_frame = !frame->GetParent();
pending_event.applied_value = applied_value;
pending_event.supplied_value = supplied_value;
pending_event.ignored_reason = ignored_reason;
if (ignored_reason == DisplayCutoutIgnoredReason::kAllowed)
pending_event.safe_areas_present = GetSafeAreasPresentUKMValue();
pending_ukm_events_.push_back(pending_event);
}
// Records any UKM events that we have not recorded yet.
void RecordPendingUKMEvents() {
for (const auto& event : pending_ukm_events_) {
ukm::builders::Layout_DisplayCutout_StateChanged builder(
web_contents_impl()->GetUkmSourceIdForLastCommittedSource());
builder.SetIsMainFrame(event.is_main_frame);
builder.SetViewportFit_Applied(static_cast<int>(event.applied_value));
builder.SetViewportFit_Supplied(static_cast<int>(event.supplied_value));
builder.SetViewportFit_IgnoredReason(event.ignored_reason);
builder.SetSafeAreasPresent(event.safe_areas_present);
builder.Record(ukm::UkmRecorder::Get());
}
pending_ukm_events_.clear();
}
int GetSafeAreasPresentUKMValue() const {
int flags = 0;
flags |= insets_.top() ? DisplayCutoutSafeArea::kTop : 0;
flags |= insets_.left() ? DisplayCutoutSafeArea::kLeft : 0;
flags |= insets_.bottom() ? DisplayCutoutSafeArea::kBottom : 0;
flags |= insets_.right() ? DisplayCutoutSafeArea::kRight : 0;
return flags;
}
// Stores pending UKM events.
std::list<PendingUKMEvent> pending_ukm_events_;
// Stores the current safe area insets.
gfx::Insets insets_ = gfx::Insets();
......
......@@ -727,7 +727,7 @@ test("content_browsertests") {
"../browser/devtools/protocol/devtools_protocol_browsertest.cc",
"../browser/devtools/render_frame_devtools_agent_host_browsertest.cc",
"../browser/devtools/site_per_process_devtools_browsertest.cc",
"../browser/display_cutout_browsertest.cc",
"../browser/display_cutout/display_cutout_browsertest.cc",
"../browser/do_not_track_browsertest.cc",
"../browser/dom_storage/dom_storage_browsertest.cc",
"../browser/download/download_browsertest.cc",
......@@ -914,6 +914,7 @@ test("content_browsertests") {
"//components/network_session_configurator/common",
"//components/payments/mojom",
"//components/services/leveldb/public/cpp:cpp",
"//components/ukm:test_support",
"//components/url_formatter:url_formatter",
"//components/viz/test:test_support",
"//content:resources",
......@@ -953,6 +954,7 @@ test("content_browsertests") {
"//services/device/public/cpp/test:test_support",
"//services/device/public/mojom",
"//services/device/public/mojom:generic_sensor",
"//services/metrics/public/cpp:ukm_builders",
"//services/network:test_support",
"//services/service_manager/public/cpp",
"//services/test/echo/public/mojom",
......
......@@ -1309,6 +1309,53 @@ be describing additional metrics about the same event.
</metric>
</event>
<event name="Layout.DisplayCutout.StateChanged">
<owner>beccahughes@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
<summary>
Recorded every time the ViewportFit that is supplied by a frame changes or
the fullscreen state of a frame or its parent WebContents changes.
</summary>
<metric name="IsMainFrame">
<summary>
Records '1' if the frame that triggered this event is the main frame.
</summary>
</metric>
<metric name="SafeAreasPresent">
<summary>
Records whether each safe area was present. It will contain the first flag
(1) if the top safe area is present. Likewise the second for the left, the
third for the bottom and the forth for the right. If the safe area is
updated whilst we are allowed to extend into the cutout then we will use
the newest safe area values.
</summary>
</metric>
<metric name="ViewportFit.Applied">
<summary>
Contains the ViewportFit value that was applied by the WebContents. The
frame that is fullscreen will always propagate it's ViewportFit value.
This is stored as a ViewportFit enum (see display_cutout.mojom).
</summary>
</metric>
<metric name="ViewportFit.IgnoredReason">
<summary>
Records the reason why the ViewportFit value of this frame was not the
applied value. It will be '0' if the value was allowed. It will be '1' if
the ViewportFit value from the frame was blocked because the WebContents
was not fullscreen. It will be '2' flag if the ViewportFit value from the
frame was blocked because another frame is fullscreen.
</summary>
</metric>
<metric name="ViewportFit.Supplied">
<summary>
Contains the ViewportFit value that was supplied by the frame that
triggered the event. This is stored as a ViewportFit enum (see
display_cutout.mojom). It can never be kAuto as we ignore events when the
page is not trying to use the viewport fit API.
</summary>
</metric>
</event>
<event name="LocalNetworkRequests">
<owner>uthakore@chromium.org</owner>
<owner>invernizzi@chromium.org</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment