blob: d20430c360ed41a33ca56ed38993a3ee0077d504 [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.
#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_PAGE_SIGNAL_RECEIVER_H_
#define CHROME_BROWSER_RESOURCE_COORDINATOR_PAGE_SIGNAL_RECEIVER_H_
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/resource_coordinator/public/mojom/page_signal.mojom.h"
namespace content {
class WebContents;
}
namespace resource_coordinator {
// A PageSignalObserver is implemented to receive notifications from
// PageSignalReceiver by adding itself to PageSignalReceiver.
class PageSignalObserver {
public:
virtual ~PageSignalObserver() = default;
// PageSignalReceiver will deliver signals with a |web_contents| even it's not
// managed by the client. Thus the clients are responsible for checking the
// passed |web_contents| by themselves.
// Also note that because these event notifications are asynchronous to
// navigation, it's possible that |web_contents| has navigated to another site
// by the time the notification arrives.
// The |page_navigation_id| parameter allows comparing the navigation_id
// against the current navigation handle of |web_contents|, and the url
// in the struct can be used post-navigation to rendezvous to the origin
// the event relates to.
virtual void OnPageAlmostIdle(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id) {}
virtual void OnRendererIsBloated(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id) {}
virtual void OnExpectedTaskQueueingDurationSet(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id,
base::TimeDelta duration) {}
virtual void OnLifecycleStateChanged(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id,
mojom::LifecycleState state) {}
virtual void OnNonPersistentNotificationCreated(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id) {}
virtual void OnLoadTimePerformanceEstimate(
content::WebContents* web_contents,
const PageNavigationIdentity& page_navigation_id,
base::TimeDelta load_duration,
base::TimeDelta cpu_usage_estimate,
uint64_t private_footprint_kb_estimate) {}
};
// Implementation of resource_coordinator::mojom::PageSignalReceiver.
// PageSignalReceiver constructs a mojo channel to PageSignalGenerator in
// resource coordinator, passes an interface pointer to PageSignalGenerator,
// receives page scoped signals from PageSignalGenerator, and dispatches them
// with WebContents to PageSignalObservers.
// The mojo channel won't be constructed until PageSignalReceiver has the first
// observer.
class PageSignalReceiver : public mojom::PageSignalReceiver {
public:
PageSignalReceiver();
~PageSignalReceiver() override;
static bool IsEnabled();
// Callers do not take ownership.
static PageSignalReceiver* GetInstance();
// mojom::PageSignalReceiver implementation.
void NotifyPageAlmostIdle(
const PageNavigationIdentity& page_navigation_id) override;
void NotifyRendererIsBloated(
const PageNavigationIdentity& page_navigation_id) override;
void SetExpectedTaskQueueingDuration(
const PageNavigationIdentity& page_navigation_id,
base::TimeDelta duration) override;
void SetLifecycleState(const PageNavigationIdentity& page_navigation_id,
mojom::LifecycleState) override;
void NotifyNonPersistentNotificationCreated(
const PageNavigationIdentity& page_navigation_id) override;
void OnLoadTimePerformanceEstimate(
const PageNavigationIdentity& page_navigation_id,
base::TimeDelta load_duration,
base::TimeDelta cpu_usage_estimate,
uint64_t private_footprint_kb_estimate) override;
void AddObserver(PageSignalObserver* observer);
void RemoveObserver(PageSignalObserver* observer);
void AssociateCoordinationUnitIDWithWebContents(
const CoordinationUnitID& cu_id,
content::WebContents* web_contents);
void SetNavigationID(content::WebContents* web_contents,
int64_t navigation_id);
void RemoveCoordinationUnitID(const CoordinationUnitID& cu_id);
// Retrieves the unique ID of the last navigation observed for |web_contents|
// or 0 if no navigation has been observed yet.
int64_t GetNavigationIDForWebContents(content::WebContents* web_contents);
private:
FRIEND_TEST_ALL_PREFIXES(PageSignalReceiverUnitTest,
NotifyObserversThatCanRemoveCoordinationUnitID);
template <typename Method, typename... Params>
void NotifyObserversIfKnownCu(
const PageNavigationIdentity& page_navigation_id,
Method m,
Params... params);
mojo::Binding<mojom::PageSignalReceiver> binding_;
std::map<CoordinationUnitID, content::WebContents*> cu_id_web_contents_map_;
std::map<content::WebContents*, int64_t> web_contents_navigation_id_map_;
base::ObserverList<PageSignalObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(PageSignalReceiver);
};
} // namespace resource_coordinator
#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_PAGE_SIGNAL_RECEIVER_H_