1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/presentation/presentation_dispatcher.h"
7 #include "base/logging.h"
8 #include "content/common/presentation/presentation_service.mojom.h"
9 #include "content/public/common/service_registry.h"
10 #include "content/public/renderer/render_frame.h"
11 #include "content/renderer/presentation/presentation_session_client.h"
12 #include "third_party/WebKit/public/platform/WebString.h"
13 #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h"
14 #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h"
15 #include "third_party/WebKit/public/web/WebDocument.h"
16 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 blink::WebPresentationError::ErrorType
GetWebPresentationErrorTypeFromMojo(
22 presentation::PresentationErrorType mojoErrorType
) {
23 switch (mojoErrorType
) {
24 case presentation::PRESENTATION_ERROR_TYPE_NO_AVAILABLE_SCREENS
:
25 return blink::WebPresentationError::ErrorTypeNoAvailableScreens
;
26 case presentation::PRESENTATION_ERROR_TYPE_SESSION_REQUEST_CANCELLED
:
27 return blink::WebPresentationError::ErrorTypeSessionRequestCancelled
;
28 case presentation::PRESENTATION_ERROR_TYPE_NO_PRESENTATION_FOUND
:
29 return blink::WebPresentationError::ErrorTypeNoPresentationFound
;
30 case presentation::PRESENTATION_ERROR_TYPE_UNKNOWN
:
32 return blink::WebPresentationError::ErrorTypeUnknown
;
36 blink::WebPresentationSessionState
GetWebPresentationSessionStateFromMojo(
37 presentation::PresentationSessionState mojoSessionState
) {
38 switch (mojoSessionState
) {
39 case presentation::PRESENTATION_SESSION_STATE_CONNECTED
:
40 return blink::WebPresentationSessionState::Connected
;
41 case presentation::PRESENTATION_SESSION_STATE_DISCONNECTED
:
42 return blink::WebPresentationSessionState::Disconnected
;
46 return blink::WebPresentationSessionState::Disconnected
;
49 GURL
GetPresentationURLFromFrame(content::RenderFrame
* frame
) {
52 GURL
url(frame
->GetWebFrame()->document().defaultPresentationURL());
53 return url
.is_valid() ? url
: GURL();
60 PresentationDispatcher::PresentationDispatcher(RenderFrame
* render_frame
)
61 : RenderFrameObserver(render_frame
),
62 controller_(nullptr) {
65 PresentationDispatcher::~PresentationDispatcher() {
66 // Controller should be destroyed before the dispatcher when frame is
71 void PresentationDispatcher::setController(
72 blink::WebPresentationController
* controller
) {
73 // There shouldn't be any swapping from one non-null controller to another.
74 DCHECK(controller
!= controller_
&& (!controller
|| !controller_
));
75 controller_
= controller
;
76 // The controller is set to null when the frame is about to be detached.
77 // Nothing is listening for screen availability anymore but the Mojo service
78 // will know about the frame being detached anyway.
81 void PresentationDispatcher::updateAvailableChangeWatched(bool watched
) {
82 GURL
presentation_url(GetPresentationURLFromFrame(render_frame()));
83 DoUpdateAvailableChangeWatched(presentation_url
.spec(), watched
);
86 void PresentationDispatcher::DoUpdateAvailableChangeWatched(
87 const std::string
& presentation_url
, bool watched
) {
88 ConnectToPresentationServiceIfNeeded();
90 presentation_service_
->GetScreenAvailability(
92 base::Bind(&PresentationDispatcher::OnScreenAvailabilityChanged
,
93 base::Unretained(this)));
95 presentation_service_
->OnScreenAvailabilityListenerRemoved(
100 void PresentationDispatcher::startSession(
101 const blink::WebString
& presentationUrl
,
102 const blink::WebString
& presentationId
,
103 blink::WebPresentationSessionClientCallbacks
* callback
) {
105 ConnectToPresentationServiceIfNeeded();
107 // The dispatcher owns the service so |this| will be valid when
108 // OnSessionCreated() is called. |callback| needs to be alive and also needs
109 // to be destroyed so we transfer its ownership to the mojo callback.
110 presentation_service_
->StartSession(
111 presentationUrl
.utf8(),
112 presentationId
.utf8(),
113 base::Bind(&PresentationDispatcher::OnSessionCreated
,
114 base::Unretained(this),
115 base::Owned(callback
)));
118 void PresentationDispatcher::joinSession(
119 const blink::WebString
& presentationUrl
,
120 const blink::WebString
& presentationId
,
121 blink::WebPresentationSessionClientCallbacks
* callback
) {
123 ConnectToPresentationServiceIfNeeded();
125 // The dispatcher owns the service so |this| will be valid when
126 // OnSessionCreated() is called. |callback| needs to be alive and also needs
127 // to be destroyed so we transfer its ownership to the mojo callback.
128 presentation_service_
->JoinSession(
129 presentationUrl
.utf8(),
130 presentationId
.utf8(),
131 base::Bind(&PresentationDispatcher::OnSessionCreated
,
132 base::Unretained(this),
133 base::Owned(callback
)));
136 void PresentationDispatcher::closeSession(
137 const blink::WebString
& presentationUrl
,
138 const blink::WebString
& presentationId
) {
139 ConnectToPresentationServiceIfNeeded();
141 presentation_service_
->CloseSession(
142 presentationUrl
.utf8(),
143 presentationId
.utf8());
146 void PresentationDispatcher::DidChangeDefaultPresentation() {
147 GURL
presentation_url(GetPresentationURLFromFrame(render_frame()));
149 ConnectToPresentationServiceIfNeeded();
150 presentation_service_
->SetDefaultPresentationURL(
151 presentation_url
.spec(), mojo::String());
154 void PresentationDispatcher::OnScreenAvailabilityChanged(
155 const std::string
& presentation_url
, bool available
) {
159 // Reset the callback to get the next event.
160 DoUpdateAvailableChangeWatched(presentation_url
,
161 controller_
->isAvailableChangeWatched());
163 controller_
->didChangeAvailability(available
);
166 void PresentationDispatcher::OnDefaultSessionStarted(
167 presentation::PresentationSessionInfoPtr session_info
) {
171 // Reset the callback to get the next event.
172 presentation_service_
->ListenForDefaultSessionStart(base::Bind(
173 &PresentationDispatcher::OnDefaultSessionStarted
,
174 base::Unretained(this)));
176 DCHECK(!session_info
.is_null());
177 controller_
->didStartDefaultSession(
178 new PresentationSessionClient(session_info
.Pass()));
181 void PresentationDispatcher::OnSessionCreated(
182 blink::WebPresentationSessionClientCallbacks
* callback
,
183 presentation::PresentationSessionInfoPtr session_info
,
184 presentation::PresentationErrorPtr error
) {
186 if (!error
.is_null()) {
187 DCHECK(session_info
.is_null());
188 callback
->onError(new blink::WebPresentationError(
189 GetWebPresentationErrorTypeFromMojo(error
->error_type
),
190 blink::WebString::fromUTF8(error
->message
)));
194 DCHECK(!session_info
.is_null());
195 callback
->onSuccess(new PresentationSessionClient(session_info
.Pass()));
198 void PresentationDispatcher::OnSessionStateChange(
199 presentation::PresentationSessionInfoPtr session_info
,
200 presentation::PresentationSessionState session_state
) {
204 presentation_service_
->ListenForSessionStateChange(base::Bind(
205 &PresentationDispatcher::OnSessionStateChange
,
206 base::Unretained(this)));
208 DCHECK(!session_info
.is_null());
209 controller_
->didChangeSessionState(
210 new PresentationSessionClient(session_info
.Pass()),
211 GetWebPresentationSessionStateFromMojo(session_state
));
214 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
215 if (presentation_service_
.get())
218 render_frame()->GetServiceRegistry()->ConnectToRemoteService(
219 &presentation_service_
);
220 presentation_service_
->ListenForDefaultSessionStart(base::Bind(
221 &PresentationDispatcher::OnDefaultSessionStarted
,
222 base::Unretained(this)));
223 presentation_service_
->ListenForSessionStateChange(base::Bind(
224 &PresentationDispatcher::OnSessionStateChange
,
225 base::Unretained(this)));
228 } // namespace content