extension_view.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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.h" 6 7#include "chrome/browser/extensions/extension_host.h" 8#include "chrome/browser/ui/views/extensions/extension_popup.h" 9#include "content/browser/renderer_host/render_view_host.h" 10#include "content/browser/renderer_host/render_widget_host_view.h" 11#include "views/widget/widget.h" 12 13#if defined(OS_WIN) 14#include "chrome/browser/renderer_host/render_widget_host_view_win.h" 15#elif defined(TOUCH_UI) 16#include "chrome/browser/renderer_host/render_widget_host_view_views.h" 17#elif defined(OS_LINUX) 18#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" 19#endif 20 21ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser) 22 : host_(host), 23 browser_(browser), 24 initialized_(false), 25 container_(NULL), 26 is_clipped_(false) { 27 host_->set_view(this); 28 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 35ExtensionView::~ExtensionView() { 36 if (parent()) 37 parent()->RemoveChildView(this); 38 CleanUp(); 39} 40 41const Extension* ExtensionView::extension() const { 42 return host_->extension(); 43} 44 45RenderViewHost* ExtensionView::render_view_host() const { 46 return host_->render_view_host(); 47} 48 49void ExtensionView::DidStopLoading() { 50 ShowIfCompletelyLoaded(); 51} 52 53void ExtensionView::SetIsClipped(bool is_clipped) { 54 if (is_clipped_ != is_clipped) { 55 is_clipped_ = is_clipped; 56 if (IsVisible()) 57 ShowIfCompletelyLoaded(); 58 } 59} 60 61void ExtensionView::SetVisible(bool is_visible) { 62 if (is_visible != IsVisible()) { 63 NativeViewHost::SetVisible(is_visible); 64 65 // Also tell RenderWidgetHostView the new visibility. Despite its name, it 66 // is not part of the View hierarchy and does not know about the change 67 // unless we tell it. 68 if (render_view_host()->view()) { 69 if (is_visible) 70 render_view_host()->view()->Show(); 71 else 72 render_view_host()->view()->Hide(); 73 } 74 } 75} 76 77void ExtensionView::OnBoundsChanged() { 78 View::OnBoundsChanged(); 79 // Propagate the new size to RenderWidgetHostView. 80 // We can't send size zero because RenderWidget DCHECKs that. 81 if (render_view_host()->view() && !bounds().IsEmpty()) 82 render_view_host()->view()->SetSize(size()); 83} 84 85void ExtensionView::CreateWidgetHostView() { 86 DCHECK(!initialized_); 87 initialized_ = true; 88 RenderWidgetHostView* view = 89 RenderWidgetHostView::CreateViewForWidget(render_view_host()); 90 91 // TODO(mpcomplete): RWHV needs a cross-platform Init function. 92#if defined(OS_WIN) 93 // Create the HWND. Note: 94 // RenderWidgetHostHWND supports windowed plugins, but if we ever also 95 // wanted to support constrained windows with this, we would need an 96 // additional HWND to parent off of because windowed plugin HWNDs cannot 97 // exist in the same z-order as constrained windows. 98 RenderWidgetHostViewWin* view_win = 99 static_cast<RenderWidgetHostViewWin*>(view); 100 HWND hwnd = view_win->Create(GetWidget()->GetNativeView()); 101 view_win->ShowWindow(SW_SHOW); 102 Attach(hwnd); 103#elif defined(TOUCH_UI) 104 RenderWidgetHostViewViews* view_views = 105 static_cast<RenderWidgetHostViewViews*>(view); 106 view_views->InitAsChild(); 107 AttachToView(view_views); 108#elif defined(OS_LINUX) 109 RenderWidgetHostViewGtk* view_gtk = 110 static_cast<RenderWidgetHostViewGtk*>(view); 111 view_gtk->InitAsChild(); 112 Attach(view_gtk->GetNativeView()); 113#else 114 NOTIMPLEMENTED(); 115#endif 116 117 host_->CreateRenderViewSoon(view); 118 SetVisible(false); 119} 120 121void ExtensionView::ShowIfCompletelyLoaded() { 122 if (IsVisible() || is_clipped_) 123 return; 124 125 // We wait to show the ExtensionView until it has loaded, and the view has 126 // actually been created. These can happen in different orders. 127 if (host_->did_stop_loading()) { 128 SetVisible(true); 129 UpdatePreferredSize(pending_preferred_size_); 130 } 131} 132 133void ExtensionView::CleanUp() { 134 if (!initialized_) 135 return; 136 if (native_view()) 137 Detach(); 138 initialized_ = false; 139} 140 141void ExtensionView::SetBackground(const SkBitmap& background) { 142 if (render_view_host()->IsRenderViewLive() && render_view_host()->view()) { 143 render_view_host()->view()->SetBackground(background); 144 } else { 145 pending_background_ = background; 146 } 147 ShowIfCompletelyLoaded(); 148} 149 150void ExtensionView::UpdatePreferredSize(const gfx::Size& new_size) { 151 // Don't actually do anything with this information until we have been shown. 152 // Size changes will not be honored by lower layers while we are hidden. 153 if (!IsVisible()) { 154 pending_preferred_size_ = new_size; 155 return; 156 } 157 158 gfx::Size preferred_size = GetPreferredSize(); 159 if (new_size != preferred_size) 160 SetPreferredSize(new_size); 161} 162 163void ExtensionView::ViewHierarchyChanged(bool is_add, 164 views::View *parent, 165 views::View *child) { 166 NativeViewHost::ViewHierarchyChanged(is_add, parent, child); 167 if (is_add && GetWidget() && !initialized_) 168 CreateWidgetHostView(); 169} 170 171void ExtensionView::PreferredSizeChanged() { 172 View::PreferredSizeChanged(); 173 if (container_) 174 container_->OnExtensionPreferredSizeChanged(this); 175} 176 177bool ExtensionView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) { 178 // Let the tab key event be processed by the renderer (instead of moving the 179 // focus to the next focusable view). 180 return (e.key_code() == ui::VKEY_TAB); 181} 182 183void ExtensionView::HandleMouseMove() { 184 if (container_) 185 container_->OnExtensionMouseMove(this); 186} 187 188void ExtensionView::HandleMouseLeave() { 189 if (container_) 190 container_->OnExtensionMouseLeave(this); 191} 192 193void ExtensionView::RenderViewCreated() { 194 if (!pending_background_.empty() && render_view_host()->view()) { 195 render_view_host()->view()->SetBackground(pending_background_); 196 pending_background_.reset(); 197 } 198 199 // Tell the renderer not to draw scroll bars in popups unless the 200 // popups are at the maximum allowed size. 201 gfx::Size largest_popup_size(ExtensionPopup::kMaxWidth, 202 ExtensionPopup::kMaxHeight); 203 host_->DisableScrollbarsForSmallWindows(largest_popup_size); 204} 205