Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: content/browser/presentation/presentation_service_impl.cc

Issue 979413002: [Presentation API] Additional plumbing for PresentationServiceImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@REAL-NEW-MASTER
Patch Set: Get rid of RunLoopUntilIdle Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/logging.h" 7 #include "base/logging.h"
8 #include "content/browser/presentation/presentation_type_converters.h"
8 #include "content/public/browser/content_browser_client.h" 9 #include "content/public/browser/content_browser_client.h"
9 #include "content/public/browser/navigation_details.h" 10 #include "content/public/browser/navigation_details.h"
10 #include "content/public/browser/render_frame_host.h" 11 #include "content/public/browser/render_frame_host.h"
11 #include "content/public/browser/render_process_host.h" 12 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/web_contents.h" 13 #include "content/public/browser/web_contents.h"
13 #include "content/public/common/content_client.h" 14 #include "content/public/common/content_client.h"
14 #include "content/public/common/frame_navigate_params.h" 15 #include "content/public/common/frame_navigate_params.h"
15 16
16 namespace content { 17 namespace content {
17 18
18 PresentationServiceImpl::PresentationServiceImpl( 19 PresentationServiceImpl::PresentationServiceImpl(
19 RenderFrameHost* render_frame_host, 20 RenderFrameHost* render_frame_host,
20 WebContents* web_contents, 21 WebContents* web_contents,
21 PresentationServiceDelegate* delegate) 22 PresentationServiceDelegate* delegate)
22 : WebContentsObserver(web_contents), 23 : WebContentsObserver(web_contents),
23 render_frame_host_(render_frame_host), 24 render_frame_host_(render_frame_host),
24 delegate_(delegate) { 25 delegate_(delegate),
26 weak_factory_(this) {
25 DCHECK(render_frame_host_); 27 DCHECK(render_frame_host_);
26 DCHECK(web_contents); 28 DCHECK(web_contents);
27 VLOG(2) << "PresentationServiceImpl: " 29 DVLOG(2) << "PresentationServiceImpl: "
28 << render_frame_host_->GetProcess()->GetID() << ", " 30 << render_frame_host_->GetProcess()->GetID() << ", "
29 << render_frame_host_->GetRoutingID(); 31 << render_frame_host_->GetRoutingID();
30 if (delegate_) 32 if (delegate_)
31 delegate_->AddObserver(this); 33 delegate_->AddObserver(this);
32 } 34 }
33 35
34 PresentationServiceImpl::~PresentationServiceImpl() { 36 PresentationServiceImpl::~PresentationServiceImpl() {
35 if (delegate_) 37 if (delegate_)
36 delegate_->RemoveObserver(this); 38 delegate_->RemoveObserver(this);
37 } 39 }
38 40
39 // static 41 // static
40 void PresentationServiceImpl::CreateMojoService( 42 void PresentationServiceImpl::CreateMojoService(
41 RenderFrameHost* render_frame_host, 43 RenderFrameHost* render_frame_host,
42 mojo::InterfaceRequest<presentation::PresentationService> request) { 44 mojo::InterfaceRequest<presentation::PresentationService> request) {
43 VLOG(2) << "PresentationServiceImpl::CreateService"; 45 DVLOG(2) << "CreateMojoService";
44 WebContents* web_contents = 46 WebContents* web_contents =
45 WebContents::FromRenderFrameHost(render_frame_host); 47 WebContents::FromRenderFrameHost(render_frame_host);
46 DCHECK(web_contents); 48 DCHECK(web_contents);
47 49
48 mojo::BindToRequest( 50 mojo::BindToRequest(
49 new PresentationServiceImpl( 51 new PresentationServiceImpl(
50 render_frame_host, 52 render_frame_host,
51 web_contents, 53 web_contents,
52 GetContentClient()->browser()->GetPresentationServiceDelegate( 54 GetContentClient()->browser()->GetPresentationServiceDelegate(
53 web_contents)), 55 web_contents)),
54 &request); 56 &request);
55 } 57 }
56 58
57 void PresentationServiceImpl::OnConnectionError() { 59 void PresentationServiceImpl::OnConnectionError() {
58 VLOG(1) << "PresentationServiceImpl::OnConnectionError: " 60 DVLOG(1) << "OnConnectionError: "
59 << render_frame_host_->GetProcess()->GetID() << ", " 61 << render_frame_host_->GetProcess()->GetID() << ", "
60 << render_frame_host_->GetRoutingID(); 62 << render_frame_host_->GetRoutingID();
61 } 63 }
62 64
63 void PresentationServiceImpl::SetDefaultPresentationURL( 65 PresentationServiceImpl::ScreenAvailabilityContext*
64 const mojo::String& presentation_url, 66 PresentationServiceImpl::GetOrCreateAvailabilityContext(
65 const mojo::String& presentation_id) { 67 const std::string& presentation_url) {
66 NOTIMPLEMENTED(); 68 auto it = availability_contexts_.find(presentation_url);
69 if (it == availability_contexts_.end()) {
mark a. foltz 2015/03/18 00:10:58 Indentation
imcheng 2015/03/18 00:56:53 Done.
70 linked_ptr<ScreenAvailabilityContext> context(
71 new ScreenAvailabilityContext(presentation_url));
72 if (!delegate_->AddScreenAvailabilityListener(
73 render_frame_host_->GetProcess()->GetID(),
74 render_frame_host_->GetRoutingID(),
75 context.get())) {
76 DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request.";
77 return nullptr;
78 }
79 it = availability_contexts_.insert(
80 std::make_pair(context->GetPresentationUrl(), context)).first;
81 }
82 return it->second.get();
67 } 83 }
68 84
69
70 void PresentationServiceImpl::GetScreenAvailability( 85 void PresentationServiceImpl::GetScreenAvailability(
71 const mojo::String& presentation_url, 86 const mojo::String& presentation_url,
72 const ScreenAvailabilityMojoCallback& callback) { 87 const ScreenAvailabilityMojoCallback& callback) {
73 VLOG(2) << "PresentationServiceImpl::GetScreenAvailability"; 88 DVLOG(2) << "GetScreenAvailability";
74 if (!delegate_) 89 if (!delegate_)
75 return; 90 return;
76 91
77 const std::string& presentation_url_str = !presentation_url.is_null() ? 92 ScreenAvailabilityContext* context =
78 presentation_url.get() : default_presentation_url_; 93 GetOrCreateAvailabilityContext(presentation_url.get());
79 94 if (!context)
80 // GetScreenAvailability() is called with no URL and there is no default
81 // Presentation URL.
82 if (presentation_url_str.empty())
83 return; 95 return;
mark a. foltz 2015/03/18 00:10:58 If the context can't be created, should we invoke
imcheng 2015/03/18 00:56:53 I don't think we should invoke the callback under
84 96 context->CallbackReceived(callback);
85 auto it = availability_contexts_.find(presentation_url_str);
86 if (it == availability_contexts_.end()) {
87 linked_ptr<ScreenAvailabilityContext> context(
88 new ScreenAvailabilityContext(presentation_url_str));
89
90 if (!delegate_->AddScreenAvailabilityListener(
91 render_frame_host_->GetProcess()->GetID(),
92 render_frame_host_->GetRoutingID(),
93 context.get())) {
94 VLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request.";
95 return;
96 }
97
98 it = availability_contexts_.insert(
99 std::make_pair(presentation_url_str, context)).first;
100 }
101
102 it->second->CallbackReceived(callback);
103 } 97 }
104 98
105 void PresentationServiceImpl::OnScreenAvailabilityListenerRemoved( 99 void PresentationServiceImpl::OnScreenAvailabilityListenerRemoved(
106 const mojo::String& presentation_url) { 100 const mojo::String& presentation_url) {
107 NOTIMPLEMENTED(); 101 DVLOG(2) << "OnScreenAvailabilityListenerRemoved";
102 if (!delegate_)
103 return;
104
105 const std::string& presentation_url_str = presentation_url.get();
106 auto it = availability_contexts_.find(presentation_url_str);
107 if (it == availability_contexts_.end())
108 return;
109
110 delegate_->RemoveScreenAvailabilityListener(
mark a. foltz 2015/03/18 00:10:58 Could we ever get into a state where the availabil
imcheng 2015/03/18 00:56:53 contexts get removed due to 2 reasons: 1) explicit
111 render_frame_host_->GetProcess()->GetID(),
112 render_frame_host_->GetRoutingID(),
113 it->second.get());
114 availability_contexts_.erase(it);
108 } 115 }
109 116
110 void PresentationServiceImpl::ListenForDefaultSessionStart( 117 void PresentationServiceImpl::ListenForDefaultSessionStart(
111 const DefaultSessionMojoCallback& callback) { 118 const DefaultSessionMojoCallback& callback) {
112 NOTIMPLEMENTED(); 119 NOTIMPLEMENTED();
113 } 120 }
114 121
115 void PresentationServiceImpl::StartSession( 122 void PresentationServiceImpl::StartSession(
116 const mojo::String& presentation_url, 123 const mojo::String& presentation_url,
117 const mojo::String& presentation_id, 124 const mojo::String& presentation_id,
118 const NewSessionMojoCallback& callback) { 125 const NewSessionMojoCallback& callback) {
119 NOTIMPLEMENTED(); 126 DVLOG(2) << "StartSession";
127 if (!delegate_)
128 return;
129
130 queued_start_session_requests_.push_back(make_linked_ptr(
131 new StartSessionRequest(presentation_url, presentation_id, callback)));
132 if (queued_start_session_requests_.size() == 1)
133 DoStartSession(presentation_url, presentation_id, callback);
120 } 134 }
121 135
122 void PresentationServiceImpl::JoinSession( 136 void PresentationServiceImpl::JoinSession(
123 const mojo::String& presentation_url, 137 const mojo::String& presentation_url,
124 const mojo::String& presentation_id, 138 const mojo::String& presentation_id,
125 const NewSessionMojoCallback& callback) { 139 const NewSessionMojoCallback& callback) {
126 NOTIMPLEMENTED(); 140 DVLOG(2) << "JoinSession";
141 if (!delegate_)
142 return;
143
144 delegate_->JoinSession(
145 render_frame_host_->GetProcess()->GetID(),
146 render_frame_host_->GetRoutingID(),
147 presentation_url,
148 presentation_id,
149 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded,
150 weak_factory_.GetWeakPtr(), false, callback),
151 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError,
152 weak_factory_.GetWeakPtr(), false, callback));
153 }
154
155 void PresentationServiceImpl::HandleQueuedStartSessionRequests() {
156 DCHECK(!queued_start_session_requests_.empty());
157 queued_start_session_requests_.pop_front();
158 if (!queued_start_session_requests_.empty()) {
159 const linked_ptr<StartSessionRequest>& request =
160 queued_start_session_requests_.front();
161 DoStartSession(request->presentation_url,
162 request->presentation_id,
163 request->callback);
164 }
165 }
166
167 void PresentationServiceImpl::DoStartSession(
168 const std::string& presentation_url,
169 const std::string& presentation_id,
170 const NewSessionMojoCallback& callback) {
171 delegate_->StartSession(
172 render_frame_host_->GetProcess()->GetID(),
173 render_frame_host_->GetRoutingID(),
174 presentation_url,
175 presentation_id,
176 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded,
177 weak_factory_.GetWeakPtr(), true, callback),
178 base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError,
179 weak_factory_.GetWeakPtr(), true, callback));
180 }
181
182 void PresentationServiceImpl::OnStartOrJoinSessionSucceeded(
183 bool is_start_session,
184 const NewSessionMojoCallback& callback,
185 const PresentationSessionInfo& session_info) {
186 callback.Run(
187 presentation::PresentationSessionInfo::From(session_info),
188 presentation::PresentationErrorPtr());
189 if (is_start_session)
190 HandleQueuedStartSessionRequests();
191 }
192
193 void PresentationServiceImpl::OnStartOrJoinSessionError(
194 bool is_start_session,
195 const NewSessionMojoCallback& callback,
196 const PresentationError& error) {
197 callback.Run(
198 presentation::PresentationSessionInfoPtr(),
199 presentation::PresentationError::From(error));
200 if (is_start_session)
201 HandleQueuedStartSessionRequests();
202 }
203
204 void PresentationServiceImpl::DoSetDefaultPresentationUrl(
205 const std::string& default_presentation_url,
206 const std::string& default_presentation_id) {
207 DCHECK(delegate_);
208 delegate_->SetDefaultPresentationUrl(
209 render_frame_host_->GetProcess()->GetID(),
210 render_frame_host_->GetRoutingID(),
211 default_presentation_url,
212 default_presentation_id);
213 default_presentation_url_ = default_presentation_url;
214 default_presentation_id_ = default_presentation_id;
215 }
216
217 void PresentationServiceImpl::SetDefaultPresentationURL(
218 const mojo::String& default_presentation_url,
219 const mojo::String& default_presentation_id) {
220 DVLOG(2) << "SetDefaultPresentationURL";
221 if (!delegate_)
222 return;
223
224 const std::string& old_default_url = default_presentation_url_;
225 const std::string& new_default_url = default_presentation_url.get();
226
227 // Don't call delegate if nothing changed.
228 if (old_default_url == new_default_url &&
229 default_presentation_id_ == default_presentation_id) {
230 return;
231 }
232
233 auto old_it = availability_contexts_.find(old_default_url);
234 // Haven't started listening yet.
235 if (old_it == availability_contexts_.end()) {
236 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id);
237 return;
238 }
239
240 // Have already started listening. Create a listener for the new URL and
241 // transfer the callback from the old listener, if any.
242 // This is done so that a listener added before default URL is changed
243 // will continue to work.
244 ScreenAvailabilityMojoCallback* old_callback = old_it->second->GetCallback();
245 ScreenAvailabilityContext* context =
246 GetOrCreateAvailabilityContext(new_default_url);
247 if (old_callback)
248 context->CallbackReceived(*old_callback);
249
250 // Remove listener for old default presentation URL.
251 delegate_->RemoveScreenAvailabilityListener(
252 render_frame_host_->GetProcess()->GetID(),
253 render_frame_host_->GetRoutingID(),
254 old_it->second.get());
255 availability_contexts_.erase(old_it);
256 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id);
127 } 257 }
128 258
129 void PresentationServiceImpl::DidNavigateAnyFrame( 259 void PresentationServiceImpl::DidNavigateAnyFrame(
130 content::RenderFrameHost* render_frame_host, 260 content::RenderFrameHost* render_frame_host,
131 const content::LoadCommittedDetails& details, 261 const content::LoadCommittedDetails& details,
132 const content::FrameNavigateParams& params) { 262 const content::FrameNavigateParams& params) {
133 VLOG(2) << "PresentationServiceImpl::DidNavigateAnyFrame"; 263 DVLOG(2) << "PresentationServiceImpl::DidNavigateAnyFrame";
134 if (render_frame_host_ != render_frame_host) 264 if (render_frame_host_ != render_frame_host)
135 return; 265 return;
136 266
137 std::string prev_url_host = details.previous_url.host(); 267 std::string prev_url_host = details.previous_url.host();
138 std::string curr_url_host = params.url.host(); 268 std::string curr_url_host = params.url.host();
139 269
140 // If a frame navigation is in-page (e.g. navigating to a fragment in 270 // If a frame navigation is in-page (e.g. navigating to a fragment in
141 // same page) then we do not unregister listeners. 271 // same page) then we do not unregister listeners.
142 bool in_page_navigation = details.is_in_page || 272 bool in_page_navigation = details.is_in_page ||
143 details.type == content::NAVIGATION_TYPE_IN_PAGE; 273 details.type == content::NAVIGATION_TYPE_IN_PAGE;
144 274
145 VLOG(2) << "DidNavigateAnyFrame: " 275 DVLOG(2) << "DidNavigateAnyFrame: "
146 << "prev host: " << prev_url_host << ", curr host: " << curr_url_host 276 << "prev host: " << prev_url_host << ", curr host: " << curr_url_host
147 << ", in_page_navigation: " << in_page_navigation; 277 << ", in_page_navigation: " << in_page_navigation;
148 278
149 if (in_page_navigation) 279 if (in_page_navigation)
150 return; 280 return;
151 281
152 // Unregister all sources if the frame actually navigated. 282 // Reset if the frame actually navigated.
153 RemoveAllListeners(); 283 Reset();
154 } 284 }
155 285
156 void PresentationServiceImpl::RenderFrameDeleted( 286 void PresentationServiceImpl::RenderFrameDeleted(
157 content::RenderFrameHost* render_frame_host) { 287 content::RenderFrameHost* render_frame_host) {
158 VLOG(2) << "PresentationServiceImpl::RenderFrameDeleted"; 288 DVLOG(2) << "PresentationServiceImpl::RenderFrameDeleted";
159 if (render_frame_host_ != render_frame_host) 289 if (render_frame_host_ != render_frame_host)
160 return; 290 return;
161 291
162 // RenderFrameDeleted means this object is getting deleted soon. 292 // RenderFrameDeleted means this object is getting deleted soon.
163 RemoveAllListeners(); 293 Reset();
164 } 294 }
165 295
166 void PresentationServiceImpl::RemoveAllListeners() { 296 void PresentationServiceImpl::Reset() {
167 VLOG(2) << "PresentationServiceImpl::RemoveAllListeners"; 297 DVLOG(2) << "PresentationServiceImpl::Reset";
168 if (!delegate_) 298 if (delegate_) {
169 return; 299 delegate_->Reset(
170
171 delegate_->RemoveAllScreenAvailabilityListeners(
172 render_frame_host_->GetProcess()->GetID(), 300 render_frame_host_->GetProcess()->GetID(),
173 render_frame_host_->GetRoutingID()); 301 render_frame_host_->GetRoutingID());
302 }
174 303
304 default_presentation_url_.clear();
305 default_presentation_id_.clear();
175 availability_contexts_.clear(); 306 availability_contexts_.clear();
307 queued_start_session_requests_.clear();
176 } 308 }
177 309
178 void PresentationServiceImpl::OnDelegateDestroyed() { 310 void PresentationServiceImpl::OnDelegateDestroyed() {
179 VLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed"; 311 DVLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed";
180 delegate_ = nullptr; 312 delegate_ = nullptr;
313 Reset();
181 } 314 }
182 315
183 PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext( 316 PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext(
184 const std::string& presentation_url) 317 const std::string& presentation_url)
185 : presentation_url_(presentation_url) { 318 : presentation_url_(presentation_url) {
186 } 319 }
187 320
188 PresentationServiceImpl::ScreenAvailabilityContext:: 321 PresentationServiceImpl::ScreenAvailabilityContext::
189 ~ScreenAvailabilityContext() { 322 ~ScreenAvailabilityContext() {
190 } 323 }
191 324
192 void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived( 325 void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived(
193 const ScreenAvailabilityMojoCallback& callback) { 326 const ScreenAvailabilityMojoCallback& callback) {
194 // NOTE: This will overwrite previously registered callback if any. 327 // NOTE: This will overwrite previously registered callback if any.
195 if (!available_ptr_) { 328 if (!available_ptr_) {
196 // No results yet, store callback for later invocation. 329 // No results yet, store callback for later invocation.
197 callback_ptr_.reset(new ScreenAvailabilityMojoCallback(callback)); 330 callback_ptr_.reset(new ScreenAvailabilityMojoCallback(callback));
198 } else { 331 } else {
199 // Run callback now, reset result. 332 // Run callback now, reset result.
200 // There shouldn't be any callbacks stored in this scenario. 333 // There shouldn't be any callbacks stored in this scenario.
201 DCHECK(!callback_ptr_); 334 DCHECK(!callback_ptr_);
202 callback.Run(*available_ptr_); 335 callback.Run(presentation_url_, *available_ptr_);
203 Reset(); 336 Reset();
204 } 337 }
205 } 338 }
206 339
207 void PresentationServiceImpl::ScreenAvailabilityContext::Reset() { 340 void PresentationServiceImpl::ScreenAvailabilityContext::Reset() {
208 callback_ptr_.reset(); 341 callback_ptr_.reset();
209 available_ptr_.reset(); 342 available_ptr_.reset();
210 } 343 }
211 344
212 std::string PresentationServiceImpl::ScreenAvailabilityContext 345 std::string PresentationServiceImpl::ScreenAvailabilityContext
213 ::GetPresentationUrl() const { 346 ::GetPresentationUrl() const {
214 return presentation_url_; 347 return presentation_url_;
215 } 348 }
216 349
217 void PresentationServiceImpl::ScreenAvailabilityContext 350 void PresentationServiceImpl::ScreenAvailabilityContext
218 ::OnScreenAvailabilityChanged(bool available) { 351 ::OnScreenAvailabilityChanged(bool available) {
219 if (!callback_ptr_) { 352 if (!callback_ptr_) {
220 // No callback, stash the result for now. 353 // No callback, stash the result for now.
221 available_ptr_.reset(new bool(available)); 354 available_ptr_.reset(new bool(available));
222 } else { 355 } else {
223 // Invoke callback and erase it. 356 // Invoke callback and erase it.
224 // There shouldn't be any result stored in this scenario. 357 // There shouldn't be any result stored in this scenario.
225 DCHECK(!available_ptr_); 358 DCHECK(!available_ptr_);
226 callback_ptr_->Run(available); 359 callback_ptr_->Run(presentation_url_, available);
227 Reset(); 360 Reset();
228 } 361 }
229 } 362 }
230 363
364 PresentationServiceImpl::ScreenAvailabilityMojoCallback*
365 PresentationServiceImpl::ScreenAvailabilityContext::GetCallback() const {
366 return callback_ptr_.get();
367 }
368
369 PresentationServiceImpl::StartSessionRequest::StartSessionRequest(
370 const std::string& presentation_url,
371 const std::string& presentation_id,
372 const NewSessionMojoCallback& callback)
373 : presentation_url(presentation_url),
374 presentation_id(presentation_id),
375 callback(callback) {
376 }
377
378 PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() {
379 }
380
231 } // namespace content 381 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698