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