diff options
author | jonross <jonross@chromium.org> | 2014-11-12 13:42:31 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-12 21:42:46 +0000 |
commit | 4f3952e7d0172a50d26a6eb57660623db70000db (patch) | |
tree | 4fd7ace867d52506e80ef5bef467545cc4898a08 /ash/content | |
parent | 98a7506987dccd2f6456d5d8399a215a4ab01590 (diff) | |
download | chromium_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/DEPS | 13 | ||||
-rw-r--r-- | ash/content/display/screen_orientation_delegate_chromeos.cc | 179 | ||||
-rw-r--r-- | ash/content/display/screen_orientation_delegate_chromeos.h | 64 | ||||
-rw-r--r-- | ash/content/display/screen_orientation_delegate_chromeos_unittest.cc | 194 |
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 |