blob: b2f013dfca2fbdb0007d3f412970f0e81d76b433 [file] [log] [blame]
// Copyright 2020 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 CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
#include <set>
#include <unordered_map>
#include "base/optional.h"
#include "ui/gfx/geometry/rect.h"
// Tracks the ad density of a page through the page's lifecycle.
// It has the following usage:
// 1. Set subframe and mainframe rects using subframe and mainframe rect
// operations (AddRect, RemoveRect, UpdateMainFrameRect).
// 2. Once a page has a main frame rect, get current density using
// DensityByHeight or DensityByArea.
class PageAdDensityTracker {
public:
PageAdDensityTracker();
~PageAdDensityTracker();
PageAdDensityTracker(const PageAdDensityTracker&) = delete;
PageAdDensityTracker& operator=(const PageAdDensityTracker&) = delete;
// Operations to track sub frame rects in the page density calcluation.
void AddRect(int rect_id, const gfx::Rect& rect);
// Removes a rect from the tracker if it is currently being tracked.
// Otherwise RemoveRect is a no op.
void RemoveRect(int rect_id);
// Operations to track the main frame dimensions. The main frame rect has to
// be set to calculate density.
void UpdateMainFrameRect(const gfx::Rect& rect);
// Returns the density by height, as a value from 0-100. If the density
// calculation fails (i.e. no main frame size), this returns -1. Percentage
// density by height is calculated as the the combined height of ads divided
// by the page's height.
int MaxPageAdDensityByHeight();
// Returns the density by area, as a value from 0-100. If the density
// calculation fails (i.e. no main frame size), this returns -1.
int MaxPageAdDensityByArea();
private:
// An event to process corresponding to the top or bottom of each rect.
struct RectEvent {
RectEvent(int id, bool is_bottom, const gfx::Rect& rect);
RectEvent(const RectEvent& other);
// A unique identifier set when adding and removing rect events
// corresponding to a single rect.
int rect_id;
bool is_bottom;
gfx::Rect rect;
// RectEvents are sorted by descending y value of the segment associated
// with the event.
bool operator<(const RectEvent& rhs) const;
};
// Iterators into the set of rect events for efficient removal of
// rect events by rect_id. Maintained by |rect_events_iterators_|.
struct RectEventSetIterators {
RectEventSetIterators(std::set<RectEvent>::iterator top,
std::set<RectEvent>::iterator bottom);
RectEventSetIterators(const RectEventSetIterators& other);
std::set<RectEvent>::const_iterator top_it;
std::set<RectEvent>::const_iterator bottom_it;
};
// Calculates the combined area and height of the set of rects, this populates
// total_height_ and total_area_.
void CalculateDensity();
// Maintain a sorted set of rect events for use in calculating ad area.
std::set<RectEvent> rect_events_;
// Map from rect_id to iterators of rect events in rect_events_. This allows
// efficient removal according to rect_id.
std::unordered_map<int, RectEventSetIterators> rect_events_iterators_;
// Percentage of page ad density as a value from 0-100. These only have
// a value of -1 when ad density has not yet been calculated successfully.
int max_page_ad_density_by_area_ = -1;
int max_page_ad_density_by_height_ = -1;
base::Optional<gfx::Rect> last_main_frame_size_;
};
#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_"