blob: e648298fd89803b344db813a7062604a42923ddc [file] [log] [blame]
James Cookb0bf8e82017-04-09 17:01:441// Copyright 2013 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/shelf/shelf_window_watcher.h"
6
skye5fd1222017-04-12 18:43:237#include "ash/public/cpp/config.h"
James Cookb0bf8e82017-04-09 17:01:448#include "ash/public/cpp/shelf_item.h"
msw109806d2017-06-02 20:11:579#include "ash/public/cpp/shelf_model.h"
James Cookb0bf8e82017-04-09 17:01:4410#include "ash/public/cpp/shell_window_ids.h"
11#include "ash/public/cpp/window_properties.h"
12#include "ash/root_window_controller.h"
13#include "ash/session/session_controller.h"
James Cookb0bf8e82017-04-09 17:01:4414#include "ash/shell.h"
15#include "ash/test/ash_test_base.h"
16#include "ash/wm/window_resizer.h"
17#include "ash/wm/window_state.h"
msw19b30c2c2017-06-01 03:21:4018#include "third_party/skia/include/core/SkBitmap.h"
19#include "ui/aura/client/aura_constants.h"
James Cookb0bf8e82017-04-09 17:01:4420#include "ui/aura/window.h"
21#include "ui/base/hit_test.h"
msw19b30c2c2017-06-01 03:21:4022#include "ui/base/resource/resource_bundle.h"
23#include "ui/gfx/image/image_skia.h"
24#include "ui/resources/grit/ui_resources.h"
James Cookb0bf8e82017-04-09 17:01:4425#include "ui/views/widget/widget.h"
msw70ac45f2017-06-05 02:02:4526#include "ui/wm/core/transient_window_controller.h"
James Cookb0bf8e82017-04-09 17:01:4427
28namespace ash {
msw19b30c2c2017-06-01 03:21:4029namespace {
30
31// Create a test 1x1 icon image with a given |color|.
32gfx::ImageSkia CreateImageSkiaIcon(SkColor color) {
33 SkBitmap bitmap;
34 bitmap.allocN32Pixels(1, 1);
35 bitmap.eraseColor(color);
36 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
37}
James Cookb0bf8e82017-04-09 17:01:4438
James Cook317781a2017-07-18 02:08:0639class ShelfWindowWatcherTest : public AshTestBase {
James Cookb0bf8e82017-04-09 17:01:4440 public:
41 ShelfWindowWatcherTest() : model_(nullptr) {}
42 ~ShelfWindowWatcherTest() override {}
43
44 void SetUp() override {
James Cook317781a2017-07-18 02:08:0645 AshTestBase::SetUp();
James Cookb0bf8e82017-04-09 17:01:4446 model_ = Shell::Get()->shelf_model();
Michael Wasserman78b6f3e2017-07-20 19:51:2047 // ShelfModel creates app list and browser shortcut items.
48 ASSERT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4449 }
50
51 void TearDown() override {
52 model_ = nullptr;
James Cook317781a2017-07-18 02:08:0653 AshTestBase::TearDown();
James Cookb0bf8e82017-04-09 17:01:4454 }
55
msw6958e7f2017-05-15 22:55:0656 static ShelfID CreateShelfItem(aura::Window* window) {
msw84b8a5f2017-05-05 00:13:3657 static int id = 0;
msw70ac45f2017-06-05 02:02:4558 ShelfID shelf_id(std::to_string(id++));
msw6958e7f2017-05-15 22:55:0659 window->SetProperty(kShelfIDKey, new std::string(shelf_id.Serialize()));
60 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
msw84b8a5f2017-05-05 00:13:3661 return shelf_id;
James Cookb0bf8e82017-04-09 17:01:4462 }
63
64 protected:
65 ShelfModel* model_;
66
67 private:
68 DISALLOW_COPY_AND_ASSIGN(ShelfWindowWatcherTest);
69};
70
71// Ensure shelf items are added and removed as windows are opened and closed.
72TEST_F(ShelfWindowWatcherTest, OpenAndClose) {
msw70ac45f2017-06-05 02:02:4573 // Windows with valid ShelfItemType and ShelfID properties get shelf items.
James Cookb0bf8e82017-04-09 17:01:4474 std::unique_ptr<views::Widget> widget1 =
75 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:0676 CreateShelfItem(widget1->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:2077 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4478 std::unique_ptr<views::Widget> widget2 =
79 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:0680 CreateShelfItem(widget2->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:2081 EXPECT_EQ(4, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4482
83 // Each ShelfItem is removed when the associated window is destroyed.
84 widget1.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:2085 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4486 widget2.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:2087 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4488}
89
mswfeae4322017-06-08 04:24:2290// Ensure shelf items are added and removed for some unknown windows in mash.
msw70ac45f2017-06-05 02:02:4591TEST_F(ShelfWindowWatcherTest, OpenAndCloseMash) {
92 if (Shell::GetAshConfig() != Config::MASH)
93 return;
94
msw70ac45f2017-06-05 02:02:4595 // Windows with no valid ShelfItemType and ShelfID properties get shelf items.
96 std::unique_ptr<views::Widget> widget1 =
97 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Michael Wasserman78b6f3e2017-07-20 19:51:2098 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:4599 std::unique_ptr<views::Widget> widget2 =
100 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Michael Wasserman78b6f3e2017-07-20 19:51:20101 EXPECT_EQ(4, model_->item_count());
msw70ac45f2017-06-05 02:02:45102
103 // Each ShelfItem is removed when the associated window is destroyed.
104 widget1.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20105 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:45106 widget2.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20107 EXPECT_EQ(2, model_->item_count());
msw70ac45f2017-06-05 02:02:45108
mswfeae4322017-06-08 04:24:22109 // Windows with type WINDOW_TYPE_NORMAL get shelf items, others do not.
110 aura::client::WindowType no_item_types[] = {
111 aura::client::WINDOW_TYPE_UNKNOWN, aura::client::WINDOW_TYPE_NORMAL,
112 aura::client::WINDOW_TYPE_POPUP, aura::client::WINDOW_TYPE_CONTROL,
113 aura::client::WINDOW_TYPE_PANEL, aura::client::WINDOW_TYPE_MENU,
114 aura::client::WINDOW_TYPE_TOOLTIP};
115 for (aura::client::WindowType type : no_item_types) {
116 std::unique_ptr<aura::Window> window =
117 base::MakeUnique<aura::Window>(nullptr, type);
118 window->Init(ui::LAYER_NOT_DRAWN);
119 Shell::GetPrimaryRootWindow()
120 ->GetChildById(kShellWindowId_DefaultContainer)
121 ->AddChild(window.get());
122 window->Show();
Michael Wasserman78b6f3e2017-07-20 19:51:20123 EXPECT_EQ(type == aura::client::WINDOW_TYPE_NORMAL ? 3 : 2,
mswfeae4322017-06-08 04:24:22124 model_->item_count());
125 }
126
msw70ac45f2017-06-05 02:02:45127 // Windows with WindowState::ignored_by_shelf set do not get shelf items.
128 widget1 =
129 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
130 wm::GetWindowState(widget1->GetNativeWindow())->set_ignored_by_shelf(true);
131 // TODO(msw): Make the flag a window property and remove this workaround.
132 widget1->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey,
133 true);
Michael Wasserman78b6f3e2017-07-20 19:51:20134 EXPECT_EQ(2, model_->item_count());
msw70ac45f2017-06-05 02:02:45135}
136
James Cookb0bf8e82017-04-09 17:01:44137TEST_F(ShelfWindowWatcherTest, CreateAndRemoveShelfItemProperties) {
138 // TODO: investigate failure in mash. http://crbug.com/695562.
skye5fd1222017-04-12 18:43:23139 if (Shell::GetAshConfig() == Config::MASH)
James Cookb0bf8e82017-04-09 17:01:44140 return;
141
James Cookb0bf8e82017-04-09 17:01:44142 // Creating windows without a valid ShelfItemType does not add items.
Michael Wasserman78b6f3e2017-07-20 19:51:20143 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44144 std::unique_ptr<views::Widget> widget1 =
145 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44146 std::unique_ptr<views::Widget> widget2 =
147 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Michael Wasserman78b6f3e2017-07-20 19:51:20148 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44149
150 // Create a ShelfItem for the first window.
msw6958e7f2017-05-15 22:55:06151 ShelfID id_w1 = CreateShelfItem(widget1->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20152 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44153
154 int index_w1 = model_->ItemIndexByID(id_w1);
155 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
156
157 // Create a ShelfItem for the second window.
msw6958e7f2017-05-15 22:55:06158 ShelfID id_w2 = CreateShelfItem(widget2->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20159 EXPECT_EQ(4, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44160
161 int index_w2 = model_->ItemIndexByID(id_w2);
162 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
163
164 // ShelfItem is removed when the item type window property is cleared.
msw6958e7f2017-05-15 22:55:06165 widget1->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
166 static_cast<int32_t>(TYPE_UNDEFINED));
Michael Wasserman78b6f3e2017-07-20 19:51:20167 EXPECT_EQ(3, model_->item_count());
msw6958e7f2017-05-15 22:55:06168 widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
169 static_cast<int32_t>(TYPE_UNDEFINED));
Michael Wasserman78b6f3e2017-07-20 19:51:20170 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44171 // Clearing twice doesn't do anything.
msw6958e7f2017-05-15 22:55:06172 widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
173 static_cast<int32_t>(TYPE_UNDEFINED));
Michael Wasserman78b6f3e2017-07-20 19:51:20174 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44175}
176
177TEST_F(ShelfWindowWatcherTest, ActivateWindow) {
178 // TODO: investigate failure in mash. http://crbug.com/695562.
skye5fd1222017-04-12 18:43:23179 if (Shell::GetAshConfig() == Config::MASH)
James Cookb0bf8e82017-04-09 17:01:44180 return;
181
James Cookb0bf8e82017-04-09 17:01:44182 std::unique_ptr<views::Widget> widget1 =
183 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44184 std::unique_ptr<views::Widget> widget2 =
185 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44186
187 // Create a ShelfItem for the first window.
msw6958e7f2017-05-15 22:55:06188 ShelfID id_w1 = CreateShelfItem(widget1->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20189 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44190 int index_w1 = model_->ItemIndexByID(id_w1);
191 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
192
193 // Create a ShelfItem for the second window.
msw6958e7f2017-05-15 22:55:06194 ShelfID id_w2 = CreateShelfItem(widget2->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20195 EXPECT_EQ(4, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44196 int index_w2 = model_->ItemIndexByID(id_w2);
197 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
198 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
199
200 // The ShelfItem for the first window is active when the window is activated.
201 widget1->Activate();
202 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w1].status);
203 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w2].status);
204
205 // The ShelfItem for the second window is active when the window is activated.
206 widget2->Activate();
207 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
208 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
209}
210
211TEST_F(ShelfWindowWatcherTest, UpdateWindowProperty) {
Michael Wasserman78b6f3e2017-07-20 19:51:20212 // Create a ShelfItem for a new window.
213 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44214 std::unique_ptr<views::Widget> widget =
215 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06216 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20217 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44218
219 int index = model_->ItemIndexByID(id);
220 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
221
msw6958e7f2017-05-15 22:55:06222 // Update the window's ShelfItemType.
223 widget->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
mswfeae4322017-06-08 04:24:22224 static_cast<int32_t>(TYPE_APP_PANEL));
James Cookb0bf8e82017-04-09 17:01:44225 // No new item is created after updating a launcher item.
Michael Wasserman78b6f3e2017-07-20 19:51:20226 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44227 // index and id are not changed after updating a launcher item.
228 EXPECT_EQ(index, model_->ItemIndexByID(id));
229 EXPECT_EQ(id, model_->items()[index].id);
230}
231
232TEST_F(ShelfWindowWatcherTest, MaximizeAndRestoreWindow) {
Michael Wasserman78b6f3e2017-07-20 19:51:20233 // Create a ShelfItem for a new window.
234 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44235 std::unique_ptr<views::Widget> widget =
236 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06237 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20238 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44239
240 int index = model_->ItemIndexByID(id);
241 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
242
msw6958e7f2017-05-15 22:55:06243 // Maximize the window.
Michael Wasserman78b6f3e2017-07-20 19:51:20244 wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeWindow());
James Cookb0bf8e82017-04-09 17:01:44245 EXPECT_FALSE(window_state->IsMaximized());
246 window_state->Maximize();
247 EXPECT_TRUE(window_state->IsMaximized());
msw6958e7f2017-05-15 22:55:06248 // No new item is created after maximizing the window.
Michael Wasserman78b6f3e2017-07-20 19:51:20249 EXPECT_EQ(3, model_->item_count());
msw6958e7f2017-05-15 22:55:06250 // index and id are not changed after maximizing the window.
James Cookb0bf8e82017-04-09 17:01:44251 EXPECT_EQ(index, model_->ItemIndexByID(id));
252 EXPECT_EQ(id, model_->items()[index].id);
253
msw6958e7f2017-05-15 22:55:06254 // Restore the window.
James Cookb0bf8e82017-04-09 17:01:44255 window_state->Restore();
256 EXPECT_FALSE(window_state->IsMaximized());
msw6958e7f2017-05-15 22:55:06257 // No new item is created after restoring the window.
Michael Wasserman78b6f3e2017-07-20 19:51:20258 EXPECT_EQ(3, model_->item_count());
msw6958e7f2017-05-15 22:55:06259 // Index and id are not changed after maximizing the window.
James Cookb0bf8e82017-04-09 17:01:44260 EXPECT_EQ(index, model_->ItemIndexByID(id));
261 EXPECT_EQ(id, model_->items()[index].id);
262}
263
264// Check |window|'s item is not changed during the dragging.
265// TODO(simonhong): Add a test for removing a Window during the dragging.
266TEST_F(ShelfWindowWatcherTest, DragWindow) {
Michael Wasserman78b6f3e2017-07-20 19:51:20267 // Create a ShelfItem for a new window.
268 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44269 std::unique_ptr<views::Widget> widget =
270 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06271 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20272 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44273
274 int index = model_->ItemIndexByID(id);
275 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
276
msw6958e7f2017-05-15 22:55:06277 // Simulate dragging of the window and check its item is not changed.
skya5e9a122017-05-22 20:45:35278 std::unique_ptr<WindowResizer> resizer(
279 CreateWindowResizer(widget->GetNativeWindow(), gfx::Point(), HTCAPTION,
Thiago Farina3b086a02017-05-30 22:32:50280 ::wm::WINDOW_MOVE_SOURCE_MOUSE));
James Cookb0bf8e82017-04-09 17:01:44281 ASSERT_TRUE(resizer.get());
282 resizer->Drag(gfx::Point(50, 50), 0);
283 resizer->CompleteDrag();
284
msw6958e7f2017-05-15 22:55:06285 // Index and id are not changed after dragging the window.
James Cookb0bf8e82017-04-09 17:01:44286 EXPECT_EQ(index, model_->ItemIndexByID(id));
287 EXPECT_EQ(id, model_->items()[index].id);
288}
289
mswfeae4322017-06-08 04:24:22290// Ensure panels and dialogs get shelf items.
291TEST_F(ShelfWindowWatcherTest, PanelAndDialogWindows) {
mswfeae4322017-06-08 04:24:22292 // An item is created for a dialog window.
Michael Wasserman78b6f3e2017-07-20 19:51:20293 EXPECT_EQ(2, model_->item_count());
mswfeae4322017-06-08 04:24:22294 std::unique_ptr<views::Widget> dialog_widget =
msw6958e7f2017-05-15 22:55:06295 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
mswfeae4322017-06-08 04:24:22296 aura::Window* dialog = dialog_widget->GetNativeWindow();
297 dialog->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
298 dialog->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
Michael Wasserman78b6f3e2017-07-20 19:51:20299 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44300
mswfeae4322017-06-08 04:24:22301 // An item is created for a panel window.
James Cookb0bf8e82017-04-09 17:01:44302 views::Widget panel_widget;
303 views::Widget::InitParams panel_params(views::Widget::InitParams::TYPE_PANEL);
304 panel_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
Scott Violet66193f72017-06-26 22:24:18305 panel_params.parent = Shell::GetPrimaryRootWindow()->GetChildById(
306 kShellWindowId_PanelContainer);
James Cookb0bf8e82017-04-09 17:01:44307 panel_widget.Init(panel_params);
308 panel_widget.Show();
mswfeae4322017-06-08 04:24:22309 aura::Window* panel = panel_widget.GetNativeWindow();
310 panel->SetProperty(kShelfIDKey, new std::string(ShelfID("b").Serialize()));
311 panel->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP_PANEL));
Michael Wasserman78b6f3e2017-07-20 19:51:20312 EXPECT_EQ(4, model_->item_count());
mswfeae4322017-06-08 04:24:22313
314 // An item is not created for an app window.
315 std::unique_ptr<views::Widget> app_widget =
316 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
317 aura::Window* app = app_widget->GetNativeWindow();
318 app->SetProperty(kShelfIDKey, new std::string(ShelfID("c").Serialize()));
319 app->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP));
Michael Wasserman78b6f3e2017-07-20 19:51:20320 EXPECT_EQ(4, model_->item_count());
mswfeae4322017-06-08 04:24:22321 app_widget.reset();
James Cookb0bf8e82017-04-09 17:01:44322
323 // Each ShelfItem is removed when the associated window is destroyed.
324 panel_widget.CloseNow();
Michael Wasserman78b6f3e2017-07-20 19:51:20325 EXPECT_EQ(3, model_->item_count());
mswfeae4322017-06-08 04:24:22326 dialog_widget.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20327 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44328}
329
msw19b30c2c2017-06-01 03:21:40330// Ensure items use the app icon and window icon aura::Window properties.
331TEST_F(ShelfWindowWatcherTest, ItemIcon) {
msw19b30c2c2017-06-01 03:21:40332 // Create a ShelfItem for a window; it should have a default icon.
Michael Wasserman78b6f3e2017-07-20 19:51:20333 EXPECT_EQ(2, model_->item_count());
msw19b30c2c2017-06-01 03:21:40334 std::unique_ptr<views::Widget> widget =
335 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
336 aura::Window* window = widget->GetNativeWindow();
337 ShelfID id = CreateShelfItem(window);
Michael Wasserman78b6f3e2017-07-20 19:51:20338 EXPECT_EQ(3, model_->item_count());
msw19b30c2c2017-06-01 03:21:40339 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
340 gfx::Image default_image = rb.GetImageNamed(IDR_DEFAULT_FAVICON_32);
Michael Wasserman78b6f3e2017-07-20 19:51:20341 EXPECT_TRUE(model_->items()[2].image.BackedBySameObjectAs(
msw19b30c2c2017-06-01 03:21:40342 default_image.AsImageSkia()));
343
344 // Setting a window icon should update the item icon.
345 const gfx::ImageSkia red = CreateImageSkiaIcon(SK_ColorRED);
346 window->SetProperty(aura::client::kWindowIconKey, new gfx::ImageSkia(red));
Michael Wasserman78b6f3e2017-07-20 19:51:20347 EXPECT_EQ(SK_ColorRED, model_->items()[2].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40348
349 // Setting an app icon should override the window icon.
350 const gfx::ImageSkia blue = CreateImageSkiaIcon(SK_ColorBLUE);
351 window->SetProperty(aura::client::kAppIconKey, new gfx::ImageSkia(blue));
Michael Wasserman78b6f3e2017-07-20 19:51:20352 EXPECT_EQ(SK_ColorBLUE, model_->items()[2].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40353
354 // Clearing the app icon should restore the window icon to the shelf item.
355 window->ClearProperty(aura::client::kAppIconKey);
Michael Wasserman78b6f3e2017-07-20 19:51:20356 EXPECT_EQ(SK_ColorRED, model_->items()[2].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40357}
358
James Cookb0bf8e82017-04-09 17:01:44359TEST_F(ShelfWindowWatcherTest, DontCreateShelfEntriesForChildWindows) {
Michael Wasserman78b6f3e2017-07-20 19:51:20360 EXPECT_EQ(2, model_->item_count());
mswfeae4322017-06-08 04:24:22361 std::unique_ptr<aura::Window> window =
362 base::MakeUnique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
James Cookb0bf8e82017-04-09 17:01:44363 window->Init(ui::LAYER_NOT_DRAWN);
mswfeae4322017-06-08 04:24:22364 window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
365 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
James Cookb0bf8e82017-04-09 17:01:44366 Shell::GetPrimaryRootWindow()
367 ->GetChildById(kShellWindowId_DefaultContainer)
368 ->AddChild(window.get());
369 window->Show();
Michael Wasserman78b6f3e2017-07-20 19:51:20370 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44371
mswfeae4322017-06-08 04:24:22372 std::unique_ptr<aura::Window> child =
373 base::MakeUnique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
374 child->Init(ui::LAYER_NOT_DRAWN);
375 child->SetProperty(kShelfIDKey, new std::string(ShelfID("b").Serialize()));
376 child->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
377 window->AddChild(child.get());
378 child->Show();
379 // There should not be a new shelf item for |child|.
Michael Wasserman78b6f3e2017-07-20 19:51:20380 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44381
mswfeae4322017-06-08 04:24:22382 child.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20383 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44384 window.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20385 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44386}
387
mswfeae4322017-06-08 04:24:22388TEST_F(ShelfWindowWatcherTest, CreateShelfEntriesForTransientWindows) {
Michael Wasserman78b6f3e2017-07-20 19:51:20389 EXPECT_EQ(2, model_->item_count());
mswfeae4322017-06-08 04:24:22390 std::unique_ptr<aura::Window> window =
391 base::MakeUnique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
msw70ac45f2017-06-05 02:02:45392 window->Init(ui::LAYER_NOT_DRAWN);
mswfeae4322017-06-08 04:24:22393 window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
394 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
msw70ac45f2017-06-05 02:02:45395 Shell::GetPrimaryRootWindow()
396 ->GetChildById(kShellWindowId_DefaultContainer)
397 ->AddChild(window.get());
398 window->Show();
Michael Wasserman78b6f3e2017-07-20 19:51:20399 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:45400
mswfeae4322017-06-08 04:24:22401 std::unique_ptr<aura::Window> transient =
402 base::MakeUnique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
403 transient->Init(ui::LAYER_NOT_DRAWN);
404 transient->SetProperty(kShelfIDKey,
405 new std::string(ShelfID("b").Serialize()));
406 transient->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
407 Shell::GetPrimaryRootWindow()
408 ->GetChildById(kShellWindowId_DefaultContainer)
409 ->AddChild(transient.get());
410 ::wm::TransientWindowController::Get()->AddTransientChild(window.get(),
411 transient.get());
412 transient->Show();
413 // There should be a new shelf item for |transient|.
Michael Wasserman78b6f3e2017-07-20 19:51:20414 EXPECT_EQ(4, model_->item_count());
msw70ac45f2017-06-05 02:02:45415
mswfeae4322017-06-08 04:24:22416 transient.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20417 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:45418 window.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20419 EXPECT_EQ(2, model_->item_count());
msw70ac45f2017-06-05 02:02:45420}
421
James Cookb0bf8e82017-04-09 17:01:44422// Ensures ShelfWindowWatcher supports windows opened prior to session start.
James Cook317781a2017-07-18 02:08:06423using ShelfWindowWatcherSessionStartTest = NoSessionAshTestBase;
James Cookb0bf8e82017-04-09 17:01:44424TEST_F(ShelfWindowWatcherSessionStartTest, PreExistingWindow) {
425 ShelfModel* model = Shell::Get()->shelf_model();
426 ASSERT_FALSE(
427 Shell::Get()->session_controller()->IsActiveUserSessionStarted());
428
Michael Wasserman78b6f3e2017-07-20 19:51:20429 // ShelfModel creates app list and browser shortcut items.
430 EXPECT_EQ(2, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44431
432 // Construct a window that should get a shelf item once the session starts.
433 std::unique_ptr<views::Widget> widget =
434 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06435 ShelfWindowWatcherTest::CreateShelfItem(widget->GetNativeWindow());
Michael Wasserman78b6f3e2017-07-20 19:51:20436 EXPECT_EQ(2, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44437
438 // Start the test user session; ShelfWindowWatcher will find the open window.
439 SetSessionStarted(true);
Michael Wasserman78b6f3e2017-07-20 19:51:20440 EXPECT_EQ(3, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44441}
442
msw19b30c2c2017-06-01 03:21:40443} // namespace
James Cookb0bf8e82017-04-09 17:01:44444} // namespace ash