Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / webui / media_router / media_router_dialog_controller_impl.cc
blobe41268edf4dbcbc47b26acc3fb08266c9ba29d72
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"
7 #include <string>
8 #include <vector>
10 #include "chrome/browser/media/router/presentation_service_delegate_impl.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/toolbar/media_router_action.h"
13 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
14 #include "chrome/browser/ui/webui/media_router/media_router_ui.h"
15 #include "chrome/common/url_constants.h"
16 #include "components/web_modal/web_contents_modal_dialog_host.h"
17 #include "content/public/browser/navigation_controller.h"
18 #include "content/public/browser/navigation_details.h"
19 #include "content/public/browser/navigation_entry.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "ui/web_dialogs/web_dialog_delegate.h"
24 #include "ui/web_dialogs/web_dialog_web_contents_delegate.h"
25 #include "url/gurl.h"
27 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
28 media_router::MediaRouterDialogControllerImpl);
30 using content::LoadCommittedDetails;
31 using content::NavigationController;
32 using content::WebContents;
33 using content::WebUIMessageHandler;
34 using ui::WebDialogDelegate;
36 namespace {
37 const int kMaxHeight = 300;
38 #if !defined(OS_MACOSX)
39 const int kMinHeight = 130;
40 #endif // !defined(OS_MACOSX)
41 const int kWidth = 340;
44 namespace media_router {
46 namespace {
48 // WebDialogDelegate that specifies what the media router dialog
49 // will look like.
50 class MediaRouterDialogDelegate : public WebDialogDelegate {
51 public:
52 explicit MediaRouterDialogDelegate(base::WeakPtr<MediaRouterAction> action) {}
53 ~MediaRouterDialogDelegate() override {}
55 // WebDialogDelegate implementation.
56 ui::ModalType GetDialogModalType() const override {
57 // Not used, returning dummy value.
58 return ui::MODAL_TYPE_WINDOW;
61 base::string16 GetDialogTitle() const override {
62 return base::string16();
65 GURL GetDialogContentURL() const override {
66 return GURL(chrome::kChromeUIMediaRouterURL);
69 void GetWebUIMessageHandlers(
70 std::vector<WebUIMessageHandler*>* handlers) const override {
71 // MediaRouterUI adds its own message handlers.
74 void GetDialogSize(gfx::Size* size) const override;
76 std::string GetDialogArgs() const override {
77 return std::string();
80 void OnDialogClosed(const std::string& json_retval) override {
81 // We don't delete |this| here because this class is owned
82 // by ConstrainedWebDialogDelegate.
83 if (action_)
84 action_->OnPopupHidden();
87 void OnCloseContents(WebContents* source, bool* out_close_dialog) override {
88 if (out_close_dialog)
89 *out_close_dialog = true;
92 bool ShouldShowDialogTitle() const override {
93 return false;
96 void SetAction(const base::WeakPtr<MediaRouterAction>& action) {
97 action_ = action;
100 private:
101 base::WeakPtr<MediaRouterAction> action_;
103 DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogDelegate);
106 void MediaRouterDialogDelegate::GetDialogSize(gfx::Size* size) const {
107 DCHECK(size);
108 // TODO(apacible): Remove after autoresizing is implemented for OSX.
109 #if defined(OS_MACOSX)
110 *size = gfx::Size(kWidth, kMaxHeight);
111 #else
112 // size is not used because the dialog is auto-resizeable.
113 *size = gfx::Size();
114 #endif
117 } // namespace
119 // static
120 MediaRouterDialogControllerImpl*
121 MediaRouterDialogControllerImpl::GetOrCreateForWebContents(
122 WebContents* web_contents) {
123 DCHECK(web_contents);
124 // This call does nothing if the controller already exists.
125 MediaRouterDialogControllerImpl::CreateForWebContents(web_contents);
126 return MediaRouterDialogControllerImpl::FromWebContents(web_contents);
129 class MediaRouterDialogControllerImpl::DialogWebContentsObserver
130 : public content::WebContentsObserver {
131 public:
132 DialogWebContentsObserver(
133 WebContents* web_contents,
134 MediaRouterDialogControllerImpl* dialog_controller)
135 : content::WebContentsObserver(web_contents),
136 dialog_controller_(dialog_controller) {
139 private:
140 void WebContentsDestroyed() override {
141 // The dialog is already closed. No need to call Close() again.
142 // NOTE: |this| is deleted after Reset() returns.
143 dialog_controller_->Reset();
146 void NavigationEntryCommitted(const LoadCommittedDetails& load_details)
147 override {
148 dialog_controller_->OnDialogNavigated(load_details);
151 void RenderProcessGone(base::TerminationStatus status) override {
152 // NOTE: |this| is deleted after CloseMediaRouterDialog() returns.
153 dialog_controller_->CloseMediaRouterDialog();
156 MediaRouterDialogControllerImpl* const dialog_controller_;
159 MediaRouterDialogControllerImpl::MediaRouterDialogControllerImpl(
160 WebContents* web_contents)
161 : MediaRouterDialogController(web_contents),
162 media_router_dialog_pending_(false) {
165 MediaRouterDialogControllerImpl::~MediaRouterDialogControllerImpl() {
168 WebContents* MediaRouterDialogControllerImpl::GetMediaRouterDialog() const {
169 DCHECK(thread_checker_.CalledOnValidThread());
170 return dialog_observer_.get() ? dialog_observer_->web_contents() : nullptr;
173 void MediaRouterDialogControllerImpl::SetMediaRouterAction(
174 const base::WeakPtr<MediaRouterAction>& action) {
175 action_ = action;
178 bool MediaRouterDialogControllerImpl::IsShowingMediaRouterDialog() const {
179 return GetMediaRouterDialog() != nullptr;
182 void MediaRouterDialogControllerImpl::CloseMediaRouterDialog() {
183 WebContents* media_router_dialog = GetMediaRouterDialog();
184 if (!media_router_dialog)
185 return;
187 content::WebUI* web_ui = media_router_dialog->GetWebUI();
188 if (web_ui) {
189 MediaRouterUI* media_router_ui =
190 static_cast<MediaRouterUI*>(web_ui->GetController());
191 if (media_router_ui)
192 media_router_ui->Close();
195 // If there was no dialog to be closed, the action icon should not have been
196 // pressed and this would be a no-op.
197 if (action_)
198 action_->OnPopupHidden();
201 void MediaRouterDialogControllerImpl::CreateMediaRouterDialog() {
202 DCHECK(!dialog_observer_.get());
204 Profile* profile =
205 Profile::FromBrowserContext(initiator()->GetBrowserContext());
206 DCHECK(profile);
208 WebDialogDelegate* web_dialog_delegate =
209 new MediaRouterDialogDelegate(action_);
210 // |web_dialog_delegate|'s owner is |constrained_delegate|.
211 // |constrained_delegate| is owned by the parent |views::View|.
212 // TODO(apacible): Remove after autoresizing is implemented for OSX.
213 #if defined(OS_MACOSX)
214 ConstrainedWebDialogDelegate* constrained_delegate =
215 ShowConstrainedWebDialog(profile, web_dialog_delegate, initiator());
216 #else
217 // TODO(apacible): Adjust min and max sizes based on new WebUI design.
218 gfx::Size min_size = gfx::Size(kWidth, kMinHeight);
219 gfx::Size max_size = gfx::Size(kWidth, kMaxHeight);
221 // |ShowConstrainedWebDialogWithAutoResize()| will end up creating
222 // ConstrainedWebDialogDelegateViewViews containing a WebContents containing
223 // the MediaRouterUI, using the provided |web_dialog_delegate|. Then, the
224 // view is shown as a modal dialog constrained to the |initiator| WebContents.
225 // The dialog will resize between the |min_size| and |max_size| bounds based
226 // on the currently rendered contents.
227 ConstrainedWebDialogDelegate* constrained_delegate =
228 ShowConstrainedWebDialogWithAutoResize(
229 profile, web_dialog_delegate, initiator(), min_size, max_size);
230 #endif
232 WebContents* media_router_dialog = constrained_delegate->GetWebContents();
234 media_router_dialog_pending_ = true;
236 dialog_observer_.reset(new DialogWebContentsObserver(
237 media_router_dialog, this));
239 if (action_)
240 action_->OnPopupShown();
243 void MediaRouterDialogControllerImpl::Reset() {
244 MediaRouterDialogController::Reset();
245 dialog_observer_.reset();
247 if (action_)
248 action_->OnPopupHidden();
251 void MediaRouterDialogControllerImpl::OnDialogNavigated(
252 const content::LoadCommittedDetails& details) {
253 DCHECK(thread_checker_.CalledOnValidThread());
254 WebContents* media_router_dialog = GetMediaRouterDialog();
255 CHECK(media_router_dialog);
256 ui::PageTransition transition_type = details.entry->GetTransitionType();
257 content::NavigationType nav_type = details.type;
259 // New |media_router_dialog| is created.
260 DCHECK(media_router_dialog_pending_);
261 DCHECK(transition_type == ui::PAGE_TRANSITION_AUTO_TOPLEVEL &&
262 nav_type == content::NAVIGATION_TYPE_NEW_PAGE)
263 << "transition_type: " << transition_type << ", "
264 << "nav_type: " << nav_type;
266 media_router_dialog_pending_ = false;
268 PopulateDialog(media_router_dialog);
271 void MediaRouterDialogControllerImpl::PopulateDialog(
272 content::WebContents* media_router_dialog) {
273 DCHECK(thread_checker_.CalledOnValidThread());
274 DCHECK(media_router_dialog);
275 if (!initiator() || !media_router_dialog->GetWebUI()) {
276 Reset();
277 return;
280 MediaRouterUI* media_router_ui = static_cast<MediaRouterUI*>(
281 media_router_dialog->GetWebUI()->GetController());
282 DCHECK(media_router_ui);
283 if (!media_router_ui) {
284 Reset();
285 return;
288 scoped_ptr<CreatePresentationSessionRequest> presentation_request(
289 TakePresentationRequest());
290 // TODO(imcheng): Don't create PresentationServiceDelegateImpl if it doesn't
291 // exist (crbug.com/508695).
292 base::WeakPtr<PresentationServiceDelegateImpl> delegate =
293 PresentationServiceDelegateImpl::GetOrCreateForWebContents(initiator())
294 ->GetWeakPtr();
295 if (!presentation_request.get()) {
296 media_router_ui->InitWithDefaultMediaSource(delegate);
297 } else {
298 media_router_ui->InitWithPresentationSessionRequest(
299 initiator(), delegate, presentation_request.Pass());
303 } // namespace media_router