#ifndef CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_
#define CONTENT_BROWSER_PRESENTATION_PRESENTATION_SERVICE_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/presentation_screen_availability_listener.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
#include "url/gurl.h"
namespace content {
class RenderFrameHost;
class CONTENT_EXPORT PresentationServiceImpl
: public blink::mojom::PresentationService,
public WebContentsObserver,
public PresentationServiceDelegate::Observer {
public:
using NewPresentationCallback =
base::OnceCallback<void(blink::mojom::PresentationConnectionResultPtr,
blink::mojom::PresentationErrorPtr)>;
static std::unique_ptr<PresentationServiceImpl> Create(
RenderFrameHost* render_frame_host);
PresentationServiceImpl(const PresentationServiceImpl&) = delete;
PresentationServiceImpl& operator=(const PresentationServiceImpl&) = delete;
~PresentationServiceImpl() override;
void Bind(mojo::PendingReceiver<blink::mojom::PresentationService> receiver);
void SetDefaultPresentationUrls(
const std::vector<GURL>& presentation_urls) override;
void SetController(mojo::PendingRemote<blink::mojom::PresentationController>
presentation_controller_remote) override;
void SetReceiver(mojo::PendingRemote<blink::mojom::PresentationReceiver>
presentation_receiver_remote) override;
void ListenForScreenAvailability(const GURL& url) override;
void StopListeningForScreenAvailability(const GURL& url) override;
void StartPresentation(const std::vector<GURL>& presentation_urls,
NewPresentationCallback callback) override;
void ReconnectPresentation(const std::vector<GURL>& presentation_urls,
const std::string& presentation_id,
NewPresentationCallback callback) override;
void CloseConnection(const GURL& presentation_url,
const std::string& presentation_id) override;
void Terminate(const GURL& presentation_url,
const std::string& presentation_id) override;
void SetControllerDelegateForTesting(
ControllerPresentationServiceDelegate* controller_delegate);
private:
friend class PresentationServiceImplTest;
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, OnDelegateDestroyed);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, DelegateFails);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
SetDefaultPresentationUrlsNoopsOnNonMainFrame);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ListenForConnectionStateChange);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ListenForConnectionClose);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
MaxPendingStartPresentationRequests);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
MaxPendingReconnectPresentationRequests);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ReceiverPresentationServiceDelegate);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ReceiverDelegateOnSubFrame);
FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest,
PresentationConnectionClosed);
static const int kMaxQueuedRequests = 10;
class CONTENT_EXPORT ScreenAvailabilityListenerImpl
: public PresentationScreenAvailabilityListener {
public:
ScreenAvailabilityListenerImpl(const GURL& availability_url,
PresentationServiceImpl* service);
~ScreenAvailabilityListenerImpl() override;
GURL GetAvailabilityUrl() override;
void OnScreenAvailabilityChanged(
blink::mojom::ScreenAvailability availability) override;
private:
const GURL availability_url_;
const raw_ptr<PresentationServiceImpl> service_;
};
class NewPresentationCallbackWrapper {
public:
explicit NewPresentationCallbackWrapper(NewPresentationCallback callback);
NewPresentationCallbackWrapper(const NewPresentationCallbackWrapper&) =
delete;
NewPresentationCallbackWrapper& operator=(
const NewPresentationCallbackWrapper&) = delete;
~NewPresentationCallbackWrapper();
void Run(blink::mojom::PresentationConnectionResultPtr result,
blink::mojom::PresentationErrorPtr error);
private:
NewPresentationCallback callback_;
};
PresentationServiceImpl(
RenderFrameHost* render_frame_host,
WebContents* web_contents,
ControllerPresentationServiceDelegate* controller_delegate,
ReceiverPresentationServiceDelegate* receiver_delegate);
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
void OnDelegateDestroyed() override;
void OnDefaultPresentationStarted(
blink::mojom::PresentationConnectionResultPtr result);
bool RunAndEraseReconnectPresentationMojoCallback(
int request_id,
blink::mojom::PresentationConnectionResultPtr result,
blink::mojom::PresentationErrorPtr error);
void Reset();
void OnStartPresentationSucceeded(
int request_id,
blink::mojom::PresentationConnectionResultPtr result);
void OnStartPresentationError(int request_id,
const blink::mojom::PresentationError& error);
void OnReconnectPresentationSucceeded(
int request_id,
blink::mojom::PresentationConnectionResultPtr result);
void OnReconnectPresentationError(
int request_id,
const blink::mojom::PresentationError& error);
void ListenForConnectionStateChange(
const blink::mojom::PresentationInfo& connection);
void OnReceiverConnectionAvailable(
blink::mojom::PresentationConnectionResultPtr result);
int RegisterReconnectPresentationCallback(NewPresentationCallback* callback);
void OnConnectionStateChanged(
const blink::mojom::PresentationInfo& connection,
const PresentationConnectionStateChangeInfo& info);
bool FrameMatches(content::RenderFrameHost* render_frame_host) const;
void OnConnectionError();
PresentationServiceDelegate* GetPresentationServiceDelegate();
const raw_ptr<RenderFrameHost> render_frame_host_;
raw_ptr<ControllerPresentationServiceDelegate> controller_delegate_;
raw_ptr<ReceiverPresentationServiceDelegate> receiver_delegate_;
mojo::Remote<blink::mojom::PresentationController>
presentation_controller_remote_;
mojo::Remote<blink::mojom::PresentationReceiver>
presentation_receiver_remote_;
std::vector<GURL> default_presentation_urls_;
using ScreenAvailabilityListenerMap =
std::map<GURL, std::unique_ptr<ScreenAvailabilityListenerImpl>>;
ScreenAvailabilityListenerMap screen_availability_listeners_;
int start_presentation_request_id_;
std::unique_ptr<NewPresentationCallbackWrapper>
pending_start_presentation_cb_;
std::unordered_map<int, std::unique_ptr<NewPresentationCallbackWrapper>>
pending_reconnect_presentation_cbs_;
mojo::ReceiverSet<blink::mojom::PresentationService>
presentation_service_receivers_;
int render_process_id_;
int render_frame_id_;
bool is_outermost_document_;
base::WeakPtrFactory<PresentationServiceImpl> weak_factory_{this};
};
}
#endif