Home | History | Annotate | Download | only in ash
      1 // Copyright (c) 2012 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 "ash/root_window_controller.h"
      6 
      7 #include "ash/session_state_delegate.h"
      8 #include "ash/shelf/shelf_layout_manager.h"
      9 #include "ash/shell.h"
     10 #include "ash/shell_window_ids.h"
     11 #include "ash/system/tray/system_tray_delegate.h"
     12 #include "ash/test/ash_test_base.h"
     13 #include "ash/wm/system_modal_container_layout_manager.h"
     14 #include "ash/wm/window_properties.h"
     15 #include "ash/wm/window_state.h"
     16 #include "ash/wm/window_util.h"
     17 #include "base/command_line.h"
     18 #include "ui/aura/client/focus_change_observer.h"
     19 #include "ui/aura/client/focus_client.h"
     20 #include "ui/aura/client/window_tree_client.h"
     21 #include "ui/aura/env.h"
     22 #include "ui/aura/root_window.h"
     23 #include "ui/aura/test/event_generator.h"
     24 #include "ui/aura/test/test_event_handler.h"
     25 #include "ui/aura/test/test_window_delegate.h"
     26 #include "ui/aura/test/test_windows.h"
     27 #include "ui/aura/window.h"
     28 #include "ui/aura/window_tracker.h"
     29 #include "ui/keyboard/keyboard_controller_proxy.h"
     30 #include "ui/keyboard/keyboard_switches.h"
     31 #include "ui/views/controls/menu/menu_controller.h"
     32 #include "ui/views/widget/widget.h"
     33 #include "ui/views/widget/widget_delegate.h"
     34 
     35 using aura::Window;
     36 using views::Widget;
     37 
     38 namespace ash {
     39 namespace {
     40 
     41 class TestDelegate : public views::WidgetDelegateView {
     42  public:
     43   explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {}
     44   virtual ~TestDelegate() {}
     45 
     46   // Overridden from views::WidgetDelegate:
     47   virtual views::View* GetContentsView() OVERRIDE {
     48     return this;
     49   }
     50 
     51   virtual ui::ModalType GetModalType() const OVERRIDE {
     52     return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
     53   }
     54 
     55  private:
     56   bool system_modal_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
     59 };
     60 
     61 class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate,
     62                              public aura::client::FocusChangeObserver {
     63  public:
     64   DeleteOnBlurDelegate() : window_(NULL) {}
     65   virtual ~DeleteOnBlurDelegate() {}
     66 
     67   void SetWindow(aura::Window* window) {
     68     window_ = window;
     69     aura::client::SetFocusChangeObserver(window_, this);
     70   }
     71 
     72  private:
     73   // aura::test::TestWindowDelegate overrides:
     74   virtual bool CanFocus() OVERRIDE {
     75     return true;
     76   }
     77 
     78   // aura::client::FocusChangeObserver implementation:
     79   virtual void OnWindowFocused(aura::Window* gained_focus,
     80                                aura::Window* lost_focus) OVERRIDE {
     81     if (window_ == lost_focus)
     82       delete window_;
     83   }
     84 
     85   aura::Window* window_;
     86 
     87   DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate);
     88 };
     89 
     90 }  // namespace
     91 
     92 namespace test {
     93 
     94 class RootWindowControllerTest : public test::AshTestBase {
     95  public:
     96   views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
     97     views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
     98         NULL, CurrentContext(), bounds);
     99     widget->Show();
    100     return widget;
    101   }
    102 
    103   views::Widget* CreateModalWidget(const gfx::Rect& bounds) {
    104     views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
    105         new TestDelegate(true), CurrentContext(), bounds);
    106     widget->Show();
    107     return widget;
    108   }
    109 
    110   views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds,
    111                                              gfx::NativeWindow parent) {
    112     views::Widget* widget =
    113         views::Widget::CreateWindowWithParentAndBounds(new TestDelegate(true),
    114                                                        parent,
    115                                                        bounds);
    116     widget->Show();
    117     return widget;
    118   }
    119 
    120   aura::Window* GetModalContainer(aura::Window* root_window) {
    121     return Shell::GetContainer(
    122         root_window,
    123         ash::internal::kShellWindowId_SystemModalContainer);
    124   }
    125 };
    126 
    127 TEST_F(RootWindowControllerTest, MoveWindows_Basic) {
    128   if (!SupportsMultipleDisplays())
    129     return;
    130 
    131   UpdateDisplay("600x600,500x500");
    132   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    133   internal::RootWindowController* controller =
    134       Shell::GetPrimaryRootWindowController();
    135   internal::ShelfLayoutManager* shelf_layout_manager =
    136       controller->GetShelfLayoutManager();
    137   shelf_layout_manager->SetAutoHideBehavior(
    138       ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    139 
    140   views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100));
    141   EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow());
    142   EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString());
    143   EXPECT_EQ("50,10 100x100",
    144             normal->GetNativeView()->GetBoundsInRootWindow().ToString());
    145 
    146   views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100));
    147   maximized->Maximize();
    148   EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow());
    149   EXPECT_EQ("600,0 500x453", maximized->GetWindowBoundsInScreen().ToString());
    150   EXPECT_EQ("0,0 500x453",
    151             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
    152 
    153   views::Widget* minimized = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
    154   minimized->Minimize();
    155   EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow());
    156   EXPECT_EQ("800,10 100x100",
    157             minimized->GetWindowBoundsInScreen().ToString());
    158 
    159   views::Widget* fullscreen = CreateTestWidget(gfx::Rect(900, 10, 100, 100));
    160   fullscreen->SetFullscreen(true);
    161   EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow());
    162 
    163   EXPECT_EQ("600,0 500x500",
    164             fullscreen->GetWindowBoundsInScreen().ToString());
    165   EXPECT_EQ("0,0 500x500",
    166             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
    167 
    168   views::Widget* unparented_control = new Widget;
    169   Widget::InitParams params;
    170   params.bounds = gfx::Rect(650, 10, 100, 100);
    171   params.context = CurrentContext();
    172   params.type = Widget::InitParams::TYPE_CONTROL;
    173   unparented_control->Init(params);
    174   EXPECT_EQ(root_windows[1],
    175             unparented_control->GetNativeView()->GetRootWindow());
    176   EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer,
    177             unparented_control->GetNativeView()->parent()->id());
    178 
    179   aura::Window* panel = CreateTestWindowInShellWithDelegateAndType(
    180       NULL, aura::client::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100));
    181   EXPECT_EQ(root_windows[1], panel->GetRootWindow());
    182   EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id());
    183 
    184   // Make sure a window that will delete itself when losing focus
    185   // will not crash.
    186   aura::WindowTracker tracker;
    187   DeleteOnBlurDelegate delete_on_blur_delegate;
    188   aura::Window* d2 = CreateTestWindowInShellWithDelegate(
    189       &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100));
    190   delete_on_blur_delegate.SetWindow(d2);
    191   aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2);
    192   tracker.Add(d2);
    193 
    194   UpdateDisplay("600x600");
    195 
    196   // d2 must have been deleted.
    197   EXPECT_FALSE(tracker.Contains(d2));
    198 
    199   EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
    200   EXPECT_EQ("50,10 100x100", normal->GetWindowBoundsInScreen().ToString());
    201   EXPECT_EQ("50,10 100x100",
    202             normal->GetNativeView()->GetBoundsInRootWindow().ToString());
    203 
    204   // Maximized area on primary display has 3px (given as
    205   // kAutoHideSize in shelf_layout_manager.cc) inset at the bottom.
    206 
    207   // First clear fullscreen status, since both fullscreen and maximized windows
    208   // share the same desktop workspace, which cancels the shelf status.
    209   fullscreen->SetFullscreen(false);
    210   EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
    211   EXPECT_EQ("0,0 600x597",
    212             maximized->GetWindowBoundsInScreen().ToString());
    213   EXPECT_EQ("0,0 600x597",
    214             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
    215 
    216   // Set fullscreen to true. In that case the 3px inset becomes invisible so
    217   // the maximized window can also use the area fully.
    218   fullscreen->SetFullscreen(true);
    219   EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
    220   EXPECT_EQ("0,0 600x600",
    221             maximized->GetWindowBoundsInScreen().ToString());
    222   EXPECT_EQ("0,0 600x600",
    223             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
    224 
    225   EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow());
    226   EXPECT_EQ("200,10 100x100",
    227             minimized->GetWindowBoundsInScreen().ToString());
    228 
    229   EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow());
    230   EXPECT_TRUE(fullscreen->IsFullscreen());
    231   EXPECT_EQ("0,0 600x600",
    232             fullscreen->GetWindowBoundsInScreen().ToString());
    233   EXPECT_EQ("0,0 600x600",
    234             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
    235 
    236   // Test if the restore bounds are correctly updated.
    237   wm::GetWindowState(maximized->GetNativeView())->Restore();
    238   EXPECT_EQ("100,10 100x100", maximized->GetWindowBoundsInScreen().ToString());
    239   EXPECT_EQ("100,10 100x100",
    240             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
    241 
    242   fullscreen->SetFullscreen(false);
    243   EXPECT_EQ("300,10 100x100",
    244             fullscreen->GetWindowBoundsInScreen().ToString());
    245   EXPECT_EQ("300,10 100x100",
    246             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
    247 
    248   // Test if the unparented widget has moved.
    249   EXPECT_EQ(root_windows[0],
    250             unparented_control->GetNativeView()->GetRootWindow());
    251   EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer,
    252             unparented_control->GetNativeView()->parent()->id());
    253 
    254   // Test if the panel has moved.
    255   EXPECT_EQ(root_windows[0], panel->GetRootWindow());
    256   EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id());
    257 }
    258 
    259 TEST_F(RootWindowControllerTest, MoveWindows_Modal) {
    260   if (!SupportsMultipleDisplays())
    261     return;
    262 
    263   UpdateDisplay("500x500,500x500");
    264 
    265   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    266   // Emulate virtual screen coordinate system.
    267   root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500));
    268   root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500));
    269 
    270   views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100));
    271   EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
    272   EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView()));
    273 
    274   views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100));
    275   EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow());
    276   EXPECT_TRUE(GetModalContainer(root_windows[1])->Contains(
    277       modal->GetNativeView()));
    278   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
    279 
    280   aura::test::EventGenerator generator_1st(root_windows[0]);
    281   generator_1st.ClickLeftButton();
    282   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
    283 
    284   UpdateDisplay("500x500");
    285   EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow());
    286   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
    287   generator_1st.ClickLeftButton();
    288   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
    289 }
    290 
    291 TEST_F(RootWindowControllerTest, ModalContainer) {
    292   UpdateDisplay("600x600");
    293   Shell* shell = Shell::GetInstance();
    294   internal::RootWindowController* controller =
    295       shell->GetPrimaryRootWindowController();
    296   EXPECT_EQ(user::LOGGED_IN_USER,
    297             shell->system_tray_delegate()->GetUserLoginStatus());
    298   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    299       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    300           controller->GetSystemModalLayoutManager(NULL));
    301 
    302   views::Widget* session_modal_widget =
    303       CreateModalWidget(gfx::Rect(300, 10, 100, 100));
    304   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    305       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    306           controller->GetSystemModalLayoutManager(
    307               session_modal_widget->GetNativeView()));
    308 
    309   shell->session_state_delegate()->LockScreen();
    310   EXPECT_EQ(user::LOGGED_IN_LOCKED,
    311             shell->system_tray_delegate()->GetUserLoginStatus());
    312   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    313       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    314           controller->GetSystemModalLayoutManager(NULL));
    315 
    316   aura::Window* lock_container =
    317       Shell::GetContainer(controller->root_window(),
    318                           internal::kShellWindowId_LockScreenContainer);
    319   views::Widget* lock_modal_widget =
    320       CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
    321   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    322       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    323           controller->GetSystemModalLayoutManager(
    324               lock_modal_widget->GetNativeView()));
    325   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    326         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    327             controller->GetSystemModalLayoutManager(
    328                 session_modal_widget->GetNativeView()));
    329 
    330   shell->session_state_delegate()->UnlockScreen();
    331 }
    332 
    333 TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
    334   UpdateDisplay("600x600");
    335   Shell* shell = Shell::GetInstance();
    336 
    337   // Configure login screen environment.
    338   SetUserLoggedIn(false);
    339   EXPECT_EQ(user::LOGGED_IN_NONE,
    340             shell->system_tray_delegate()->GetUserLoginStatus());
    341   EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers());
    342   EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted());
    343 
    344   internal::RootWindowController* controller =
    345       shell->GetPrimaryRootWindowController();
    346   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    347       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    348           controller->GetSystemModalLayoutManager(NULL));
    349 
    350   aura::Window* lock_container =
    351       Shell::GetContainer(controller->root_window(),
    352                           internal::kShellWindowId_LockScreenContainer);
    353   views::Widget* login_modal_widget =
    354       CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
    355   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    356       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    357           controller->GetSystemModalLayoutManager(
    358               login_modal_widget->GetNativeView()));
    359   login_modal_widget->Close();
    360 
    361   // Configure user session environment.
    362   SetUserLoggedIn(true);
    363   SetSessionStarted(true);
    364   EXPECT_EQ(user::LOGGED_IN_USER,
    365             shell->system_tray_delegate()->GetUserLoginStatus());
    366   EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers());
    367   EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted());
    368   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    369       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    370           controller->GetSystemModalLayoutManager(NULL));
    371 
    372   views::Widget* session_modal_widget =
    373         CreateModalWidget(gfx::Rect(300, 10, 100, 100));
    374   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    375       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    376           controller->GetSystemModalLayoutManager(
    377               session_modal_widget->GetNativeView()));
    378 }
    379 
    380 TEST_F(RootWindowControllerTest, ModalContainerBlockedSession) {
    381   UpdateDisplay("600x600");
    382   Shell* shell = Shell::GetInstance();
    383   internal::RootWindowController* controller =
    384       shell->GetPrimaryRootWindowController();
    385   aura::Window* lock_container =
    386       Shell::GetContainer(controller->root_window(),
    387                           internal::kShellWindowId_LockScreenContainer);
    388   for (int block_reason = FIRST_BLOCK_REASON;
    389        block_reason < NUMBER_OF_BLOCK_REASONS;
    390        ++block_reason) {
    391     views::Widget* session_modal_widget =
    392           CreateModalWidget(gfx::Rect(300, 10, 100, 100));
    393     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    394         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    395             controller->GetSystemModalLayoutManager(
    396                 session_modal_widget->GetNativeView()));
    397     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    398         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    399             controller->GetSystemModalLayoutManager(NULL));
    400     session_modal_widget->Close();
    401 
    402     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
    403 
    404     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    405         internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    406             controller->GetSystemModalLayoutManager(NULL));
    407 
    408     views::Widget* lock_modal_widget =
    409         CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100),
    410                                     lock_container);
    411     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    412         internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
    413               controller->GetSystemModalLayoutManager(
    414                   lock_modal_widget->GetNativeView()));
    415 
    416     session_modal_widget =
    417           CreateModalWidget(gfx::Rect(300, 10, 100, 100));
    418     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
    419         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
    420             controller->GetSystemModalLayoutManager(
    421                 session_modal_widget->GetNativeView()));
    422     session_modal_widget->Close();
    423 
    424     lock_modal_widget->Close();
    425     UnblockUserSession();
    426   }
    427 }
    428 
    429 TEST_F(RootWindowControllerTest, GetWindowForFullscreenMode) {
    430   UpdateDisplay("600x600");
    431   internal::RootWindowController* controller =
    432       Shell::GetInstance()->GetPrimaryRootWindowController();
    433 
    434   Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
    435   w1->Maximize();
    436   Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
    437   w2->SetFullscreen(true);
    438   // |w3| is a transient child of |w2|.
    439   Widget* w3 = Widget::CreateWindowWithParentAndBounds(NULL,
    440       w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
    441 
    442   // Test that GetWindowForFullscreenMode() finds the fullscreen window when one
    443   // of its transient children is active.
    444   w3->Activate();
    445   EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
    446 
    447   // If the topmost window is not fullscreen, it returns NULL.
    448   w1->Activate();
    449   EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
    450   w1->Close();
    451   w3->Close();
    452 
    453   // Only w2 remains, if minimized GetWindowForFullscreenMode should return
    454   // NULL.
    455   w2->Activate();
    456   EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
    457   w2->Minimize();
    458   EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
    459 }
    460 
    461 // Test that user session window can't be focused if user session blocked by
    462 // some overlapping UI.
    463 TEST_F(RootWindowControllerTest, FocusBlockedWindow) {
    464   UpdateDisplay("600x600");
    465   internal::RootWindowController* controller =
    466       Shell::GetInstance()->GetPrimaryRootWindowController();
    467   aura::Window* lock_container =
    468       Shell::GetContainer(controller->root_window(),
    469                           internal::kShellWindowId_LockScreenContainer);
    470   aura::Window* lock_window = Widget::CreateWindowWithParentAndBounds(NULL,
    471       lock_container, gfx::Rect(0, 0, 100, 100))->GetNativeView();
    472   lock_window->Show();
    473   aura::Window* session_window =
    474       CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView();
    475   session_window->Show();
    476 
    477   for (int block_reason = FIRST_BLOCK_REASON;
    478        block_reason < NUMBER_OF_BLOCK_REASONS;
    479        ++block_reason) {
    480     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
    481     lock_window->Focus();
    482     EXPECT_TRUE(lock_window->HasFocus());
    483     session_window->Focus();
    484     EXPECT_FALSE(session_window->HasFocus());
    485     UnblockUserSession();
    486   }
    487 }
    488 
    489 // Tracks whether OnWindowDestroying() has been invoked.
    490 class DestroyedWindowObserver : public aura::WindowObserver {
    491  public:
    492   DestroyedWindowObserver() : destroyed_(false), window_(NULL) {}
    493   virtual ~DestroyedWindowObserver() {
    494     Shutdown();
    495   }
    496 
    497   void SetWindow(Window* window) {
    498     window_ = window;
    499     window->AddObserver(this);
    500   }
    501 
    502   bool destroyed() const { return destroyed_; }
    503 
    504   // WindowObserver overrides:
    505   virtual void OnWindowDestroying(Window* window) OVERRIDE {
    506     destroyed_ = true;
    507     Shutdown();
    508   }
    509 
    510  private:
    511   void Shutdown() {
    512     if (!window_)
    513       return;
    514     window_->RemoveObserver(this);
    515     window_ = NULL;
    516   }
    517 
    518   bool destroyed_;
    519   Window* window_;
    520 
    521   DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver);
    522 };
    523 
    524 // Verifies shutdown doesn't delete windows that are not owned by the parent.
    525 TEST_F(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) {
    526   DestroyedWindowObserver observer1;
    527   aura::test::TestWindowDelegate delegate1;
    528   aura::Window* window1 = new aura::Window(&delegate1);
    529   window1->SetType(aura::client::WINDOW_TYPE_CONTROL);
    530   window1->set_owned_by_parent(false);
    531   observer1.SetWindow(window1);
    532   window1->Init(ui::LAYER_NOT_DRAWN);
    533   aura::client::ParentWindowWithContext(
    534       window1, Shell::GetInstance()->GetPrimaryRootWindow(), gfx::Rect());
    535 
    536   DestroyedWindowObserver observer2;
    537   aura::Window* window2 = new aura::Window(NULL);
    538   window2->set_owned_by_parent(false);
    539   observer2.SetWindow(window2);
    540   window2->Init(ui::LAYER_NOT_DRAWN);
    541   Shell::GetInstance()->GetPrimaryRootWindow()->AddChild(window2);
    542 
    543   Shell::GetInstance()->GetPrimaryRootWindowController()->CloseChildWindows();
    544 
    545   ASSERT_FALSE(observer1.destroyed());
    546   delete window1;
    547 
    548   ASSERT_FALSE(observer2.destroyed());
    549   delete window2;
    550 }
    551 
    552 typedef test::NoSessionAshTestBase NoSessionRootWindowControllerTest;
    553 
    554 // Make sure that an event handler exists for entire display area.
    555 TEST_F(NoSessionRootWindowControllerTest, Event) {
    556   aura::Window* root = Shell::GetPrimaryRootWindow();
    557   const gfx::Size size = root->bounds().size();
    558   aura::Window* event_target = root->GetEventHandlerForPoint(gfx::Point(0, 0));
    559   EXPECT_TRUE(event_target);
    560   EXPECT_EQ(event_target,
    561             root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
    562   EXPECT_EQ(event_target,
    563             root->GetEventHandlerForPoint(gfx::Point(size.width() - 1, 0)));
    564   EXPECT_EQ(event_target,
    565             root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
    566   EXPECT_EQ(event_target,
    567             root->GetEventHandlerForPoint(
    568                 gfx::Point(size.width() - 1, size.height() - 1)));
    569 }
    570 
    571 class VirtualKeyboardRootWindowControllerTest : public test::AshTestBase {
    572  public:
    573   VirtualKeyboardRootWindowControllerTest() {};
    574   virtual ~VirtualKeyboardRootWindowControllerTest() {};
    575 
    576   virtual void SetUp() OVERRIDE {
    577     CommandLine::ForCurrentProcess()->AppendSwitch(
    578         keyboard::switches::kEnableVirtualKeyboard);
    579     test::AshTestBase::SetUp();
    580     Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
    581         Shell::GetInstance()->keyboard_controller());
    582   }
    583 
    584  private:
    585   DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest);
    586 };
    587 
    588 // Test for http://crbug.com/297858. Virtual keyboard container should only show
    589 // on primary root window.
    590 TEST_F(VirtualKeyboardRootWindowControllerTest,
    591        VirtualKeyboardOnPrimaryRootWindowOnly) {
    592   if (!SupportsMultipleDisplays())
    593     return;
    594 
    595   UpdateDisplay("500x500,500x500");
    596 
    597   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    598   aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
    599   aura::Window* secondary_root_window =
    600       root_windows[0] == primary_root_window ?
    601           root_windows[1] : root_windows[0];
    602 
    603   ASSERT_TRUE(Shell::GetContainer(
    604       primary_root_window,
    605       internal::kShellWindowId_VirtualKeyboardContainer));
    606   ASSERT_FALSE(Shell::GetContainer(
    607       secondary_root_window,
    608       internal::kShellWindowId_VirtualKeyboardContainer));
    609 }
    610 
    611 // Test for http://crbug.com/263599. Virtual keyboard should be able to receive
    612 // events at blocked user session.
    613 TEST_F(VirtualKeyboardRootWindowControllerTest,
    614        ClickVirtualKeyboardInBlockedWindow) {
    615   aura::Window* root_window = Shell::GetPrimaryRootWindow();
    616   aura::Window* keyboard_container = Shell::GetContainer(root_window,
    617       internal::kShellWindowId_VirtualKeyboardContainer);
    618   ASSERT_TRUE(keyboard_container);
    619   keyboard_container->Show();
    620 
    621   aura::Window* keyboard_window = Shell::GetInstance()->keyboard_controller()->
    622       proxy()->GetKeyboardWindow();
    623   keyboard_container->AddChild(keyboard_window);
    624   keyboard_window->SetBounds(gfx::Rect());
    625   keyboard_window->Show();
    626 
    627   aura::test::TestEventHandler* handler = new aura::test::TestEventHandler;
    628   root_window->SetEventFilter(handler);
    629 
    630   aura::test::EventGenerator event_generator(root_window, keyboard_window);
    631   event_generator.ClickLeftButton();
    632   int expected_mouse_presses = 1;
    633   EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2);
    634 
    635   for (int block_reason = FIRST_BLOCK_REASON;
    636        block_reason < NUMBER_OF_BLOCK_REASONS;
    637        ++block_reason) {
    638     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
    639     event_generator.ClickLeftButton();
    640     expected_mouse_presses++;
    641     EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2);
    642     UnblockUserSession();
    643   }
    644 }
    645 
    646 // Test for http://crbug.com/299787. RootWindowController should delete
    647 // the old container since the keyboard controller creates a new window in
    648 // GetWindowContainer().
    649 TEST_F(VirtualKeyboardRootWindowControllerTest,
    650        DeleteOldContainerOnVirtualKeyboardInit) {
    651   aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
    652   aura::Window* keyboard_container = Shell::GetContainer(root_window,
    653       internal::kShellWindowId_VirtualKeyboardContainer);
    654   ASSERT_TRUE(keyboard_container);
    655   // Track the keyboard container window.
    656   aura::WindowTracker tracker;
    657   tracker.Add(keyboard_container);
    658   // Mock a login user profile change to reinitialize the keyboard.
    659   ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
    660   // keyboard_container should no longer be present.
    661   EXPECT_FALSE(tracker.Contains(keyboard_container));
    662 }
    663 
    664 }  // namespace test
    665 }  // namespace ash
    666