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_
->ListenForScreenAvailability(
92 base::Bind(&PresentationDispatcher::OnScreenAvailabilityChanged
,
93 base::Unretained(this)));
95 presentation_service_
->RemoveScreenAvailabilityListener(presentation_url
);
99 void PresentationDispatcher::startSession(
100 const blink::WebString
& presentationUrl
,
101 const blink::WebString
& presentationId
,
102 blink::WebPresentationSessionClientCallbacks
* callback
) {
104 ConnectToPresentationServiceIfNeeded();
106 // The dispatcher owns the service so |this| will be valid when
107 // OnSessionCreated() is called. |callback| needs to be alive and also needs
108 // to be destroyed so we transfer its ownership to the mojo callback.
109 presentation_service_
->StartSession(
110 presentationUrl
.utf8(),
111 presentationId
.utf8(),
112 base::Bind(&PresentationDispatcher::OnSessionCreated
,
113 base::Unretained(this),
114 base::Owned(callback
)));
117 void PresentationDispatcher::joinSession(
118 const blink::WebString
& presentationUrl
,
119 const blink::WebString
& presentationId
,
120 blink::WebPresentationSessionClientCallbacks
* callback
) {
122 ConnectToPresentationServiceIfNeeded();
124 // The dispatcher owns the service so |this| will be valid when
125 // OnSessionCreated() is called. |callback| needs to be alive and also needs
126 // to be destroyed so we transfer its ownership to the mojo callback.
127 presentation_service_
->JoinSession(
128 presentationUrl
.utf8(),
129 presentationId
.utf8(),
130 base::Bind(&PresentationDispatcher::OnSessionCreated
,
131 base::Unretained(this),
132 base::Owned(callback
)));
135 void PresentationDispatcher::closeSession(
136 const blink::WebString
& presentationUrl
,
137 const blink::WebString
& presentationId
) {
138 ConnectToPresentationServiceIfNeeded();
140 presentation_service_
->CloseSession(
141 presentationUrl
.utf8(),
142 presentationId
.utf8());
145 void PresentationDispatcher::DidChangeDefaultPresentation() {
146 GURL
presentation_url(GetPresentationURLFromFrame(render_frame()));
148 ConnectToPresentationServiceIfNeeded();
149 presentation_service_
->SetDefaultPresentationURL(
150 presentation_url
.spec(), mojo::String());
153 void PresentationDispatcher::OnScreenAvailabilityChanged(
154 const std::string
& presentation_url
, bool available
) {
158 // Reset the callback to get the next event.
159 DoUpdateAvailableChangeWatched(presentation_url
,
160 controller_
->isAvailableChangeWatched());
162 controller_
->didChangeAvailability(available
);
165 void PresentationDispatcher::OnDefaultSessionStarted(
166 presentation::PresentationSessionInfoPtr session_info
) {
170 // Reset the callback to get the next event.
171 presentation_service_
->ListenForDefaultSessionStart(base::Bind(
172 &PresentationDispatcher::OnDefaultSessionStarted
,
173 base::Unretained(this)));
175 DCHECK(!session_info
.is_null());
176 controller_
->didStartDefaultSession(
177 new PresentationSessionClient(session_info
.Pass()));
180 void PresentationDispatcher::OnSessionCreated(
181 blink::WebPresentationSessionClientCallbacks
* callback
,
182 presentation::PresentationSessionInfoPtr session_info
,
183 presentation::PresentationErrorPtr error
) {
185 if (!error
.is_null()) {
186 DCHECK(session_info
.is_null());
187 callback
->onError(new blink::WebPresentationError(
188 GetWebPresentationErrorTypeFromMojo(error
->error_type
),
189 blink::WebString::fromUTF8(error
->message
)));
193 DCHECK(!session_info
.is_null());
194 callback
->onSuccess(new PresentationSessionClient(session_info
.Pass()));
197 void PresentationDispatcher::OnSessionStateChange(
198 presentation::PresentationSessionInfoPtr session_info
,
199 presentation::PresentationSessionState session_state
) {
203 presentation_service_
->ListenForSessionStateChange(base::Bind(
204 &PresentationDispatcher::OnSessionStateChange
,
205 base::Unretained(this)));
207 DCHECK(!session_info
.is_null());
208 controller_
->didChangeSessionState(
209 new PresentationSessionClient(session_info
.Pass()),
210 GetWebPresentationSessionStateFromMojo(session_state
));
213 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
214 if (presentation_service_
.get())
217 render_frame()->GetServiceRegistry()->ConnectToRemoteService(
218 &presentation_service_
);
219 // TODO(imcheng): Uncomment these once they are implemented on the browser
220 // side. (crbug.com/459006)
222 presentation_service_->ListenForDefaultSessionStart(base::Bind(
223 &PresentationDispatcher::OnDefaultSessionStarted,
224 base::Unretained(this)));
225 presentation_service_->ListenForSessionStateChange(base::Bind(
226 &PresentationDispatcher::OnSessionStateChange,
227 base::Unretained(this)));
231 } // namespace content