Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / shell / browser / shell_views.cc
blob7d8309a723382d186ffcfbc27ed86e7e8221e85f
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/controls/button/label_button.h"
20 #include "ui/views/controls/textfield/textfield.h"
21 #include "ui/views/controls/textfield/textfield_controller.h"
22 #include "ui/views/controls/webview/webview.h"
23 #include "ui/views/layout/fill_layout.h"
24 #include "ui/views/layout/grid_layout.h"
25 #include "ui/views/test/desktop_test_views_delegate.h"
26 #include "ui/views/view.h"
27 #include "ui/views/widget/desktop_aura/desktop_screen.h"
28 #include "ui/views/widget/widget.h"
29 #include "ui/views/widget/widget_delegate.h"
31 #if defined(OS_CHROMEOS)
32 #include "chromeos/dbus/dbus_thread_manager.h"
33 #include "ui/aura/test/test_screen.h"
34 #include "ui/shell/minimal_shell.h"
35 #endif
37 #if defined(OS_WIN)
38 #include <fcntl.h>
39 #include <io.h>
40 #endif
42 namespace content {
44 namespace {
45 // ViewDelegate implementation for aura content shell
46 class ShellViewsDelegateAura : public views::DesktopTestViewsDelegate {
47 public:
48 ShellViewsDelegateAura() : use_transparent_windows_(false) {
51 virtual ~ShellViewsDelegateAura() {
54 void SetUseTransparentWindows(bool transparent) {
55 use_transparent_windows_ = transparent;
58 // Overridden from views::TestViewsDelegate:
59 virtual bool UseTransparentWindows() const OVERRIDE {
60 return use_transparent_windows_;
63 private:
64 bool use_transparent_windows_;
66 DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegateAura);
69 // Maintain the UI controls and web view for content shell
70 class ShellWindowDelegateView : public views::WidgetDelegateView,
71 public views::TextfieldController,
72 public views::ButtonListener {
73 public:
74 enum UIControl {
75 BACK_BUTTON,
76 FORWARD_BUTTON,
77 STOP_BUTTON
80 ShellWindowDelegateView(Shell* shell)
81 : shell_(shell),
82 toolbar_view_(new View),
83 contents_view_(new View) {
85 virtual ~ShellWindowDelegateView() {}
87 // Update the state of UI controls
88 void SetAddressBarURL(const GURL& url) {
89 url_entry_->SetText(ASCIIToUTF16(url.spec()));
91 void SetWebContents(WebContents* web_contents) {
92 contents_view_->SetLayoutManager(new views::FillLayout());
93 web_view_ = new views::WebView(web_contents->GetBrowserContext());
94 web_view_->SetWebContents(web_contents);
95 web_contents->GetView()->Focus();
96 contents_view_->AddChildView(web_view_);
97 Layout();
99 void SetWindowTitle(const string16& title) { title_ = title; }
100 void EnableUIControl(UIControl control, bool is_enabled) {
101 if (control == BACK_BUTTON) {
102 back_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
103 : views::CustomButton::STATE_DISABLED);
104 } else if (control == FORWARD_BUTTON) {
105 forward_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
106 : views::CustomButton::STATE_DISABLED);
107 } else if (control == STOP_BUTTON) {
108 stop_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
109 : views::CustomButton::STATE_DISABLED);
113 private:
114 // Initialize the UI control contained in shell window
115 void InitShellWindow() {
116 set_background(views::Background::CreateStandardPanelBackground());
118 views::GridLayout* layout = new views::GridLayout(this);
119 SetLayoutManager(layout);
121 views::ColumnSet* column_set = layout->AddColumnSet(0);
122 column_set->AddPaddingColumn(0, 2);
123 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
124 views::GridLayout::USE_PREF, 0, 0);
125 column_set->AddPaddingColumn(0, 2);
127 layout->AddPaddingRow(0, 2);
129 // Add toolbar buttons and URL text field
131 layout->StartRow(0, 0);
132 views::GridLayout* toolbar_layout = new views::GridLayout(toolbar_view_);
133 toolbar_view_->SetLayoutManager(toolbar_layout);
135 views::ColumnSet* toolbar_column_set =
136 toolbar_layout->AddColumnSet(0);
137 // Back button
138 back_button_ = new views::LabelButton(this, ASCIIToUTF16("Back"));
139 back_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
140 gfx::Size back_button_size = back_button_->GetPreferredSize();
141 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
142 views::GridLayout::CENTER, 0,
143 views::GridLayout::FIXED,
144 back_button_size.width(),
145 back_button_size.width() / 2);
146 // Forward button
147 forward_button_ = new views::LabelButton(this, ASCIIToUTF16("Forward"));
148 forward_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
149 gfx::Size forward_button_size = forward_button_->GetPreferredSize();
150 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
151 views::GridLayout::CENTER, 0,
152 views::GridLayout::FIXED,
153 forward_button_size.width(),
154 forward_button_size.width() / 2);
155 // Refresh button
156 refresh_button_ = new views::LabelButton(this, ASCIIToUTF16("Refresh"));
157 refresh_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
158 gfx::Size refresh_button_size = refresh_button_->GetPreferredSize();
159 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
160 views::GridLayout::CENTER, 0,
161 views::GridLayout::FIXED,
162 refresh_button_size.width(),
163 refresh_button_size.width() / 2);
164 // Stop button
165 stop_button_ = new views::LabelButton(this, ASCIIToUTF16("Stop"));
166 stop_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
167 gfx::Size stop_button_size = stop_button_->GetPreferredSize();
168 toolbar_column_set->AddColumn(views::GridLayout::CENTER,
169 views::GridLayout::CENTER, 0,
170 views::GridLayout::FIXED,
171 stop_button_size.width(),
172 stop_button_size.width() / 2);
173 toolbar_column_set->AddPaddingColumn(0, 2);
174 // URL entry
175 url_entry_ = new views::Textfield();
176 url_entry_->SetController(this);
177 toolbar_column_set->AddColumn(views::GridLayout::FILL,
178 views::GridLayout::FILL, 1,
179 views::GridLayout::USE_PREF, 0, 0);
181 // Fill up the first row
182 toolbar_layout->StartRow(0, 0);
183 toolbar_layout->AddView(back_button_);
184 toolbar_layout->AddView(forward_button_);
185 toolbar_layout->AddView(refresh_button_);
186 toolbar_layout->AddView(stop_button_);
187 toolbar_layout->AddView(url_entry_);
189 layout->AddView(toolbar_view_);
192 layout->AddPaddingRow(0, 5);
194 // Add web contents view as the second row
196 layout->StartRow(1, 0);
197 layout->AddView(contents_view_);
200 layout->AddPaddingRow(0, 5);
202 // Overridden from TextfieldController
203 virtual void ContentsChanged(views::Textfield* sender,
204 const string16& new_contents) OVERRIDE {
206 virtual bool HandleKeyEvent(views::Textfield* sender,
207 const ui::KeyEvent& key_event) OVERRIDE {
208 if (sender == url_entry_ && key_event.key_code() == ui::VKEY_RETURN) {
209 std::string text = UTF16ToUTF8(url_entry_->text());
210 GURL url(text);
211 if (!url.has_scheme()) {
212 url = GURL(std::string("http://") + std::string(text));
213 url_entry_->SetText(ASCIIToUTF16(url.spec()));
215 shell_->LoadURL(url);
216 return true;
218 return false;
221 // Overridden from ButtonListener
222 virtual void ButtonPressed(views::Button* sender,
223 const ui::Event& event) OVERRIDE {
224 if (sender == back_button_)
225 shell_->GoBackOrForward(-1);
226 else if (sender == forward_button_)
227 shell_->GoBackOrForward(1);
228 else if (sender == refresh_button_)
229 shell_->Reload();
230 else if (sender == stop_button_)
231 shell_->Stop();
234 // Overridden from WidgetDelegateView
235 virtual bool CanResize() const OVERRIDE { return true; }
236 virtual bool CanMaximize() const OVERRIDE { return true; }
237 virtual string16 GetWindowTitle() const OVERRIDE {
238 return title_;
240 virtual void WindowClosing() OVERRIDE {
241 if (shell_) {
242 delete shell_;
243 shell_ = NULL;
246 virtual View* GetContentsView() OVERRIDE { return this; }
248 // Overridden from View
249 virtual void ViewHierarchyChanged(
250 const ViewHierarchyChangedDetails& details) OVERRIDE {
251 if (details.is_add && details.child == this) {
252 InitShellWindow();
256 private:
257 // Hold a reference of Shell for deleting it when the window is closing
258 Shell* shell_;
260 // Window title
261 string16 title_;
263 // Toolbar view contains forward/backward/reload button and URL entry
264 View* toolbar_view_;
265 views::LabelButton* back_button_;
266 views::LabelButton* forward_button_;
267 views::LabelButton* refresh_button_;
268 views::LabelButton* stop_button_;
269 views::Textfield* url_entry_;
271 // Contents view contains the web contents view
272 View* contents_view_;
273 views::WebView* web_view_;
275 DISALLOW_COPY_AND_ASSIGN(ShellWindowDelegateView);
278 } // namespace
280 #if defined(OS_CHROMEOS)
281 shell::MinimalShell* Shell::minimal_shell_ = NULL;
282 #endif
283 views::ViewsDelegate* Shell::views_delegate_ = NULL;
285 // static
286 void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
287 #if defined(OS_WIN)
288 _setmode(_fileno(stdout), _O_BINARY);
289 _setmode(_fileno(stderr), _O_BINARY);
290 #endif
291 #if defined(OS_CHROMEOS)
292 chromeos::DBusThreadManager::Initialize();
293 gfx::Screen::SetScreenInstance(
294 gfx::SCREEN_TYPE_NATIVE, aura::TestScreen::Create());
295 minimal_shell_ = new shell::MinimalShell(default_window_size);
296 #else
297 gfx::Screen::SetScreenInstance(
298 gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
299 #endif
300 views_delegate_ = new ShellViewsDelegateAura();
303 void Shell::PlatformExit() {
304 std::vector<Shell*> windows = windows_;
305 for (std::vector<Shell*>::iterator it = windows.begin();
306 it != windows.end(); ++it) {
307 (*it)->window_widget_->Close();
309 #if defined(OS_CHROMEOS)
310 if (minimal_shell_)
311 delete minimal_shell_;
312 #endif
313 if (views_delegate_)
314 delete views_delegate_;
315 #if defined(OS_CHROMEOS)
316 chromeos::DBusThreadManager::Shutdown();
317 #endif
318 aura::Env::DeleteInstance();
321 void Shell::PlatformCleanUp() {
324 void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
325 ShellWindowDelegateView* delegate_view =
326 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
327 if (control == BACK_BUTTON) {
328 delegate_view->EnableUIControl(ShellWindowDelegateView::BACK_BUTTON,
329 is_enabled);
330 } else if (control == FORWARD_BUTTON) {
331 delegate_view->EnableUIControl(ShellWindowDelegateView::FORWARD_BUTTON,
332 is_enabled);
333 } else if (control == STOP_BUTTON) {
334 delegate_view->EnableUIControl(ShellWindowDelegateView::STOP_BUTTON,
335 is_enabled);
339 void Shell::PlatformSetAddressBarURL(const GURL& url) {
340 ShellWindowDelegateView* delegate_view =
341 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
342 delegate_view->SetAddressBarURL(url);
345 void Shell::PlatformSetIsLoading(bool loading) {
348 void Shell::PlatformCreateWindow(int width, int height) {
349 #if defined(OS_CHROMEOS)
350 window_widget_ =
351 views::Widget::CreateWindowWithContextAndBounds(
352 new ShellWindowDelegateView(this),
353 minimal_shell_->GetDefaultParent(NULL, NULL, gfx::Rect()),
354 gfx::Rect(0, 0, width, height));
355 #else
356 window_widget_ =
357 views::Widget::CreateWindowWithBounds(new ShellWindowDelegateView(this),
358 gfx::Rect(0, 0, width, height));
359 #endif
361 window_ = window_widget_->GetNativeWindow();
362 // Call ShowRootWindow on RootWindow created by MinimalShell without
363 // which XWindow owned by RootWindow doesn't get mapped.
364 window_->GetRootWindow()->ShowRootWindow();
365 window_widget_->Show();
368 void Shell::PlatformSetContents() {
369 ShellWindowDelegateView* delegate_view =
370 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
371 delegate_view->SetWebContents(web_contents_.get());
374 void Shell::PlatformResizeSubViews() {
377 void Shell::Close() {
378 window_widget_->CloseNow();
381 void Shell::PlatformSetTitle(const string16& title) {
382 ShellWindowDelegateView* delegate_view =
383 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
384 delegate_view->SetWindowTitle(title);
385 window_widget_->UpdateWindowTitle();
388 } // namespace content