Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: ui/keyboard/content/keyboard_ui_content.cc

Issue 1392713002: Extract content dependency from keyboard code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "ui/keyboard/content/keyboard_ui_content.h"
6
7 #include "base/command_line.h"
8 #include "base/values.h"
9 #include "content/public/browser/render_widget_host.h"
10 #include "content/public/browser/render_widget_host_iterator.h"
11 #include "content/public/browser/render_widget_host_view.h"
12 #include "content/public/browser/site_instance.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_delegate.h"
16 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/browser/web_ui.h"
18 #include "content/public/common/bindings_policy.h"
19 #include "ui/aura/layout_manager.h"
20 #include "ui/aura/window.h"
21 #include "ui/base/ime/input_method.h"
22 #include "ui/base/ime/text_input_client.h"
23 #include "ui/keyboard/content/keyboard_constants.h"
24 #include "ui/keyboard/keyboard_controller.h"
25 #include "ui/keyboard/keyboard_switches.h"
26 #include "ui/keyboard/keyboard_util.h"
27 #include "ui/wm/core/shadow.h"
28
29 namespace {
30
31 // The WebContentsDelegate for the keyboard.
32 // The delegate deletes itself when the keyboard is destroyed.
33 class KeyboardContentsDelegate : public content::WebContentsDelegate,
34 public content::WebContentsObserver {
35 public:
36 KeyboardContentsDelegate(keyboard::KeyboardUIContent* ui) : ui_(ui) {}
sky 2015/10/09 18:23:29 explicit
37 ~KeyboardContentsDelegate() override {}
38
39 private:
40 // Overridden from content::WebContentsDelegate:
41 content::WebContents* OpenURLFromTab(
42 content::WebContents* source,
43 const content::OpenURLParams& params) override {
44 source->GetController().LoadURL(
45 params.url, params.referrer, params.transition, params.extra_headers);
46 Observe(source);
47 return source;
48 }
49
50 bool CanDragEnter(content::WebContents* source,
51 const content::DropData& data,
52 blink::WebDragOperationsMask operations_allowed) override {
53 return false;
54 }
55
56 bool ShouldCreateWebContents(
57 content::WebContents* web_contents,
58 int route_id,
59 int main_frame_route_id,
60 WindowContainerType window_container_type,
61 const std::string& frame_name,
62 const GURL& target_url,
63 const std::string& partition_id,
64 content::SessionStorageNamespace* session_storage_namespace) override {
65 return false;
66 }
67
68 bool IsPopupOrPanel(const content::WebContents* source) const override {
69 return true;
70 }
71
72 void MoveContents(content::WebContents* source,
73 const gfx::Rect& pos) override {
74 aura::Window* keyboard = ui_->GetKeyboardWindow();
75 // keyboard window must have been added to keyboard container window at this
76 // point. Otherwise, wrong keyboard bounds is used and may cause problem as
77 // described in crbug.com/367788.
78 DCHECK(keyboard->parent());
79 // keyboard window bounds may not set to |pos| after this call. If keyboard
80 // is in FULL_WIDTH mode, only the height of keyboard window will be
81 // changed.
82 keyboard->SetBounds(pos);
83 }
84
85 // Overridden from content::WebContentsDelegate:
86 void RequestMediaAccessPermission(
87 content::WebContents* web_contents,
88 const content::MediaStreamRequest& request,
89 const content::MediaResponseCallback& callback) override {
90 ui_->RequestAudioInput(web_contents, request, callback);
91 }
92
93 // Overridden from content::WebContentsObserver:
94 void WebContentsDestroyed() override { delete this; }
95
96 keyboard::KeyboardUIContent* ui_;
97
98 DISALLOW_COPY_AND_ASSIGN(KeyboardContentsDelegate);
99 };
100
101 } // namespace
102
103 namespace keyboard {
104
105 class WindowBoundsChangeObserver : public aura::WindowObserver {
106 public:
107 explicit WindowBoundsChangeObserver(KeyboardUIContent* ui) : ui_(ui) {}
108 ~WindowBoundsChangeObserver() override {}
109
110 void AddObservedWindow(aura::Window* window) {
111 if (!window->HasObserver(this)) {
112 window->AddObserver(this);
113 observed_windows_.insert(window);
114 }
115 }
116 void RemoveAllObservedWindows() {
117 for (std::set<aura::Window*>::iterator it = observed_windows_.begin();
118 it != observed_windows_.end(); ++it)
119 (*it)->RemoveObserver(this);
120 observed_windows_.clear();
121 }
122
123 private:
124 void OnWindowBoundsChanged(aura::Window* window,
125 const gfx::Rect& old_bounds,
126 const gfx::Rect& new_bounds) override {
127 ui_->UpdateInsetsForWindow(window);
128 }
129 void OnWindowDestroyed(aura::Window* window) override {
130 if (window->HasObserver(this))
131 window->RemoveObserver(this);
132 observed_windows_.erase(window);
133 }
134
135 KeyboardUIContent* ui_;
136 std::set<aura::Window*> observed_windows_;
137
138 DISALLOW_COPY_AND_ASSIGN(WindowBoundsChangeObserver);
139 };
140
141 KeyboardUIContent::KeyboardUIContent(content::BrowserContext* context)
142 : browser_context_(context),
143 default_url_(kKeyboardURL),
144 window_bounds_observer_(new WindowBoundsChangeObserver(this)) {
145 }
146
147 KeyboardUIContent::~KeyboardUIContent() {
148 ResetInsets();
149 }
150
151 void KeyboardUIContent::LoadSystemKeyboard() {
152 DCHECK(keyboard_contents_);
153 if (keyboard_contents_->GetURL() != default_url_) {
154 // TODO(bshe): The height of system virtual keyboard and IME virtual
155 // keyboard may different. The height needs to be restored too.
156 LoadContents(default_url_);
157 }
158 }
159
160 void KeyboardUIContent::UpdateInsetsForWindow(aura::Window* window) {
161 aura::Window* keyboard_window = GetKeyboardWindow();
162 scoped_ptr<content::RenderWidgetHostIterator> widgets(
163 content::RenderWidgetHost::GetRenderWidgetHosts());
164 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
165 content::RenderWidgetHostView* view = widget->GetView();
166 if (view && window->Contains(view->GetNativeView())) {
167 gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen();
168 gfx::Rect intersect =
169 gfx::IntersectRects(window_bounds, keyboard_window->bounds());
170 int overlap = ShouldEnableInsets(window) ? intersect.height() : 0;
171 if (overlap > 0 && overlap < window_bounds.height())
172 view->SetInsets(gfx::Insets(0, 0, overlap, 0));
173 else
174 view->SetInsets(gfx::Insets());
175 return;
176 }
177 }
178 }
179
180 aura::Window* KeyboardUIContent::GetKeyboardWindow() {
181 if (!keyboard_contents_) {
182 content::BrowserContext* context = browser_context();
183 keyboard_contents_.reset(content::WebContents::Create(
184 content::WebContents::CreateParams(context,
185 content::SiteInstance::CreateForURL(context,
186 GetVirtualKeyboardUrl()))));
187 keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this));
188 SetupWebContents(keyboard_contents_.get());
189 LoadContents(GetVirtualKeyboardUrl());
190 keyboard_contents_->GetNativeView()->AddObserver(this);
191 }
192
193 return keyboard_contents_->GetNativeView();
194 }
195
196 bool KeyboardUIContent::HasKeyboardWindow() const {
197 return keyboard_contents_;
198 }
199
200 void KeyboardUIContent::ReloadKeyboardIfNeeded() {
201 DCHECK(keyboard_contents_);
202 if (keyboard_contents_->GetURL() != GetVirtualKeyboardUrl()) {
203 if (keyboard_contents_->GetURL().GetOrigin() !=
204 GetVirtualKeyboardUrl().GetOrigin()) {
205 // Sets keyboard window rectangle to 0 and close current page before
206 // navigate to a keyboard in a different extension. This keeps the UX the
207 // same as Android. Note we need to explicitly close current page as it
208 // might try to resize keyboard window in javascript on a resize event.
209 GetKeyboardWindow()->SetBounds(gfx::Rect());
210 keyboard_contents_->ClosePage();
211 keyboard_controller()->SetKeyboardMode(FULL_WIDTH);
212 }
213 LoadContents(GetVirtualKeyboardUrl());
214 }
215 }
216
217 void KeyboardUIContent::InitInsets(const gfx::Rect& new_bounds) {
218 // Adjust the height of the viewport for visible windows on the primary
219 // display.
220 // TODO(kevers): Add EnvObserver to properly initialize insets if a
221 // window is created while the keyboard is visible.
222 scoped_ptr<content::RenderWidgetHostIterator> widgets(
223 content::RenderWidgetHost::GetRenderWidgetHosts());
224 aura::Window* keyboard_window = GetKeyboardWindow();
225 aura::Window* root_window = keyboard_window->GetRootWindow();
226 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
227 content::RenderWidgetHostView* view = widget->GetView();
228 // Can be NULL, e.g. if the RenderWidget is being destroyed or
229 // the render process crashed.
230 if (view) {
231 aura::Window* window = view->GetNativeView();
232 // If virtual keyboard failed to load, a widget that displays error
233 // message will be created and adds as a child of the virtual keyboard
234 // window. We want to avoid add BoundsChangedObserver to that window.
235 if (!keyboard_window->Contains(window) &&
236 window->GetRootWindow() == root_window) {
237 gfx::Rect window_bounds = window->GetBoundsInScreen();
238 gfx::Rect intersect = gfx::IntersectRects(window_bounds,
239 new_bounds);
240 int overlap = intersect.height();
241 if (overlap > 0 && overlap < window_bounds.height())
242 view->SetInsets(gfx::Insets(0, 0, overlap, 0));
243 else
244 view->SetInsets(gfx::Insets());
245 AddBoundsChangedObserver(window);
246 }
247 }
248 }
249 }
250
251 void KeyboardUIContent::ResetInsets() {
252 const gfx::Insets insets;
253 scoped_ptr<content::RenderWidgetHostIterator> widgets(
254 content::RenderWidgetHost::GetRenderWidgetHosts());
255 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
256 content::RenderWidgetHostView* view = widget->GetView();
257 if (view)
258 view->SetInsets(insets);
259 }
260 window_bounds_observer_->RemoveAllObservedWindows();
261 }
262
263 void KeyboardUIContent::SetupWebContents(content::WebContents* contents) {
264 }
265
266 void KeyboardUIContent::OnWindowBoundsChanged(aura::Window* window,
267 const gfx::Rect& old_bounds,
268 const gfx::Rect& new_bounds) {
269 if (!shadow_) {
270 shadow_.reset(new wm::Shadow());
271 shadow_->Init(wm::Shadow::STYLE_ACTIVE);
272 shadow_->layer()->SetVisible(true);
273 DCHECK(keyboard_contents_->GetNativeView()->parent());
274 keyboard_contents_->GetNativeView()->parent()->layer()->Add(
275 shadow_->layer());
276 }
277
278 shadow_->SetContentBounds(new_bounds);
279 }
280
281 void KeyboardUIContent::OnWindowDestroyed(aura::Window* window) {
282 window->RemoveObserver(this);
283 }
284
285 void KeyboardUIContent::LoadContents(const GURL& url) {
286 if (keyboard_contents_) {
287 content::OpenURLParams params(
288 url,
289 content::Referrer(),
290 SINGLETON_TAB,
291 ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
292 false);
293 keyboard_contents_->OpenURL(params);
294 }
295 }
296
297 const GURL& KeyboardUIContent::GetVirtualKeyboardUrl() {
298 if (keyboard::IsInputViewEnabled()) {
299 const GURL& override_url = GetOverrideContentUrl();
300 return override_url.is_valid() ? override_url : default_url_;
301 } else {
302 return default_url_;
303 }
304 }
305
306 bool KeyboardUIContent::ShouldEnableInsets(aura::Window* window) {
307 aura::Window* keyboard_window = GetKeyboardWindow();
308 return (keyboard_window->GetRootWindow() == window->GetRootWindow() &&
309 keyboard::IsKeyboardOverscrollEnabled() &&
310 keyboard_window->IsVisible() &&
311 keyboard_controller()->keyboard_visible());
312 }
313
314 void KeyboardUIContent::AddBoundsChangedObserver(aura::Window* window) {
315 aura::Window* target_window = window ? window->GetToplevelWindow() : nullptr;
316 if (target_window)
317 window_bounds_observer_->AddObservedWindow(target_window);
318 }
319
320 } // namespace keyboard
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698