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