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