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 |