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.
5 #include "chrome/browser/ui/views/extensions/extension_view_views.h"
7 #include "chrome/browser/extensions/extension_host.h"
8 #include "chrome/browser/ui/views/extensions/extension_popup.h"
9 #include "content/public/browser/content_browser_client.h"
10 #include "content/public/browser/render_view_host.h"
11 #include "content/public/browser/render_widget_host_view.h"
12 #include "content/public/browser/web_contents.h"
13 #include "content/public/browser/web_contents_view.h"
14 #include "extensions/common/view_type.h"
15 #include "ui/events/event.h"
16 #include "ui/views/widget/widget.h"
19 #include "ui/base/cursor/cursor.h"
22 ExtensionViewViews::ExtensionViewViews(extensions::ExtensionHost* host,
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.
35 ExtensionViewViews::~ExtensionViewViews() {
37 parent()->RemoveChildView(this);
41 const extensions::Extension* ExtensionViewViews::extension() const {
42 return host_->extension();
45 content::RenderViewHost* ExtensionViewViews::render_view_host() const {
46 return host_->render_view_host();
49 void ExtensionViewViews::DidStopLoading() {
50 ShowIfCompletelyLoaded();
53 void ExtensionViewViews::SetIsClipped(bool is_clipped) {
54 if (is_clipped_ != is_clipped) {
55 is_clipped_ = is_clipped;
57 ShowIfCompletelyLoaded();
61 gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) {
62 return gfx::kNullCursor;
65 void ExtensionViewViews::SetVisible(bool is_visible) {
66 if (is_visible != visible()) {
67 NativeViewHost::SetVisible(is_visible);
69 // Also tell RenderWidgetHostView the new visibility. Despite its name, it
70 // is not part of the View hierarchy and does not know about the change
72 if (render_view_host()->GetView()) {
74 render_view_host()->GetView()->Show();
76 render_view_host()->GetView()->Hide();
81 void ExtensionViewViews::CreateWidgetHostView() {
82 DCHECK(!initialized_);
84 Attach(host_->host_contents()->GetView()->GetNativeView());
85 host_->CreateRenderViewSoon();
89 void ExtensionViewViews::ShowIfCompletelyLoaded() {
90 if (visible() || is_clipped_)
93 // We wait to show the ExtensionViewViews until it has loaded, and the view
94 // has actually been created. These can happen in different orders.
95 if (host_->did_stop_loading()) {
97 ResizeDueToAutoResize(pending_preferred_size_);
101 void ExtensionViewViews::CleanUp() {
106 initialized_ = false;
109 void ExtensionViewViews::ResizeDueToAutoResize(const gfx::Size& new_size) {
110 // Don't actually do anything with this information until we have been shown.
111 // Size changes will not be honored by lower layers while we are hidden.
113 pending_preferred_size_ = new_size;
117 gfx::Size preferred_size = GetPreferredSize();
118 if (new_size != preferred_size)
119 SetPreferredSize(new_size);
122 void ExtensionViewViews::ViewHierarchyChanged(
123 const ViewHierarchyChangedDetails& details) {
124 NativeViewHost::ViewHierarchyChanged(details);
125 if (details.is_add && GetWidget() && !initialized_)
126 CreateWidgetHostView();
129 bool ExtensionViewViews::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
130 // Let the tab key event be processed by the renderer (instead of moving the
131 // focus to the next focusable view). Also handle Backspace, since otherwise
132 // (on Windows at least), pressing Backspace, when focus is on a text field
133 // within the ExtensionViewViews, will navigate the page back instead of
134 // erasing a character.
135 return (e.key_code() == ui::VKEY_TAB || e.key_code() == ui::VKEY_BACK);
138 void ExtensionViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
139 // Propagate the new size to RenderWidgetHostView.
140 // We can't send size zero because RenderWidget DCHECKs that.
141 if (render_view_host()->GetView() && !bounds().IsEmpty()) {
142 render_view_host()->GetView()->SetSize(size());
145 container_->OnViewWasResized();
149 void ExtensionViewViews::PreferredSizeChanged() {
150 View::PreferredSizeChanged();
152 container_->OnExtensionSizeChanged(this);
155 void ExtensionViewViews::OnFocus() {
156 host()->host_contents()->GetView()->Focus();
159 void ExtensionViewViews::RenderViewCreated() {
160 extensions::ViewType host_type = host_->extension_host_type();
161 if (host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) {
162 gfx::Size min_size(ExtensionPopup::kMinWidth,
163 ExtensionPopup::kMinHeight);
164 gfx::Size max_size(ExtensionPopup::kMaxWidth,
165 ExtensionPopup::kMaxHeight);
166 render_view_host()->EnableAutoResize(min_size, max_size);
170 container_->OnViewWasResized();
173 void ExtensionViewViews::HandleKeyboardEvent(
174 const content::NativeWebKeyboardEvent& event) {
175 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,