| Index: ash/rotator/screen_rotation_animator_unittest.cc
 | 
| diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
 | 
| index 09e64d3a7457df980bb18b3d9e67ff3f3168b45f..19de9cebb14f7c317448a2714d58e5395fa80edf 100644
 | 
| --- a/ash/rotator/screen_rotation_animator_unittest.cc
 | 
| +++ b/ash/rotator/screen_rotation_animator_unittest.cc
 | 
| @@ -5,6 +5,7 @@
 | 
|  #include "ash/rotator/screen_rotation_animator.h"
 | 
|  
 | 
|  #include "ash/ash_switches.h"
 | 
| +#include "ash/display/window_tree_host_manager.h"
 | 
|  #include "ash/public/cpp/config.h"
 | 
|  #include "ash/rotator/screen_rotation_animator_observer.h"
 | 
|  #include "ash/rotator/test/screen_rotation_animator_test_api.h"
 | 
| @@ -59,53 +60,128 @@ class AnimationObserver : public ScreenRotationAnimatorObserver {
 | 
|  
 | 
|  class TestScreenRotationAnimator : public ScreenRotationAnimator {
 | 
|   public:
 | 
| -  TestScreenRotationAnimator(int64_t display_id, const base::Closure& callback);
 | 
| +  TestScreenRotationAnimator(int64_t display_id,
 | 
| +                             const base::Closure& before_callback,
 | 
| +                             const base::Closure& after_callback);
 | 
|    ~TestScreenRotationAnimator() override {}
 | 
|  
 | 
|   private:
 | 
| -  CopyCallback CreateAfterCopyCallback(
 | 
| +  CopyCallback CreateAfterCopyCallbackBeforeRotation(
 | 
| +      std::unique_ptr<ScreenRotationRequest> rotation_request) override;
 | 
| +  CopyCallback CreateAfterCopyCallbackAfterRotation(
 | 
|        std::unique_ptr<ScreenRotationRequest> rotation_request) override;
 | 
|  
 | 
|    void IntersectBefore(CopyCallback next_callback,
 | 
|                         std::unique_ptr<cc::CopyOutputResult> result);
 | 
| +  void IntersectAfter(CopyCallback next_callback,
 | 
| +                      std::unique_ptr<cc::CopyOutputResult> result);
 | 
|  
 | 
| -  base::Closure intersect_callback_;
 | 
| +  base::Closure intersect_before_callback_;
 | 
| +  base::Closure intersect_after_callback_;
 | 
|  
 | 
|    DISALLOW_COPY_AND_ASSIGN(TestScreenRotationAnimator);
 | 
|  };
 | 
|  
 | 
|  TestScreenRotationAnimator::TestScreenRotationAnimator(
 | 
|      int64_t display_id,
 | 
| -    const base::Closure& callback)
 | 
| -    : ScreenRotationAnimator(display_id), intersect_callback_(callback) {}
 | 
| +    const base::Closure& before_callback,
 | 
| +    const base::Closure& after_callback)
 | 
| +    : ScreenRotationAnimator(display_id),
 | 
| +      intersect_before_callback_(before_callback),
 | 
| +      intersect_after_callback_(after_callback) {}
 | 
|  
 | 
|  ScreenRotationAnimator::CopyCallback
 | 
| -TestScreenRotationAnimator::CreateAfterCopyCallback(
 | 
| +TestScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
 | 
|      std::unique_ptr<ScreenRotationRequest> rotation_request) {
 | 
| -  CopyCallback next_callback = ScreenRotationAnimator::CreateAfterCopyCallback(
 | 
| -      std::move(rotation_request));
 | 
| +  CopyCallback next_callback =
 | 
| +      ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
 | 
| +          std::move(rotation_request));
 | 
|    return base::Bind(&TestScreenRotationAnimator::IntersectBefore,
 | 
|                      base::Unretained(this), next_callback);
 | 
|  }
 | 
|  
 | 
| +ScreenRotationAnimator::CopyCallback
 | 
| +TestScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
 | 
| +    std::unique_ptr<ScreenRotationRequest> rotation_request) {
 | 
| +  CopyCallback next_callback =
 | 
| +      ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
 | 
| +          std::move(rotation_request));
 | 
| +  return base::Bind(&TestScreenRotationAnimator::IntersectAfter,
 | 
| +                    base::Unretained(this), next_callback);
 | 
| +}
 | 
| +
 | 
|  void TestScreenRotationAnimator::IntersectBefore(
 | 
|      CopyCallback next_callback,
 | 
|      std::unique_ptr<cc::CopyOutputResult> result) {
 | 
| -  intersect_callback_.Run();
 | 
| +  intersect_before_callback_.Run();
 | 
| +  next_callback.Run(std::move(result));
 | 
| +}
 | 
| +
 | 
| +void TestScreenRotationAnimator::IntersectAfter(
 | 
| +    CopyCallback next_callback,
 | 
| +    std::unique_ptr<cc::CopyOutputResult> result) {
 | 
| +  intersect_after_callback_.Run();
 | 
|    next_callback.Run(std::move(result));
 | 
|  }
 | 
|  
 | 
|  }  // namespace
 | 
|  
 | 
| -class ScreenRotationAnimatorTest : public test::AshTestBase {
 | 
| +class ScreenRotationAnimatorSlowAnimationTest : public test::AshTestBase {
 | 
| + public:
 | 
| +  ScreenRotationAnimatorSlowAnimationTest() {}
 | 
| +  ~ScreenRotationAnimatorSlowAnimationTest() override {}
 | 
| +
 | 
| +  // AshTestBase:
 | 
| +  void SetUp() override;
 | 
| +
 | 
| + protected:
 | 
| +  int64_t display_id() const { return display_.id(); }
 | 
| +
 | 
| +  ScreenRotationAnimator* animator() { return animator_.get(); }
 | 
| +
 | 
| +  test::ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
 | 
| +
 | 
| + private:
 | 
| +  display::Display display_;
 | 
| +
 | 
| +  std::unique_ptr<ScreenRotationAnimator> animator_;
 | 
| +
 | 
| +  std::unique_ptr<test::ScreenRotationAnimatorTestApi> test_api_;
 | 
| +
 | 
| +  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
 | 
| +
 | 
| +  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorSlowAnimationTest);
 | 
| +};
 | 
| +
 | 
| +void ScreenRotationAnimatorSlowAnimationTest::SetUp() {
 | 
| +  AshTestBase::SetUp();
 | 
| +
 | 
| +  display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
 | 
| +  if (Shell::GetAshConfig() == Config::MASH) {
 | 
| +    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| +                display_id());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  animator_ = base::MakeUnique<ScreenRotationAnimator>(display_.id());
 | 
| +  test_api_ =
 | 
| +      base::MakeUnique<test::ScreenRotationAnimatorTestApi>(animator_.get());
 | 
| +  test_api()->DisableAnimationTimers();
 | 
| +  non_zero_duration_mode_ =
 | 
| +      base::MakeUnique<ui::ScopedAnimationDurationScaleMode>(
 | 
| +          ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
 | 
| +}
 | 
| +
 | 
| +class ScreenRotationAnimatorSmoothAnimationTest : public test::AshTestBase {
 | 
|   public:
 | 
| -  ScreenRotationAnimatorTest() {}
 | 
| -  ~ScreenRotationAnimatorTest() override {}
 | 
| +  ScreenRotationAnimatorSmoothAnimationTest() {}
 | 
| +  ~ScreenRotationAnimatorSmoothAnimationTest() override {}
 | 
|  
 | 
|    // AshTestBase:
 | 
|    void SetUp() override;
 | 
|  
 | 
|    void RemoveSecondaryDisplay(const std::string& specs);
 | 
| +  void QuitWaitForCopyCallback();
 | 
|  
 | 
|   protected:
 | 
|    int64_t display_id() const { return display_.id(); }
 | 
| @@ -113,7 +189,8 @@ class ScreenRotationAnimatorTest : public test::AshTestBase {
 | 
|    TestScreenRotationAnimator* animator() { return animator_.get(); }
 | 
|  
 | 
|    void SetScreenRotationAnimator(int64_t display_id,
 | 
| -                                 const base::Closure& callback);
 | 
| +                                 const base::Closure& before_callback,
 | 
| +                                 const base::Closure& after_callback);
 | 
|  
 | 
|    test::ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
 | 
|  
 | 
| @@ -130,41 +207,56 @@ class ScreenRotationAnimatorTest : public test::AshTestBase {
 | 
|  
 | 
|    std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
 | 
|  
 | 
| -  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorTest);
 | 
| +  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorSmoothAnimationTest);
 | 
|  };
 | 
|  
 | 
| -void ScreenRotationAnimatorTest::RemoveSecondaryDisplay(
 | 
| +void ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay(
 | 
|      const std::string& specs) {
 | 
|    UpdateDisplay(specs);
 | 
| +  QuitWaitForCopyCallback();
 | 
| +}
 | 
| +
 | 
| +void ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback() {
 | 
|    run_loop_->QuitWhenIdle();
 | 
|  }
 | 
|  
 | 
| -void ScreenRotationAnimatorTest::SetUp() {
 | 
| +void ScreenRotationAnimatorSmoothAnimationTest::SetUp() {
 | 
|    AshTestBase::SetUp();
 | 
|  
 | 
|    display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
 | 
| +  if (Shell::GetAshConfig() == Config::MASH) {
 | 
| +    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| +                display_id());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  base::CommandLine::ForCurrentProcess()->AppendSwitch(
 | 
| +      switches::kAshEnableSmoothScreenRotation);
 | 
|    run_loop_ = base::MakeUnique<base::RunLoop>();
 | 
| -  SetScreenRotationAnimator(display_.id(), run_loop_->QuitWhenIdleClosure());
 | 
| +  SetScreenRotationAnimator(display_.id(), run_loop_->QuitWhenIdleClosure(),
 | 
| +                            run_loop_->QuitWhenIdleClosure());
 | 
|    non_zero_duration_mode_ =
 | 
|        base::MakeUnique<ui::ScopedAnimationDurationScaleMode>(
 | 
|            ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
 | 
|  }
 | 
|  
 | 
| -void ScreenRotationAnimatorTest::SetScreenRotationAnimator(
 | 
| +void ScreenRotationAnimatorSmoothAnimationTest::SetScreenRotationAnimator(
 | 
|      int64_t display_id,
 | 
| -    const base::Closure& callback) {
 | 
| -  animator_ =
 | 
| -      base::MakeUnique<TestScreenRotationAnimator>(display_id, callback);
 | 
| +    const base::Closure& before_callback,
 | 
| +    const base::Closure& after_callback) {
 | 
| +  animator_ = base::MakeUnique<TestScreenRotationAnimator>(
 | 
| +      display_id, before_callback, after_callback);
 | 
|    test_api_ =
 | 
|        base::MakeUnique<test::ScreenRotationAnimatorTestApi>(animator_.get());
 | 
|    test_api()->DisableAnimationTimers();
 | 
|  }
 | 
|  
 | 
| -void ScreenRotationAnimatorTest::WaitForCopyCallback() {
 | 
| +void ScreenRotationAnimatorSmoothAnimationTest::WaitForCopyCallback() {
 | 
| +  run_loop_.reset(new base::RunLoop());
 | 
|    run_loop_->Run();
 | 
|  }
 | 
|  
 | 
| -TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserver) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserver) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -187,7 +279,7 @@ TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserver) {
 | 
|    animator()->RemoveScreenRotationAnimatorObserver(&observer);
 | 
|  }
 | 
|  
 | 
| -TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserverOnce) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserverOnce) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -214,7 +306,7 @@ TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserverOnce) {
 | 
|    animator()->RemoveScreenRotationAnimatorObserver(&observer);
 | 
|  }
 | 
|  
 | 
| -TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotation) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesToDifferentRotation) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -231,7 +323,8 @@ TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotation) {
 | 
|    EXPECT_FALSE(test_api()->HasActiveAnimations());
 | 
|  }
 | 
|  
 | 
| -TEST_F(ScreenRotationAnimatorTest, ShouldNotRotateTheSameRotation) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest,
 | 
| +       ShouldNotRotateTheSameRotation) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -248,7 +341,7 @@ TEST_F(ScreenRotationAnimatorTest, ShouldNotRotateTheSameRotation) {
 | 
|  // Simulates the situation that if there is a new rotation request during
 | 
|  // animation, it should stop the animation immediately and add the new rotation
 | 
|  // request to the |last_pending_request_|.
 | 
| -TEST_F(ScreenRotationAnimatorTest, RotatesDuringRotation) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesDuringRotation) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -270,7 +363,7 @@ TEST_F(ScreenRotationAnimatorTest, RotatesDuringRotation) {
 | 
|  
 | 
|  // If there are multiple requests queued during animation, it should process the
 | 
|  // last request and finish the rotation animation.
 | 
| -TEST_F(ScreenRotationAnimatorTest, ShouldCompleteAnimations) {
 | 
| +TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldCompleteAnimations) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -297,7 +390,8 @@ TEST_F(ScreenRotationAnimatorTest, ShouldCompleteAnimations) {
 | 
|  }
 | 
|  
 | 
|  // Test enable smooth screen rotation code path.
 | 
| -TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotationWithCopyCallback) {
 | 
| +TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
 | 
| +       RotatesToDifferentRotationWithCopyCallback) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -305,9 +399,12 @@ TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotationWithCopyCallback) {
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| +  SetScreenRotationAnimator(
 | 
| +      display_manager()->GetDisplayAt(0).id(), run_loop_->QuitWhenIdleClosure(),
 | 
| +      base::Bind(
 | 
| +          &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
 | 
| +          base::Unretained(this)));
 | 
|    SetDisplayRotation(display_id(), display::Display::ROTATE_0);
 | 
| -  base::CommandLine::ForCurrentProcess()->AppendSwitch(
 | 
| -      switches::kAshEnableSmoothScreenRotation);
 | 
|    animator()->Rotate(display::Display::ROTATE_90,
 | 
|                       display::Display::RotationSource::ROTATION_SOURCE_USER);
 | 
|    WaitForCopyCallback();
 | 
| @@ -317,8 +414,10 @@ TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotationWithCopyCallback) {
 | 
|    EXPECT_FALSE(test_api()->HasActiveAnimations());
 | 
|  }
 | 
|  
 | 
| -// If the external display is removed, it should not crash.
 | 
| -TEST_F(ScreenRotationAnimatorTest, RemoveSecondaryDisplayAfterCopyCallback) {
 | 
| +// If the external secondary display is removed before the first copy request
 | 
| +// callback called, it should not crash.
 | 
| +TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
 | 
| +       RemoveExternalSecondaryDisplayBeforeFirstCopyCallback) {
 | 
|    // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
|    if (Shell::GetAshConfig() == Config::MASH) {
 | 
|      ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| @@ -333,10 +432,10 @@ TEST_F(ScreenRotationAnimatorTest, RemoveSecondaryDisplayAfterCopyCallback) {
 | 
|        display_manager()->GetDisplayAt(0).id();
 | 
|    SetScreenRotationAnimator(
 | 
|        display_manager()->GetDisplayAt(1).id(),
 | 
| -      base::Bind(&ScreenRotationAnimatorTest::RemoveSecondaryDisplay,
 | 
| -                 base::Unretained(this), "640x480"));
 | 
| -  base::CommandLine::ForCurrentProcess()->AppendSwitch(
 | 
| -      switches::kAshEnableSmoothScreenRotation);
 | 
| +      base::Bind(
 | 
| +          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
 | 
| +          base::Unretained(this), "640x480"),
 | 
| +      run_loop_->QuitWhenIdleClosure());
 | 
|    SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
 | 
|                       display::Display::ROTATE_0);
 | 
|    animator()->Rotate(display::Display::ROTATE_90,
 | 
| @@ -346,4 +445,99 @@ TEST_F(ScreenRotationAnimatorTest, RemoveSecondaryDisplayAfterCopyCallback) {
 | 
|    EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
 | 
|  }
 | 
|  
 | 
| +// If the external primary display is removed before the first copy request
 | 
| +// callback called, it should not crash.
 | 
| +TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
 | 
| +       RemoveExternalPrimaryDisplayBeforeFirstCopyCallback) {
 | 
| +  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
| +  if (Shell::GetAshConfig() == Config::MASH) {
 | 
| +    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| +                display_id());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  UpdateDisplay("640x480,800x600");
 | 
| +  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
 | 
| +
 | 
| +  Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
 | 
| +      display_manager()->GetDisplayAt(1).id());
 | 
| +  const unsigned int secondary_display_id =
 | 
| +      display_manager()->GetDisplayAt(0).id();
 | 
| +  SetScreenRotationAnimator(
 | 
| +      display_manager()->GetDisplayAt(1).id(),
 | 
| +      base::Bind(
 | 
| +          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
 | 
| +          base::Unretained(this), "640x480"),
 | 
| +      run_loop_->QuitWhenIdleClosure());
 | 
| +  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
 | 
| +                     display::Display::ROTATE_0);
 | 
| +  animator()->Rotate(display::Display::ROTATE_90,
 | 
| +                     display::Display::RotationSource::ROTATION_SOURCE_USER);
 | 
| +  WaitForCopyCallback();
 | 
| +  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
 | 
| +  EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
 | 
| +}
 | 
| +
 | 
| +// If the external secondary display is removed before the second copy request
 | 
| +// callback called, it should not crash.
 | 
| +TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
 | 
| +       RemoveExternalSecondaryDisplayBeforeSecondCopyCallback) {
 | 
| +  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
| +  if (Shell::GetAshConfig() == Config::MASH) {
 | 
| +    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| +                display_id());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  UpdateDisplay("640x480,800x600");
 | 
| +  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
 | 
| +
 | 
| +  const unsigned int primary_display_id =
 | 
| +      display_manager()->GetDisplayAt(0).id();
 | 
| +  SetScreenRotationAnimator(
 | 
| +      display_manager()->GetDisplayAt(1).id(), run_loop_->QuitWhenIdleClosure(),
 | 
| +      base::Bind(
 | 
| +          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
 | 
| +          base::Unretained(this), "640x480"));
 | 
| +  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
 | 
| +                     display::Display::ROTATE_0);
 | 
| +  animator()->Rotate(display::Display::ROTATE_90,
 | 
| +                     display::Display::RotationSource::ROTATION_SOURCE_USER);
 | 
| +  WaitForCopyCallback();
 | 
| +  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
 | 
| +  EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
 | 
| +}
 | 
| +
 | 
| +// If the external primary display is removed before the second copy request
 | 
| +// callback called, it should not crash.
 | 
| +TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
 | 
| +       RemoveExternalPrimaryDisplayBeforeSecondCopyCallback) {
 | 
| +  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
 | 
| +  if (Shell::GetAshConfig() == Config::MASH) {
 | 
| +    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
 | 
| +                display_id());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  UpdateDisplay("640x480,800x600");
 | 
| +  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
 | 
| +
 | 
| +  Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
 | 
| +      display_manager()->GetDisplayAt(1).id());
 | 
| +  const unsigned int secondary_display_id =
 | 
| +      display_manager()->GetDisplayAt(0).id();
 | 
| +  SetScreenRotationAnimator(
 | 
| +      display_manager()->GetDisplayAt(1).id(), run_loop_->QuitWhenIdleClosure(),
 | 
| +      base::Bind(
 | 
| +          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
 | 
| +          base::Unretained(this), "640x480"));
 | 
| +  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
 | 
| +                     display::Display::ROTATE_0);
 | 
| +  animator()->Rotate(display::Display::ROTATE_90,
 | 
| +                     display::Display::RotationSource::ROTATION_SOURCE_USER);
 | 
| +  WaitForCopyCallback();
 | 
| +  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
 | 
| +  EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
 | 
| +}
 | 
| +
 | 
|  }  // namespace ash
 | 
| 
 |