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

Side by Side Diff: chrome/browser/ui/webui/media_router/media_router_dialog_controller.cc

Issue 1224093004: [Media Router] 2nd take on fix route response callback lifetime in UI. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated comments Created 5 years, 5 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 "chrome/browser/ui/webui/media_router/media_router_dialog_controller.h" 5 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "chrome/browser/media/router/presentation_service_delegate_impl.h"
10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" 12 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
12 #include "chrome/browser/ui/webui/media_router/media_router_ui.h" 13 #include "chrome/browser/ui/webui/media_router/media_router_ui.h"
13 #include "chrome/common/url_constants.h" 14 #include "chrome/common/url_constants.h"
14 #include "components/web_modal/web_contents_modal_dialog_host.h" 15 #include "components/web_modal/web_contents_modal_dialog_host.h"
15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/navigation_controller.h" 17 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/navigation_details.h" 18 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/navigation_entry.h" 19 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_frame_host.h" 20 #include "content/public/browser/render_frame_host.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 // static 104 // static
104 MediaRouterDialogController* 105 MediaRouterDialogController*
105 MediaRouterDialogController::GetOrCreateForWebContents( 106 MediaRouterDialogController::GetOrCreateForWebContents(
106 WebContents* web_contents) { 107 WebContents* web_contents) {
107 DCHECK(web_contents); 108 DCHECK(web_contents);
108 // This call does nothing if the controller already exists. 109 // This call does nothing if the controller already exists.
109 MediaRouterDialogController::CreateForWebContents(web_contents); 110 MediaRouterDialogController::CreateForWebContents(web_contents);
110 return MediaRouterDialogController::FromWebContents(web_contents); 111 return MediaRouterDialogController::FromWebContents(web_contents);
111 } 112 }
112 113
114 // Base class used when a Media Router dialog needs to make a presentation
115 // route request to the Media Router. The route request can be due to either
116 // a Presentation API request or the browser (see subclasses below).
117 // MediaRouterDialogCallbacks ensures that the route response is received and
118 // handled properly even if the dialog was destroyed while the request is in
119 // progress.
120 // Instances are created by calling |AddDialogCallbacks()| on the
121 // MediaRouterDialogController corresponding to the dialog's initiator
122 // WebContents. |OnPresentationRouteResponseReceived()| of the created instance
123 // can then be used as the response callback of |MediaRouter::CreateRoute()|.
124 // Instances are deleted from MediaRouterDialogController when
125 // |OnPresentationRouteResponseReceived()| is invoked.
126 // TODO(imcheng): Currently it is assumed that MediaRouter requests will
127 // always be eventually resolved, but this may not be true due to
128 // implementation errors, in which case DialogCallbacks objects may be leaked.
129 // We should have some timeout mechanism to make sure they self-destruct
130 // after certain conditions and timeout are met.
131 class MediaRouterDialogController::MediaRouterDialogCallbacks {
132 public:
133 MediaRouterDialogCallbacks(
134 const MediaRouteResponseCallback& route_response_callback,
135 MediaRouterDialogController* dialog_controller)
136 : route_response_callback_(route_response_callback),
137 dialog_controller_(dialog_controller),
138 weak_factory_(this) {
139 DCHECK(!route_response_callback_.is_null());
140 DCHECK(dialog_controller_);
141 }
142
143 virtual ~MediaRouterDialogCallbacks() {}
144
145 virtual void OnPresentationRouteResponseReceived(scoped_ptr<MediaRoute> route,
Kevin M 2015/07/13 21:55:26 Make the body of this function call a different pu
imcheng 2015/07/14 01:00:23 Good idea. Done.
146 const std::string& error) {
147 route_response_callback_.Run(route.Pass(), error);
148 dialog_controller_->DestroyDialogCallbacks(this);
Kevin M 2015/07/13 21:55:26 Suggestion: make a note that no additional process
imcheng 2015/07/14 01:00:23 Done.
149 }
150
151 base::WeakPtr<MediaRouterDialogCallbacks> GetWeakPtr() {
152 return weak_factory_.GetWeakPtr();
153 }
154
155 private:
156 MediaRouteResponseCallback route_response_callback_;
157
158 // Reference to the MediaRouterDialogController that owns this instance.
159 MediaRouterDialogController* const dialog_controller_;
160
161 base::WeakPtrFactory<MediaRouterDialogCallbacks> weak_factory_;
162
163 DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogCallbacks);
164 };
165
166 class MediaRouterDialogController::BrowserInitiatedMediaRouterDialogCallbacks
Kevin M 2015/07/13 21:55:26 Nit: that's a big identifier. This is just a child
imcheng 2015/07/14 01:00:24 Done.
167 : public MediaRouterDialogController::MediaRouterDialogCallbacks {
168 public:
169 BrowserInitiatedMediaRouterDialogCallbacks(
170 const MediaRouteResponseCallback& route_response_callback,
171 MediaRouterDialogController* dialog_controller,
172 content::WebContents* initiator)
173 : MediaRouterDialogController::MediaRouterDialogCallbacks(
174 route_response_callback,
175 dialog_controller),
176 initiator_(initiator) {
177 DCHECK(initiator_);
178 }
179 ~BrowserInitiatedMediaRouterDialogCallbacks() override {}
180
181 // MediaRouterDialogCallbacks override.
182 void OnPresentationRouteResponseReceived(scoped_ptr<MediaRoute> route,
183 const std::string& error) override {
184 if (route) {
Kevin M 2015/07/13 21:55:26 Suggestion: DCHECK(route || !error.empty()) ?
imcheng 2015/07/14 01:00:24 Done.
185 PresentationServiceDelegateImpl* delegate =
186 PresentationServiceDelegateImpl::FromWebContents(initiator_);
187 if (delegate) {
188 // Response was due to a browser-initiated request. Let
189 // PresentationServiceDelegateImpl perform the match against the default
190 // presentation URL.
191 delegate->OnRouteCreated(*route);
192 }
193 }
194
195 MediaRouterDialogCallbacks::OnPresentationRouteResponseReceived(
196 route.Pass(), error);
197 }
198
199 private:
200 // Used for obtaining a reference to its PresentationServiceDelegateImpl
201 // in case of browser-initiated presentation. As this instance is owned
202 // by the MediaRouterDialogController, |initiator_| will outlive this
203 // instance.
204 content::WebContents* initiator_;
205 };
206
207 class MediaRouterDialogController::PresentationMediaRouterDialogCallbacks
208 : public MediaRouterDialogController::MediaRouterDialogCallbacks {
209 public:
210 PresentationMediaRouterDialogCallbacks(
211 const MediaRouteResponseCallback& route_response_callback,
212 MediaRouterDialogController* dialog_controller,
213 scoped_ptr<CreateSessionRequest> presentation_request)
214 : MediaRouterDialogController::MediaRouterDialogCallbacks(
215 route_response_callback,
216 dialog_controller),
217 presentation_request_(presentation_request.Pass()) {
218 DCHECK(presentation_request_);
219 }
220
221 ~PresentationMediaRouterDialogCallbacks() override {}
222
223 // MediaRouterDialogCallbacks overrides.
224 void OnPresentationRouteResponseReceived(scoped_ptr<MediaRoute> route,
225 const std::string& error) override {
226 if (!route) {
227 presentation_request_->MaybeInvokeErrorCallback(
228 content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN,
229 error));
230 } else {
231 presentation_request_->MaybeInvokeSuccessCallback(
232 route->media_route_id());
233 }
234 MediaRouterDialogCallbacks::OnPresentationRouteResponseReceived(
235 route.Pass(), error);
236 }
237
238 private:
239 scoped_ptr<CreateSessionRequest> presentation_request_;
240 };
241
113 class MediaRouterDialogController::DialogWebContentsObserver 242 class MediaRouterDialogController::DialogWebContentsObserver
114 : public content::WebContentsObserver { 243 : public content::WebContentsObserver {
115 public: 244 public:
116 DialogWebContentsObserver( 245 DialogWebContentsObserver(
117 WebContents* web_contents, 246 WebContents* web_contents,
118 MediaRouterDialogController* dialog_controller) 247 MediaRouterDialogController* dialog_controller)
119 : content::WebContentsObserver(web_contents), 248 : content::WebContentsObserver(web_contents),
120 dialog_controller_(dialog_controller) { 249 dialog_controller_(dialog_controller) {
121 } 250 }
122 251
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 454
326 MediaRouterUI* media_router_ui = static_cast<MediaRouterUI*>( 455 MediaRouterUI* media_router_ui = static_cast<MediaRouterUI*>(
327 media_router_dialog->GetWebUI()->GetController()); 456 media_router_dialog->GetWebUI()->GetController());
328 DCHECK(media_router_ui); 457 DCHECK(media_router_ui);
329 if (!media_router_ui) { 458 if (!media_router_ui) {
330 Reset(); 459 Reset();
331 return; 460 return;
332 } 461 }
333 462
334 if (!presentation_request_.get()) { 463 if (!presentation_request_.get()) {
335 PresentationServiceDelegateImpl::CreateForWebContents(initiator); 464 // TODO(imcheng): Don't create PresentationServiceDelegateImpl if it doesn't
336 PresentationServiceDelegateImpl* delegate = 465 // exist (crbug.com/508695).
337 PresentationServiceDelegateImpl::FromWebContents(initiator); 466 base::WeakPtr<PresentationServiceDelegateImpl> delegate =
338 CHECK(delegate); 467 PresentationServiceDelegateImpl::GetOrCreateForWebContents(initiator)
468 ->GetWeakPtr();
339 media_router_ui->InitWithDefaultMediaSource(delegate); 469 media_router_ui->InitWithDefaultMediaSource(delegate);
340 } else { 470 } else {
341 media_router_ui->InitWithPresentationSessionRequest( 471 media_router_ui->InitWithPresentationSessionRequest(
342 initiator, presentation_request_.Pass()); 472 initiator, presentation_request_.Pass());
343 } 473 }
344 } 474 }
345 475
476 MediaRouteResponseCallback
477 MediaRouterDialogController::AddPresentationRouteRequest(
478 const MediaRouteResponseCallback& route_response_callback,
479 scoped_ptr<CreateSessionRequest> presentation_request) {
480 scoped_ptr<MediaRouterDialogCallbacks> dialog_callbacks;
481 if (!presentation_request) {
482 dialog_callbacks.reset(new BrowserInitiatedMediaRouterDialogCallbacks(
483 route_response_callback, this, initiator_));
484 } else {
485 dialog_callbacks.reset(new PresentationMediaRouterDialogCallbacks(
486 route_response_callback, this, presentation_request.Pass()));
487 }
488 MediaRouteResponseCallback new_route_response_callback = base::Bind(
489 &MediaRouterDialogCallbacks::OnPresentationRouteResponseReceived,
490 dialog_callbacks->GetWeakPtr());
491 pending_dialog_callbacks_.push_back(dialog_callbacks.Pass());
492 return new_route_response_callback;
493 }
494
495 void MediaRouterDialogController::DestroyDialogCallbacks(
496 MediaRouterDialogCallbacks* callbacks) {
497 auto it = std::find(pending_dialog_callbacks_.begin(),
498 pending_dialog_callbacks_.end(), callbacks);
499 if (it != pending_dialog_callbacks_.end())
500 pending_dialog_callbacks_.erase(it);
501 }
502
346 } // namespace media_router 503 } // namespace media_router
347 504
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698