summaryrefslogtreecommitdiffstats
path: root/ash/content
diff options
context:
space:
mode:
authorjonross <jonross@chromium.org>2014-11-12 13:42:31 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-12 21:42:46 +0000
commit4f3952e7d0172a50d26a6eb57660623db70000db (patch)
tree4fd7ace867d52506e80ef5bef467545cc4898a08 /ash/content
parent98a7506987dccd2f6456d5d8399a215a4ab01590 (diff)
downloadchromium_src-4f3952e7d0172a50d26a6eb57660623db70000db.zip
chromium_src-4f3952e7d0172a50d26a6eb57660623db70000db.tar.gz
chromium_src-4f3952e7d0172a50d26a6eb57660623db70000db.tar.bz2
Implement ScreenOrientationDelegate on ChromeOS
Extend content::ScreenOrientationDelegate within ash to provide functionality on ChromeOS. Also provides a fix for a bug in ScreenOrientationProvider that was found during development. TEST=Manual testing on TouchView device with an HTML page that performs ScreenOrientation requests. BUG=396760 Review URL: https://codereview.chromium.org/648733003 Cr-Commit-Position: refs/heads/master@{#303898}
Diffstat (limited to 'ash/content')
-rw-r--r--ash/content/display/DEPS13
-rw-r--r--ash/content/display/screen_orientation_delegate_chromeos.cc179
-rw-r--r--ash/content/display/screen_orientation_delegate_chromeos.h64
-rw-r--r--ash/content/display/screen_orientation_delegate_chromeos_unittest.cc194
4 files changed, 450 insertions, 0 deletions
diff --git a/ash/content/display/DEPS b/ash/content/display/DEPS
new file mode 100644
index 0000000..42cea3c
--- /dev/null
+++ b/ash/content/display/DEPS
@@ -0,0 +1,13 @@
+include_rules = [
+ "+content/public/browser/screen_orientation_delegate.h",
+ "+content/public/browser/screen_orientation_provider.h",
+ "+content/public/browser/browser_context.h",
+ "+content/public/browser/web_contents.h",
+ "+third_party/WebKit/public/platform/WebScreenOrientationLockType.h",
+]
+
+specific_include_rules = {
+ ".*test\.cc": [
+ "+content/public/test/test_browser_context.h"
+ ],
+}
diff --git a/ash/content/display/screen_orientation_delegate_chromeos.cc b/ash/content/display/screen_orientation_delegate_chromeos.cc
new file mode 100644
index 0000000..f1f2e77
--- /dev/null
+++ b/ash/content/display/screen_orientation_delegate_chromeos.cc
@@ -0,0 +1,179 @@
+// Copyright 2014 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 "ash/content/display/screen_orientation_delegate_chromeos.h"
+
+#include "ash/ash_switches.h"
+#include "ash/display/display_info.h"
+#include "ash/display/display_manager.h"
+#include "ash/shell.h"
+#include "ash/wm/maximize_mode/maximize_mode_controller.h"
+#include "base/command_line.h"
+#include "content/public/browser/screen_orientation_provider.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/aura/window.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace {
+
+blink::WebScreenOrientationLockType GetDisplayNaturalOrientation() {
+ ash::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+ if (!display_manager->HasInternalDisplay())
+ return blink::WebScreenOrientationLockLandscape;
+
+ ash::DisplayInfo info =
+ display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId());
+ gfx::Size size = info.size_in_pixel();
+ switch (info.rotation()) {
+ case gfx::Display::ROTATE_0:
+ case gfx::Display::ROTATE_180:
+ return size.height() >= size.width()
+ ? blink::WebScreenOrientationLockPortrait
+ : blink::WebScreenOrientationLockLandscape;
+ case gfx::Display::ROTATE_90:
+ case gfx::Display::ROTATE_270:
+ return size.height() < size.width()
+ ? blink::WebScreenOrientationLockPortrait
+ : blink::WebScreenOrientationLockLandscape;
+ }
+ NOTREACHED();
+}
+
+} // namespace
+
+namespace ash {
+
+ScreenOrientationDelegate::ScreenOrientationDelegate()
+ : locking_window_(NULL),
+ natural_orientation_(GetDisplayNaturalOrientation()) {
+ content::ScreenOrientationProvider::SetDelegate(this);
+}
+
+ScreenOrientationDelegate::~ScreenOrientationDelegate() {
+ content::ScreenOrientationProvider::SetDelegate(NULL);
+}
+
+bool ScreenOrientationDelegate::FullScreenRequired(
+ content::WebContents* web_contents) {
+ return true;
+}
+
+void ScreenOrientationDelegate::Lock(
+ content::WebContents* web_contents,
+ blink::WebScreenOrientationLockType lock_orientation) {
+ aura::Window* requesting_window = web_contents->GetNativeView();
+
+ // TODO(jonross): Make ScreenOrientationDelegate responsible for rotation
+ // lock. Have MaximizeModeController, and TrayRotationLock both use it
+ // instead.
+ MaximizeModeController* controller =
+ Shell::GetInstance()->maximize_mode_controller();
+
+ // TODO(jonross): Track one rotation lock per window. When the active window
+ // changes apply any corresponding rotation lock.
+ if (!locking_window_)
+ locking_window_ = requesting_window;
+ else if (requesting_window != locking_window_)
+ return;
+
+ switch (lock_orientation) {
+ case blink::WebScreenOrientationLockAny:
+ controller->SetRotationLocked(false);
+ locking_window_ = NULL;
+ break;
+ case blink::WebScreenOrientationLockDefault:
+ NOTREACHED();
+ break;
+ case blink::WebScreenOrientationLockPortraitPrimary:
+ LockRotationToPrimaryOrientation(blink::WebScreenOrientationLockPortrait);
+ break;
+ case blink::WebScreenOrientationLockLandscape:
+ case blink::WebScreenOrientationLockPortrait:
+ LockToRotationMatchingOrientation(lock_orientation);
+ break;
+ case blink::WebScreenOrientationLockPortraitSecondary:
+ LockRotationToSecondaryOrientation(
+ blink::WebScreenOrientationLockPortrait);
+ break;
+ case blink::WebScreenOrientationLockLandscapeSecondary:
+ LockRotationToSecondaryOrientation(
+ blink::WebScreenOrientationLockLandscape);
+ break;
+ case blink::WebScreenOrientationLockLandscapePrimary:
+ LockRotationToPrimaryOrientation(
+ blink::WebScreenOrientationLockLandscape);
+ break;
+ case blink::WebScreenOrientationLockNatural:
+ controller->LockRotation(gfx::Display::ROTATE_0);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+bool ScreenOrientationDelegate::ScreenOrientationProviderSupported() {
+ return Shell::GetInstance()
+ ->maximize_mode_controller()
+ ->IsMaximizeModeWindowManagerEnabled() &&
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshEnableTouchViewTesting);
+}
+
+void ScreenOrientationDelegate::Unlock(content::WebContents* web_contents) {
+ aura::Window* requesting_window = web_contents->GetNativeView();
+ if (requesting_window != locking_window_)
+ return;
+ locking_window_ = NULL;
+ Shell::GetInstance()->maximize_mode_controller()->SetRotationLocked(false);
+}
+
+void ScreenOrientationDelegate::LockRotationToPrimaryOrientation(
+ blink::WebScreenOrientationLockType lock_orientation) {
+ Shell::GetInstance()->maximize_mode_controller()->LockRotation(
+ natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_0
+ : gfx::Display::ROTATE_90);
+}
+
+void ScreenOrientationDelegate::LockRotationToSecondaryOrientation(
+ blink::WebScreenOrientationLockType lock_orientation) {
+ Shell::GetInstance()->maximize_mode_controller()->LockRotation(
+ natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_180
+ : gfx::Display::ROTATE_270);
+}
+
+void ScreenOrientationDelegate::LockToRotationMatchingOrientation(
+ blink::WebScreenOrientationLockType lock_orientation) {
+ // TODO(jonross): Update MaximizeModeController to allow rotation between
+ // two angles of an orientation (e.g. from ROTATE_0 to ROTATE_180, and from
+ // ROTATE_90 to ROTATE_270)
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ if (!display_manager->HasInternalDisplay())
+ return;
+
+ gfx::Display::Rotation rotation =
+ display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId())
+ .rotation();
+ MaximizeModeController* controller =
+ Shell::GetInstance()->maximize_mode_controller();
+ if (natural_orientation_ == lock_orientation) {
+ if (rotation == gfx::Display::ROTATE_0 ||
+ rotation == gfx::Display::ROTATE_180) {
+ controller->SetRotationLocked(true);
+ } else {
+ controller->LockRotation(gfx::Display::ROTATE_0);
+ }
+ } else {
+ if (rotation == gfx::Display::ROTATE_90 ||
+ rotation == gfx::Display::ROTATE_270) {
+ controller->SetRotationLocked(true);
+ } else {
+ controller->LockRotation(gfx::Display::ROTATE_90);
+ }
+ }
+}
+
+} // namespace ash
diff --git a/ash/content/display/screen_orientation_delegate_chromeos.h b/ash/content/display/screen_orientation_delegate_chromeos.h
new file mode 100644
index 0000000..d1f4455
--- /dev/null
+++ b/ash/content/display/screen_orientation_delegate_chromeos.h
@@ -0,0 +1,64 @@
+// Copyright 2014 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.
+
+#ifndef ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_
+#define ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_
+
+#include "base/macros.h"
+#include "content/public/browser/screen_orientation_delegate.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+
+namespace aura {
+class Window;
+}
+
+namespace content {
+class WebContents;
+}
+
+namespace ash {
+
+// Implements ChromeOS specific functionality for ScreenOrientationProvider.
+class ScreenOrientationDelegate : public content::ScreenOrientationDelegate {
+ public:
+ ScreenOrientationDelegate();
+ virtual ~ScreenOrientationDelegate();
+
+ // content::ScreenOrientationDelegate:
+ bool FullScreenRequired(content::WebContents* web_contents) override;
+ void Lock(content::WebContents* web_contents,
+ blink::WebScreenOrientationLockType lock_orientation) override;
+ bool ScreenOrientationProviderSupported() override;
+ void Unlock(content::WebContents* web_contents) override;
+
+ private:
+ // Locks rotation to the angle matching the primary orientation for
+ // |lock_orientation|.
+ void LockRotationToPrimaryOrientation(
+ blink::WebScreenOrientationLockType lock_orientation);
+
+ // Locks rotation to the angle matching the secondary orientation for
+ // |lock_orientation|.
+ void LockRotationToSecondaryOrientation(
+ blink::WebScreenOrientationLockType lock_orientation);
+
+ // For orientations that do not specify primary or secondary, locks to the
+ // current rotation if it matches |lock_orientation|. Otherwise locks to a
+ // matching rotation.
+ void LockToRotationMatchingOrientation(
+ blink::WebScreenOrientationLockType lock_orientation);
+
+ // The window that has applied the current lock. No other window can apply a
+ // lock until the current window unlocks rotation.
+ aura::Window* locking_window_;
+
+ // The orientation of the display when at a rotation of 0.
+ blink::WebScreenOrientationLockType natural_orientation_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegate);
+};
+
+} // namespace ash
+
+#endif // ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_
diff --git a/ash/content/display/screen_orientation_delegate_chromeos_unittest.cc b/ash/content/display/screen_orientation_delegate_chromeos_unittest.cc
new file mode 100644
index 0000000..28d9bda
--- /dev/null
+++ b/ash/content/display/screen_orientation_delegate_chromeos_unittest.cc
@@ -0,0 +1,194 @@
+// Copyright 2014 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 "ash/ash_switches.h"
+#include "ash/content/display/screen_orientation_delegate_chromeos.h"
+#include "ash/display/display_info.h"
+#include "ash/display/display_manager.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_helper.h"
+#include "ash/test/test_shell_delegate.h"
+#include "ash/wm/maximize_mode/maximize_mode_controller.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_browser_context.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+#include "ui/gfx/display.h"
+#include "ui/views/test/webview_test_helper.h"
+#include "ui/views/view.h"
+#include "ui/views/views_delegate.h"
+
+namespace ash {
+
+namespace {
+
+gfx::Display::Rotation Rotation() {
+ return Shell::GetInstance()
+ ->display_manager()
+ ->GetDisplayInfo(gfx::Display::InternalDisplayId())
+ .rotation();
+}
+
+bool RotationLocked() {
+ return Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
+}
+
+} // namespace
+
+class ScreenOrientationDelegateTest : public test::AshTestBase {
+ public:
+ ScreenOrientationDelegateTest();
+ virtual ~ScreenOrientationDelegateTest();
+
+ ScreenOrientationDelegate* delegate() { return screen_orientation_delegate_; }
+
+ // Creates and initializes and empty content::WebContents that is backed by a
+ // content::BrowserContext and that has an aura::Window.
+ content::WebContents* CreateWebContents();
+
+ // Creates a secondary content::WebContents, with a separate
+ // content::BrowserContext.
+ content::WebContents* CreateSecondaryWebContents();
+
+ // test::AshTestBase:
+ void SetUp() override;
+
+ private:
+ ScreenOrientationDelegate* screen_orientation_delegate_;
+
+ // Optional content::BrowserContext used for two window tests.
+ scoped_ptr<content::BrowserContext> secondary_browser_context_;
+
+ // Setups underlying content layer so that content::WebContents can be
+ // generated.
+ scoped_ptr<views::WebViewTestHelper> webview_test_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegateTest);
+};
+
+ScreenOrientationDelegateTest::ScreenOrientationDelegateTest() {
+ webview_test_helper_.reset(new views::WebViewTestHelper());
+}
+
+ScreenOrientationDelegateTest::~ScreenOrientationDelegateTest() {
+}
+
+content::WebContents* ScreenOrientationDelegateTest::CreateWebContents() {
+ return views::ViewsDelegate::views_delegate->CreateWebContents(
+ ash_test_helper()->test_shell_delegate()->GetActiveBrowserContext(),
+ nullptr);
+}
+
+content::WebContents*
+ScreenOrientationDelegateTest::CreateSecondaryWebContents() {
+ secondary_browser_context_.reset(new content::TestBrowserContext());
+ return views::ViewsDelegate::views_delegate->CreateWebContents(
+ secondary_browser_context_.get(), nullptr);
+}
+
+void ScreenOrientationDelegateTest::SetUp() {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kAshUseFirstDisplayAsInternal);
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kAshEnableTouchViewTesting);
+ test::AshTestBase::SetUp();
+ screen_orientation_delegate_ =
+ Shell::GetInstance()->screen_orientation_delegate();
+}
+
+// Tests that a content::WebContents can lock rotation.
+TEST_F(ScreenOrientationDelegateTest, LockOrientation) {
+ scoped_ptr<content::WebContents> content(CreateWebContents());
+ ASSERT_NE(nullptr, content->GetNativeView());
+ ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
+ ASSERT_FALSE(RotationLocked());
+
+ delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
+ EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
+ EXPECT_TRUE(RotationLocked());
+}
+
+// Tests that a content::WebContents can unlock rotation.
+TEST_F(ScreenOrientationDelegateTest, Unlock) {
+ scoped_ptr<content::WebContents> content(CreateWebContents());
+ ASSERT_NE(nullptr, content->GetNativeView());
+ ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
+ ASSERT_FALSE(RotationLocked());
+
+ delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
+ EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
+ EXPECT_TRUE(RotationLocked());
+
+ delegate()->Unlock(content.get());
+ EXPECT_FALSE(RotationLocked());
+}
+
+// Tests that a content::WebContents is able to change the orientation of the
+// display after having locked rotation.
+TEST_F(ScreenOrientationDelegateTest, OrientationChanges) {
+ scoped_ptr<content::WebContents> content(CreateWebContents());
+ ASSERT_NE(nullptr, content->GetNativeView());
+ ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
+ ASSERT_FALSE(RotationLocked());
+
+ delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortrait);
+ EXPECT_EQ(gfx::Display::ROTATE_90, Rotation());
+ EXPECT_TRUE(RotationLocked());
+
+ delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
+ EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
+}
+
+// Tests that a user initiated rotation lock cannot be unlocked by a
+// content::WebContents.
+TEST_F(ScreenOrientationDelegateTest, UserLockRejectsUnlock) {
+ Shell::GetInstance()->maximize_mode_controller()->SetRotationLocked(true);
+
+ scoped_ptr<content::WebContents> content(CreateWebContents());
+ delegate()->Unlock(content.get());
+ EXPECT_TRUE(RotationLocked());
+}
+
+// Tests that orientation can only be set by the first content::WebContents that
+// has set a rotation lock.
+TEST_F(ScreenOrientationDelegateTest, SecondContentCannotChangeOrientation) {
+ scoped_ptr<content::WebContents> content1(CreateWebContents());
+ scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
+ ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
+
+ delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
+ delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait);
+ EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
+}
+
+// Tests that only the content::WebContents that set a rotation lock can perform
+// an unlock.
+TEST_F(ScreenOrientationDelegateTest, SecondContentCannotUnlock) {
+ scoped_ptr<content::WebContents> content1(CreateWebContents());
+ scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
+ ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
+
+ delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
+ delegate()->Unlock(content2.get());
+ EXPECT_TRUE(RotationLocked());
+}
+
+// Tests that alternate content::WebContents can set a rotation lock after a
+// preexisting lock has been released.
+TEST_F(ScreenOrientationDelegateTest, AfterUnlockSecondContentCanLock) {
+ scoped_ptr<content::WebContents> content1(CreateWebContents());
+ scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
+ ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
+
+ delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
+ delegate()->Unlock(content1.get());
+ delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait);
+ EXPECT_EQ(gfx::Display::ROTATE_90, Rotation());
+ EXPECT_TRUE(RotationLocked());
+}
+
+} // namespace ash