- add sources.
[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_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"
17
18 #if defined(USE_AURA)
19 #include "ui/base/cursor/cursor.h"
20 #endif
21
22 ExtensionViewViews::ExtensionViewViews(extensions::ExtensionHost* host,
23                                        Browser* browser)
24     : host_(host),
25       browser_(browser),
26       initialized_(false),
27       container_(NULL),
28       is_clipped_(false) {
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   set_focusable(true);
33 }
34
35 ExtensionViewViews::~ExtensionViewViews() {
36   if (parent())
37     parent()->RemoveChildView(this);
38   CleanUp();
39 }
40
41 const extensions::Extension* ExtensionViewViews::extension() const {
42   return host_->extension();
43 }
44
45 content::RenderViewHost* ExtensionViewViews::render_view_host() const {
46   return host_->render_view_host();
47 }
48
49 void ExtensionViewViews::DidStopLoading() {
50   ShowIfCompletelyLoaded();
51 }
52
53 void ExtensionViewViews::SetIsClipped(bool is_clipped) {
54   if (is_clipped_ != is_clipped) {
55     is_clipped_ = is_clipped;
56     if (visible())
57       ShowIfCompletelyLoaded();
58   }
59 }
60
61 gfx::NativeCursor ExtensionViewViews::GetCursor(const ui::MouseEvent& event) {
62   return gfx::kNullCursor;
63 }
64
65 void ExtensionViewViews::SetVisible(bool is_visible) {
66   if (is_visible != visible()) {
67     NativeViewHost::SetVisible(is_visible);
68
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
71     // unless we tell it.
72     if (render_view_host()->GetView()) {
73       if (is_visible)
74         render_view_host()->GetView()->Show();
75       else
76         render_view_host()->GetView()->Hide();
77     }
78   }
79 }
80
81 void ExtensionViewViews::CreateWidgetHostView() {
82   DCHECK(!initialized_);
83   initialized_ = true;
84   Attach(host_->host_contents()->GetView()->GetNativeView());
85   host_->CreateRenderViewSoon();
86   SetVisible(false);
87 }
88
89 void ExtensionViewViews::ShowIfCompletelyLoaded() {
90   if (visible() || is_clipped_)
91     return;
92
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()) {
96     SetVisible(true);
97     ResizeDueToAutoResize(pending_preferred_size_);
98   }
99 }
100
101 void ExtensionViewViews::CleanUp() {
102   if (!initialized_)
103     return;
104   if (native_view())
105     Detach();
106   initialized_ = false;
107 }
108
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.
112   if (!visible()) {
113     pending_preferred_size_ = new_size;
114     return;
115   }
116
117   gfx::Size preferred_size = GetPreferredSize();
118   if (new_size != preferred_size)
119     SetPreferredSize(new_size);
120 }
121
122 void ExtensionViewViews::ViewHierarchyChanged(
123     const ViewHierarchyChangedDetails& details) {
124   NativeViewHost::ViewHierarchyChanged(details);
125   if (details.is_add && GetWidget() && !initialized_)
126     CreateWidgetHostView();
127 }
128
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);
136 }
137
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());
143
144     if (container_)
145       container_->OnViewWasResized();
146   }
147 }
148
149 void ExtensionViewViews::PreferredSizeChanged() {
150   View::PreferredSizeChanged();
151   if (container_)
152     container_->OnExtensionSizeChanged(this);
153 }
154
155 void ExtensionViewViews::OnFocus() {
156   host()->host_contents()->GetView()->Focus();
157 }
158
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);
167   }
168
169   if (container_)
170     container_->OnViewWasResized();
171 }
172
173 void ExtensionViewViews::HandleKeyboardEvent(
174     const content::NativeWebKeyboardEvent& event) {
175   unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
176                                                         GetFocusManager());
177 }