Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / extensions / extension_dialog.cc
1 // Copyright (c) 2012 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/extensions/extension_dialog.h"
6
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/extension_view_host.h"
9 #include "chrome/browser/extensions/extension_view_host_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/views/constrained_window_views.h"
12 #include "chrome/browser/ui/views/extensions/extension_dialog_observer.h"
13 #include "content/public/browser/notification_details.h"
14 #include "content/public/browser/notification_source.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/render_widget_host_view.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_view.h"
19 #include "ui/base/base_window.h"
20 #include "ui/gfx/screen.h"
21 #include "ui/views/background.h"
22 #include "ui/views/widget/widget.h"
23 #include "url/gurl.h"
24
25 using content::BrowserContext;
26 using content::WebContents;
27
28 ExtensionDialog::ExtensionDialog(extensions::ExtensionViewHost* host,
29                                  ExtensionDialogObserver* observer)
30     : host_(host),
31       observer_(observer) {
32   AddRef();  // Balanced in DeleteDelegate();
33
34   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
35                  content::Source<BrowserContext>(host->browser_context()));
36   // Listen for the containing view calling window.close();
37   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
38                  content::Source<BrowserContext>(host->browser_context()));
39   // Listen for a crash or other termination of the extension process.
40   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
41                  content::Source<BrowserContext>(host->browser_context()));
42 }
43
44 ExtensionDialog::~ExtensionDialog() {
45 }
46
47 // static
48 ExtensionDialog* ExtensionDialog::Show(
49     const GURL& url,
50     aura::Window* parent_window,
51     Profile* profile,
52     WebContents* web_contents,
53     int width,
54     int height,
55     int min_width,
56     int min_height,
57     const base::string16& title,
58     ExtensionDialogObserver* observer) {
59   extensions::ExtensionViewHost* host =
60       extensions::ExtensionViewHostFactory::CreateDialogHost(url, profile);
61   if (!host)
62     return NULL;
63   // Preferred size must be set before views::Widget::CreateWindowWithParent
64   // is called because CreateWindowWithParent refers the result of CanResize().
65   host->view()->SetPreferredSize(gfx::Size(width, height));
66   host->view()->set_minimum_size(gfx::Size(min_width, min_height));
67   host->SetAssociatedWebContents(web_contents);
68
69   DCHECK(parent_window);
70   ExtensionDialog* dialog = new ExtensionDialog(host, observer);
71   dialog->set_title(title);
72   dialog->InitWindow(parent_window, width, height);
73
74   // Show a white background while the extension loads.  This is prettier than
75   // flashing a black unfilled window frame.
76   host->view()->set_background(
77       views::Background::CreateSolidBackground(0xFF, 0xFF, 0xFF));
78   host->view()->SetVisible(true);
79
80   // Ensure the DOM JavaScript can respond immediately to keyboard shortcuts.
81   host->host_contents()->GetView()->Focus();
82   return dialog;
83 }
84
85 void ExtensionDialog::InitWindow(aura::Window* parent,
86                                  int width,
87                                  int height) {
88   views::Widget* window = CreateBrowserModalDialogViews(this, parent);
89
90   // Center the window over the browser.
91   gfx::Point center = parent->GetBoundsInScreen().CenterPoint();
92   int x = center.x() - width / 2;
93   int y = center.y() - height / 2;
94   // Ensure the top left and top right of the window are on screen, with
95   // priority given to the top left.
96   gfx::Rect screen_rect = gfx::Screen::GetScreenFor(parent)->
97       GetDisplayNearestPoint(center).bounds();
98   gfx::Rect bounds_rect = gfx::Rect(x, y, width, height);
99   bounds_rect.AdjustToFit(screen_rect);
100   window->SetBounds(bounds_rect);
101
102   window->Show();
103   // TODO(jamescook): Remove redundant call to Activate()?
104   window->Activate();
105 }
106
107 void ExtensionDialog::ObserverDestroyed() {
108   observer_ = NULL;
109 }
110
111 void ExtensionDialog::MaybeFocusRenderView() {
112   views::FocusManager* focus_manager = GetWidget()->GetFocusManager();
113   DCHECK(focus_manager != NULL);
114
115   // Already there's a focused view, so no need to switch the focus.
116   if (focus_manager->GetFocusedView())
117     return;
118
119   content::RenderWidgetHostView* view = host()->render_view_host()->GetView();
120   if (!view)
121     return;
122
123   view->Focus();
124 }
125
126 /////////////////////////////////////////////////////////////////////////////
127 // views::DialogDelegate overrides.
128
129 int ExtensionDialog::GetDialogButtons() const {
130   // The only user, SelectFileDialogExtension, provides its own buttons.
131   return ui::DIALOG_BUTTON_NONE;
132 }
133
134 bool ExtensionDialog::CanResize() const {
135   // Can resize only if minimum contents size set.
136   return host_->view()->GetPreferredSize() != gfx::Size();
137 }
138
139 void ExtensionDialog::SetMinimumContentsSize(int width, int height) {
140   host_->view()->SetPreferredSize(gfx::Size(width, height));
141 }
142
143 ui::ModalType ExtensionDialog::GetModalType() const {
144   return ui::MODAL_TYPE_WINDOW;
145 }
146
147 bool ExtensionDialog::ShouldShowWindowTitle() const {
148   return !window_title_.empty();
149 }
150
151 base::string16 ExtensionDialog::GetWindowTitle() const {
152   return window_title_;
153 }
154
155 void ExtensionDialog::WindowClosing() {
156   if (observer_)
157     observer_->ExtensionDialogClosing(this);
158 }
159
160 void ExtensionDialog::DeleteDelegate() {
161   // The window has finished closing.  Allow ourself to be deleted.
162   Release();
163 }
164
165 views::Widget* ExtensionDialog::GetWidget() {
166   return host_->view()->GetWidget();
167 }
168
169 const views::Widget* ExtensionDialog::GetWidget() const {
170   return host_->view()->GetWidget();
171 }
172
173 views::View* ExtensionDialog::GetContentsView() {
174   return host_->view();
175 }
176
177 bool ExtensionDialog::UseNewStyleForThisDialog() const {
178   return false;
179 }
180
181 /////////////////////////////////////////////////////////////////////////////
182 // content::NotificationObserver overrides.
183
184 void ExtensionDialog::Observe(int type,
185                              const content::NotificationSource& source,
186                              const content::NotificationDetails& details) {
187   switch (type) {
188     case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING:
189       // Avoid potential overdraw by removing the temporary background after
190       // the extension finishes loading.
191       host_->view()->set_background(NULL);
192       // The render view is created during the LoadURL(), so we should
193       // set the focus to the view if nobody else takes the focus.
194       if (content::Details<extensions::ExtensionHost>(host()) == details)
195         MaybeFocusRenderView();
196       break;
197     case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE:
198       // If we aren't the host of the popup, then disregard the notification.
199       if (content::Details<extensions::ExtensionHost>(host()) != details)
200         return;
201       GetWidget()->Close();
202       break;
203     case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED:
204       if (content::Details<extensions::ExtensionHost>(host()) != details)
205         return;
206       if (observer_)
207         observer_->ExtensionTerminated(this);
208       break;
209     default:
210       NOTREACHED() << L"Received unexpected notification";
211       break;
212   }
213 }