| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_ |
| #define COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "build/build_config.h" |
| #include "components/media_router/browser/media_router.h" |
| #include "components/media_router/browser/presentation/presentation_service_delegate_observers.h" |
| #include "components/media_router/browser/presentation/start_presentation_context.h" |
| #include "components/media_router/browser/presentation/web_contents_presentation_manager.h" |
| #include "components/media_router/common/media_source.h" |
| #include "components/media_router/common/mojom/media_router.mojom.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" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace content { |
| class PresentationScreenAvailabilityListener; |
| class WebContents; |
| } // namespace content |
| |
| 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. |
| // It is accessed through the WebContentsPresentationManager interface by |
| // clients (e.g. the UI code) that is interested in the presentation status of |
| // the WebContents, but not in other aspects such as the render frame. |
| class PresentationServiceDelegateImpl |
| : public content::WebContentsUserData<PresentationServiceDelegateImpl>, |
| public content::ControllerPresentationServiceDelegate, |
| public WebContentsPresentationManager { |
| public: |
| // 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(const PresentationServiceDelegateImpl&) = |
| delete; |
| PresentationServiceDelegateImpl& operator=( |
| const PresentationServiceDelegateImpl&) = delete; |
| |
| ~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; |
| |
| // WebContentsPresentationManager implementation. |
| void AddObserver(content::PresentationObserver* observer) override; |
| void RemoveObserver(content::PresentationObserver* observer) override; |
| bool HasDefaultPresentationRequest() const override; |
| const content::PresentationRequest& GetDefaultPresentationRequest() |
| const override; |
| void OnPresentationResponse(const content::PresentationRequest& request, |
| mojom::RoutePresentationConnectionPtr connection, |
| const RouteRequestResult& result) override; |
| std::vector<MediaRoute> GetMediaRoutes() override; |
| base::WeakPtr<WebContentsPresentationManager> GetWeakPtr() override; |
| |
| // Returns the WebContents that owns this instance. |
| content::WebContents* web_contents() { return &GetWebContents(); } |
| |
| bool HasScreenAvailabilityListenerForTest( |
| int render_process_id, |
| int render_frame_id, |
| const MediaSource::Id& source_id) const; |
| |
| void set_start_presentation_cb( |
| base::RepeatingCallback<void(std::unique_ptr<StartPresentationContext>)> |
| callback) { |
| start_presentation_cb_ = std::move(callback); |
| } |
| |
| 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 content::GlobalRenderFrameHostId& render_frame_host_id); |
| |
| void OnJoinRouteResponse( |
| const content::GlobalRenderFrameHostId& render_frame_host_id, |
| const GURL& presentation_url, |
| const std::string& presentation_id, |
| content::PresentationConnectionCallback success_cb, |
| content::PresentationConnectionErrorCallback error_cb, |
| mojom::RoutePresentationConnectionPtr connection, |
| const RouteRequestResult& result); |
| |
| void OnStartPresentationSucceeded( |
| const content::GlobalRenderFrameHostId& render_frame_host_id, |
| content::PresentationConnectionCallback success_cb, |
| const blink::mojom::PresentationInfo& new_presentation_info, |
| mojom::RoutePresentationConnectionPtr connection, |
| 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. |
| void AddPresentation( |
| const content::GlobalRenderFrameHostId& 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 content::GlobalRenderFrameHostId& 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 content::GlobalRenderFrameHostId& render_frame_host_id, |
| const std::string& presentation_id) const; |
| |
| // Ensures that |connection| contains a valid pair of |
| // blink::mojom::PresentationConnection{PtrInfo,Request} objects which will be |
| // used for all Presentation API communication in a newly-connected |
| // presentation. |
| void EnsurePresentationConnection( |
| const content::GlobalRenderFrameHostId& render_frame_host_id, |
| const blink::mojom::PresentationInfo& presentation_info, |
| mojom::RoutePresentationConnectionPtr* connection); |
| |
| void NotifyDefaultPresentationChanged( |
| const content::PresentationRequest* request); |
| void NotifyMediaRoutesChanged(); |
| |
| // Invoked by the MR when a Presentation Connection state changes in a frame. |
| // It calls |RemovePresentation()| when the connection is closed/terminated. |
| void OnConnectionStateChanged( |
| const content::GlobalRenderFrameHostId& render_frame_host_id, |
| const blink::mojom::PresentationInfo& connection, |
| const content::PresentationConnectionStateChangedCallback& |
| state_changed_cb, |
| const content::PresentationConnectionStateChangeInfo& info); |
| |
| // Reference to the associated browser profile's MediaRouter instance. |
| raw_ptr<MediaRouter> router_; |
| |
| // References to the observers listening for changes to the default |
| // presentation and presentation MediaRoutes associated with the |
| // WebContents. |
| base::ObserverList<content::PresentationObserver> presentation_observers_; |
| |
| // Default presentation request for the owning WebContents. |
| absl::optional<content::PresentationRequest> default_presentation_request_; |
| |
| // Callback to invoke when the default presentation has started. |
| content::DefaultPresentationConnectionCallback |
| default_presentation_started_callback_; |
| |
| // If this callback is set when a request to start a presentation is made, |
| // it is called instead of showing the Media Router dialog. |
| base::RepeatingCallback<void(std::unique_ptr<StartPresentationContext>)> |
| start_presentation_cb_; |
| |
| // Maps a frame identifier to a PresentationFrame object for frames |
| // that are using Presentation API. |
| std::unordered_map<content::GlobalRenderFrameHostId, |
| std::unique_ptr<PresentationFrame>, |
| content::GlobalRenderFrameHostIdHasher> |
| presentation_frames_; |
| |
| PresentationServiceDelegateObservers observers_; |
| |
| base::WeakPtrFactory<PresentationServiceDelegateImpl> weak_factory_{this}; |
| |
| WEB_CONTENTS_USER_DATA_KEY_DECL(); |
| }; |
| |
| } // namespace media_router |
| |
| #endif // COMPONENTS_MEDIA_ROUTER_BROWSER_PRESENTATION_PRESENTATION_SERVICE_DELEGATE_IMPL_H_ |