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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.h"
10 #include "chrome/browser/media/router/presentation_service_delegate_impl.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
13 #include "chrome/browser/ui/webui/media_router/media_router_ui.h"
14 #include "chrome/common/url_constants.h"
15 #include "components/web_modal/web_contents_modal_dialog_host.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "ui/web_dialogs/web_dialog_delegate.h"
23 #include "ui/web_dialogs/web_dialog_web_contents_delegate.h"
26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
27 media_router::MediaRouterDialogControllerImpl
);
29 using content::LoadCommittedDetails
;
30 using content::NavigationController
;
31 using content::WebContents
;
32 using content::WebUIMessageHandler
;
33 using ui::WebDialogDelegate
;
36 const int kMaxHeight
= 260;
37 #if !defined(OS_MACOSX)
38 const int kMinHeight
= 130;
39 #endif // !defined(OS_MACOSX)
40 const int kWidth
= 340;
43 namespace media_router
{
47 // WebDialogDelegate that specifies what the media router dialog
49 class MediaRouterDialogDelegate
: public WebDialogDelegate
{
51 MediaRouterDialogDelegate() {}
52 ~MediaRouterDialogDelegate() override
{}
54 // WebDialogDelegate implementation.
55 ui::ModalType
GetDialogModalType() const override
{
56 // Not used, returning dummy value.
57 return ui::MODAL_TYPE_WINDOW
;
60 base::string16
GetDialogTitle() const override
{
61 return base::string16();
64 GURL
GetDialogContentURL() const override
{
65 return GURL(chrome::kChromeUIMediaRouterURL
);
68 void GetWebUIMessageHandlers(
69 std::vector
<WebUIMessageHandler
*>* handlers
) const override
{
70 // MediaRouterUI adds its own message handlers.
73 void GetDialogSize(gfx::Size
* size
) const override
;
75 std::string
GetDialogArgs() const override
{
79 void OnDialogClosed(const std::string
& json_retval
) override
{
80 // We don't delete |this| here because this class is owned
81 // by ConstrainedWebDialogDelegate.
84 void OnCloseContents(WebContents
* source
, bool* out_close_dialog
) override
{
86 *out_close_dialog
= true;
89 bool ShouldShowDialogTitle() const override
{
94 DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogDelegate
);
97 void MediaRouterDialogDelegate::GetDialogSize(gfx::Size
* size
) const {
99 // TODO(apacible): Remove after autoresizing is implemented for OSX.
100 #if defined(OS_MACOSX)
101 *size
= gfx::Size(kWidth
, kMaxHeight
);
103 // size is not used because the dialog is auto-resizeable.
111 MediaRouterDialogControllerImpl
*
112 MediaRouterDialogControllerImpl::GetOrCreateForWebContents(
113 WebContents
* web_contents
) {
114 DCHECK(web_contents
);
115 // This call does nothing if the controller already exists.
116 MediaRouterDialogControllerImpl::CreateForWebContents(web_contents
);
117 return MediaRouterDialogControllerImpl::FromWebContents(web_contents
);
120 class MediaRouterDialogControllerImpl::DialogWebContentsObserver
121 : public content::WebContentsObserver
{
123 DialogWebContentsObserver(
124 WebContents
* web_contents
,
125 MediaRouterDialogControllerImpl
* dialog_controller
)
126 : content::WebContentsObserver(web_contents
),
127 dialog_controller_(dialog_controller
) {
131 void WebContentsDestroyed() override
{
132 // The dialog is already closed. No need to call Close() again.
133 // NOTE: |this| is deleted after Reset() returns.
134 dialog_controller_
->Reset();
137 void NavigationEntryCommitted(const LoadCommittedDetails
& load_details
)
139 dialog_controller_
->OnDialogNavigated(load_details
);
142 void RenderProcessGone(base::TerminationStatus status
) override
{
143 // NOTE: |this| is deleted after CloseMediaRouterDialog() returns.
144 dialog_controller_
->CloseMediaRouterDialog();
147 MediaRouterDialogControllerImpl
* const dialog_controller_
;
150 MediaRouterDialogControllerImpl::MediaRouterDialogControllerImpl(
151 WebContents
* web_contents
)
152 : MediaRouterDialogController(web_contents
),
153 media_router_dialog_pending_(false) {
156 MediaRouterDialogControllerImpl::~MediaRouterDialogControllerImpl() {
159 WebContents
* MediaRouterDialogControllerImpl::GetMediaRouterDialog() const {
160 DCHECK(thread_checker_
.CalledOnValidThread());
161 return dialog_observer_
.get() ? dialog_observer_
->web_contents() : nullptr;
164 bool MediaRouterDialogControllerImpl::IsShowingMediaRouterDialog() const {
165 return GetMediaRouterDialog() != nullptr;
168 void MediaRouterDialogControllerImpl::CloseMediaRouterDialog() {
169 WebContents
* media_router_dialog
= GetMediaRouterDialog();
170 if (!media_router_dialog
)
173 content::WebUI
* web_ui
= media_router_dialog
->GetWebUI();
175 MediaRouterUI
* media_router_ui
=
176 static_cast<MediaRouterUI
*>(web_ui
->GetController());
178 media_router_ui
->Close();
182 void MediaRouterDialogControllerImpl::CreateMediaRouterDialog() {
183 DCHECK(!dialog_observer_
.get());
186 Profile::FromBrowserContext(initiator()->GetBrowserContext());
189 WebDialogDelegate
* web_dialog_delegate
= new MediaRouterDialogDelegate
;
191 // |web_dialog_delegate|'s owner is |constrained_delegate|.
192 // |constrained_delegate| is owned by the parent |views::View|.
193 // TODO(apacible): Remove after autoresizing is implemented for OSX.
194 #if defined(OS_MACOSX)
195 ConstrainedWebDialogDelegate
* constrained_delegate
=
196 ShowConstrainedWebDialog(profile
, web_dialog_delegate
, initiator());
198 // TODO(apacible): Adjust min and max sizes based on new WebUI design.
199 gfx::Size min_size
= gfx::Size(kWidth
, kMinHeight
);
200 gfx::Size max_size
= gfx::Size(kWidth
, kMaxHeight
);
202 // |ShowConstrainedWebDialogWithAutoResize()| will end up creating
203 // ConstrainedWebDialogDelegateViewViews containing a WebContents containing
204 // the MediaRouterUI, using the provided |web_dialog_delegate|. Then, the
205 // view is shown as a modal dialog constrained to the |initiator| WebContents.
206 // The dialog will resize between the |min_size| and |max_size| bounds based
207 // on the currently rendered contents.
208 ConstrainedWebDialogDelegate
* constrained_delegate
=
209 ShowConstrainedWebDialogWithAutoResize(
210 profile
, web_dialog_delegate
, initiator(), min_size
, max_size
);
213 WebContents
* media_router_dialog
= constrained_delegate
->GetWebContents();
215 media_router_dialog_pending_
= true;
217 dialog_observer_
.reset(new DialogWebContentsObserver(
218 media_router_dialog
, this));
221 void MediaRouterDialogControllerImpl::Reset() {
222 MediaRouterDialogController::Reset();
223 dialog_observer_
.reset();
226 void MediaRouterDialogControllerImpl::OnDialogNavigated(
227 const content::LoadCommittedDetails
& details
) {
228 DCHECK(thread_checker_
.CalledOnValidThread());
229 WebContents
* media_router_dialog
= GetMediaRouterDialog();
230 CHECK(media_router_dialog
);
231 ui::PageTransition transition_type
= details
.entry
->GetTransitionType();
232 content::NavigationType nav_type
= details
.type
;
234 // New |media_router_dialog| is created.
235 DCHECK(media_router_dialog_pending_
);
236 DCHECK(transition_type
== ui::PAGE_TRANSITION_AUTO_TOPLEVEL
&&
237 nav_type
== content::NAVIGATION_TYPE_NEW_PAGE
)
238 << "transition_type: " << transition_type
<< ", "
239 << "nav_type: " << nav_type
;
241 media_router_dialog_pending_
= false;
243 PopulateDialog(media_router_dialog
);
246 void MediaRouterDialogControllerImpl::PopulateDialog(
247 content::WebContents
* media_router_dialog
) {
248 DCHECK(thread_checker_
.CalledOnValidThread());
249 DCHECK(media_router_dialog
);
250 if (!initiator() || !media_router_dialog
->GetWebUI()) {
255 MediaRouterUI
* media_router_ui
= static_cast<MediaRouterUI
*>(
256 media_router_dialog
->GetWebUI()->GetController());
257 DCHECK(media_router_ui
);
258 if (!media_router_ui
) {
263 scoped_ptr
<CreatePresentationSessionRequest
> presentation_request(
264 PassPresentationRequest());
265 // TODO(imcheng): Don't create PresentationServiceDelegateImpl if it doesn't
266 // exist (crbug.com/508695).
267 base::WeakPtr
<PresentationServiceDelegateImpl
> delegate
=
268 PresentationServiceDelegateImpl::GetOrCreateForWebContents(initiator())
270 if (!presentation_request
.get()) {
271 media_router_ui
->InitWithDefaultMediaSource(delegate
);
273 media_router_ui
->InitWithPresentationSessionRequest(
274 initiator(), delegate
, presentation_request
.Pass());
278 } // namespace media_router