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_view_views.h" 6 7 #include "chrome/browser/extensions/extension_view_host.h" 8 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/views/extensions/extension_popup.h" 10 #include "content/public/browser/content_browser_client.h" 11 #include "content/public/browser/render_view_host.h" 12 #include "content/public/browser/render_widget_host_view.h" 13 #include "content/public/browser/web_contents.h" 14 #include "extensions/browser/extension_host.h" 15 #include "extensions/common/view_type.h" 16 #include "ui/events/event.h" 17 #include "ui/views/widget/widget.h" 18 19 #if defined(USE_AURA) 20 #include "ui/base/cursor/cursor.h" 21 #endif 22 23 ExtensionViewViews::ExtensionViewViews(extensions::ExtensionHost* host, 24 Browser* browser) 25 : host_(host), 26 browser_(browser), 27 initialized_(false), 28 container_(NULL), 29 is_clipped_(false) { 30 // This view needs to be focusable so it can act as the focused view for the 31 // focus manager. This is required to have SkipDefaultKeyEventProcessing 32 // called so the tab key events are forwarded to the renderer. 33 SetFocusable(true); 34 } 35 36 ExtensionViewViews::~ExtensionViewViews() { 37 if (parent()) 38 parent()->RemoveChildView(this); 39 CleanUp(); 40 } 41 42 gfx::Size ExtensionViewViews::GetMinimumSize() const { 43 // If the minimum size has never been set, returns the preferred size (same 44 // behavior as views::View). 45 return (minimum_size_ == gfx::Size()) ? GetPreferredSize() : minimum_size_; 46 } 47 48 void ExtensionViewViews::SetVisible(bool is_visible) { 49 if (is_visible != visible()) { 50 NativeViewHost::SetVisible(is_visible); 51 52 // Also tell RenderWidgetHostView the new visibility. Despite its name, it 53 // is not part of the View hierarchy and does not know about the change 54 // unless we tell it. 55 content::RenderWidgetHostView* host_view = render_view_host()->GetView(); 56 if (host_view) { 57 if (is_visible) 58 host_view->Show(); 59 else 60 host_view->Hide(); 61 } 62 } 63 } 64 65 gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) { 66 return gfx::kNullCursor; 67 } 68 69 void ExtensionViewViews::ViewHierarchyChanged( 70 const ViewHierarchyChangedDetails& details) { 71 NativeViewHost::ViewHierarchyChanged(details); 72 if (details.is_add && GetWidget() && !initialized_) 73 CreateWidgetHostView(); 74 } 75 76 void ExtensionViewViews::SetIsClipped(bool is_clipped) { 77 if (is_clipped_ != is_clipped) { 78 is_clipped_ = is_clipped; 79 if (visible()) 80 ShowIfCompletelyLoaded(); 81 } 82 } 83 84 void ExtensionViewViews::Init() { 85 // Initialization continues in ViewHierarchyChanged(). 86 } 87 88 Browser* ExtensionViewViews::GetBrowser() { 89 return browser_; 90 } 91 92 gfx::NativeView ExtensionViewViews::GetNativeView() { 93 return native_view(); 94 } 95 96 void ExtensionViewViews::ResizeDueToAutoResize(const gfx::Size& new_size) { 97 // Don't actually do anything with this information until we have been shown. 98 // Size changes will not be honored by lower layers while we are hidden. 99 if (!visible()) { 100 pending_preferred_size_ = new_size; 101 return; 102 } 103 104 if (new_size != GetPreferredSize()) 105 SetPreferredSize(new_size); 106 } 107 108 void ExtensionViewViews::RenderViewCreated() { 109 extensions::ViewType host_type = host_->extension_host_type(); 110 if (host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) { 111 render_view_host()->EnableAutoResize( 112 gfx::Size(ExtensionPopup::kMinWidth, ExtensionPopup::kMinHeight), 113 gfx::Size(ExtensionPopup::kMaxWidth, ExtensionPopup::kMaxHeight)); 114 } 115 } 116 117 void ExtensionViewViews::HandleKeyboardEvent( 118 content::WebContents* source, 119 const content::NativeWebKeyboardEvent& event) { 120 if (browser_) { 121 // Handle lower priority browser shortcuts such as Ctrl-f. 122 browser_->HandleKeyboardEvent(source, event); 123 return; 124 } 125 126 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, 127 GetFocusManager()); 128 } 129 130 void ExtensionViewViews::DidStopLoading() { 131 ShowIfCompletelyLoaded(); 132 } 133 134 bool ExtensionViewViews::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { 135 // Let the tab key event be processed by the renderer (instead of moving the 136 // focus to the next focusable view). Also handle Backspace, since otherwise 137 // (on Windows at least), pressing Backspace, when focus is on a text field 138 // within the ExtensionViewViews, will navigate the page back instead of 139 // erasing a character. 140 return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK); 141 } 142 143 void ExtensionViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) { 144 // Propagate the new size to RenderWidgetHostView. 145 // We can't send size zero because RenderWidget DCHECKs that. 146 if (render_view_host()->GetView() && !bounds().IsEmpty()) 147 render_view_host()->GetView()->SetSize(size()); 148 } 149 150 void ExtensionViewViews::PreferredSizeChanged() { 151 View::PreferredSizeChanged(); 152 if (container_) 153 container_->OnExtensionSizeChanged(this); 154 } 155 156 void ExtensionViewViews::OnFocus() { 157 host()->host_contents()->Focus(); 158 } 159 160 void ExtensionViewViews::CreateWidgetHostView() { 161 DCHECK(!initialized_); 162 initialized_ = true; 163 Attach(host_->host_contents()->GetNativeView()); 164 host_->CreateRenderViewSoon(); 165 SetVisible(false); 166 } 167 168 void ExtensionViewViews::ShowIfCompletelyLoaded() { 169 if (visible() || is_clipped_) 170 return; 171 172 // We wait to show the ExtensionViewViews until it has loaded, and the view 173 // has actually been created. These can happen in different orders. 174 if (host_->did_stop_loading()) { 175 SetVisible(true); 176 ResizeDueToAutoResize(pending_preferred_size_); 177 } 178 } 179 180 void ExtensionViewViews::CleanUp() { 181 if (!initialized_) 182 return; 183 if (native_view()) 184 Detach(); 185 initialized_ = false; 186 } 187 188 namespace extensions { 189 190 // static 191 scoped_ptr<ExtensionView> ExtensionViewHost::CreateExtensionView( 192 ExtensionViewHost* host, 193 Browser* browser) { 194 scoped_ptr<ExtensionViewViews> view(new ExtensionViewViews(host, browser)); 195 // We own |view_|, so don't auto delete when it's removed from the view 196 // hierarchy. 197 view->set_owned_by_client(); 198 return view.PassAs<ExtensionView>(); 199 } 200 201 } // namespace extensions 202