extension_view_views.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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 set_focusable(true); 33} 34 35ExtensionViewViews::~ExtensionViewViews() { 36 if (parent()) 37 parent()->RemoveChildView(this); 38 CleanUp(); 39} 40 41const extensions::Extension* ExtensionViewViews::extension() const { 42 return host_->extension(); 43} 44 45content::RenderViewHost* ExtensionViewViews::render_view_host() const { 46 return host_->render_view_host(); 47} 48 49void ExtensionViewViews::DidStopLoading() { 50 ShowIfCompletelyLoaded(); 51} 52 53void ExtensionViewViews::SetIsClipped(bool is_clipped) { 54 if (is_clipped_ != is_clipped) { 55 is_clipped_ = is_clipped; 56 if (visible()) 57 ShowIfCompletelyLoaded(); 58 } 59} 60 61gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) { 62 return gfx::kNullCursor; 63} 64 65void ExtensionViewViews::SetVisible(bool is_visible) { 66 if (is_visible != visible()) { 67 NativeViewHost::SetVisible(is_visible); 68 69 // Also tell RenderWidgetHostView the new visibility. Despite its name, it 70 // is not part of the View hierarchy and does not know about the change 71 // unless we tell it. 72 if (render_view_host()->GetView()) { 73 if (is_visible) 74 render_view_host()->GetView()->Show(); 75 else 76 render_view_host()->GetView()->Hide(); 77 } 78 } 79} 80 81void ExtensionViewViews::CreateWidgetHostView() { 82 DCHECK(!initialized_); 83 initialized_ = true; 84 Attach(host_->host_contents()->GetView()->GetNativeView()); 85 host_->CreateRenderViewSoon(); 86 SetVisible(false); 87} 88 89void ExtensionViewViews::ShowIfCompletelyLoaded() { 90 if (visible() || is_clipped_) 91 return; 92 93 // We wait to show the ExtensionViewViews until it has loaded, and the view 94 // has actually been created. These can happen in different orders. 95 if (host_->did_stop_loading()) { 96 SetVisible(true); 97 ResizeDueToAutoResize(pending_preferred_size_); 98 } 99} 100 101void ExtensionViewViews::CleanUp() { 102 if (!initialized_) 103 return; 104 if (native_view()) 105 Detach(); 106 initialized_ = false; 107} 108 109void ExtensionViewViews::ResizeDueToAutoResize(const gfx::Size& new_size) { 110 // Don't actually do anything with this information until we have been shown. 111 // Size changes will not be honored by lower layers while we are hidden. 112 if (!visible()) { 113 pending_preferred_size_ = new_size; 114 return; 115 } 116 117 gfx::Size preferred_size = GetPreferredSize(); 118 if (new_size != preferred_size) 119 SetPreferredSize(new_size); 120} 121 122void ExtensionViewViews::ViewHierarchyChanged( 123 const ViewHierarchyChangedDetails& details) { 124 NativeViewHost::ViewHierarchyChanged(details); 125 if (details.is_add && GetWidget() && !initialized_) 126 CreateWidgetHostView(); 127} 128 129bool ExtensionViewViews::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { 130 // Let the tab key event be processed by the renderer (instead of moving the 131 // focus to the next focusable view). Also handle Backspace, since otherwise 132 // (on Windows at least), pressing Backspace, when focus is on a text field 133 // within the ExtensionViewViews, will navigate the page back instead of 134 // erasing a character. 135 return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK); 136} 137 138void ExtensionViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) { 139 // Propagate the new size to RenderWidgetHostView. 140 // We can't send size zero because RenderWidget DCHECKs that. 141 if (render_view_host()->GetView() && !bounds().IsEmpty()) { 142 render_view_host()->GetView()->SetSize(size()); 143 144 if (container_) 145 container_->OnViewWasResized(); 146 } 147} 148 149void ExtensionViewViews::PreferredSizeChanged() { 150 View::PreferredSizeChanged(); 151 if (container_) 152 container_->OnExtensionSizeChanged(this); 153} 154 155void ExtensionViewViews::OnFocus() { 156 host()->host_contents()->GetView()->Focus(); 157} 158 159void ExtensionViewViews::RenderViewCreated() { 160 extensions::ViewType host_type = host_->extension_host_type(); 161 if (host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) { 162 gfx::Size min_size(ExtensionPopup::kMinWidth, 163 ExtensionPopup::kMinHeight); 164 gfx::Size max_size(ExtensionPopup::kMaxWidth, 165 ExtensionPopup::kMaxHeight); 166 render_view_host()->EnableAutoResize(min_size, max_size); 167 } 168 169 if (container_) 170 container_->OnViewWasResized(); 171} 172 173void ExtensionViewViews::HandleKeyboardEvent( 174 const content::NativeWebKeyboardEvent& event) { 175 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, 176 GetFocusManager()); 177} 178