OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/presentation/presentation_service_impl.h" | 5 #include "content/browser/presentation/presentation_service_impl.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "content/browser/presentation/presentation_type_converters.h" | 10 #include "content/browser/presentation/presentation_type_converters.h" |
9 #include "content/public/browser/content_browser_client.h" | 11 #include "content/public/browser/content_browser_client.h" |
10 #include "content/public/browser/navigation_details.h" | 12 #include "content/public/browser/navigation_details.h" |
11 #include "content/public/browser/render_frame_host.h" | 13 #include "content/public/browser/render_frame_host.h" |
12 #include "content/public/browser/render_process_host.h" | 14 #include "content/public/browser/render_process_host.h" |
13 #include "content/public/browser/web_contents.h" | 15 #include "content/public/browser/web_contents.h" |
14 #include "content/public/common/content_client.h" | 16 #include "content/public/common/content_client.h" |
15 #include "content/public/common/frame_navigate_params.h" | 17 #include "content/public/common/frame_navigate_params.h" |
16 | 18 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 it = availability_contexts_.insert( | 81 it = availability_contexts_.insert( |
80 std::make_pair(context->GetPresentationUrl(), context)).first; | 82 std::make_pair(context->GetPresentationUrl(), context)).first; |
81 } | 83 } |
82 return it->second.get(); | 84 return it->second.get(); |
83 } | 85 } |
84 | 86 |
85 void PresentationServiceImpl::GetScreenAvailability( | 87 void PresentationServiceImpl::GetScreenAvailability( |
86 const mojo::String& presentation_url, | 88 const mojo::String& presentation_url, |
87 const ScreenAvailabilityMojoCallback& callback) { | 89 const ScreenAvailabilityMojoCallback& callback) { |
88 DVLOG(2) << "GetScreenAvailability"; | 90 DVLOG(2) << "GetScreenAvailability"; |
89 if (!delegate_) | 91 if (!delegate_) { |
| 92 callback.Run(presentation_url, false); |
90 return; | 93 return; |
| 94 } |
91 | 95 |
92 ScreenAvailabilityContext* context = | 96 ScreenAvailabilityContext* context = |
93 GetOrCreateAvailabilityContext(presentation_url.get()); | 97 GetOrCreateAvailabilityContext(presentation_url.get()); |
94 if (!context) | 98 if (!context) { |
| 99 callback.Run(presentation_url, false); |
95 return; | 100 return; |
| 101 } |
96 context->CallbackReceived(callback); | 102 context->CallbackReceived(callback); |
97 } | 103 } |
98 | 104 |
99 void PresentationServiceImpl::OnScreenAvailabilityListenerRemoved( | 105 void PresentationServiceImpl::OnScreenAvailabilityListenerRemoved( |
100 const mojo::String& presentation_url) { | 106 const mojo::String& presentation_url) { |
101 DVLOG(2) << "OnScreenAvailabilityListenerRemoved"; | 107 DVLOG(2) << "OnScreenAvailabilityListenerRemoved"; |
102 if (!delegate_) | 108 if (!delegate_) |
103 return; | 109 return; |
104 | 110 |
105 const std::string& presentation_url_str = presentation_url.get(); | 111 const std::string& presentation_url_str = presentation_url.get(); |
106 auto it = availability_contexts_.find(presentation_url_str); | 112 auto it = availability_contexts_.find(presentation_url_str); |
107 if (it == availability_contexts_.end()) | 113 if (it == availability_contexts_.end()) |
108 return; | 114 return; |
109 | 115 |
110 delegate_->RemoveScreenAvailabilityListener( | 116 delegate_->RemoveScreenAvailabilityListener( |
111 render_frame_host_->GetProcess()->GetID(), | 117 render_frame_host_->GetProcess()->GetID(), |
112 render_frame_host_->GetRoutingID(), | 118 render_frame_host_->GetRoutingID(), |
113 it->second.get()); | 119 it->second.get()); |
| 120 // Resolve the context's pending callbacks before removing it. |
| 121 it->second->OnScreenAvailabilityChanged(false); |
114 availability_contexts_.erase(it); | 122 availability_contexts_.erase(it); |
115 } | 123 } |
116 | 124 |
117 void PresentationServiceImpl::ListenForDefaultSessionStart( | 125 void PresentationServiceImpl::ListenForDefaultSessionStart( |
118 const DefaultSessionMojoCallback& callback) { | 126 const DefaultSessionMojoCallback& callback) { |
119 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
120 } | 128 } |
121 | 129 |
122 void PresentationServiceImpl::StartSession( | 130 void PresentationServiceImpl::StartSession( |
123 const mojo::String& presentation_url, | 131 const mojo::String& presentation_url, |
124 const mojo::String& presentation_id, | 132 const mojo::String& presentation_id, |
125 const NewSessionMojoCallback& callback) { | 133 const NewSessionMojoCallback& callback) { |
126 DVLOG(2) << "StartSession"; | 134 DVLOG(2) << "StartSession"; |
127 if (!delegate_) | 135 if (!delegate_) { |
| 136 callback.Run( |
| 137 presentation::PresentationSessionInfoPtr(), |
| 138 presentation::PresentationError::From( |
| 139 PresentationError(PRESENTATION_ERROR_UNKNOWN, ""))); |
128 return; | 140 return; |
| 141 } |
129 | 142 |
130 queued_start_session_requests_.push_back(make_linked_ptr( | 143 queued_start_session_requests_.push_back(make_linked_ptr( |
131 new StartSessionRequest(presentation_url, presentation_id, callback))); | 144 new StartSessionRequest(presentation_url, presentation_id, callback))); |
132 if (queued_start_session_requests_.size() == 1) | 145 if (queued_start_session_requests_.size() == 1) |
133 DoStartSession(presentation_url, presentation_id, callback); | 146 DoStartSession(presentation_url, presentation_id, callback); |
134 } | 147 } |
135 | 148 |
136 void PresentationServiceImpl::JoinSession( | 149 void PresentationServiceImpl::JoinSession( |
137 const mojo::String& presentation_url, | 150 const mojo::String& presentation_url, |
138 const mojo::String& presentation_id, | 151 const mojo::String& presentation_id, |
139 const NewSessionMojoCallback& callback) { | 152 const NewSessionMojoCallback& callback) { |
140 DVLOG(2) << "JoinSession"; | 153 DVLOG(2) << "JoinSession"; |
141 if (!delegate_) | 154 if (!delegate_) { |
| 155 callback.Run( |
| 156 presentation::PresentationSessionInfoPtr(), |
| 157 presentation::PresentationError::From( |
| 158 PresentationError(PRESENTATION_ERROR_UNKNOWN, ""))); |
142 return; | 159 return; |
| 160 } |
143 | 161 |
144 delegate_->JoinSession( | 162 delegate_->JoinSession( |
145 render_frame_host_->GetProcess()->GetID(), | 163 render_frame_host_->GetProcess()->GetID(), |
146 render_frame_host_->GetRoutingID(), | 164 render_frame_host_->GetRoutingID(), |
147 presentation_url, | 165 presentation_url, |
148 presentation_id, | 166 presentation_id, |
| 167 // TODO(imcheng): These callbacks may be dropped. http://crbug.com/468575 |
149 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, | 168 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, |
150 weak_factory_.GetWeakPtr(), false, callback), | 169 weak_factory_.GetWeakPtr(), false, callback), |
151 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError, | 170 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError, |
152 weak_factory_.GetWeakPtr(), false, callback)); | 171 weak_factory_.GetWeakPtr(), false, callback)); |
153 } | 172 } |
154 | 173 |
155 void PresentationServiceImpl::HandleQueuedStartSessionRequests() { | 174 void PresentationServiceImpl::HandleQueuedStartSessionRequests() { |
156 DCHECK(!queued_start_session_requests_.empty()); | 175 DCHECK(!queued_start_session_requests_.empty()); |
157 queued_start_session_requests_.pop_front(); | 176 queued_start_session_requests_.pop_front(); |
158 if (!queued_start_session_requests_.empty()) { | 177 if (!queued_start_session_requests_.empty()) { |
159 const linked_ptr<StartSessionRequest>& request = | 178 const linked_ptr<StartSessionRequest>& request = |
160 queued_start_session_requests_.front(); | 179 queued_start_session_requests_.front(); |
161 DoStartSession(request->presentation_url, | 180 DoStartSession(request->presentation_url, |
162 request->presentation_id, | 181 request->presentation_id, |
163 request->callback); | 182 request->callback); |
164 } | 183 } |
165 } | 184 } |
166 | 185 |
167 void PresentationServiceImpl::DoStartSession( | 186 void PresentationServiceImpl::DoStartSession( |
168 const std::string& presentation_url, | 187 const std::string& presentation_url, |
169 const std::string& presentation_id, | 188 const std::string& presentation_id, |
170 const NewSessionMojoCallback& callback) { | 189 const NewSessionMojoCallback& callback) { |
171 delegate_->StartSession( | 190 delegate_->StartSession( |
172 render_frame_host_->GetProcess()->GetID(), | 191 render_frame_host_->GetProcess()->GetID(), |
173 render_frame_host_->GetRoutingID(), | 192 render_frame_host_->GetRoutingID(), |
174 presentation_url, | 193 presentation_url, |
175 presentation_id, | 194 presentation_id, |
| 195 // TODO(imcheng): These callbacks may be dropped. http://crbug.com/468575 |
176 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, | 196 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, |
177 weak_factory_.GetWeakPtr(), true, callback), | 197 weak_factory_.GetWeakPtr(), true, callback), |
178 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError, | 198 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError, |
179 weak_factory_.GetWeakPtr(), true, callback)); | 199 weak_factory_.GetWeakPtr(), true, callback)); |
180 } | 200 } |
181 | 201 |
182 void PresentationServiceImpl::OnStartOrJoinSessionSucceeded( | 202 void PresentationServiceImpl::OnStartOrJoinSessionSucceeded( |
183 bool is_start_session, | 203 bool is_start_session, |
184 const NewSessionMojoCallback& callback, | 204 const NewSessionMojoCallback& callback, |
185 const PresentationSessionInfo& session_info) { | 205 const PresentationSessionInfo& session_info) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 } | 251 } |
232 | 252 |
233 auto old_it = availability_contexts_.find(old_default_url); | 253 auto old_it = availability_contexts_.find(old_default_url); |
234 // Haven't started listening yet. | 254 // Haven't started listening yet. |
235 if (old_it == availability_contexts_.end()) { | 255 if (old_it == availability_contexts_.end()) { |
236 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); | 256 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); |
237 return; | 257 return; |
238 } | 258 } |
239 | 259 |
240 // Have already started listening. Create a listener for the new URL and | 260 // Have already started listening. Create a listener for the new URL and |
241 // transfer the callback from the old listener, if any. | 261 // transfer the callbacks from the old listener, if any. |
242 // This is done so that a listener added before default URL is changed | 262 // This is done so that a listener added before default URL is changed |
243 // will continue to work. | 263 // will continue to work. |
244 ScreenAvailabilityMojoCallback* old_callback = old_it->second->GetCallback(); | |
245 ScreenAvailabilityContext* context = | 264 ScreenAvailabilityContext* context = |
246 GetOrCreateAvailabilityContext(new_default_url); | 265 GetOrCreateAvailabilityContext(new_default_url); |
247 if (old_callback) | 266 old_it->second->PassPendingCallbacks(context); |
248 context->CallbackReceived(*old_callback); | |
249 | 267 |
250 // Remove listener for old default presentation URL. | 268 // Remove listener for old default presentation URL. |
251 delegate_->RemoveScreenAvailabilityListener( | 269 delegate_->RemoveScreenAvailabilityListener( |
252 render_frame_host_->GetProcess()->GetID(), | 270 render_frame_host_->GetProcess()->GetID(), |
253 render_frame_host_->GetRoutingID(), | 271 render_frame_host_->GetRoutingID(), |
254 old_it->second.get()); | 272 old_it->second.get()); |
255 availability_contexts_.erase(old_it); | 273 availability_contexts_.erase(old_it); |
256 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); | 274 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); |
257 } | 275 } |
258 | 276 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 void PresentationServiceImpl::Reset() { | 314 void PresentationServiceImpl::Reset() { |
297 DVLOG(2) << "PresentationServiceImpl::Reset"; | 315 DVLOG(2) << "PresentationServiceImpl::Reset"; |
298 if (delegate_) { | 316 if (delegate_) { |
299 delegate_->Reset( | 317 delegate_->Reset( |
300 render_frame_host_->GetProcess()->GetID(), | 318 render_frame_host_->GetProcess()->GetID(), |
301 render_frame_host_->GetRoutingID()); | 319 render_frame_host_->GetRoutingID()); |
302 } | 320 } |
303 | 321 |
304 default_presentation_url_.clear(); | 322 default_presentation_url_.clear(); |
305 default_presentation_id_.clear(); | 323 default_presentation_id_.clear(); |
| 324 for (const auto& context : availability_contexts_) { |
| 325 context.second->OnScreenAvailabilityChanged(false); |
| 326 } |
306 availability_contexts_.clear(); | 327 availability_contexts_.clear(); |
| 328 // TODO(imcheng): This may drop callbacks. See http://crbug.com/468575. |
307 queued_start_session_requests_.clear(); | 329 queued_start_session_requests_.clear(); |
308 } | 330 } |
309 | 331 |
310 void PresentationServiceImpl::OnDelegateDestroyed() { | 332 void PresentationServiceImpl::OnDelegateDestroyed() { |
311 DVLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed"; | 333 DVLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed"; |
312 delegate_ = nullptr; | 334 delegate_ = nullptr; |
313 Reset(); | 335 Reset(); |
314 } | 336 } |
315 | 337 |
316 PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext( | 338 PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext( |
317 const std::string& presentation_url) | 339 const std::string& presentation_url) |
318 : presentation_url_(presentation_url) { | 340 : presentation_url_(presentation_url) { |
319 } | 341 } |
320 | 342 |
321 PresentationServiceImpl::ScreenAvailabilityContext:: | 343 PresentationServiceImpl::ScreenAvailabilityContext:: |
322 ~ScreenAvailabilityContext() { | 344 ~ScreenAvailabilityContext() { |
323 } | 345 } |
324 | 346 |
325 void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived( | 347 void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived( |
326 const ScreenAvailabilityMojoCallback& callback) { | 348 const ScreenAvailabilityMojoCallback& callback) { |
327 // NOTE: This will overwrite previously registered callback if any. | 349 // NOTE: This will overwrite previously registered callback if any. |
328 if (!available_ptr_) { | 350 if (!available_ptr_) { |
329 // No results yet, store callback for later invocation. | 351 // No results yet, store callback for later invocation. |
330 callback_ptr_.reset(new ScreenAvailabilityMojoCallback(callback)); | 352 callbacks_.push_back(new ScreenAvailabilityMojoCallback(callback)); |
331 } else { | 353 } else { |
332 // Run callback now, reset result. | 354 // Run callback now, reset result. |
333 // There shouldn't be any callbacks stored in this scenario. | 355 // There shouldn't be any callbacks stored in this scenario. |
334 DCHECK(!callback_ptr_); | 356 DCHECK(!HasPendingCallbacks()); |
335 callback.Run(presentation_url_, *available_ptr_); | 357 callback.Run(presentation_url_, *available_ptr_); |
336 Reset(); | 358 available_ptr_.reset(); |
337 } | 359 } |
338 } | 360 } |
339 | 361 |
340 void PresentationServiceImpl::ScreenAvailabilityContext::Reset() { | |
341 callback_ptr_.reset(); | |
342 available_ptr_.reset(); | |
343 } | |
344 | |
345 std::string PresentationServiceImpl::ScreenAvailabilityContext | 362 std::string PresentationServiceImpl::ScreenAvailabilityContext |
346 ::GetPresentationUrl() const { | 363 ::GetPresentationUrl() const { |
347 return presentation_url_; | 364 return presentation_url_; |
348 } | 365 } |
349 | 366 |
350 void PresentationServiceImpl::ScreenAvailabilityContext | 367 void PresentationServiceImpl::ScreenAvailabilityContext |
351 ::OnScreenAvailabilityChanged(bool available) { | 368 ::OnScreenAvailabilityChanged(bool available) { |
352 if (!callback_ptr_) { | 369 if (!HasPendingCallbacks()) { |
353 // No callback, stash the result for now. | 370 // No callback, stash the result for now. |
354 available_ptr_.reset(new bool(available)); | 371 available_ptr_.reset(new bool(available)); |
355 } else { | 372 } else { |
356 // Invoke callback and erase it. | 373 // Invoke callbacks and erase them. |
357 // There shouldn't be any result stored in this scenario. | 374 // There shouldn't be any result stored in this scenario. |
358 DCHECK(!available_ptr_); | 375 DCHECK(!available_ptr_); |
359 callback_ptr_->Run(presentation_url_, available); | 376 ScopedVector<ScreenAvailabilityMojoCallback> callbacks; |
360 Reset(); | 377 callbacks.swap(callbacks_); |
| 378 for (const auto& callback : callbacks) |
| 379 callback->Run(presentation_url_, available); |
361 } | 380 } |
362 } | 381 } |
363 | 382 |
364 PresentationServiceImpl::ScreenAvailabilityMojoCallback* | 383 void PresentationServiceImpl::ScreenAvailabilityContext |
365 PresentationServiceImpl::ScreenAvailabilityContext::GetCallback() const { | 384 ::PassPendingCallbacks( |
366 return callback_ptr_.get(); | 385 PresentationServiceImpl::ScreenAvailabilityContext* other) { |
| 386 std::vector<ScreenAvailabilityMojoCallback*> callbacks; |
| 387 callbacks_.release(&callbacks); |
| 388 std::copy(callbacks.begin(), callbacks.end(), |
| 389 std::back_inserter(other->callbacks_)); |
| 390 } |
| 391 |
| 392 bool PresentationServiceImpl::ScreenAvailabilityContext |
| 393 ::HasPendingCallbacks() const { |
| 394 return !callbacks_.empty(); |
367 } | 395 } |
368 | 396 |
369 PresentationServiceImpl::StartSessionRequest::StartSessionRequest( | 397 PresentationServiceImpl::StartSessionRequest::StartSessionRequest( |
370 const std::string& presentation_url, | 398 const std::string& presentation_url, |
371 const std::string& presentation_id, | 399 const std::string& presentation_id, |
372 const NewSessionMojoCallback& callback) | 400 const NewSessionMojoCallback& callback) |
373 : presentation_url(presentation_url), | 401 : presentation_url(presentation_url), |
374 presentation_id(presentation_id), | 402 presentation_id(presentation_id), |
375 callback(callback) { | 403 callback(callback) { |
376 } | 404 } |
377 | 405 |
378 PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() { | 406 PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() { |
379 } | 407 } |
380 | 408 |
381 } // namespace content | 409 } // namespace content |
| 410 |
OLD | NEW |