• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ui/views/extensions/extension_popup.h"
8 #include "content/public/browser/content_browser_client.h"
9 #include "content/public/browser/render_view_host.h"
10 #include "content/public/browser/render_widget_host_view.h"
11 #include "content/public/browser/web_contents.h"
12 #include "extensions/browser/extension_host.h"
13 #include "extensions/common/view_type.h"
14 #include "ui/events/event.h"
15 #include "ui/views/widget/widget.h"
16 
17 #if defined(USE_AURA)
18 #include "ui/base/cursor/cursor.h"
19 #endif
20 
ExtensionViewViews(extensions::ExtensionHost * host,Browser * browser)21 ExtensionViewViews::ExtensionViewViews(extensions::ExtensionHost* host,
22                                        Browser* browser)
23     : host_(host),
24       browser_(browser),
25       initialized_(false),
26       container_(NULL),
27       is_clipped_(false) {
28   // This view needs to be focusable so it can act as the focused view for the
29   // focus manager. This is required to have SkipDefaultKeyEventProcessing
30   // called so the tab key events are forwarded to the renderer.
31   SetFocusable(true);
32 }
33 
~ExtensionViewViews()34 ExtensionViewViews::~ExtensionViewViews() {
35   if (parent())
36     parent()->RemoveChildView(this);
37   CleanUp();
38 }
39 
GetMinimumSize() const40 gfx::Size ExtensionViewViews::GetMinimumSize() const {
41   // If the minimum size has never been set, returns the preferred size (same
42   // behavior as views::View).
43   return (minimum_size_ == gfx::Size()) ? GetPreferredSize() : minimum_size_;
44 }
45 
SetVisible(bool is_visible)46 void ExtensionViewViews::SetVisible(bool is_visible) {
47   if (is_visible != visible()) {
48     NativeViewHost::SetVisible(is_visible);
49 
50     // Also tell RenderWidgetHostView the new visibility. Despite its name, it
51     // is not part of the View hierarchy and does not know about the change
52     // unless we tell it.
53     content::RenderWidgetHostView* host_view = render_view_host()->GetView();
54     if (host_view) {
55       if (is_visible)
56         host_view->Show();
57       else
58         host_view->Hide();
59     }
60   }
61 }
62 
GetCursor(const ui::MouseEvent & event)63 gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) {
64   return gfx::kNullCursor;
65 }
66 
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)67 void ExtensionViewViews::ViewHierarchyChanged(
68     const ViewHierarchyChangedDetails& details) {
69   NativeViewHost::ViewHierarchyChanged(details);
70   if (details.is_add && GetWidget() && !initialized_)
71     CreateWidgetHostView();
72 }
73 
DidStopLoading()74 void ExtensionViewViews::DidStopLoading() {
75   ShowIfCompletelyLoaded();
76 }
77 
SetIsClipped(bool is_clipped)78 void ExtensionViewViews::SetIsClipped(bool is_clipped) {
79   if (is_clipped_ != is_clipped) {
80     is_clipped_ = is_clipped;
81     if (visible())
82       ShowIfCompletelyLoaded();
83   }
84 }
85 
ResizeDueToAutoResize(const gfx::Size & new_size)86 void ExtensionViewViews::ResizeDueToAutoResize(const gfx::Size& new_size) {
87   // Don't actually do anything with this information until we have been shown.
88   // Size changes will not be honored by lower layers while we are hidden.
89   if (!visible()) {
90     pending_preferred_size_ = new_size;
91     return;
92   }
93 
94   if (new_size != GetPreferredSize())
95     SetPreferredSize(new_size);
96 }
97 
RenderViewCreated()98 void ExtensionViewViews::RenderViewCreated() {
99   extensions::ViewType host_type = host_->extension_host_type();
100   if (host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) {
101     render_view_host()->EnableAutoResize(
102         gfx::Size(ExtensionPopup::kMinWidth, ExtensionPopup::kMinHeight),
103         gfx::Size(ExtensionPopup::kMaxWidth, ExtensionPopup::kMaxHeight));
104   }
105 }
106 
HandleKeyboardEvent(const content::NativeWebKeyboardEvent & event)107 void ExtensionViewViews::HandleKeyboardEvent(
108     const content::NativeWebKeyboardEvent& event) {
109   unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
110                                                         GetFocusManager());
111 }
112 
SkipDefaultKeyEventProcessing(const ui::KeyEvent & e)113 bool ExtensionViewViews::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
114   // Let the tab key event be processed by the renderer (instead of moving the
115   // focus to the next focusable view). Also handle Backspace, since otherwise
116   // (on Windows at least), pressing Backspace, when focus is on a text field
117   // within the ExtensionViewViews, will navigate the page back instead of
118   // erasing a character.
119   return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK);
120 }
121 
OnBoundsChanged(const gfx::Rect & previous_bounds)122 void ExtensionViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
123   // Propagate the new size to RenderWidgetHostView.
124   // We can't send size zero because RenderWidget DCHECKs that.
125   if (render_view_host()->GetView() && !bounds().IsEmpty())
126     render_view_host()->GetView()->SetSize(size());
127 }
128 
PreferredSizeChanged()129 void ExtensionViewViews::PreferredSizeChanged() {
130   View::PreferredSizeChanged();
131   if (container_)
132     container_->OnExtensionSizeChanged(this);
133 }
134 
OnFocus()135 void ExtensionViewViews::OnFocus() {
136   host()->host_contents()->Focus();
137 }
138 
CreateWidgetHostView()139 void ExtensionViewViews::CreateWidgetHostView() {
140   DCHECK(!initialized_);
141   initialized_ = true;
142   Attach(host_->host_contents()->GetNativeView());
143   host_->CreateRenderViewSoon();
144   SetVisible(false);
145 }
146 
ShowIfCompletelyLoaded()147 void ExtensionViewViews::ShowIfCompletelyLoaded() {
148   if (visible() || is_clipped_)
149     return;
150 
151   // We wait to show the ExtensionViewViews until it has loaded, and the view
152   // has actually been created. These can happen in different orders.
153   if (host_->did_stop_loading()) {
154     SetVisible(true);
155     ResizeDueToAutoResize(pending_preferred_size_);
156   }
157 }
158 
CleanUp()159 void ExtensionViewViews::CleanUp() {
160   if (!initialized_)
161     return;
162   if (native_view())
163     Detach();
164   initialized_ = false;
165 }
166