// Copyright 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 "ash/shelf/shelf_window_watcher.h"

#include <memory>

#include "ash/public/cpp/shelf_item.h"
#include "ash/public/cpp/shelf_model.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/window_factory.h"
#include "ash/wm/desks/desks_util.h"
#include "ash/wm/window_resizer.h"
#include "ash/wm/window_state.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/transient_window_controller.h"

namespace ash {
namespace {

// Create a test 1x1 icon image with a given |color|.
gfx::ImageSkia CreateImageSkiaIcon(SkColor color) {
  SkBitmap bitmap;
  bitmap.allocN32Pixels(1, 1);
  bitmap.eraseColor(color);
  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
}

class ShelfWindowWatcherTest : public AshTestBase {
 public:
  ShelfWindowWatcherTest() : model_(nullptr) {}
  ~ShelfWindowWatcherTest() override = default;

  void SetUp() override {
    AshTestBase::SetUp();
    model_ = Shell::Get()->shelf_model();
    // ShelfModel creates an app list item and back button.
    ASSERT_EQ(2, model_->item_count());
  }

  void TearDown() override {
    model_ = nullptr;
    AshTestBase::TearDown();
  }

  static ShelfID CreateShelfItem(aura::Window* window) {
    static int id = 0;
    ShelfID shelf_id(std::to_string(id++));
    window->SetProperty(kShelfIDKey, new std::string(shelf_id.Serialize()));
    window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
    return shelf_id;
  }

 protected:
  ShelfModel* model_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ShelfWindowWatcherTest);
};

// Ensure shelf items are added and removed as windows are opened and closed.
TEST_F(ShelfWindowWatcherTest, OpenAndClose) {
  // Windows with valid ShelfItemType and ShelfID properties get shelf items.
  std::unique_ptr<views::Widget> widget1 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  CreateShelfItem(widget1->GetNativeWindow());
  EXPECT_EQ(3, model_->item_count());
  std::unique_ptr<views::Widget> widget2 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  CreateShelfItem(widget2->GetNativeWindow());
  EXPECT_EQ(4, model_->item_count());

  // Each ShelfItem is removed when the associated window is destroyed.
  widget1.reset();
  EXPECT_EQ(3, model_->item_count());
  widget2.reset();
  EXPECT_EQ(2, model_->item_count());
}

// Ensure shelf items are added and removed for some unknown windows in mash.
TEST_F(ShelfWindowWatcherTest, OpenAndCloseMash) {
  if (!::features::IsMultiProcessMash())
    return;

  // Windows with no valid ShelfItemType and ShelfID properties get shelf items.
  std::unique_ptr<views::Widget> widget1 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  EXPECT_EQ(3, model_->item_count());
  std::unique_ptr<views::Widget> widget2 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  EXPECT_EQ(4, model_->item_count());

  // Each ShelfItem is removed when the associated window is destroyed.
  widget1.reset();
  EXPECT_EQ(3, model_->item_count());
  widget2.reset();
  EXPECT_EQ(2, model_->item_count());

  // Windows with type WINDOW_TYPE_NORMAL get shelf items, others do not.
  // WINDOW_TYPE_CONTROL is not toplevel and should not be added to the
  // container.
  aura::client::WindowType no_item_types[] = {
      aura::client::WINDOW_TYPE_UNKNOWN, aura::client::WINDOW_TYPE_NORMAL,
      aura::client::WINDOW_TYPE_POPUP, aura::client::WINDOW_TYPE_MENU,
      aura::client::WINDOW_TYPE_TOOLTIP};
  for (aura::client::WindowType type : no_item_types) {
    std::unique_ptr<aura::Window> window =
        window_factory::NewWindow(nullptr, type);
    window->Init(ui::LAYER_NOT_DRAWN);
    Shell::GetPrimaryRootWindow()
        ->GetChildById(desks_util::GetActiveDeskContainerId())
        ->AddChild(window.get());
    window->Show();
    EXPECT_EQ(type == aura::client::WINDOW_TYPE_NORMAL ? 3 : 2,
              model_->item_count());
  }
}

TEST_F(ShelfWindowWatcherTest, CreateAndRemoveShelfItemProperties) {
  // Creating windows without a valid ShelfItemType only adds items in mash.
  std::unique_ptr<views::Widget> widget1 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  std::unique_ptr<views::Widget> widget2 = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  const bool is_mash = ::features::IsMultiProcessMash();
  EXPECT_EQ(is_mash ? 4 : 2, model_->item_count());

  // Create a ShelfItem for the first window.
  ShelfID id_w1 = CreateShelfItem(widget1->GetNativeWindow());
  EXPECT_EQ(is_mash ? 4 : 3, model_->item_count());

  int index_w1 = model_->ItemIndexByID(id_w1);
  EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);

  // Create a ShelfItem for the second window.
  ShelfID id_w2 = CreateShelfItem(widget2->GetNativeWindow());
  EXPECT_EQ(4, model_->item_count());

  int index_w2 = model_->ItemIndexByID(id_w2);
  EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w2].status);

  // ShelfItem is removed when the type property is cleared in classic ash.
  widget1->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
                                          static_cast<int32_t>(TYPE_UNDEFINED));
  EXPECT_EQ(is_mash ? 4 : 3, model_->item_count());
  widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
                                          static_cast<int32_t>(TYPE_UNDEFINED));
  EXPECT_EQ(is_mash ? 4 : 2, model_->item_count());
  // Clearing twice doesn't do anything.
  widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
                                          static_cast<int32_t>(TYPE_UNDEFINED));
  EXPECT_EQ(is_mash ? 4 : 2, model_->item_count());

  // Closing the windows will remove the items in mash.
  widget1->CloseNow();
  EXPECT_EQ(is_mash ? 3 : 2, model_->item_count());
  widget2->CloseNow();
  EXPECT_EQ(2, model_->item_count());
}

TEST_F(ShelfWindowWatcherTest, UpdateWindowProperty) {
  // Create a ShelfItem for a new window.
  std::unique_ptr<views::Widget> widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  ShelfID id = CreateShelfItem(widget->GetNativeWindow());
  EXPECT_EQ(3, model_->item_count());

  int index = model_->ItemIndexByID(id);
  EXPECT_EQ(STATUS_RUNNING, model_->items()[index].status);

  // No new item is created after updating a launcher item.
  EXPECT_EQ(3, model_->item_count());
  // index and id are not changed after updating a launcher item.
  EXPECT_EQ(index, model_->ItemIndexByID(id));
  EXPECT_EQ(id, model_->items()[index].id);
}

TEST_F(ShelfWindowWatcherTest, MaximizeAndRestoreWindow) {
  // Create a ShelfItem for a new window.
  std::unique_ptr<views::Widget> widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  ShelfID id = CreateShelfItem(widget->GetNativeWindow());
  EXPECT_EQ(3, model_->item_count());

  int index = model_->ItemIndexByID(id);
  EXPECT_EQ(STATUS_RUNNING, model_->items()[index].status);

  // Maximize the window.
  wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeWindow());
  EXPECT_FALSE(window_state->IsMaximized());
  window_state->Maximize();
  EXPECT_TRUE(window_state->IsMaximized());
  // No new item is created after maximizing the window.
  EXPECT_EQ(3, model_->item_count());
  // index and id are not changed after maximizing the window.
  EXPECT_EQ(index, model_->ItemIndexByID(id));
  EXPECT_EQ(id, model_->items()[index].id);

  // Restore the window.
  window_state->Restore();
  EXPECT_FALSE(window_state->IsMaximized());
  // No new item is created after restoring the window.
  EXPECT_EQ(3, model_->item_count());
  // Index and id are not changed after maximizing the window.
  EXPECT_EQ(index, model_->ItemIndexByID(id));
  EXPECT_EQ(id, model_->items()[index].id);
}

// Check |window|'s item is not changed during the dragging.
// TODO(simonhong): Add a test for removing a Window during the dragging.
TEST_F(ShelfWindowWatcherTest, DragWindow) {
  // Create a ShelfItem for a new window.
  std::unique_ptr<views::Widget> widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  ShelfID id = CreateShelfItem(widget->GetNativeWindow());
  EXPECT_EQ(3, model_->item_count());

  int index = model_->ItemIndexByID(id);
  EXPECT_EQ(STATUS_RUNNING, model_->items()[index].status);

  // Simulate dragging of the window and check its item is not changed.
  std::unique_ptr<WindowResizer> resizer(
      CreateWindowResizer(widget->GetNativeWindow(), gfx::Point(), HTCAPTION,
                          ::wm::WINDOW_MOVE_SOURCE_MOUSE));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(gfx::Point(50, 50), 0);
  resizer->CompleteDrag();

  // Index and id are not changed after dragging the window.
  EXPECT_EQ(index, model_->ItemIndexByID(id));
  EXPECT_EQ(id, model_->items()[index].id);
}

// Ensure dialogs get shelf items.
TEST_F(ShelfWindowWatcherTest, DialogWindows) {
  // An item is created for a dialog window.
  std::unique_ptr<views::Widget> dialog_widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  aura::Window* dialog = dialog_widget->GetNativeWindow();
  dialog->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
  dialog->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
  EXPECT_EQ(3, model_->item_count());

  // An item is not created for an app window.
  std::unique_ptr<views::Widget> app_widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  aura::Window* app = app_widget->GetNativeWindow();
  app->SetProperty(kShelfIDKey, new std::string(ShelfID("c").Serialize()));
  app->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP));
  EXPECT_EQ(3, model_->item_count());
  app_widget.reset();

  // Each ShelfItem is removed when the associated window is destroyed.
  dialog_widget.reset();
  EXPECT_EQ(2, model_->item_count());
}

// Ensure items use the app icon and window icon aura::Window properties.
TEST_F(ShelfWindowWatcherTest, ItemIcon) {
  // Create a ShelfItem for a window; it should have a default icon.
  std::unique_ptr<views::Widget> widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  aura::Window* window = widget->GetNativeWindow();
  ShelfID id = CreateShelfItem(window);
  EXPECT_EQ(3, model_->item_count());
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  gfx::Image default_image = rb.GetImageNamed(IDR_DEFAULT_FAVICON_32);
  EXPECT_TRUE(model_->items()[2].image.BackedBySameObjectAs(
      default_image.AsImageSkia()));

  // Setting a window icon should update the item icon.
  const gfx::ImageSkia red = CreateImageSkiaIcon(SK_ColorRED);
  window->SetProperty(aura::client::kWindowIconKey, new gfx::ImageSkia(red));
  EXPECT_EQ(SK_ColorRED, model_->items()[2].image.bitmap()->getColor(0, 0));

  // Setting an app icon should override the window icon.
  const gfx::ImageSkia blue = CreateImageSkiaIcon(SK_ColorBLUE);
  window->SetProperty(aura::client::kAppIconKey, new gfx::ImageSkia(blue));
  EXPECT_EQ(SK_ColorBLUE, model_->items()[2].image.bitmap()->getColor(0, 0));

  // Clearing the app icon should restore the window icon to the shelf item.
  window->ClearProperty(aura::client::kAppIconKey);
  EXPECT_EQ(SK_ColorRED, model_->items()[2].image.bitmap()->getColor(0, 0));
}

TEST_F(ShelfWindowWatcherTest, DontCreateShelfEntriesForChildWindows) {
  std::unique_ptr<aura::Window> window =
      window_factory::NewWindow(nullptr, aura::client::WINDOW_TYPE_NORMAL);
  window->Init(ui::LAYER_NOT_DRAWN);
  window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
  window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
  Shell::GetPrimaryRootWindow()
      ->GetChildById(desks_util::GetActiveDeskContainerId())
      ->AddChild(window.get());
  window->Show();
  EXPECT_EQ(3, model_->item_count());

  std::unique_ptr<aura::Window> child =
      window_factory::NewWindow(nullptr, aura::client::WINDOW_TYPE_NORMAL);
  child->Init(ui::LAYER_NOT_DRAWN);
  child->SetProperty(kShelfIDKey, new std::string(ShelfID("b").Serialize()));
  child->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
  window->AddChild(child.get());
  child->Show();
  // There should not be a new shelf item for |child|.
  EXPECT_EQ(3, model_->item_count());

  child.reset();
  EXPECT_EQ(3, model_->item_count());
  window.reset();
  EXPECT_EQ(2, model_->item_count());
}

TEST_F(ShelfWindowWatcherTest, CreateShelfEntriesForTransientWindows) {
  std::unique_ptr<aura::Window> window =
      window_factory::NewWindow(nullptr, aura::client::WINDOW_TYPE_NORMAL);
  window->Init(ui::LAYER_NOT_DRAWN);
  window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
  window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
  Shell::GetPrimaryRootWindow()
      ->GetChildById(desks_util::GetActiveDeskContainerId())
      ->AddChild(window.get());
  window->Show();
  EXPECT_EQ(3, model_->item_count());

  std::unique_ptr<aura::Window> transient =
      window_factory::NewWindow(nullptr, aura::client::WINDOW_TYPE_NORMAL);
  transient->Init(ui::LAYER_NOT_DRAWN);
  transient->SetProperty(kShelfIDKey,
                         new std::string(ShelfID("b").Serialize()));
  transient->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
  Shell::GetPrimaryRootWindow()
      ->GetChildById(desks_util::GetActiveDeskContainerId())
      ->AddChild(transient.get());
  ::wm::TransientWindowController::Get()->AddTransientChild(window.get(),
                                                            transient.get());
  transient->Show();
  // There should be a new shelf item for |transient|.
  EXPECT_EQ(4, model_->item_count());

  transient.reset();
  EXPECT_EQ(3, model_->item_count());
  window.reset();
  EXPECT_EQ(2, model_->item_count());
}

// Ensures ShelfWindowWatcher supports windows opened prior to session start.
using ShelfWindowWatcherSessionStartTest = NoSessionAshTestBase;
TEST_F(ShelfWindowWatcherSessionStartTest, PreExistingWindow) {
  ShelfModel* model = Shell::Get()->shelf_model();
  ASSERT_FALSE(
      Shell::Get()->session_controller()->IsActiveUserSessionStarted());

  // ShelfModel creates an app list item and back button.
  EXPECT_EQ(2, model->item_count());

  // Construct a window that should get a shelf item once the session starts.
  std::unique_ptr<views::Widget> widget = CreateTestWidget(
      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect());
  ShelfWindowWatcherTest::CreateShelfItem(widget->GetNativeWindow());
  EXPECT_EQ(2, model->item_count());

  // Start the test user session; ShelfWindowWatcher will find the open window.
  CreateUserSessions(1);
  EXPECT_EQ(3, model->item_count());
}

}  // namespace
}  // namespace ash
