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/offscreen_presentation_manager.h" |
| 6 |
| 7 #include "base/memory/ptr_util.h" |
| 8 #include "content/public/browser/render_frame_host.h" |
| 9 #include "content/public/browser/render_process_host.h" |
| 10 #include "content/public/browser/web_contents.h" |
| 11 |
| 12 namespace media_router { |
| 13 |
| 14 // OffscreenPresentationConnection implementation. |
| 15 // //////////////////////////////// |
| 16 |
| 17 OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 18 OffscreenPresentationConnection( |
| 19 OffscreenPresentationManager::OffscreenPresentationSession* session) |
| 20 : session_(session) { |
| 21 DCHECK(session_); |
| 22 } |
| 23 |
| 24 OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 25 ~OffscreenPresentationConnection() { |
| 26 if (session_) { |
| 27 content::PresentationConnectionStateChangeInfo remove_reason( |
| 28 content::PRESENTATION_CONNECTION_STATE_CLOSED); |
| 29 remove_reason.close_reason = |
| 30 content::PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY; |
| 31 session_->RemoveConnection(this, remove_reason); |
| 32 } |
| 33 } |
| 34 |
| 35 void OffscreenPresentationManager::OffscreenPresentationConnection::SendMessage( |
| 36 std::unique_ptr<content::PresentationSessionMessage> message, |
| 37 const content::SendMessageCallback& callback) { |
| 38 if (!session_) { |
| 39 callback.Run(false); |
| 40 return; |
| 41 } |
| 42 |
| 43 session_->SendMessageFrom(this, std::move(message), callback); |
| 44 } |
| 45 |
| 46 void OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 47 ListenForMessages( |
| 48 const content::PresentationSessionMessageCallback& callback) { |
| 49 DCHECK(messages_callback_.is_null()); |
| 50 DCHECK(!callback.is_null()); |
| 51 messages_callback_ = callback; |
| 52 } |
| 53 |
| 54 void OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 55 ListenForStateChange( |
| 56 const content::PresentationConnectionStateChangedCallback& callback) { |
| 57 DCHECK(state_change_callback_.is_null()); |
| 58 DCHECK(!state_change_callback_.is_null()); |
| 59 state_change_callback_ = callback; |
| 60 } |
| 61 |
| 62 void OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 63 RemoveFromPresentation( |
| 64 const content::PresentationConnectionStateChangeInfo& remove_reason) { |
| 65 if (session_) { |
| 66 session_->RemoveConnection(this, remove_reason); |
| 67 session_ = nullptr; |
| 68 } |
| 69 } |
| 70 |
| 71 void OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 72 OnConnectionStateChanged( |
| 73 const content::PresentationConnectionStateChangeInfo& info) { |
| 74 if (!state_change_callback_.is_null()) |
| 75 state_change_callback_.Run(info); |
| 76 |
| 77 if (info.state == content::PRESENTATION_CONNECTION_STATE_CLOSED || |
| 78 info.state == content::PRESENTATION_CONNECTION_STATE_TERMINATED) { |
| 79 session_ = nullptr; |
| 80 } |
| 81 } |
| 82 |
| 83 void OffscreenPresentationManager::OffscreenPresentationConnection:: |
| 84 OnMessageReceived( |
| 85 std::unique_ptr<content::PresentationSessionMessage> message) { |
| 86 if (messages_callback_.is_null()) |
| 87 return; |
| 88 |
| 89 // TODO(imcheng): Implement message queueing/batching. |
| 90 ScopedVector<content::PresentationSessionMessage> messages; |
| 91 messages.push_back(std::move(message)); |
| 92 messages_callback_.Run(messages, true); |
| 93 } |
| 94 |
| 95 // OffscreenPresentationManager implementation. //////////////////////////////// |
| 96 |
| 97 OffscreenPresentationManager::~OffscreenPresentationManager() {} |
| 98 |
| 99 void OffscreenPresentationManager::RegisterOffscreenPresentationReceiver( |
| 100 const std::string& presentation_id, |
| 101 const ReceiverConnectionAvailableCallback& receiver_available_callback) { |
| 102 DCHECK(!ContainsKey(offscreen_presentations_, presentation_id)); |
| 103 |
| 104 offscreen_presentations_.insert( |
| 105 std::make_pair(presentation_id, |
| 106 base::WrapUnique(new OffscreenPresentation( |
| 107 presentation_id, receiver_available_callback, this)))); |
| 108 } |
| 109 |
| 110 void OffscreenPresentationManager::UnregisterOffscreenPresentationReceiver( |
| 111 const std::string& presentation_id) { |
| 112 DCHECK(ContainsKey(offscreen_presentations_, presentation_id)); |
| 113 offscreen_presentations_.erase(presentation_id); |
| 114 } |
| 115 |
| 116 std::unique_ptr<OffscreenPresentationManager::OffscreenPresentationConnection> |
| 117 OffscreenPresentationManager::ConnectToOffscreenPresentation( |
| 118 const std::string& presentation_id, |
| 119 const RenderFrameHostId& controller_frame_id) { |
| 120 auto it = offscreen_presentations_.find(presentation_id); |
| 121 if (it == offscreen_presentations_.end()) |
| 122 return std::unique_ptr<OffscreenPresentationConnection>(); |
| 123 |
| 124 return it->second->AddSession(controller_frame_id); |
| 125 } |
| 126 |
| 127 OffscreenPresentationManager::OffscreenPresentationManager() {} |
| 128 |
| 129 // OffscreenPresentationSession implementation. ///////////////////////////// |
| 130 |
| 131 OffscreenPresentationManager::OffscreenPresentationSession:: |
| 132 OffscreenPresentationSession(const RenderFrameHostId& controller_frame_id, |
| 133 OffscreenPresentation* presentation) |
| 134 : controller_frame_id_(controller_frame_id), |
| 135 presentation_(presentation), |
| 136 controller_(nullptr), |
| 137 receiver_(nullptr) { |
| 138 DCHECK(presentation_); |
| 139 } |
| 140 |
| 141 void OffscreenPresentationManager::OffscreenPresentationSession::Init( |
| 142 OffscreenPresentationManager::OffscreenPresentationConnection* controller, |
| 143 OffscreenPresentationManager::OffscreenPresentationConnection* receiver) { |
| 144 DCHECK(!controller_); |
| 145 DCHECK(!receiver_); |
| 146 DCHECK(controller); |
| 147 DCHECK(receiver); |
| 148 controller_ = controller; |
| 149 receiver_ = receiver; |
| 150 } |
| 151 |
| 152 OffscreenPresentationManager::OffscreenPresentationSession:: |
| 153 ~OffscreenPresentationSession() { |
| 154 DCHECK(!controller_ || !receiver_); |
| 155 } |
| 156 |
| 157 void OffscreenPresentationManager::OffscreenPresentationSession:: |
| 158 RemoveConnection( |
| 159 OffscreenPresentationConnection* connection, |
| 160 const content::PresentationConnectionStateChangeInfo& remove_reason) { |
| 161 DCHECK(connection); |
| 162 OffscreenPresentationConnection* other_connection = nullptr; |
| 163 if (connection == controller_) { |
| 164 controller_ = nullptr; |
| 165 other_connection = receiver_; |
| 166 } else { |
| 167 DCHECK(connection == receiver_); |
| 168 receiver_ = nullptr; |
| 169 other_connection = controller_; |
| 170 } |
| 171 |
| 172 DCHECK(other_connection); |
| 173 other_connection->OnConnectionStateChanged(remove_reason); |
| 174 presentation_->RemoveSession(controller_frame_id_); |
| 175 // |this| is deleted beyond this point. |
| 176 } |
| 177 |
| 178 void OffscreenPresentationManager::OffscreenPresentationSession:: |
| 179 SendMessageFrom( |
| 180 OffscreenPresentationConnection* connection, |
| 181 std::unique_ptr<content::PresentationSessionMessage> message, |
| 182 const content::SendMessageCallback& callback) { |
| 183 OffscreenPresentationConnection* other_connection = |
| 184 connection == controller_ ? receiver_ : controller_; |
| 185 DCHECK(other_connection); |
| 186 |
| 187 other_connection->OnMessageReceived(std::move(message)); |
| 188 callback.Run(true); |
| 189 } |
| 190 |
| 191 // OffscreenPresentation implementation. /////////////////////////////////////// |
| 192 |
| 193 OffscreenPresentationManager::OffscreenPresentation::OffscreenPresentation( |
| 194 const std::string& presentation_id, |
| 195 const ReceiverConnectionAvailableCallback& receiver_available_callback, |
| 196 OffscreenPresentationManager* manager) |
| 197 : presentation_id_(presentation_id), |
| 198 receiver_available_callback_(receiver_available_callback), |
| 199 manager_(manager) { |
| 200 DCHECK(!receiver_available_callback_.is_null()); |
| 201 DCHECK(manager_); |
| 202 } |
| 203 |
| 204 OffscreenPresentationManager::OffscreenPresentation::~OffscreenPresentation() { |
| 205 // The receiver must have destroyed all connections before unregistration. |
| 206 DCHECK(sessions_.empty()); |
| 207 } |
| 208 |
| 209 std::unique_ptr<OffscreenPresentationManager::OffscreenPresentationConnection> |
| 210 OffscreenPresentationManager::OffscreenPresentation::AddSession( |
| 211 const RenderFrameHostId& controller_frame_id) { |
| 212 if (ContainsKey(sessions_, controller_frame_id)) { |
| 213 DLOG(ERROR) << "Frame " << controller_frame_id.first << ", " |
| 214 << controller_frame_id.second << " already registered as a " |
| 215 << "controller for presentation " << presentation_id_; |
| 216 return std::unique_ptr<OffscreenPresentationConnection>(); |
| 217 } |
| 218 |
| 219 std::unique_ptr<OffscreenPresentationSession> session( |
| 220 new OffscreenPresentationSession(controller_frame_id, this)); |
| 221 std::unique_ptr<OffscreenPresentationConnection> controller_connection( |
| 222 new OffscreenPresentationConnection(session.get())); |
| 223 std::unique_ptr<OffscreenPresentationConnection> receiver_connection( |
| 224 new OffscreenPresentationConnection(session.get())); |
| 225 |
| 226 session->Init(controller_connection.get(), receiver_connection.get()); |
| 227 sessions_.insert(std::make_pair(controller_frame_id, std::move(session))); |
| 228 receiver_available_callback_.Run(std::move(receiver_connection)); |
| 229 return controller_connection; |
| 230 } |
| 231 |
| 232 void OffscreenPresentationManager::OffscreenPresentation::RemoveSession( |
| 233 const RenderFrameHostId& controller_frame_id) { |
| 234 DCHECK(ContainsKey(sessions_, controller_frame_id)); |
| 235 sessions_.erase(controller_frame_id); |
| 236 } |
| 237 |
| 238 } // namespace media_router |
OLD | NEW |