• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExtensionView(ExtensionHost * host,Browser * browser)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 
~ExtensionView()35 ExtensionView::~ExtensionView() {
36   if (parent())
37     parent()->RemoveChildView(this);
38   CleanUp();
39 }
40 
extension() const41 const Extension* ExtensionView::extension() const {
42   return host_->extension();
43 }
44 
render_view_host() const45 RenderViewHost* ExtensionView::render_view_host() const {
46   return host_->render_view_host();
47 }
48 
DidStopLoading()49 void ExtensionView::DidStopLoading() {
50   ShowIfCompletelyLoaded();
51 }
52 
SetIsClipped(bool is_clipped)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 
SetVisible(bool is_visible)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 
CreateWidgetHostView()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 
ShowIfCompletelyLoaded()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 
CleanUp()125 void ExtensionView::CleanUp() {
126   if (!initialized_)
127     return;
128   if (native_view())
129     Detach();
130   initialized_ = false;
131 }
132 
SetBackground(const SkBitmap & background)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 
UpdatePreferredSize(const gfx::Size & new_size)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 
ViewHierarchyChanged(bool is_add,views::View * parent,views::View * child)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 
PreferredSizeChanged()163 void ExtensionView::PreferredSizeChanged() {
164   View::PreferredSizeChanged();
165   if (container_)
166     container_->OnExtensionPreferredSizeChanged(this);
167 }
168 
SkipDefaultKeyEventProcessing(const views::KeyEvent & e)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 
OnBoundsChanged(const gfx::Rect & previous_bounds)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 
HandleMouseMove()182 void ExtensionView::HandleMouseMove() {
183   if (container_)
184     container_->OnExtensionMouseMove(this);
185 }
186 
HandleMouseLeave()187 void ExtensionView::HandleMouseLeave() {
188   if (container_)
189     container_->OnExtensionMouseLeave(this);
190 }
191 
RenderViewCreated()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