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/keyboard_controller_proxy.h" 6 7 #include "base/command_line.h" 8 #include "base/values.h" 9 #include "content/public/browser/site_instance.h" 10 #include "content/public/browser/web_contents.h" 11 #include "content/public/browser/web_contents.h" 12 #include "content/public/browser/web_contents_delegate.h" 13 #include "content/public/browser/web_contents_observer.h" 14 #include "content/public/browser/web_ui.h" 15 #include "content/public/common/bindings_policy.h" 16 #include "ui/aura/layout_manager.h" 17 #include "ui/aura/window.h" 18 #include "ui/base/ime/input_method.h" 19 #include "ui/base/ime/text_input_client.h" 20 #include "ui/keyboard/keyboard_constants.h" 21 #include "ui/keyboard/keyboard_switches.h" 22 #include "ui/keyboard/keyboard_util.h" 23 #include "ui/wm/core/shadow.h" 24 25 namespace { 26 27 // The WebContentsDelegate for the keyboard. 28 // The delegate deletes itself when the keyboard is destroyed. 29 class KeyboardContentsDelegate : public content::WebContentsDelegate, 30 public content::WebContentsObserver { 31 public: 32 KeyboardContentsDelegate(keyboard::KeyboardControllerProxy* proxy) 33 : proxy_(proxy) {} 34 virtual ~KeyboardContentsDelegate() {} 35 36 private: 37 // Overridden from content::WebContentsDelegate: 38 virtual content::WebContents* OpenURLFromTab( 39 content::WebContents* source, 40 const content::OpenURLParams& params) OVERRIDE { 41 source->GetController().LoadURL( 42 params.url, params.referrer, params.transition, params.extra_headers); 43 Observe(source); 44 return source; 45 } 46 47 virtual bool IsPopupOrPanel( 48 const content::WebContents* source) const OVERRIDE { 49 return true; 50 } 51 52 virtual void MoveContents(content::WebContents* source, 53 const gfx::Rect& pos) OVERRIDE { 54 aura::Window* keyboard = proxy_->GetKeyboardWindow(); 55 // keyboard window must have been added to keyboard container window at this 56 // point. Otherwise, wrong keyboard bounds is used and may cause problem as 57 // described in crbug.com/367788. 58 DCHECK(keyboard->parent()); 59 gfx::Rect bounds = keyboard->bounds(); 60 int new_height = pos.height(); 61 bounds.set_y(bounds.y() + bounds.height() - new_height); 62 bounds.set_height(new_height); 63 keyboard->SetBounds(bounds); 64 } 65 66 // Overridden from content::WebContentsDelegate: 67 virtual void RequestMediaAccessPermission(content::WebContents* web_contents, 68 const content::MediaStreamRequest& request, 69 const content::MediaResponseCallback& callback) OVERRIDE { 70 proxy_->RequestAudioInput(web_contents, request, callback); 71 } 72 73 // Overridden from content::WebContentsObserver: 74 virtual void WebContentsDestroyed() OVERRIDE { 75 delete this; 76 } 77 78 keyboard::KeyboardControllerProxy* proxy_; 79 80 DISALLOW_COPY_AND_ASSIGN(KeyboardContentsDelegate); 81 }; 82 83 } // namespace 84 85 namespace keyboard { 86 87 KeyboardControllerProxy::KeyboardControllerProxy() 88 : default_url_(kKeyboardURL) { 89 } 90 91 KeyboardControllerProxy::~KeyboardControllerProxy() { 92 } 93 94 const GURL& KeyboardControllerProxy::GetVirtualKeyboardUrl() { 95 if (keyboard::IsInputViewEnabled()) { 96 const GURL& override_url = GetOverrideContentUrl(); 97 return override_url.is_valid() ? override_url : default_url_; 98 } else { 99 return default_url_; 100 } 101 } 102 103 void KeyboardControllerProxy::LoadContents(const GURL& url) { 104 if (keyboard_contents_) { 105 content::OpenURLParams params( 106 url, 107 content::Referrer(), 108 SINGLETON_TAB, 109 content::PAGE_TRANSITION_AUTO_TOPLEVEL, 110 false); 111 keyboard_contents_->OpenURL(params); 112 } 113 } 114 115 aura::Window* KeyboardControllerProxy::GetKeyboardWindow() { 116 if (!keyboard_contents_) { 117 content::BrowserContext* context = GetBrowserContext(); 118 keyboard_contents_.reset(content::WebContents::Create( 119 content::WebContents::CreateParams(context, 120 content::SiteInstance::CreateForURL(context, 121 GetVirtualKeyboardUrl())))); 122 keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this)); 123 SetupWebContents(keyboard_contents_.get()); 124 LoadContents(GetVirtualKeyboardUrl()); 125 keyboard_contents_->GetNativeView()->AddObserver(this); 126 } 127 128 return keyboard_contents_->GetNativeView(); 129 } 130 131 bool KeyboardControllerProxy::HasKeyboardWindow() const { 132 return keyboard_contents_; 133 } 134 135 void KeyboardControllerProxy::ShowKeyboardContainer(aura::Window* container) { 136 GetKeyboardWindow()->Show(); 137 container->Show(); 138 } 139 140 void KeyboardControllerProxy::HideKeyboardContainer(aura::Window* container) { 141 container->Hide(); 142 GetKeyboardWindow()->Hide(); 143 } 144 145 void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) { 146 } 147 148 void KeyboardControllerProxy::EnsureCaretInWorkArea() { 149 if (GetInputMethod()->GetTextInputClient()) { 150 aura::Window* keyboard_window = GetKeyboardWindow(); 151 aura::Window* root_window = keyboard_window->GetRootWindow(); 152 gfx::Rect available_bounds = root_window->bounds(); 153 gfx::Rect keyboard_bounds = keyboard_window->bounds(); 154 available_bounds.set_height(available_bounds.height() - 155 keyboard_bounds.height()); 156 GetInputMethod()->GetTextInputClient()->EnsureCaretInRect(available_bounds); 157 } 158 } 159 160 void KeyboardControllerProxy::LoadSystemKeyboard() { 161 DCHECK(keyboard_contents_); 162 if (keyboard_contents_->GetURL() != default_url_) { 163 // TODO(bshe): The height of system virtual keyboard and IME virtual 164 // keyboard may different. The height needs to be restored too. 165 LoadContents(default_url_); 166 } 167 } 168 169 void KeyboardControllerProxy::ReloadKeyboardIfNeeded() { 170 DCHECK(keyboard_contents_); 171 if (keyboard_contents_->GetURL() != GetVirtualKeyboardUrl()) { 172 LoadContents(GetVirtualKeyboardUrl()); 173 } 174 } 175 176 void KeyboardControllerProxy::SetupWebContents(content::WebContents* contents) { 177 } 178 179 void KeyboardControllerProxy::OnWindowBoundsChanged( 180 aura::Window* window, 181 const gfx::Rect& old_bounds, 182 const gfx::Rect& new_bounds) { 183 if (!shadow_) { 184 shadow_.reset(new wm::Shadow()); 185 shadow_->Init(wm::Shadow::STYLE_ACTIVE); 186 shadow_->layer()->SetVisible(true); 187 DCHECK(keyboard_contents_->GetNativeView()->parent()); 188 keyboard_contents_->GetNativeView()->parent()->layer()->Add( 189 shadow_->layer()); 190 } 191 192 shadow_->SetContentBounds(new_bounds); 193 } 194 195 void KeyboardControllerProxy::OnWindowDestroyed(aura::Window* window) { 196 window->RemoveObserver(this); 197 } 198 199 } // namespace keyboard 200