1// Copyright (c) 2011 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.
4
5#include "chrome/browser/ui/views/html_dialog_view.h"
6
7#include <vector>
8
9#include "chrome/browser/ui/browser_dialogs.h"
10#include "chrome/browser/ui/views/window.h"
11#include "content/browser/tab_contents/tab_contents.h"
12#include "content/common/native_web_keyboard_event.h"
13#include "ui/base/keycodes/keyboard_codes.h"
14#include "views/events/event.h"
15#include "views/widget/root_view.h"
16#include "views/widget/widget.h"
17#include "views/window/window.h"
18
19#if defined(OS_LINUX)
20#include "views/window/window_gtk.h"
21#endif
22
23namespace browser {
24
25// Declared in browser_dialogs.h so that others don't need to depend on our .h.
26gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
27                                 HtmlDialogUIDelegate* delegate) {
28  HtmlDialogView* html_view =
29      new HtmlDialogView(profile, delegate);
30  browser::CreateViewsWindow(parent, gfx::Rect(), html_view);
31  html_view->InitDialog();
32  html_view->window()->Show();
33  return html_view->window()->GetNativeWindow();
34}
35
36}  // namespace browser
37
38////////////////////////////////////////////////////////////////////////////////
39// HtmlDialogView, public:
40
41HtmlDialogView::HtmlDialogView(Profile* profile,
42                               HtmlDialogUIDelegate* delegate)
43    : DOMView(),
44      HtmlDialogTabContentsDelegate(profile),
45      delegate_(delegate) {
46}
47
48HtmlDialogView::~HtmlDialogView() {
49}
50
51////////////////////////////////////////////////////////////////////////////////
52// HtmlDialogView, views::View implementation:
53
54gfx::Size HtmlDialogView::GetPreferredSize() {
55  gfx::Size out;
56  if (delegate_)
57    delegate_->GetDialogSize(&out);
58  return out;
59}
60
61bool HtmlDialogView::AcceleratorPressed(const views::Accelerator& accelerator) {
62  // Pressing ESC closes the dialog.
63  DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.GetKeyCode());
64  OnWindowClosed();
65  OnDialogClosed(std::string());
66  return true;
67}
68
69////////////////////////////////////////////////////////////////////////////////
70// HtmlDialogView, views::WindowDelegate implementation:
71
72bool HtmlDialogView::CanResize() const {
73  return true;
74}
75
76bool HtmlDialogView::IsModal() const {
77  if (delegate_)
78    return delegate_->IsDialogModal();
79  return false;
80}
81
82std::wstring HtmlDialogView::GetWindowTitle() const {
83  if (delegate_)
84    return delegate_->GetDialogTitle();
85  return std::wstring();
86}
87
88void HtmlDialogView::WindowClosing() {
89  // If we still have a delegate that means we haven't notified it of the
90  // dialog closing. This happens if the user clicks the Close button on the
91  // dialog.
92  if (delegate_) {
93    OnWindowClosed();
94    OnDialogClosed("");
95  }
96}
97
98views::View* HtmlDialogView::GetContentsView() {
99  return this;
100}
101
102views::View* HtmlDialogView::GetInitiallyFocusedView() {
103  return this;
104}
105
106bool HtmlDialogView::ShouldShowWindowTitle() const {
107  return ShouldShowDialogTitle();
108}
109
110////////////////////////////////////////////////////////////////////////////////
111// HtmlDialogUIDelegate implementation:
112
113bool HtmlDialogView::IsDialogModal() const {
114  return IsModal();
115}
116
117std::wstring HtmlDialogView::GetDialogTitle() const {
118  return GetWindowTitle();
119}
120
121GURL HtmlDialogView::GetDialogContentURL() const {
122  if (delegate_)
123    return delegate_->GetDialogContentURL();
124  return GURL();
125}
126
127void HtmlDialogView::GetWebUIMessageHandlers(
128    std::vector<WebUIMessageHandler*>* handlers) const {
129  if (delegate_)
130    delegate_->GetWebUIMessageHandlers(handlers);
131}
132
133void HtmlDialogView::GetDialogSize(gfx::Size* size) const {
134  if (delegate_)
135    delegate_->GetDialogSize(size);
136}
137
138std::string HtmlDialogView::GetDialogArgs() const {
139  if (delegate_)
140    return delegate_->GetDialogArgs();
141  return std::string();
142}
143
144void HtmlDialogView::OnDialogClosed(const std::string& json_retval) {
145  HtmlDialogTabContentsDelegate::Detach();
146  if (delegate_) {
147    HtmlDialogUIDelegate* dialog_delegate = delegate_;
148    delegate_ = NULL;  // We will not communicate further with the delegate.
149    dialog_delegate->OnDialogClosed(json_retval);
150  }
151  window()->CloseWindow();
152}
153
154void HtmlDialogView::OnWindowClosed() {
155  if (delegate_)
156      delegate_->OnWindowClosed();
157}
158
159void HtmlDialogView::OnCloseContents(TabContents* source,
160                                     bool* out_close_dialog) {
161  if (delegate_)
162    delegate_->OnCloseContents(source, out_close_dialog);
163}
164
165bool HtmlDialogView::ShouldShowDialogTitle() const {
166  if (delegate_)
167    return delegate_->ShouldShowDialogTitle();
168  return true;
169}
170
171bool HtmlDialogView::HandleContextMenu(const ContextMenuParams& params) {
172  if (delegate_)
173    return delegate_->HandleContextMenu(params);
174  return HtmlDialogTabContentsDelegate::HandleContextMenu(params);
175}
176
177////////////////////////////////////////////////////////////////////////////////
178// TabContentsDelegate implementation:
179
180void HtmlDialogView::MoveContents(TabContents* source, const gfx::Rect& pos) {
181  // The contained web page wishes to resize itself. We let it do this because
182  // if it's a dialog we know about, we trust it not to be mean to the user.
183  GetWidget()->SetBounds(pos);
184}
185
186// A simplified version of BrowserView::HandleKeyboardEvent().
187// We don't handle global keyboard shortcuts here, but that's fine since
188// they're all browser-specific. (This may change in the future.)
189void HtmlDialogView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
190#if defined(OS_WIN)
191  // Any unhandled keyboard/character messages should be defproced.
192  // This allows stuff like F10, etc to work correctly.
193  DefWindowProc(event.os_event.hwnd, event.os_event.message,
194                  event.os_event.wParam, event.os_event.lParam);
195#elif defined(OS_LINUX)
196  views::WindowGtk* window_gtk = static_cast<views::WindowGtk*>(window());
197  if (event.os_event && !event.skip_in_browser) {
198    views::KeyEvent views_event(reinterpret_cast<GdkEvent*>(event.os_event));
199    window_gtk->HandleKeyboardEvent(views_event);
200  }
201#endif
202}
203
204void HtmlDialogView::CloseContents(TabContents* source) {
205  bool close_dialog = false;
206  OnCloseContents(source, &close_dialog);
207  if (close_dialog)
208    OnDialogClosed(std::string());
209}
210
211////////////////////////////////////////////////////////////////////////////////
212// HtmlDialogView:
213
214void HtmlDialogView::InitDialog() {
215  // Now Init the DOMView. This view runs in its own process to render the html.
216  DOMView::Init(profile(), NULL);
217
218  tab_contents_->set_delegate(this);
219
220  // Set the delegate. This must be done before loading the page. See
221  // the comment above HtmlDialogUI in its header file for why.
222  HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
223                                                  this);
224
225  // Pressing the ESC key will close the dialog.
226  AddAccelerator(views::Accelerator(ui::VKEY_ESCAPE, false, false, false));
227
228  DOMView::LoadURL(GetDialogContentURL());
229}
230