OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/shell/shell.h" | 5 #include "content/shell/shell.h" |
6 | 6 |
| 7 #include "base/utf_string_conversions.h" |
| 8 #include "ui/aura/desktop/desktop_screen.h" |
| 9 #include "ui/aura/desktop/desktop_stacking_client.h" |
| 10 #include "ui/aura/display_manager.h" |
| 11 #include "ui/aura/env.h" |
| 12 #include "ui/aura/root_window.h" |
| 13 #include "ui/aura/window.h" |
| 14 #include "ui/aura/single_display_manager.h" |
| 15 #include "ui/base/accessibility/accessibility_types.h" |
| 16 #include "ui/base/clipboard/clipboard.h" |
| 17 #include "ui/base/resource/resource_bundle.h" |
| 18 #include "ui/gfx/screen.h" |
| 19 #include "ui/views/controls/button/text_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/view.h" |
| 26 #include "ui/views/views_delegate.h" |
| 27 #include "ui/views/widget/desktop_native_widget_helper_aura.h" |
| 28 #include "ui/views/widget/widget.h" |
| 29 #include "ui/views/widget/widget_delegate.h" |
| 30 |
| 31 namespace views { |
| 32 // ViewDelegate implementation for aura content shell |
| 33 class ShellViewsDelegateAura : public ViewsDelegate { |
| 34 public: |
| 35 ShellViewsDelegateAura() |
| 36 : use_transparent_windows_(false) { |
| 37 DCHECK(!ViewsDelegate::views_delegate); |
| 38 ViewsDelegate::views_delegate = this; |
| 39 } |
| 40 |
| 41 virtual ~ShellViewsDelegateAura() { |
| 42 ViewsDelegate::views_delegate = NULL; |
| 43 } |
| 44 |
| 45 void SetUseTransparentWindows(bool transparent) { |
| 46 use_transparent_windows_ = transparent; |
| 47 } |
| 48 |
| 49 // Overridden from ViewsDelegate: |
| 50 virtual ui::Clipboard* GetClipboard() const OVERRIDE { |
| 51 if (!clipboard_.get()) { |
| 52 clipboard_.reset(new ui::Clipboard); |
| 53 } |
| 54 return clipboard_.get(); |
| 55 } |
| 56 |
| 57 virtual void SaveWindowPlacement(const Widget* window, |
| 58 const std::string& window_name, |
| 59 const gfx::Rect& bounds, |
| 60 ui::WindowShowState show_state) OVERRIDE { |
| 61 } |
| 62 |
| 63 virtual bool GetSavedWindowPlacement( |
| 64 const std::string& window_name, |
| 65 gfx::Rect* bounds, |
| 66 ui::WindowShowState* show_state) const OVERRIDE { |
| 67 return false; |
| 68 } |
| 69 |
| 70 virtual void NotifyAccessibilityEvent( |
| 71 View* view, ui::AccessibilityTypes::Event event_type) OVERRIDE {} |
| 72 |
| 73 virtual void NotifyMenuItemFocused(const string16& menu_name, |
| 74 const string16& menu_item_name, |
| 75 int item_index, |
| 76 int item_count, |
| 77 bool has_submenu) OVERRIDE {} |
| 78 #if defined(OS_WIN) |
| 79 virtual HICON GetDefaultWindowIcon() const OVERRIDE { |
| 80 return NULL; |
| 81 } |
| 82 #endif |
| 83 virtual NonClientFrameView* CreateDefaultNonClientFrameView( |
| 84 Widget* widget) OVERRIDE { |
| 85 return NULL; |
| 86 } |
| 87 virtual bool UseTransparentWindows() const OVERRIDE { |
| 88 return use_transparent_windows_; |
| 89 } |
| 90 virtual void AddRef() OVERRIDE {} |
| 91 virtual void ReleaseRef() OVERRIDE {} |
| 92 |
| 93 virtual int GetDispositionForEvent(int event_flags) OVERRIDE { |
| 94 return 0; |
| 95 } |
| 96 |
| 97 virtual views::NativeWidgetHelperAura* CreateNativeWidgetHelper( |
| 98 views::NativeWidgetAura* native_widget) OVERRIDE { |
| 99 return new views::DesktopNativeWidgetHelperAura(native_widget); |
| 100 } |
| 101 |
| 102 virtual content::WebContents* CreateWebContents( |
| 103 content::BrowserContext* browser_context, |
| 104 content::SiteInstance* site_instance) OVERRIDE { |
| 105 return NULL; |
| 106 } |
| 107 |
| 108 private: |
| 109 mutable scoped_ptr<ui::Clipboard> clipboard_; |
| 110 bool use_transparent_windows_; |
| 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegateAura); |
| 113 }; |
| 114 |
| 115 // Maintain the UI controls and web view for content shell |
| 116 class ShellWindowDelegateView : public WidgetDelegateView, |
| 117 public TextfieldController, |
| 118 public ButtonListener { |
| 119 public: |
| 120 enum UIControl { |
| 121 BACK_BUTTON, |
| 122 FORWARD_BUTTON, |
| 123 STOP_BUTTON |
| 124 }; |
| 125 |
| 126 ShellWindowDelegateView(content::Shell* shell) |
| 127 : shell_(shell), |
| 128 toolbar_view_(new View), |
| 129 contents_view_(new View) { |
| 130 } |
| 131 virtual ~ShellWindowDelegateView() {} |
| 132 |
| 133 // Update the state of UI controls |
| 134 void SetAddressBarURL(const GURL& url) { |
| 135 url_entry_->SetText(ASCIIToUTF16(url.spec())); |
| 136 } |
| 137 void SetWebContents(content::WebContents* web_contents) { |
| 138 contents_view_->SetLayoutManager(new FillLayout()); |
| 139 web_view_ = new WebView(web_contents->GetBrowserContext()); |
| 140 web_view_->SetWebContents(web_contents); |
| 141 web_contents->Focus(); |
| 142 contents_view_->AddChildView(web_view_); |
| 143 Layout(); |
| 144 } |
| 145 void SetWindowTitle(const string16& title) { title_ = title; } |
| 146 void EnableUIControl(UIControl control, bool is_enabled) { |
| 147 if (control == BACK_BUTTON) { |
| 148 back_button_->SetState(is_enabled ? CustomButton::BS_NORMAL |
| 149 : CustomButton::BS_DISABLED); |
| 150 } else if (control == FORWARD_BUTTON) { |
| 151 forward_button_->SetState(is_enabled ? CustomButton::BS_NORMAL |
| 152 : CustomButton::BS_DISABLED); |
| 153 } else if (control == STOP_BUTTON) { |
| 154 stop_button_->SetState(is_enabled ? CustomButton::BS_NORMAL |
| 155 : CustomButton::BS_DISABLED); |
| 156 } |
| 157 } |
| 158 |
| 159 private: |
| 160 // Initialize the UI control contained in shell window |
| 161 void InitShellWindow() { |
| 162 set_background(Background::CreateStandardPanelBackground()); |
| 163 |
| 164 GridLayout* layout = new GridLayout(this); |
| 165 SetLayoutManager(layout); |
| 166 |
| 167 ColumnSet* column_set = layout->AddColumnSet(0); |
| 168 column_set->AddPaddingColumn(0, 2); |
| 169 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, |
| 170 GridLayout::USE_PREF, 0, 0); |
| 171 column_set->AddPaddingColumn(0, 2); |
| 172 |
| 173 layout->AddPaddingRow(0, 2); |
| 174 |
| 175 // Add toolbar buttons and URL text field |
| 176 { |
| 177 layout->StartRow(0, 0); |
| 178 GridLayout* toolbar_layout = new GridLayout(toolbar_view_); |
| 179 toolbar_view_->SetLayoutManager(toolbar_layout); |
| 180 |
| 181 ColumnSet* toolbar_column_set = |
| 182 toolbar_layout->AddColumnSet(0); |
| 183 // Back button |
| 184 back_button_ = new NativeTextButton(this, ASCIIToUTF16("Back")); |
| 185 gfx::Size back_button_size = back_button_->GetPreferredSize(); |
| 186 toolbar_column_set->AddColumn(GridLayout::CENTER, |
| 187 GridLayout::CENTER, 0, |
| 188 GridLayout::FIXED, |
| 189 back_button_size.width(), |
| 190 back_button_size.width() / 2); |
| 191 // Forward button |
| 192 forward_button_ = new NativeTextButton(this, ASCIIToUTF16("Forward")); |
| 193 gfx::Size forward_button_size = forward_button_->GetPreferredSize(); |
| 194 toolbar_column_set->AddColumn(GridLayout::CENTER, |
| 195 GridLayout::CENTER, 0, |
| 196 GridLayout::FIXED, |
| 197 forward_button_size.width(), |
| 198 forward_button_size.width() / 2); |
| 199 // Refresh button |
| 200 refresh_button_ = new NativeTextButton(this, ASCIIToUTF16("Refresh")); |
| 201 gfx::Size refresh_button_size = refresh_button_->GetPreferredSize(); |
| 202 toolbar_column_set->AddColumn(GridLayout::CENTER, |
| 203 GridLayout::CENTER, 0, |
| 204 GridLayout::FIXED, |
| 205 refresh_button_size.width(), |
| 206 refresh_button_size.width() / 2); |
| 207 // Stop button |
| 208 stop_button_ = new NativeTextButton(this, ASCIIToUTF16("Stop")); |
| 209 gfx::Size stop_button_size = stop_button_->GetPreferredSize(); |
| 210 toolbar_column_set->AddColumn(GridLayout::CENTER, |
| 211 GridLayout::CENTER, 0, |
| 212 GridLayout::FIXED, |
| 213 stop_button_size.width(), |
| 214 stop_button_size.width() / 2); |
| 215 toolbar_column_set->AddPaddingColumn(0, 2); |
| 216 // URL entry |
| 217 url_entry_ = new Textfield(); |
| 218 url_entry_->SetController(this); |
| 219 toolbar_column_set->AddColumn(GridLayout::FILL, |
| 220 GridLayout::FILL, 1, |
| 221 GridLayout::USE_PREF, 0, 0); |
| 222 |
| 223 // Fill up the first row |
| 224 toolbar_layout->StartRow(0, 0); |
| 225 toolbar_layout->AddView(back_button_); |
| 226 toolbar_layout->AddView(forward_button_); |
| 227 toolbar_layout->AddView(refresh_button_); |
| 228 toolbar_layout->AddView(stop_button_); |
| 229 toolbar_layout->AddView(url_entry_); |
| 230 |
| 231 layout->AddView(toolbar_view_); |
| 232 } |
| 233 |
| 234 layout->AddPaddingRow(0, 5); |
| 235 |
| 236 // Add web contents view as the second row |
| 237 { |
| 238 layout->StartRow(1, 0); |
| 239 layout->AddView(contents_view_); |
| 240 } |
| 241 |
| 242 layout->AddPaddingRow(0, 5); |
| 243 } |
| 244 // Overriden from TextfieldController |
| 245 virtual void ContentsChanged(Textfield* sender, |
| 246 const string16& new_contents) OVERRIDE { |
| 247 } |
| 248 virtual bool HandleKeyEvent(Textfield* sender, |
| 249 const KeyEvent& key_event) OVERRIDE { |
| 250 if (sender == url_entry_ && key_event.key_code() == ui::VKEY_RETURN) { |
| 251 std::string text = UTF16ToUTF8(url_entry_->text()); |
| 252 GURL url(text); |
| 253 if (!url.has_scheme()) { |
| 254 url = GURL(std::string("http://") + std::string(text)); |
| 255 url_entry_->SetText(ASCIIToUTF16(url.spec())); |
| 256 } |
| 257 shell_->LoadURL(url); |
| 258 return true; |
| 259 } |
| 260 return false; |
| 261 } |
| 262 |
| 263 // Overriden from ButtonListener |
| 264 virtual void ButtonPressed(Button* sender, |
| 265 const Event& event) OVERRIDE { |
| 266 if (sender == back_button_) |
| 267 shell_->GoBackOrForward(-1); |
| 268 else if (sender == forward_button_) |
| 269 shell_->GoBackOrForward(1); |
| 270 else if (sender == refresh_button_) |
| 271 shell_->Reload(); |
| 272 else if (sender == stop_button_) |
| 273 shell_->Stop(); |
| 274 } |
| 275 |
| 276 // Overriden from WidgetDelegateView |
| 277 virtual bool CanResize() const OVERRIDE { return true; } |
| 278 virtual bool CanMaximize() const OVERRIDE { return true; } |
| 279 virtual string16 GetWindowTitle() const OVERRIDE { |
| 280 return title_; |
| 281 } |
| 282 virtual void WindowClosing() OVERRIDE { |
| 283 if (shell_) delete shell_; |
| 284 } |
| 285 virtual View* GetContentsView() OVERRIDE { return this; } |
| 286 |
| 287 // Overriden from View |
| 288 virtual void ViewHierarchyChanged(bool is_add, |
| 289 View* parent, |
| 290 View* child) OVERRIDE { |
| 291 if (is_add && child == this) { |
| 292 InitShellWindow(); |
| 293 } |
| 294 } |
| 295 |
| 296 private: |
| 297 // Hold a reference of Shell for deleting it when the window is closing |
| 298 content::Shell* shell_; |
| 299 |
| 300 // Window title |
| 301 string16 title_; |
| 302 |
| 303 // Toolbar view contains forward/backward/reload button and URL entry |
| 304 View* toolbar_view_; |
| 305 NativeTextButton* back_button_; |
| 306 NativeTextButton* forward_button_; |
| 307 NativeTextButton* refresh_button_; |
| 308 NativeTextButton* stop_button_; |
| 309 Textfield* url_entry_; |
| 310 |
| 311 // Contents view contains the web contents view |
| 312 View* contents_view_; |
| 313 WebView* web_view_; |
| 314 |
| 315 DISALLOW_COPY_AND_ASSIGN(ShellWindowDelegateView); |
| 316 }; |
| 317 |
| 318 } // namespace views |
| 319 |
7 namespace content { | 320 namespace content { |
8 | 321 |
| 322 using views::ShellWindowDelegateView; |
| 323 using views::ShellViewsDelegateAura; |
| 324 |
| 325 aura::client::StackingClient* Shell::stacking_client_ = NULL; |
| 326 views::ViewsDelegate* Shell::views_delegate_ = NULL; |
9 // static | 327 // static |
10 void Shell::PlatformInitialize() { | 328 void Shell::PlatformInitialize() { |
| 329 aura::Env::GetInstance()->SetDisplayManager(new aura::SingleDisplayManager); |
| 330 stacking_client_ = new aura::DesktopStackingClient(); |
| 331 gfx::Screen::SetInstance(aura::CreateDesktopScreen()); |
| 332 views_delegate_ = new ShellViewsDelegateAura(); |
| 333 |
| 334 // Loading locale resources for Widget::CreateWindowWithBounds initialization |
| 335 // in which CustomFrameView requires the accessible name for buttons. |
| 336 ui::ResourceBundle::GetSharedInstance().ReloadLocaleResources("en-US"); |
11 } | 337 } |
12 | 338 |
13 base::StringPiece Shell::PlatformResourceProvider(int key) { | 339 base::StringPiece Shell::PlatformResourceProvider(int key) { |
14 return base::StringPiece(); | 340 return base::StringPiece(); |
15 } | 341 } |
16 | 342 |
17 void Shell::PlatformExit() { | 343 void Shell::PlatformExit() { |
| 344 if (stacking_client_) |
| 345 delete stacking_client_; |
| 346 if (views_delegate_) |
| 347 delete views_delegate_; |
| 348 aura::Env::DeleteInstance(); |
18 } | 349 } |
19 | 350 |
20 void Shell::PlatformCleanUp() { | 351 void Shell::PlatformCleanUp() { |
21 } | 352 } |
22 | 353 |
23 void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) { | 354 void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) { |
| 355 ShellWindowDelegateView* delegate_view = |
| 356 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate()); |
| 357 if (control == BACK_BUTTON) { |
| 358 delegate_view->EnableUIControl(ShellWindowDelegateView::BACK_BUTTON, |
| 359 is_enabled); |
| 360 } else if (control == FORWARD_BUTTON) { |
| 361 delegate_view->EnableUIControl(ShellWindowDelegateView::FORWARD_BUTTON, |
| 362 is_enabled); |
| 363 } else if (control == STOP_BUTTON) { |
| 364 delegate_view->EnableUIControl(ShellWindowDelegateView::STOP_BUTTON, |
| 365 is_enabled); |
| 366 } |
24 } | 367 } |
25 | 368 |
26 void Shell::PlatformSetAddressBarURL(const GURL& url) { | 369 void Shell::PlatformSetAddressBarURL(const GURL& url) { |
| 370 ShellWindowDelegateView* delegate_view = |
| 371 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate()); |
| 372 delegate_view->SetAddressBarURL(url); |
27 } | 373 } |
28 | 374 |
29 void Shell::PlatformSetIsLoading(bool loading) { | 375 void Shell::PlatformSetIsLoading(bool loading) { |
30 } | 376 } |
31 | 377 |
32 void Shell::PlatformCreateWindow(int width, int height) { | 378 void Shell::PlatformCreateWindow(int width, int height) { |
| 379 window_widget_ = |
| 380 views::Widget::CreateWindowWithBounds(new ShellWindowDelegateView(this), |
| 381 gfx::Rect(0, 0, width, height)); |
| 382 window_ = window_widget_->GetNativeWindow(); |
| 383 window_widget_->Show(); |
33 } | 384 } |
34 | 385 |
35 void Shell::PlatformSetContents() { | 386 void Shell::PlatformSetContents() { |
| 387 ShellWindowDelegateView* delegate_view = |
| 388 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate()); |
| 389 delegate_view->SetWebContents(web_contents_.get()); |
36 } | 390 } |
37 | 391 |
38 void Shell::PlatformResizeSubViews() { | 392 void Shell::PlatformResizeSubViews() { |
39 } | 393 } |
40 | 394 |
41 void Shell::Close() { | 395 void Shell::Close() { |
| 396 window_widget_->Close(); |
42 } | 397 } |
43 | 398 |
44 void Shell::PlatformSetTitle(const string16& title) { | 399 void Shell::PlatformSetTitle(const string16& title) { |
| 400 ShellWindowDelegateView* delegate_view = |
| 401 static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate()); |
| 402 delegate_view->SetWindowTitle(title); |
| 403 window_widget_->UpdateWindowTitle(); |
45 } | 404 } |
46 | 405 |
47 } // namespace content | 406 } // namespace content |
OLD | NEW |