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