IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / shell / browser / shell_views.cc
blob741c6badaa5bd85ed5430002b51eb5ecb91266b5
1 // Copyright 2013 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 "content/shell/browser/shell.h"
7 #include "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "content/public/browser/web_contents.h"
10 #include "content/public/browser/web_contents_view.h"
11 #include "ui/aura/env.h"
12 #include "ui/aura/root_window.h"
13 #include "ui/aura/window.h"
14 #include "ui/base/accessibility/accessibility_types.h"
15 #include "ui/base/clipboard/clipboard.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/events/event.h"
18 #include "ui/gfx/screen.h"
19 #include "ui/views/background.h"
20 #include "ui/views/controls/button/label_button.h"
21 #include "ui/views/controls/textfield/textfield.h"
22 #include "ui/views/controls/textfield/textfield_controller.h"
23 #include "ui/views/controls/webview/webview.h"
24 #include "ui/views/layout/fill_layout.h"
25 #include "ui/views/layout/grid_layout.h"
26 #include "ui/views/test/desktop_test_views_delegate.h"
27 #include "ui/views/view.h"
28 #include "ui/views/widget/desktop_aura/desktop_screen.h"
29 #include "ui/views/widget/widget.h"
30 #include "ui/views/widget/widget_delegate.h"
32 #if defined(OS_CHROMEOS)
33 #include "chromeos/dbus/dbus_thread_manager.h"
34 #include "ui/aura/test/test_screen.h"
35 #include "ui/wm/test/wm_test_helper.h"
36 #endif
38 #if defined(OS_WIN)
39 #include <fcntl.h>
40 #include <io.h>
41 #endif
43 namespace content {
45 namespace {
46 // ViewDelegate implementation for aura content shell
47 class ShellViewsDelegateAura : public views::DesktopTestViewsDelegate {
48 public:
49 ShellViewsDelegateAura() : use_transparent_windows_(false) {
52 virtual ~ShellViewsDelegateAura() {
55 void SetUseTransparentWindows(bool transparent) {
56 use_transparent_windows_ = transparent;
59 private:
60 bool use_transparent_windows_;
62 DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegateAura);
65 // Maintain the UI controls and web view for content shell
66 class ShellWindowDelegateView : public views::WidgetDelegateView,
67 public views::TextfieldController,
68 public views::ButtonListener {
69 public:
70 enum UIControl {
71 BACK_BUTTON,
72 FORWARD_BUTTON,
73 STOP_BUTTON
76 ShellWindowDelegateView(Shell* shell)
77 : shell_(shell),
78 toolbar_view_(new View),
79 contents_view_(new View) {
81 virtual ~ShellWindowDelegateView() {}
83 // Update the state of UI controls
84 void SetAddressBarURL(const GURL& url) {
85 url_entry_->SetText(base::ASCIIToUTF16(url.spec()));
87 void SetWebContents(WebContents* web_contents, const gfx::Size& size) {
88 contents_view_->SetLayoutManager(new views::FillLayout());
89 web_view_ = new views::WebView(web_contents->GetBrowserContext());
90 web_view_->SetWebContents(web_contents);
91 web_view_->SetPreferredSize(size);
92 web_contents->GetView()->Focus();
93 contents_view_->AddChildView(web_view_);
94 Layout();
96 // Resize the widget, keeping the same origin.
97 gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
98 bounds.set_size(GetWidget()->GetRootView()->GetPreferredSize());
99 GetWidget()->SetBounds(bounds);
101 // Resizing a widget on chromeos doesn't automatically resize the root, need
102 // to explicitly do that.
103 #if defined(OS_CHROMEOS)
104 GetWidget()->GetNativeWindow()->GetDispatcher()->SetHostSize(
105 bounds.size());
106 #endif
109 void SetWindowTitle(const base::string16& title) { title_ = title; }
110 void EnableUIControl(UIControl control, bool is_enabled) {
111 if (control == BACK_BUTTON) {
112 back_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
113 : views::CustomButton::STATE_DISABLED);
114 } else if (control == FORWARD_BUTTON) {
115 forward_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
116 : views::CustomButton::STATE_DISABLED);
117 } else if (control == STOP_BUTTON) {
118 stop_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
119 : views::CustomButton::STATE_DISABLED);
123 private:
124 // Initialize the UI control contained in shell window
125 void InitShellWindow() {
126 set_background(views::Background::CreateStandardPanelBackground());
128 views::GridLayout* layout = new views::GridLayout(this);
129 SetLayoutManager(layout);
131 views::ColumnSet* column_set = layout->AddColumnSet(0);
132 column_set->AddPaddingColumn(0, 2);
133 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
134 views::GridLayout::USE_PREF, 0, 0);
135 column_set->AddPaddingColumn(0, 2);
137 layout->AddPaddingRow(0, 2);
139 // Add toolbar buttons and URL text field
141 layout->StartRow(0, 0);
142 views::GridLayout* toolbar_layout = new views::GridLayout(toolbar_view_);
143 toolbar_view_->SetLayoutManager(toolbar_layout);
145 views::ColumnSet* toolbar_column_set =
146 toolbar_layout->AddColumnSet(0);
147 // Back button
148 back_button_ = new views::LabelButton(this, base::ASCIIToUTF16("Back"));
149 back_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
150 gfx::Size back_button_size = back_button_->GetPreferredSize();
151 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
152 views::GridLayout::CENTER, 0,
153 views::GridLayout::FIXED,
154 back_button_size.width(),
155 back_button_size.width() / 2);
156 // Forward button
157 forward_button_ =
158 new views::LabelButton(this, base::ASCIIToUTF16("Forward"));
159 forward_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
160 gfx::Size forward_button_size = forward_button_->GetPreferredSize();
161 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
162 views::GridLayout::CENTER, 0,
163 views::GridLayout::FIXED,
164 forward_button_size.width(),
165 forward_button_size.width() / 2);
166 // Refresh button
167 refresh_button_ =
168 new views::LabelButton(this, base::ASCIIToUTF16("Refresh"));
169 refresh_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
170 gfx::Size refresh_button_size = refresh_button_->GetPreferredSize();
171 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
172 views::GridLayout::CENTER, 0,
173 views::GridLayout::FIXED,
174 refresh_button_size.width(),
175 refresh_button_size.width() / 2);
176 // Stop button
177 stop_button_ = new views::LabelButton(this, base::ASCIIToUTF16("Stop"));
178 stop_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
179 gfx::Size stop_button_size = stop_button_->GetPreferredSize();
180 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
181 views::GridLayout::CENTER, 0,
182 views::GridLayout::FIXED,
183 stop_button_size.width(),
184 stop_button_size.width() / 2);
185 toolbar_column_set->AddPaddingColumn(0, 2);
186 // URL entry
187 url_entry_ = new views::Textfield();
188 url_entry_->SetController(this);
189 toolbar_column_set->AddColumn(views::GridLayout::FILL,
190 views::GridLayout::FILL, 1,
191 views::GridLayout::USE_PREF, 0, 0);
193 // Fill up the first row
194 toolbar_layout->StartRow(0, 0);
195 toolbar_layout->AddView(back_button_);
196 toolbar_layout->AddView(forward_button_);
197 toolbar_layout->AddView(refresh_button_);
198 toolbar_layout->AddView(stop_button_);
199 toolbar_layout->AddView(url_entry_);
201 layout->AddView(toolbar_view_);
204 layout->AddPaddingRow(0, 5);
206 // Add web contents view as the second row
208 layout->StartRow(1, 0);
209 layout->AddView(contents_view_);
212 layout->AddPaddingRow(0, 5);
214 // Overridden from TextfieldController
215 virtual void ContentsChanged(views::Textfield* sender,
216 const base::string16& new_contents) OVERRIDE {
218 virtual bool HandleKeyEvent(views::Textfield* sender,
219 const ui::KeyEvent& key_event) OVERRIDE {
220 if (sender == url_entry_ && key_event.key_code() == ui::VKEY_RETURN) {
221 std::string text = base::UTF16ToUTF8(url_entry_->text());
222 GURL url(text);
223 if (!url.has_scheme()) {
224 url = GURL(std::string("http://") + std::string(text));
225 url_entry_->SetText(base::ASCIIToUTF16(url.spec()));
227 shell_->LoadURL(url);
228 return true;
230 return false;
233 // Overridden from ButtonListener
234 virtual void ButtonPressed(views::Button* sender,
235 const ui::Event& event) OVERRIDE {
236 if (sender == back_button_)
237 shell_->GoBackOrForward(-1);
238 else if (sender == forward_button_)
239 shell_->GoBackOrForward(1);
240 else if (sender == refresh_button_)
241 shell_->Reload();
242 else if (sender == stop_button_)
243 shell_->Stop();
246 // Overridden from WidgetDelegateView
247 virtual bool CanResize() const OVERRIDE { return true; }
248 virtual bool CanMaximize() const OVERRIDE { return true; }
249 virtual base::string16 GetWindowTitle() const OVERRIDE {
250 return title_;
252 virtual void WindowClosing() OVERRIDE {
253 if (shell_) {
254 delete shell_;
255 shell_ = NULL;
258 virtual View* GetContentsView() OVERRIDE { return this; }
260 // Overridden from View
261 virtual void ViewHierarchyChanged(
262 const ViewHierarchyChangedDetails& details) OVERRIDE {
263 if (details.is_add && details.child == this) {
264 InitShellWindow();
268 private:
269 // Hold a reference of Shell for deleting it when the window is closing
270 Shell* shell_;
272 // Window title
273 base::string16 title_;
275 // Toolbar view contains forward/backward/reload button and URL entry
276 View* toolbar_view_;
277 views::LabelButton* back_button_;
278 views::LabelButton* forward_button_;
279 views::LabelButton* refresh_button_;
280 views::LabelButton* stop_button_;
281 views::Textfield* url_entry_;
283 // Contents view contains the web contents view
284 View* contents_view_;
285 views::WebView* web_view_;
287 DISALLOW_COPY_AND_ASSIGN(ShellWindowDelegateView);
290 } // namespace
292 #if defined(OS_CHROMEOS)
293 wm::WMTestHelper* Shell::wm_test_helper_ = NULL;
294 #endif
295 views::ViewsDelegate* Shell::views_delegate_ = NULL;
297 // static
298 void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
299 #if defined(OS_WIN)
300 _setmode(_fileno(stdout), _O_BINARY);
301 _setmode(_fileno(stderr), _O_BINARY);
302 #endif
303 #if defined(OS_CHROMEOS)
304 chromeos::DBusThreadManager::Initialize();
305 gfx::Screen::SetScreenInstance(
306 gfx::SCREEN_TYPE_NATIVE, aura::TestScreen::Create());
307 wm_test_helper_ = new wm::WMTestHelper(default_window_size);
308 #else
309 gfx::Screen::SetScreenInstance(
310 gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
311 #endif
312 views_delegate_ = new ShellViewsDelegateAura();
315 void Shell::PlatformExit() {
316 #if defined(OS_CHROMEOS)
317 if (wm_test_helper_)
318 delete wm_test_helper_;
319 #endif
320 if (views_delegate_)
321 delete views_delegate_;
322 #if defined(OS_CHROMEOS)
323 chromeos::DBusThreadManager::Shutdown();
324 #endif
325 aura::Env::DeleteInstance();
328 void Shell::PlatformCleanUp() {
331 void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
332 ShellWindowDelegateView* delegate_view =
333 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
334 if (control == BACK_BUTTON) {
335 delegate_view->EnableUIControl(ShellWindowDelegateView::BACK_BUTTON,
336 is_enabled);
337 } else if (control == FORWARD_BUTTON) {
338 delegate_view->EnableUIControl(ShellWindowDelegateView::FORWARD_BUTTON,
339 is_enabled);
340 } else if (control == STOP_BUTTON) {
341 delegate_view->EnableUIControl(ShellWindowDelegateView::STOP_BUTTON,
342 is_enabled);
346 void Shell::PlatformSetAddressBarURL(const GURL& url) {
347 ShellWindowDelegateView* delegate_view =
348 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
349 delegate_view->SetAddressBarURL(url);
352 void Shell::PlatformSetIsLoading(bool loading) {
355 void Shell::PlatformCreateWindow(int width, int height) {
356 #if defined(OS_CHROMEOS)
357 window_widget_ = views::Widget::CreateWindowWithContextAndBounds(
358 new ShellWindowDelegateView(this),
359 wm_test_helper_->GetDefaultParent(NULL, NULL, gfx::Rect()),
360 gfx::Rect(0, 0, width, height));
361 #else
362 window_widget_ = views::Widget::CreateWindowWithBounds(
363 new ShellWindowDelegateView(this), gfx::Rect(0, 0, width, height));
364 #endif
366 content_size_ = gfx::Size(width, height);
368 window_ = window_widget_->GetNativeWindow();
369 // Call ShowRootWindow on RootWindow created by WMTestHelper without
370 // which XWindow owned by RootWindow doesn't get mapped.
371 window_->GetDispatcher()->host()->Show();
372 window_widget_->Show();
375 void Shell::PlatformSetContents() {
376 ShellWindowDelegateView* delegate_view =
377 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
378 delegate_view->SetWebContents(web_contents_.get(), content_size_);
381 void Shell::PlatformResizeSubViews() {
384 void Shell::Close() {
385 window_widget_->CloseNow();
388 void Shell::PlatformSetTitle(const base::string16& title) {
389 ShellWindowDelegateView* delegate_view =
390 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
391 delegate_view->SetWindowTitle(title);
392 window_widget_->UpdateWindowTitle();
395 } // namespace content