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

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: Addressed Kevin's 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.
mark a. foltz 2015/07/14 21:36:32 This description doesn't quite match up with the b
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(
mark a. foltz 2015/07/14 21:36:32 Nit: This object wraps a single callback, so maybe
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 void OnPresentationRouteResponseReceived(scoped_ptr<MediaRoute> route,
146 const std::string& error) {
147 DCHECK(route || !error.empty());
148 ProcessPresentationRouteResponse(route.get(), error);
haibinlu 2015/07/14 01:44:55 ProcessCreateRouteResponse
imcheng 2015/07/14 16:45:37 ditto
149 route_response_callback_.Run(route.Pass(), error);
150 // No additional processing should be done after this call as |this| will
151 // be deleted immediately afterwards.
152 dialog_controller_->DestroyDialogCallbacks(this);
153 }
154
155 base::WeakPtr<MediaRouterDialogCallbacks> GetWeakPtr() {
156 return weak_factory_.GetWeakPtr();
157 }
158
159 private:
160 // Invoked from |ProcessPresentationRouteResponse|, before
161 // |route_response_callback_| is run and the instance is deleted.
162 virtual void ProcessPresentationRouteResponse(const MediaRoute* route,
163 const std::string& error) = 0;
164
165 MediaRouteResponseCallback route_response_callback_;
166
167 // Reference to the MediaRouterDialogController that owns this instance.
168 MediaRouterDialogController* const dialog_controller_;
169
170 base::WeakPtrFactory<MediaRouterDialogCallbacks> weak_factory_;
171
172 DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogCallbacks);
173 };
174
175 class MediaRouterDialogController::BrowserInitiatedCallbacks
176 : public MediaRouterDialogController::MediaRouterDialogCallbacks {
177 public:
178 BrowserInitiatedCallbacks(
179 const MediaRouteResponseCallback& route_response_callback,
180 MediaRouterDialogController* dialog_controller,
181 content::WebContents* initiator)
182 : MediaRouterDialogController::MediaRouterDialogCallbacks(
183 route_response_callback,
184 dialog_controller),
185 initiator_(initiator) {
186 DCHECK(initiator_);
187 }
188 ~BrowserInitiatedCallbacks() override {}
189
190 private:
191 // MediaRouterDialogCallbacks override.
192 void ProcessPresentationRouteResponse(const MediaRoute* route,
193 const std::string& error) override {
194 if (route) {
195 PresentationServiceDelegateImpl* delegate =
196 PresentationServiceDelegateImpl::FromWebContents(initiator_);
197 if (delegate) {
198 // Response was due to a browser-initiated request. Let
199 // PresentationServiceDelegateImpl perform the match against the default
200 // presentation URL.
201 delegate->OnRouteCreated(*route);
haibinlu 2015/07/14 01:44:55 how is browser initiated tab-mirroring handled?
imcheng 2015/07/14 16:45:37 For mirroring, instead of creating an instance of
202 }
203 }
204 }
205
206 // Used for obtaining a reference to its PresentationServiceDelegateImpl
207 // in case of browser-initiated presentation. As this instance is owned
208 // by the MediaRouterDialogController, |initiator_| will outlive this
209 // instance.
210 content::WebContents* initiator_;
211 };
212
213 class MediaRouterDialogController::PresentationInitiatedCallbacks
214 : public MediaRouterDialogController::MediaRouterDialogCallbacks {
215 public:
216 PresentationInitiatedCallbacks(
217 const MediaRouteResponseCallback& route_response_callback,
218 MediaRouterDialogController* dialog_controller,
219 scoped_ptr<CreateSessionRequest> presentation_request)
220 : MediaRouterDialogController::MediaRouterDialogCallbacks(
221 route_response_callback,
222 dialog_controller),
223 presentation_request_(presentation_request.Pass()) {
224 DCHECK(presentation_request_);
225 }
226
227 ~PresentationInitiatedCallbacks() override {}
228
229 private:
230 // MediaRouterDialogCallbacks overrides.
231 void ProcessPresentationRouteResponse(const MediaRoute* route,
232 const std::string& error) override {
233 if (!route) {
234 presentation_request_->MaybeInvokeErrorCallback(
235 content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN,
236 error));
237 } else {
238 presentation_request_->MaybeInvokeSuccessCallback(
239 route->media_route_id());
240 }
241 }
242
243 scoped_ptr<CreateSessionRequest> presentation_request_;
244 };
245
113 class MediaRouterDialogController::DialogWebContentsObserver 246 class MediaRouterDialogController::DialogWebContentsObserver
114 : public content::WebContentsObserver { 247 : public content::WebContentsObserver {
115 public: 248 public:
116 DialogWebContentsObserver( 249 DialogWebContentsObserver(
117 WebContents* web_contents, 250 WebContents* web_contents,
118 MediaRouterDialogController* dialog_controller) 251 MediaRouterDialogController* dialog_controller)
119 : content::WebContentsObserver(web_contents), 252 : content::WebContentsObserver(web_contents),
120 dialog_controller_(dialog_controller) { 253 dialog_controller_(dialog_controller) {
121 } 254 }
122 255
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 458
326 MediaRouterUI* media_router_ui = static_cast<MediaRouterUI*>( 459 MediaRouterUI* media_router_ui = static_cast<MediaRouterUI*>(
327 media_router_dialog->GetWebUI()->GetController()); 460 media_router_dialog->GetWebUI()->GetController());
328 DCHECK(media_router_ui); 461 DCHECK(media_router_ui);
329 if (!media_router_ui) { 462 if (!media_router_ui) {
330 Reset(); 463 Reset();
331 return; 464 return;
332 } 465 }
333 466
334 if (!presentation_request_.get()) { 467 if (!presentation_request_.get()) {
335 PresentationServiceDelegateImpl::CreateForWebContents(initiator); 468 // TODO(imcheng): Don't create PresentationServiceDelegateImpl if it doesn't
mark a. foltz 2015/07/14 21:36:32 Does there just need to be a separate method on PS
imcheng 2015/07/16 01:06:52 Yes, we could call FromWebContents only to check f
336 PresentationServiceDelegateImpl* delegate = 469 // exist (crbug.com/508695).
337 PresentationServiceDelegateImpl::FromWebContents(initiator); 470 base::WeakPtr<PresentationServiceDelegateImpl> delegate =
338 CHECK(delegate); 471 PresentationServiceDelegateImpl::GetOrCreateForWebContents(initiator)
472 ->GetWeakPtr();
339 media_router_ui->InitWithDefaultMediaSource(delegate); 473 media_router_ui->InitWithDefaultMediaSource(delegate);
340 } else { 474 } else {
341 media_router_ui->InitWithPresentationSessionRequest( 475 media_router_ui->InitWithPresentationSessionRequest(
342 initiator, presentation_request_.Pass()); 476 initiator, presentation_request_.Pass());
343 } 477 }
344 } 478 }
345 479
480 MediaRouteResponseCallback
481 MediaRouterDialogController::AddPresentationRouteRequest(
mark a. foltz 2015/07/14 21:36:32 Please split this into two methods: AddPresentati
482 const MediaRouteResponseCallback& route_response_callback,
483 scoped_ptr<CreateSessionRequest> presentation_request) {
484 scoped_ptr<MediaRouterDialogCallbacks> dialog_callbacks;
485 if (!presentation_request) {
486 dialog_callbacks.reset(new BrowserInitiatedCallbacks(
487 route_response_callback, this, initiator_));
488 } else {
489 dialog_callbacks.reset(new PresentationInitiatedCallbacks(
490 route_response_callback, this, presentation_request.Pass()));
491 }
492 MediaRouteResponseCallback new_route_response_callback = base::Bind(
493 &MediaRouterDialogCallbacks::OnPresentationRouteResponseReceived,
494 dialog_callbacks->GetWeakPtr());
495 pending_dialog_callbacks_.push_back(dialog_callbacks.Pass());
496 return new_route_response_callback;
497 }
498
499 void MediaRouterDialogController::DestroyDialogCallbacks(
500 MediaRouterDialogCallbacks* callbacks) {
501 auto it = std::find(pending_dialog_callbacks_.begin(),
502 pending_dialog_callbacks_.end(), callbacks);
503 if (it != pending_dialog_callbacks_.end())
504 pending_dialog_callbacks_.erase(it);
505 }
506
346 } // namespace media_router 507 } // namespace media_router
347 508
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698