blob: 5db27b42a2d1d74b398cfb1da9f8e94b24b31043 [file] [log] [blame]
// Copyright 2015 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_MEDIA_ROUTER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
#define CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "build/build_config.h"
#include "chrome/browser/media/router/media_router.h"
#include "chrome/browser/media/router/presentation/presentation_service_delegate_observers.h"
#include "chrome/browser/media/router/presentation/render_frame_host_id.h"
#include "chrome/common/media_router/media_source.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
namespace content {
class PresentationScreenAvailabilityListener;
class WebContents;
} // namespace content
namespace url {
class Origin;
} // namespace url
namespace media_router {
class MediaRoute;
class PresentationFrame;
class RouteRequestResult;
// Implementation of PresentationServiceDelegate that interfaces an instance of
// WebContents with the Chrome Media Router. It uses the Media Router to handle
// presentation API calls forwarded from PresentationServiceImpl. In addition,
// it also provides default presentation URL that is required for creating
// browser-initiated presentations. It is scoped to the lifetime of a
// WebContents, and is managed by the associated WebContents.
class PresentationServiceDelegateImpl
: public content::WebContentsUserData<PresentationServiceDelegateImpl>,
public content::ControllerPresentationServiceDelegate {
public:
// Observer interface for listening to default presentation request
// changes for the WebContents.
class DefaultPresentationRequestObserver {
public:
virtual ~DefaultPresentationRequestObserver() = default;
// Called when default presentation request for the corresponding
// WebContents is set or changed.
// |default_presentation_info|: New default presentation request.
virtual void OnDefaultPresentationChanged(
const content::PresentationRequest& default_presentation_request) = 0;
// Called when default presentation request for the corresponding
// WebContents has been removed.
virtual void OnDefaultPresentationRemoved() = 0;
};
// Retrieves the instance of PresentationServiceDelegateImpl that was attached
// to the specified WebContents. If no instance was attached, creates one,
// and attaches it to the specified WebContents.
static PresentationServiceDelegateImpl* GetOrCreateForWebContents(
content::WebContents* web_contents);
~PresentationServiceDelegateImpl() override;
// content::PresentationServiceDelegate implementation.
void AddObserver(
int render_process_id,
int render_frame_id,
content::PresentationServiceDelegate::Observer* observer) override;
void RemoveObserver(int render_process_id, int render_frame_id) override;
bool AddScreenAvailabilityListener(
int render_process_id,
int render_frame_id,
content::PresentationScreenAvailabilityListener* listener) override;
void RemoveScreenAvailabilityListener(
int render_process_id,
int render_frame_id,
content::PresentationScreenAvailabilityListener* listener) override;
void Reset(int render_process_id, int render_frame_id) override;
void SetDefaultPresentationUrls(
const content::PresentationRequest& request,
content::DefaultPresentationConnectionCallback callback) override;
void StartPresentation(
const content::PresentationRequest& request,
content::PresentationConnectionCallback success_cb,
content::PresentationConnectionErrorCallback error_cb) override;
void ReconnectPresentation(
const content::PresentationRequest& request,
const std::string& presentation_id,
content::PresentationConnectionCallback success_cb,
content::PresentationConnectionErrorCallback error_cb) override;
void CloseConnection(int render_process_id,
int render_frame_id,
const std::string& presentation_id) override;
void Terminate(int render_process_id,
int render_frame_id,
const std::string& presentation_id) override;
std::unique_ptr<media::FlingingController> GetFlingingController(
int render_process_id,
int render_frame_id,
const std::string& presentation_id) override;
void ListenForConnectionStateChange(
int render_process_id,
int render_frame_id,
const blink::mojom::PresentationInfo& connection,
const content::PresentationConnectionStateChangedCallback&
state_changed_cb) override;
void ConnectToPresentation(
int render_process_id,
int render_frame_id,
const blink::mojom::PresentationInfo& presentation_info,
content::PresentationConnectionPtr controller_connection_ptr,
content::PresentationConnectionRequest receiver_connection_request)
override;
// Callback invoked when a default PresentationRequest is started from a
// browser-initiated dialog.
void OnRouteResponse(const content::PresentationRequest& request,
const RouteRequestResult& result);
// Adds / removes an observer for listening to default PresentationRequest
// changes. This class does not own |observer|. When |observer| is about to
// be destroyed, |RemoveDefaultPresentationRequestObserver| must be called.
void AddDefaultPresentationRequestObserver(
DefaultPresentationRequestObserver* observer);
void RemoveDefaultPresentationRequestObserver(
DefaultPresentationRequestObserver* observer);
// Gets the default presentation request for the owning WebContents. It
// is an error to call this method if the default presentation request does
// not exist.
const content::PresentationRequest& GetDefaultPresentationRequest() const;
// Returns true if there is a default presentation request for the owning tab
// WebContents.
bool HasDefaultPresentationRequest() const;
// Returns the WebContents that owns this instance.
content::WebContents* web_contents() const { return web_contents_; }
base::WeakPtr<PresentationServiceDelegateImpl> GetWeakPtr();
bool HasScreenAvailabilityListenerForTest(
int render_process_id,
int render_frame_id,
const MediaSource::Id& source_id) const;
private:
friend class content::WebContentsUserData<PresentationServiceDelegateImpl>;
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
DelegateObservers);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
SetDefaultPresentationUrl);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
DefaultPresentationRequestObserver);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
DefaultPresentationUrlCallback);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
TestCloseConnectionForLocalPresentation);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
ConnectToLocalPresentation);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
ConnectToPresentation);
explicit PresentationServiceDelegateImpl(content::WebContents* web_contents);
PresentationFrame* GetOrAddPresentationFrame(
const RenderFrameHostId& render_frame_host_id);
void OnJoinRouteResponse(
const RenderFrameHostId& render_frame_host_id,
const GURL& presentation_url,
const std::string& presentation_id,
content::PresentationConnectionCallback success_cb,
content::PresentationConnectionErrorCallback error_cb,
const RouteRequestResult& result);
void OnStartPresentationSucceeded(
const RenderFrameHostId& render_frame_host_id,
content::PresentationConnectionCallback success_cb,
const blink::mojom::PresentationInfo& new_presentation_info,
const MediaRoute& route);
// Notifies the PresentationFrame of |render_frame_host_id| that a
// presentation and its corresponding MediaRoute has been created.
// The PresentationFrame will be created if it does not already exist.
// This must be called before |ConnectToPresentation()|.
void AddPresentation(const RenderFrameHostId& render_frame_host_id,
const blink::mojom::PresentationInfo& presentation_info,
const MediaRoute& route);
// Notifies the PresentationFrame of |render_frame_host_id| that a
// presentation and its corresponding MediaRoute has been removed.
void RemovePresentation(const RenderFrameHostId& render_frame_host_id,
const std::string& presentation_id);
// Clears the default presentation request for the owning WebContents and
// notifies observers of changes. Also resets
// |default_presentation_started_callback_|.
void ClearDefaultPresentationRequest();
// Returns the ID of the route corresponding to |presentation_id| in the given
// frame, or empty if no such route exist.
MediaRoute::Id GetRouteId(const RenderFrameHostId& render_frame_host_id,
const std::string& presentation_id) const;
#if !defined(OS_ANDROID)
// Returns true if auto-join requests should be cancelled for |origin|.
bool ShouldCancelAutoJoinForOrigin(const url::Origin& origin) const;
#endif
// References to the WebContents that owns this instance, and associated
// browser profile's MediaRouter instance.
content::WebContents* const web_contents_;
MediaRouter* router_;
// References to the observers listening for changes to the default
// presentation of the associated WebContents.
base::ObserverList<DefaultPresentationRequestObserver>
default_presentation_request_observers_;
// Default presentation request for the owning WebContents.
base::Optional<content::PresentationRequest> default_presentation_request_;
// Callback to invoke when the default presentation has started.
content::DefaultPresentationConnectionCallback
default_presentation_started_callback_;
// Maps a frame identifier to a PresentationFrame object for frames
// that are using Presentation API.
std::unordered_map<RenderFrameHostId,
std::unique_ptr<PresentationFrame>,
RenderFrameHostIdHasher>
presentation_frames_;
PresentationServiceDelegateObservers observers_;
base::WeakPtrFactory<PresentationServiceDelegateImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PresentationServiceDelegateImpl);
};
} // namespace media_router
#endif // CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_