Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
|
mark a. foltz
2015/05/11 07:36:21
Copyright
haibinlu
2015/05/13 01:40:19
Done.
| |
| 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/presentation_service_delegate_impl.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/guid.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "base/strings/stringprintf.h" | |
| 12 #include "chrome/browser/media/router/create_session_request.h" | |
| 13 #include "chrome/browser/media/router/media_route.h" | |
| 14 #include "chrome/browser/media/router/media_router.h" | |
| 15 #include "chrome/browser/media/router/media_router_impl.h" | |
|
mark a. foltz
2015/05/11 07:36:21
Why does this class need to know about the MR impl
haibinlu
2015/05/13 01:40:19
removed.
| |
| 16 #include "chrome/browser/media/router/media_router_impl_factory.h" | |
| 17 #include "chrome/browser/media/router/media_sink.h" | |
| 18 #include "chrome/browser/media/router/media_source_helper.h" | |
| 19 #include "chrome/browser/media/router/presentation_helper.h" | |
| 20 #include "chrome/browser/media/router/presentation_media_sinks_observer.h" | |
| 21 #include "chrome/browser/sessions/session_tab_helper.h" | |
| 22 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller.h" | |
| 23 #include "content/public/browser/presentation_screen_availability_listener.h" | |
| 24 #include "content/public/browser/presentation_session.h" | |
| 25 #include "content/public/browser/render_frame_host.h" | |
| 26 #include "content/public/browser/render_process_host.h" | |
| 27 | |
| 28 DEFINE_WEB_CONTENTS_USER_DATA_KEY( | |
| 29 media_router::PresentationServiceDelegateImpl); | |
| 30 | |
| 31 using content::RenderFrameHost; | |
| 32 | |
| 33 namespace media_router { | |
| 34 | |
| 35 PresentationServiceDelegateImpl::PresentationServiceDelegateImpl( | |
| 36 content::WebContents* web_contents) | |
| 37 : num_observers_(0u), | |
| 38 web_contents_(web_contents), | |
| 39 router_(MediaRouterImplFactory::GetMediaRouterForBrowserContext( | |
| 40 web_contents_->GetBrowserContext())), | |
| 41 weak_factory_(this) { | |
| 42 DCHECK(router_); | |
| 43 } | |
| 44 | |
| 45 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() { | |
| 46 DCHECK(observers_.empty()); | |
| 47 DCHECK_EQ(0u, num_observers_); | |
| 48 | |
| 49 for (const auto& delegate_observer_entry : delegate_observers_) | |
| 50 delegate_observer_entry.second->OnDelegateDestroyed(); | |
| 51 } | |
| 52 | |
| 53 void PresentationServiceDelegateImpl::AddObserver( | |
| 54 int render_process_id, | |
| 55 int render_frame_id, | |
| 56 content::PresentationServiceDelegate::Observer* observer) { | |
| 57 DCHECK(observer); | |
| 58 | |
| 59 RenderFrameHostId rfh_id(render_process_id, render_frame_id); | |
| 60 DCHECK(!ContainsKey(delegate_observers_, rfh_id)); | |
| 61 | |
| 62 delegate_observers_[rfh_id] = observer; | |
| 63 } | |
| 64 | |
| 65 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id, | |
| 66 int render_frame_id) { | |
| 67 delegate_observers_.erase( | |
| 68 RenderFrameHostId(render_process_id, render_frame_id)); | |
| 69 } | |
| 70 | |
| 71 MediaSource PresentationServiceDelegateImpl::GetMediaSourceFromListener( | |
| 72 content::PresentationScreenAvailabilityListener* listener) { | |
| 73 // If the default presentation URL is empty then fall back to 1-UA mode, | |
| 74 // i.e. offscreeen tab rendering. | |
| 75 std::string presentation_url(listener->GetPresentationUrl()); | |
| 76 return presentation_url.empty() | |
| 77 ? ForTabMediaSource(SessionTabHelper::IdForTab(web_contents_)) | |
| 78 : ForPresentationUrl(presentation_url); | |
| 79 } | |
| 80 | |
| 81 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener( | |
| 82 int render_process_id, | |
| 83 int routing_id, | |
| 84 content::PresentationScreenAvailabilityListener* listener) { | |
| 85 DCHECK(listener); | |
| 86 | |
| 87 if (num_observers_ >= kMaxNumSources) { | |
| 88 return false; | |
| 89 } | |
| 90 | |
| 91 RenderFrameHostId rfh_id(render_process_id, routing_id); | |
| 92 MediaSource source(GetMediaSourceFromListener(listener)); | |
| 93 auto& observers_for_frame = observers_[rfh_id]; | |
| 94 // Already exists. | |
| 95 if (ContainsKey(observers_for_frame, source.id())) | |
| 96 return false; | |
| 97 | |
| 98 linked_ptr<PresentationMediaSinksObserver> observer( | |
| 99 new PresentationMediaSinksObserver(router_, listener, source)); | |
| 100 observers_for_frame.insert(std::make_pair(source.id(), observer)); | |
| 101 num_observers_++; | |
| 102 return true; | |
| 103 } | |
| 104 | |
| 105 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener( | |
| 106 int render_process_id, | |
| 107 int routing_id, | |
| 108 content::PresentationScreenAvailabilityListener* listener) { | |
| 109 DCHECK(listener); | |
| 110 | |
| 111 RenderFrameHostId rfh_id(render_process_id, routing_id); | |
| 112 MediaSource source(GetMediaSourceFromListener(listener)); | |
| 113 auto it = observers_.find(rfh_id); | |
| 114 if (it != observers_.end()) { | |
| 115 auto& observers_by_id = it->second; | |
| 116 auto observer_it = observers_by_id.find(source.id()); | |
| 117 if (observer_it != observers_by_id.end()) { | |
| 118 observers_by_id.erase(observer_it); | |
| 119 num_observers_--; | |
| 120 | |
| 121 if (observers_by_id.empty()) | |
| 122 observers_.erase(it); | |
| 123 } | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 void PresentationServiceDelegateImpl::Reset(int render_process_id, | |
| 128 int routing_id) { | |
| 129 RenderFrameHostId rfh_id(render_process_id, routing_id); | |
| 130 UnregisterAllObserversFromFrame(rfh_id); | |
| 131 default_presentation_infos_.erase(rfh_id); | |
| 132 if (IsMainFrame(rfh_id)) | |
| 133 UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), std::string()); | |
| 134 } | |
| 135 | |
| 136 void PresentationServiceDelegateImpl::SetDefaultPresentationUrl( | |
| 137 int render_process_id, | |
| 138 int render_frame_id, | |
| 139 const std::string& default_presentation_url, | |
| 140 const std::string& default_presentation_id) { | |
| 141 RenderFrameHostId rfh_id(render_process_id, render_frame_id); | |
| 142 if (default_presentation_url.empty() && default_presentation_id.empty()) { | |
| 143 default_presentation_infos_.erase(rfh_id); | |
| 144 } else { | |
| 145 default_presentation_infos_[rfh_id].reset( | |
| 146 new content::PresentationSessionInfo(default_presentation_url, | |
| 147 default_presentation_id)); | |
| 148 } | |
| 149 | |
| 150 if (IsMainFrame(rfh_id)) { | |
| 151 // This is the main frame, that means tab-level default presentation | |
| 152 // might have been updated. | |
| 153 MediaSource new_default_source; | |
| 154 if (!default_presentation_url.empty()) | |
| 155 new_default_source = ForPresentationUrl(default_presentation_url); | |
| 156 std::string new_default_source_host(GetSourceHostForFrame(rfh_id)); | |
| 157 UpdateDefaultMediaSourceAndNotifyObservers(new_default_source, | |
| 158 new_default_source_host); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 bool PresentationServiceDelegateImpl::IsMainFrame( | |
| 163 RenderFrameHostId rfh_id) const { | |
| 164 RenderFrameHost* main_frame = web_contents_->GetMainFrame(); | |
| 165 return main_frame && GetRenderFrameHostId(main_frame) == rfh_id; | |
| 166 } | |
| 167 | |
| 168 void PresentationServiceDelegateImpl:: | |
| 169 UpdateDefaultMediaSourceAndNotifyObservers( | |
| 170 const MediaSource& new_default_source, | |
| 171 const std::string& new_default_source_host) { | |
| 172 if (!new_default_source.Equals(default_source_) || | |
| 173 new_default_source_host != default_source_host_) { | |
| 174 default_source_ = new_default_source; | |
| 175 default_source_host_ = new_default_source_host; | |
| 176 FOR_EACH_OBSERVER( | |
| 177 DefaultMediaSourceObserver, default_media_source_observers_, | |
| 178 OnDefaultMediaSourceChanged(default_source_, default_source_host_)); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 std::string PresentationServiceDelegateImpl::GetOrGeneratePresentationId( | |
| 183 RenderFrameHostId rfh_id, | |
| 184 const std::string& presentation_id) const { | |
| 185 if (!presentation_id.empty()) | |
| 186 return presentation_id; | |
| 187 | |
| 188 auto it = default_presentation_infos_.find(rfh_id); | |
| 189 if (it != default_presentation_infos_.end()) { | |
| 190 const std::string& default_presentation_id = it->second->presentation_id; | |
| 191 if (!default_presentation_id.empty()) | |
| 192 return default_presentation_id; | |
| 193 } | |
| 194 | |
| 195 return base::GenerateGUID(); | |
| 196 } | |
| 197 | |
| 198 void PresentationServiceDelegateImpl::StartSession( | |
| 199 int render_process_id, | |
| 200 int render_frame_id, | |
| 201 const std::string& presentation_url, | |
| 202 const std::string& presentation_id, | |
| 203 const PresentationSessionSuccessCallback& success_cb, | |
| 204 const PresentationSessionErrorCallback& error_cb) { | |
| 205 if (presentation_url.empty() || !IsValidPresentationUrl(presentation_url)) { | |
| 206 error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, | |
| 207 "Invalid presentation arguments.")); | |
| 208 return; | |
| 209 } | |
| 210 | |
| 211 RenderFrameHostId rfh_id(render_process_id, render_frame_id); | |
| 212 scoped_ptr<CreateSessionRequest> context(new CreateSessionRequest( | |
| 213 presentation_url, GetOrGeneratePresentationId(rfh_id, presentation_id), | |
| 214 GURL(GetSourceHostForFrame(rfh_id)), success_cb, error_cb)); | |
| 215 | |
| 216 // NOTE: Currently this request is ignored if a dialog is already open, e.g. | |
| 217 // via browser action. In practice, this should rarely happen, but log | |
| 218 // an error message in case it does. | |
| 219 MediaRouterDialogController* controller = | |
| 220 MediaRouterDialogController::GetInstance(); | |
| 221 DCHECK(controller); | |
| 222 bool created = controller->ShowMediaRouterDialogForPresentation( | |
| 223 web_contents_, context.Pass()); | |
| 224 if (!created) { | |
| 225 LOG(ERROR) << "Media router dialog already exists. Ignoring StartSession."; | |
| 226 error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, | |
| 227 "Unable to create dialog.")); | |
| 228 return; | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 void PresentationServiceDelegateImpl::JoinSession( | |
| 233 int render_process_id, | |
| 234 int render_frame_id, | |
| 235 const std::string& presentation_url, | |
| 236 const std::string& presentation_id, | |
| 237 const PresentationSessionSuccessCallback& success_cb, | |
| 238 const PresentationSessionErrorCallback& error_cb) { | |
| 239 NOTIMPLEMENTED(); | |
| 240 } | |
| 241 | |
| 242 void PresentationServiceDelegateImpl::ListenForSessionMessages( | |
| 243 int render_process_id, | |
| 244 int render_frame_id, | |
| 245 const PresentationSessionMessageCallback& message_cb) { | |
| 246 NOTIMPLEMENTED(); | |
| 247 } | |
| 248 | |
| 249 void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) { | |
| 250 const MediaSource& source = route.media_source(); | |
| 251 DCHECK(!source.Empty()); | |
| 252 if (default_source_.Equals(source)) { | |
| 253 RenderFrameHost* main_frame = web_contents_->GetMainFrame(); | |
| 254 if (main_frame) { | |
| 255 RenderFrameHostId rfh_id(GetRenderFrameHostId(main_frame)); | |
| 256 auto it = delegate_observers_.find(rfh_id); | |
| 257 if (it != delegate_observers_.end()) { | |
| 258 // TODO(imcheng): Pass in valid default presentation ID once it is | |
| 259 // available from MediaRoute URN. | |
| 260 it->second->OnDefaultPresentationStarted( | |
| 261 content::PresentationSessionInfo(GetPresentationUrl(source), | |
| 262 std::string())); | |
| 263 } | |
| 264 } | |
| 265 } | |
| 266 } | |
| 267 | |
| 268 MediaSource PresentationServiceDelegateImpl::GetDefaultMediaSource() const { | |
| 269 return default_source_; | |
| 270 } | |
| 271 | |
| 272 std::string PresentationServiceDelegateImpl::GetSourceHostForFrame( | |
| 273 RenderFrameHostId rfh_id) const { | |
| 274 RenderFrameHost* rfh = RenderFrameHost::FromID(rfh_id.first, rfh_id.second); | |
| 275 DCHECK(rfh); | |
| 276 std::string host = rfh->GetLastCommittedURL().host(); | |
| 277 if (StartsWithASCII(host, "www.", false)) | |
| 278 host = host.substr(4); | |
| 279 return host; | |
| 280 } | |
| 281 | |
| 282 void PresentationServiceDelegateImpl::UnregisterAllObserversFromFrame( | |
| 283 RenderFrameHostId rfh_id) { | |
| 284 auto it = observers_.find(rfh_id); | |
| 285 if (it != observers_.end()) { | |
| 286 auto& observers_by_id = it->second; | |
| 287 num_observers_ -= observers_by_id.size(); | |
| 288 observers_.erase(it); | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver( | |
| 293 DefaultMediaSourceObserver* observer) { | |
| 294 default_media_source_observers_.AddObserver(observer); | |
| 295 } | |
| 296 | |
| 297 void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver( | |
| 298 DefaultMediaSourceObserver* observer) { | |
| 299 default_media_source_observers_.RemoveObserver(observer); | |
| 300 } | |
| 301 | |
| 302 void PresentationServiceDelegateImpl::SetMediaRouterForTest( | |
| 303 MediaRouter* router) { | |
| 304 router_ = router; | |
| 305 } | |
| 306 | |
| 307 // static | |
| 308 PresentationServiceDelegateImpl::RenderFrameHostId | |
| 309 PresentationServiceDelegateImpl::GetRenderFrameHostId(RenderFrameHost* rfh) { | |
| 310 int render_process_id = rfh->GetProcess()->GetID(); | |
| 311 int routing_id = rfh->GetRoutingID(); | |
| 312 return RenderFrameHostId(render_process_id, routing_id); | |
| 313 } | |
| 314 | |
| 315 base::WeakPtr<PresentationServiceDelegateImpl> | |
| 316 PresentationServiceDelegateImpl::GetWeakPtr() { | |
| 317 return weak_factory_.GetWeakPtr(); | |
| 318 } | |
| 319 | |
| 320 } // namespace media_router | |
| OLD | NEW |