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