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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ui/keyboard/content/keyboard_ui_content.cc
diff --git a/ui/keyboard/content/keyboard_ui_content.cc b/ui/keyboard/content/keyboard_ui_content.cc
new file mode 100644
index 0000000000000000000000000000000000000000..715a1d93a3da2bce64ac889cfd29c4000f91ea34
--- /dev/null
+++ b/ui/keyboard/content/keyboard_ui_content.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/keyboard/content/keyboard_ui_content.h"
+
+#include "base/command_line.h"
+#include "base/values.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/common/bindings_policy.h"
+#include "ui/aura/layout_manager.h"
+#include "ui/aura/window.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/keyboard/content/keyboard_constants.h"
+#include "ui/keyboard/keyboard_controller.h"
+#include "ui/keyboard/keyboard_switches.h"
+#include "ui/keyboard/keyboard_util.h"
+#include "ui/wm/core/shadow.h"
+
+namespace {
+
+// The WebContentsDelegate for the keyboard.
+// The delegate deletes itself when the keyboard is destroyed.
+class KeyboardContentsDelegate : public content::WebContentsDelegate,
+ public content::WebContentsObserver {
+ public:
+ KeyboardContentsDelegate(keyboard::KeyboardUIContent* ui) : ui_(ui) {}
sky 2015/10/09 18:23:29 explicit
+ ~KeyboardContentsDelegate() override {}
+
+ private:
+ // Overridden from content::WebContentsDelegate:
+ content::WebContents* OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) override {
+ source->GetController().LoadURL(
+ params.url, params.referrer, params.transition, params.extra_headers);
+ Observe(source);
+ return source;
+ }
+
+ bool CanDragEnter(content::WebContents* source,
+ const content::DropData& data,
+ blink::WebDragOperationsMask operations_allowed) override {
+ return false;
+ }
+
+ bool ShouldCreateWebContents(
+ content::WebContents* web_contents,
+ int route_id,
+ int main_frame_route_id,
+ WindowContainerType window_container_type,
+ const std::string& frame_name,
+ const GURL& target_url,
+ const std::string& partition_id,
+ content::SessionStorageNamespace* session_storage_namespace) override {
+ return false;
+ }
+
+ bool IsPopupOrPanel(const content::WebContents* source) const override {
+ return true;
+ }
+
+ void MoveContents(content::WebContents* source,
+ const gfx::Rect& pos) override {
+ aura::Window* keyboard = ui_->GetKeyboardWindow();
+ // keyboard window must have been added to keyboard container window at this
+ // point. Otherwise, wrong keyboard bounds is used and may cause problem as
+ // described in crbug.com/367788.
+ DCHECK(keyboard->parent());
+ // keyboard window bounds may not set to |pos| after this call. If keyboard
+ // is in FULL_WIDTH mode, only the height of keyboard window will be
+ // changed.
+ keyboard->SetBounds(pos);
+ }
+
+ // Overridden from content::WebContentsDelegate:
+ void RequestMediaAccessPermission(
+ content::WebContents* web_contents,
+ const content::MediaStreamRequest& request,
+ const content::MediaResponseCallback& callback) override {
+ ui_->RequestAudioInput(web_contents, request, callback);
+ }
+
+ // Overridden from content::WebContentsObserver:
+ void WebContentsDestroyed() override { delete this; }
+
+ keyboard::KeyboardUIContent* ui_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardContentsDelegate);
+};
+
+} // namespace
+
+namespace keyboard {
+
+class WindowBoundsChangeObserver : public aura::WindowObserver {
+ public:
+ explicit WindowBoundsChangeObserver(KeyboardUIContent* ui) : ui_(ui) {}
+ ~WindowBoundsChangeObserver() override {}
+
+ void AddObservedWindow(aura::Window* window) {
+ if (!window->HasObserver(this)) {
+ window->AddObserver(this);
+ observed_windows_.insert(window);
+ }
+ }
+ void RemoveAllObservedWindows() {
+ for (std::set<aura::Window*>::iterator it = observed_windows_.begin();
+ it != observed_windows_.end(); ++it)
+ (*it)->RemoveObserver(this);
+ observed_windows_.clear();
+ }
+
+ private:
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override {
+ ui_->UpdateInsetsForWindow(window);
+ }
+ void OnWindowDestroyed(aura::Window* window) override {
+ if (window->HasObserver(this))
+ window->RemoveObserver(this);
+ observed_windows_.erase(window);
+ }
+
+ KeyboardUIContent* ui_;
+ std::set<aura::Window*> observed_windows_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowBoundsChangeObserver);
+};
+
+KeyboardUIContent::KeyboardUIContent(content::BrowserContext* context)
+ : browser_context_(context),
+ default_url_(kKeyboardURL),
+ window_bounds_observer_(new WindowBoundsChangeObserver(this)) {
+}
+
+KeyboardUIContent::~KeyboardUIContent() {
+ ResetInsets();
+}
+
+void KeyboardUIContent::LoadSystemKeyboard() {
+ DCHECK(keyboard_contents_);
+ if (keyboard_contents_->GetURL() != default_url_) {
+ // TODO(bshe): The height of system virtual keyboard and IME virtual
+ // keyboard may different. The height needs to be restored too.
+ LoadContents(default_url_);
+ }
+}
+
+void KeyboardUIContent::UpdateInsetsForWindow(aura::Window* window) {
+ aura::Window* keyboard_window = GetKeyboardWindow();
+ scoped_ptr<content::RenderWidgetHostIterator> widgets(
+ content::RenderWidgetHost::GetRenderWidgetHosts());
+ while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
+ content::RenderWidgetHostView* view = widget->GetView();
+ if (view && window->Contains(view->GetNativeView())) {
+ gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen();
+ gfx::Rect intersect =
+ gfx::IntersectRects(window_bounds, keyboard_window->bounds());
+ int overlap = ShouldEnableInsets(window) ? intersect.height() : 0;
+ if (overlap > 0 && overlap < window_bounds.height())
+ view->SetInsets(gfx::Insets(0, 0, overlap, 0));
+ else
+ view->SetInsets(gfx::Insets());
+ return;
+ }
+ }
+}
+
+aura::Window* KeyboardUIContent::GetKeyboardWindow() {
+ if (!keyboard_contents_) {
+ content::BrowserContext* context = browser_context();
+ keyboard_contents_.reset(content::WebContents::Create(
+ content::WebContents::CreateParams(context,
+ content::SiteInstance::CreateForURL(context,
+ GetVirtualKeyboardUrl()))));
+ keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this));
+ SetupWebContents(keyboard_contents_.get());
+ LoadContents(GetVirtualKeyboardUrl());
+ keyboard_contents_->GetNativeView()->AddObserver(this);
+ }
+
+ return keyboard_contents_->GetNativeView();
+}
+
+bool KeyboardUIContent::HasKeyboardWindow() const {
+ return keyboard_contents_;
+}
+
+void KeyboardUIContent::ReloadKeyboardIfNeeded() {
+ DCHECK(keyboard_contents_);
+ if (keyboard_contents_->GetURL() != GetVirtualKeyboardUrl()) {
+ if (keyboard_contents_->GetURL().GetOrigin() !=
+ GetVirtualKeyboardUrl().GetOrigin()) {
+ // Sets keyboard window rectangle to 0 and close current page before
+ // navigate to a keyboard in a different extension. This keeps the UX the
+ // same as Android. Note we need to explicitly close current page as it
+ // might try to resize keyboard window in javascript on a resize event.
+ GetKeyboardWindow()->SetBounds(gfx::Rect());
+ keyboard_contents_->ClosePage();
+ keyboard_controller()->SetKeyboardMode(FULL_WIDTH);
+ }
+ LoadContents(GetVirtualKeyboardUrl());
+ }
+}
+
+void KeyboardUIContent::InitInsets(const gfx::Rect& new_bounds) {
+ // Adjust the height of the viewport for visible windows on the primary
+ // display.
+ // TODO(kevers): Add EnvObserver to properly initialize insets if a
+ // window is created while the keyboard is visible.
+ scoped_ptr<content::RenderWidgetHostIterator> widgets(
+ content::RenderWidgetHost::GetRenderWidgetHosts());
+ aura::Window* keyboard_window = GetKeyboardWindow();
+ aura::Window* root_window = keyboard_window->GetRootWindow();
+ while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
+ content::RenderWidgetHostView* view = widget->GetView();
+ // Can be NULL, e.g. if the RenderWidget is being destroyed or
+ // the render process crashed.
+ if (view) {
+ aura::Window* window = view->GetNativeView();
+ // If virtual keyboard failed to load, a widget that displays error
+ // message will be created and adds as a child of the virtual keyboard
+ // window. We want to avoid add BoundsChangedObserver to that window.
+ if (!keyboard_window->Contains(window) &&
+ window->GetRootWindow() == root_window) {
+ gfx::Rect window_bounds = window->GetBoundsInScreen();
+ gfx::Rect intersect = gfx::IntersectRects(window_bounds,
+ new_bounds);
+ int overlap = intersect.height();
+ if (overlap > 0 && overlap < window_bounds.height())
+ view->SetInsets(gfx::Insets(0, 0, overlap, 0));
+ else
+ view->SetInsets(gfx::Insets());
+ AddBoundsChangedObserver(window);
+ }
+ }
+ }
+}
+
+void KeyboardUIContent::ResetInsets() {
+ const gfx::Insets insets;
+ scoped_ptr<content::RenderWidgetHostIterator> widgets(
+ content::RenderWidgetHost::GetRenderWidgetHosts());
+ while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
+ content::RenderWidgetHostView* view = widget->GetView();
+ if (view)
+ view->SetInsets(insets);
+ }
+ window_bounds_observer_->RemoveAllObservedWindows();
+}
+
+void KeyboardUIContent::SetupWebContents(content::WebContents* contents) {
+}
+
+void KeyboardUIContent::OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ if (!shadow_) {
+ shadow_.reset(new wm::Shadow());
+ shadow_->Init(wm::Shadow::STYLE_ACTIVE);
+ shadow_->layer()->SetVisible(true);
+ DCHECK(keyboard_contents_->GetNativeView()->parent());
+ keyboard_contents_->GetNativeView()->parent()->layer()->Add(
+ shadow_->layer());
+ }
+
+ shadow_->SetContentBounds(new_bounds);
+}
+
+void KeyboardUIContent::OnWindowDestroyed(aura::Window* window) {
+ window->RemoveObserver(this);
+}
+
+void KeyboardUIContent::LoadContents(const GURL& url) {
+ if (keyboard_contents_) {
+ content::OpenURLParams params(
+ url,
+ content::Referrer(),
+ SINGLETON_TAB,
+ ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ false);
+ keyboard_contents_->OpenURL(params);
+ }
+}
+
+const GURL& KeyboardUIContent::GetVirtualKeyboardUrl() {
+ if (keyboard::IsInputViewEnabled()) {
+ const GURL& override_url = GetOverrideContentUrl();
+ return override_url.is_valid() ? override_url : default_url_;
+ } else {
+ return default_url_;
+ }
+}
+
+bool KeyboardUIContent::ShouldEnableInsets(aura::Window* window) {
+ aura::Window* keyboard_window = GetKeyboardWindow();
+ return (keyboard_window->GetRootWindow() == window->GetRootWindow() &&
+ keyboard::IsKeyboardOverscrollEnabled() &&
+ keyboard_window->IsVisible() &&
+ keyboard_controller()->keyboard_visible());
+}
+
+void KeyboardUIContent::AddBoundsChangedObserver(aura::Window* window) {
+ aura::Window* target_window = window ? window->GetToplevelWindow() : nullptr;
+ if (target_window)
+ window_bounds_observer_->AddObservedWindow(target_window);
+}
+
+} // namespace keyboard

Powered by Google App Engine
This is Rietveld 408576698