OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chrome/browser/media/router/receiver_presentation_service_delegate_imp
l.h" |
| 6 |
| 7 #include "chrome/browser/media/router/offscreen_presentation_manager.h" |
| 8 #include "chrome/browser/media/router/offscreen_presentation_manager_factory.h" |
| 9 #include "chrome/browser/profiles/profile.h" |
| 10 #include "content/public/browser/render_frame_host.h" |
| 11 #include "content/public/browser/render_process_host.h" |
| 12 |
| 13 DEFINE_WEB_CONTENTS_USER_DATA_KEY( |
| 14 media_router::ReceiverPresentationServiceDelegateImpl); |
| 15 |
| 16 using content::PresentationServiceDelegate; |
| 17 using content::RenderFrameHost; |
| 18 |
| 19 namespace media_router { |
| 20 |
| 21 using OffscreenPresentationConnection = |
| 22 OffscreenPresentationManager::OffscreenPresentationConnection; |
| 23 |
| 24 // static |
| 25 void ReceiverPresentationServiceDelegateImpl::CreateForWebContents( |
| 26 content::WebContents* web_contents, |
| 27 const std::string& presentation_id) { |
| 28 DCHECK(web_contents); |
| 29 |
| 30 if (FromWebContents(web_contents)) |
| 31 return; |
| 32 |
| 33 web_contents->SetUserData(UserDataKey(), |
| 34 new ReceiverPresentationServiceDelegateImpl( |
| 35 web_contents, presentation_id)); |
| 36 } |
| 37 |
| 38 ReceiverPresentationServiceDelegateImpl:: |
| 39 ~ReceiverPresentationServiceDelegateImpl() { |
| 40 for (auto& observer_pair : observers_) |
| 41 observer_pair.second->OnDelegateDestroyed(); |
| 42 |
| 43 receiver_connections_.clear(); |
| 44 offscreen_presentation_manager_->UnregisterOffscreenPresentationReceiver( |
| 45 presentation_id_); |
| 46 } |
| 47 |
| 48 void ReceiverPresentationServiceDelegateImpl::AddObserver( |
| 49 int render_process_id, |
| 50 int render_frame_id, |
| 51 content::PresentationServiceDelegate::Observer* observer) { |
| 52 DCHECK(observer); |
| 53 |
| 54 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 55 DCHECK(!ContainsKey(observers_, rfh_id)); |
| 56 observers_[rfh_id] = observer; |
| 57 } |
| 58 |
| 59 void ReceiverPresentationServiceDelegateImpl::RemoveObserver( |
| 60 int render_process_id, |
| 61 int render_frame_id) { |
| 62 observers_.erase(RenderFrameHostId(render_process_id, render_frame_id)); |
| 63 } |
| 64 |
| 65 bool ReceiverPresentationServiceDelegateImpl::AddScreenAvailabilityListener( |
| 66 int render_process_id, |
| 67 int render_frame_id, |
| 68 content::PresentationScreenAvailabilityListener* listener) { |
| 69 NOTIMPLEMENTED(); |
| 70 return false; |
| 71 } |
| 72 |
| 73 void ReceiverPresentationServiceDelegateImpl::RemoveScreenAvailabilityListener( |
| 74 int render_process_id, |
| 75 int render_frame_id, |
| 76 content::PresentationScreenAvailabilityListener* listener) { |
| 77 NOTIMPLEMENTED(); |
| 78 } |
| 79 |
| 80 void ReceiverPresentationServiceDelegateImpl::Reset(int render_process_id, |
| 81 int render_frame_id) { |
| 82 DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id; |
| 83 |
| 84 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 85 if (rfh_id != current_frame_id_) { |
| 86 DVLOG(2) << __FUNCTION__ << ": not main frame"; |
| 87 return; |
| 88 } |
| 89 |
| 90 current_frame_id_ = RenderFrameHostId(); |
| 91 receiver_connections_.clear(); |
| 92 receiver_available_callback_.Reset(); |
| 93 } |
| 94 |
| 95 void ReceiverPresentationServiceDelegateImpl::SetDefaultPresentationUrl( |
| 96 int render_process_id, |
| 97 int render_frame_id, |
| 98 const std::string& default_presentation_url, |
| 99 const content::PresentationSessionStartedCallback& callback) { |
| 100 NOTIMPLEMENTED(); |
| 101 } |
| 102 |
| 103 void ReceiverPresentationServiceDelegateImpl::StartSession( |
| 104 int render_process_id, |
| 105 int render_frame_id, |
| 106 const std::string& presentation_url, |
| 107 const content::PresentationSessionStartedCallback& success_cb, |
| 108 const content::PresentationSessionErrorCallback& error_cb) { |
| 109 NOTIMPLEMENTED(); |
| 110 error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, |
| 111 "Not implemented")); |
| 112 } |
| 113 |
| 114 void ReceiverPresentationServiceDelegateImpl::JoinSession( |
| 115 int render_process_id, |
| 116 int render_frame_id, |
| 117 const std::string& presentation_url, |
| 118 const std::string& presentation_id, |
| 119 const content::PresentationSessionStartedCallback& success_cb, |
| 120 const content::PresentationSessionErrorCallback& error_cb) { |
| 121 NOTIMPLEMENTED(); |
| 122 error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, |
| 123 "Not implemented")); |
| 124 } |
| 125 |
| 126 void ReceiverPresentationServiceDelegateImpl::CloseConnection( |
| 127 int render_process_id, |
| 128 int render_frame_id, |
| 129 const std::string& presentation_id) { |
| 130 NOTIMPLEMENTED(); |
| 131 } |
| 132 |
| 133 void ReceiverPresentationServiceDelegateImpl::Terminate( |
| 134 int render_process_id, |
| 135 int render_frame_id, |
| 136 const std::string& presentation_id) { |
| 137 NOTIMPLEMENTED(); |
| 138 } |
| 139 |
| 140 void ReceiverPresentationServiceDelegateImpl::ListenForSessionMessages( |
| 141 int render_process_id, |
| 142 int render_frame_id, |
| 143 const content::PresentationSessionInfo& session_info, |
| 144 const content::PresentationSessionMessageCallback& message_cb) { |
| 145 DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id; |
| 146 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 147 if (rfh_id != current_frame_id_ && !BindToFrame(rfh_id)) { |
| 148 DVLOG(2) << __FUNCTION__ << ": not main frame"; |
| 149 return; |
| 150 } |
| 151 |
| 152 OffscreenPresentationConnection* connection = FindConnection(session_info); |
| 153 if (!connection) { |
| 154 LOG(ERROR) << __FUNCTION__ << ": presentation does not exist."; |
| 155 return; |
| 156 } |
| 157 |
| 158 connection->ListenForMessages(message_cb); |
| 159 } |
| 160 |
| 161 void ReceiverPresentationServiceDelegateImpl::SendMessage( |
| 162 int render_process_id, |
| 163 int render_frame_id, |
| 164 const content::PresentationSessionInfo& session_info, |
| 165 std::unique_ptr<content::PresentationSessionMessage> message, |
| 166 const content::SendMessageCallback& send_message_cb) { |
| 167 DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id; |
| 168 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 169 if (rfh_id != current_frame_id_ && !BindToFrame(rfh_id)) { |
| 170 DVLOG(2) << __FUNCTION__ << ": not main frame"; |
| 171 send_message_cb.Run(false); |
| 172 return; |
| 173 } |
| 174 |
| 175 OffscreenPresentationConnection* connection = FindConnection(session_info); |
| 176 if (!connection) { |
| 177 LOG(ERROR) << __FUNCTION__ << ": presentation does not exist."; |
| 178 send_message_cb.Run(false); |
| 179 return; |
| 180 } |
| 181 |
| 182 connection->SendMessage(std::move(message), send_message_cb); |
| 183 } |
| 184 |
| 185 void ReceiverPresentationServiceDelegateImpl::ListenForConnectionStateChange( |
| 186 int render_process_id, |
| 187 int render_frame_id, |
| 188 const content::PresentationSessionInfo& connection, |
| 189 const content::PresentationConnectionStateChangedCallback& |
| 190 state_changed_cb) { |
| 191 DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id; |
| 192 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 193 if (rfh_id != current_frame_id_ && !BindToFrame(rfh_id)) { |
| 194 DVLOG(2) << __FUNCTION__ << ": not main frame"; |
| 195 return; |
| 196 } |
| 197 |
| 198 OffscreenPresentationConnection* offscreen_connection = |
| 199 FindConnection(connection); |
| 200 if (!offscreen_connection) { |
| 201 LOG(ERROR) << __FUNCTION__ << ": presentation does not exist."; |
| 202 return; |
| 203 } |
| 204 |
| 205 offscreen_connection->ListenForStateChange(state_changed_cb); |
| 206 } |
| 207 |
| 208 std::vector<content::PresentationSessionInfo> |
| 209 ReceiverPresentationServiceDelegateImpl::GetReceiverConnections( |
| 210 int render_process_id, |
| 211 int render_frame_id, |
| 212 const content::PresentationSessionStartedCallback& callback) { |
| 213 DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id; |
| 214 RenderFrameHostId rfh_id(render_process_id, render_frame_id); |
| 215 if (rfh_id != current_frame_id_ && !BindToFrame(rfh_id)) { |
| 216 DVLOG(2) << __FUNCTION__ << ": not main frame"; |
| 217 return std::vector<content::PresentationSessionInfo>(); |
| 218 } |
| 219 |
| 220 receiver_available_callback_ = callback; |
| 221 |
| 222 // TODO(imcheng): This is currently broken for the multiple controllers case. |
| 223 // We need additional ID to distinguish between controllers. crbug.com/529911 |
| 224 std::vector<content::PresentationSessionInfo> connections; |
| 225 if (!receiver_connections_.empty()) { |
| 226 connections.push_back( |
| 227 content::PresentationSessionInfo(std::string(), presentation_id_)); |
| 228 } |
| 229 return connections; |
| 230 } |
| 231 |
| 232 ReceiverPresentationServiceDelegateImpl:: |
| 233 ReceiverPresentationServiceDelegateImpl(content::WebContents* web_contents, |
| 234 const std::string& presentation_id) |
| 235 : web_contents_(web_contents), |
| 236 presentation_id_(presentation_id), |
| 237 offscreen_presentation_manager_( |
| 238 OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext( |
| 239 Profile::FromBrowserContext(web_contents_->GetBrowserContext()) |
| 240 ->GetOriginalProfile())) { |
| 241 DCHECK(web_contents_); |
| 242 DCHECK(!presentation_id.empty()); |
| 243 DCHECK(offscreen_presentation_manager_); |
| 244 DCHECK(web_contents_->GetBrowserContext()->IsOffTheRecord()); |
| 245 |
| 246 offscreen_presentation_manager_->RegisterOffscreenPresentationReceiver( |
| 247 presentation_id_, base::Bind(&ReceiverPresentationServiceDelegateImpl:: |
| 248 OnReceiverConnectionAvailable, |
| 249 base::Unretained(this))); |
| 250 } |
| 251 |
| 252 void ReceiverPresentationServiceDelegateImpl::OnReceiverConnectionAvailable( |
| 253 std::unique_ptr<OffscreenPresentationConnection> connection) { |
| 254 // TODO(imcheng): Fix this for the multiple controllers case. |
| 255 if (!receiver_available_callback_.is_null()) |
| 256 receiver_available_callback_.Run( |
| 257 content::PresentationSessionInfo(std::string(), presentation_id_)); |
| 258 |
| 259 receiver_connections_.push_back(std::move(connection)); |
| 260 } |
| 261 |
| 262 bool ReceiverPresentationServiceDelegateImpl::IsMainFrame( |
| 263 const RenderFrameHostId& rfh_id) const { |
| 264 content::RenderFrameHost* render_frame_host = web_contents_->GetMainFrame(); |
| 265 DCHECK(render_frame_host); |
| 266 |
| 267 return rfh_id.first == render_frame_host->GetProcess()->GetID() && |
| 268 rfh_id.second == render_frame_host->GetRoutingID(); |
| 269 } |
| 270 |
| 271 bool ReceiverPresentationServiceDelegateImpl::BindToFrame( |
| 272 const RenderFrameHostId& rfh_id) { |
| 273 if (current_frame_id_ != RenderFrameHostId() || !IsMainFrame(rfh_id)) |
| 274 return false; |
| 275 |
| 276 current_frame_id_ = rfh_id; |
| 277 return true; |
| 278 } |
| 279 |
| 280 OffscreenPresentationConnection* |
| 281 ReceiverPresentationServiceDelegateImpl::FindConnection( |
| 282 const content::PresentationSessionInfo& session_info) { |
| 283 // TODO(imcheng): Need additional information to locate correct connection |
| 284 // in multiple controllers case. crbug.com/529911 |
| 285 if (receiver_connections_.empty()) { |
| 286 DVLOG(2) << "Session not found: " << session_info.presentation_id; |
| 287 return nullptr; |
| 288 } else { |
| 289 return receiver_connections_.front().get(); |
| 290 } |
| 291 } |
| 292 |
| 293 } // namespace media_router |
OLD | NEW |