Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1072)

Side by Side Diff: chrome/browser/ui/app_list/arc/arc_app_unittest.cc

Issue 1413153007: arc-app-launcher: Minimal support for ARC app launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 <algorithm>
6 #include <map>
7 #include <string>
8 #include <vector>
9
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_util.h"
14 #include "base/task_runner_util.h"
15 #include "chrome/browser/ui/app_list/app_list_test_util.h"
16 #include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
17 #include "chrome/browser/ui/app_list/arc/arc_app_item.h"
18 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
19 #include "chrome/browser/ui/app_list/arc/arc_app_model_builder.h"
20 #include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/arc/arc_bridge_service.h"
23 #include "components/arc/test/fake_arc_bridge_service.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/app_list/app_list_model.h"
27 #include "ui/gfx/image/image_skia.h"
28
29 namespace {
30
31 std::string GetAppId(const arc::AppInfo& app_info) {
32 return ArcAppListPrefs::GetAppId(app_info.package, app_info.activity);
33 }
34
35 } // namespace
36
37 class ArcAppModelBuilderTest : public AppListTestBase {
38 public:
39 ArcAppModelBuilderTest() {}
40 ~ArcAppModelBuilderTest() override {
41 // Release profile file in order to keep right sequence.
42 profile_.reset();
43 }
44
45 void SetUp() override {
46 AppListTestBase::SetUp();
47
48 // Make sure we have enough data for test.
49 for (int i = 0; i < 3; ++i) {
50 arc::AppInfo app;
51 char buffer[16];
52 base::snprintf(buffer, arraysize(buffer), "Fake App %d", i);
53 app.name = buffer;
54 base::snprintf(buffer, arraysize(buffer), "fake.app.%d", i);
55 app.package = buffer;
56 base::snprintf(buffer, arraysize(buffer), "fake.app.%d.activity", i);
57 app.activity = buffer;
58 fake_apps_.push_back(app);
59 }
60
61 bridge_service_.reset(new arc::FakeArcBridgeService());
62
63 // Check initial conditions.
64 EXPECT_EQ(bridge_service_.get(), arc::ArcBridgeService::Get());
65 EXPECT_EQ(true, !arc::ArcBridgeService::Get()->available());
66 EXPECT_EQ(arc::ArcBridgeService::State::STOPPED,
67 arc::ArcBridgeService::Get()->state());
68
69 CreateBuilder();
70
71 // At this point we should have ArcAppListPrefs as observer of service.
72 EXPECT_EQ(
73 true,
74 bridge_service()->HasObserver(ArcAppListPrefs::Get(profile_.get())));
75 }
76
77 void TearDown() override { ResetBuilder(); }
78
79 protected:
80 // Creates a new builder, destroying any existing one.
81 void CreateBuilder() {
82 ResetBuilder(); // Destroy any existing builder in the correct order.
83
84 model_.reset(new app_list::AppListModel);
85 controller_.reset(new test::TestAppListControllerDelegate);
86 builder_.reset(new ArcAppModelBuilder(controller_.get()));
87 builder_->InitializeWithProfile(profile_.get(), model_.get());
88 }
89
90 void ResetBuilder() {
91 builder_.reset();
92 controller_.reset();
93 model_.reset();
94 }
95
96 size_t GetArcItemCount() const {
97 size_t arc_count = 0;
98 const size_t count = model_->top_level_item_list()->item_count();
99 for (size_t i = 0; i < count; ++i) {
100 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
101 if (item->GetItemType() == ArcAppItem::kItemType) {
102 ++arc_count;
103 }
104 }
105 return arc_count;
106 }
107
108 ArcAppItem* GetArcItem(size_t index) const {
109 size_t arc_count = 0;
110 const size_t count = model_->top_level_item_list()->item_count();
111 ArcAppItem* arc_item = nullptr;
112 for (size_t i = 0; i < count; ++i) {
113 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
114 if (item->GetItemType() == ArcAppItem::kItemType) {
115 if (arc_count++ == index) {
116 arc_item = reinterpret_cast<ArcAppItem*>(item);
117 break;
118 }
119 }
120 }
121 EXPECT_NE(nullptr, arc_item);
122 return arc_item;
123 }
124
125 ArcAppItem* FindArcItem(const std::string& id) const {
126 const size_t count = GetArcItemCount();
127 for (size_t i = 0; i < count; ++i) {
128 ArcAppItem* item = GetArcItem(i);
129 if (item && item->id() == id) {
130 return item;
131 }
132 }
133 return nullptr;
134 }
135
136 // Validate that prefs and model have right content.
137 void ValidateHaveApps(const std::vector<arc::AppInfo> apps) {
138 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
139 const std::vector<std::string> ids = prefs->GetAppIds();
140 ASSERT_EQ(apps.size(), ids.size());
141 ASSERT_EQ(apps.size(), GetArcItemCount());
142 // In principle, order of items is not defined.
143 for (auto& app : apps) {
144 const std::string id = GetAppId(app);
145 EXPECT_NE(std::find(ids.begin(), ids.end(), id), ids.end());
146 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
147 ASSERT_NE(nullptr, app_info.get());
148 EXPECT_EQ(app.name, app_info->name);
149 EXPECT_EQ(app.package, app_info->package);
150 EXPECT_EQ(app.activity, app_info->activity);
151
152 const ArcAppItem* app_item = FindArcItem(id);
153 ASSERT_NE(nullptr, app_item);
154 EXPECT_EQ(app.name, app_item->GetDisplayName());
155 }
156 }
157
158 // Validate that requested apps have required ready state and other apps have
159 // opposite state.
160 void ValidateAppReadyState(const std::vector<arc::AppInfo> apps, bool ready) {
161 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
162 ASSERT_NE(nullptr, prefs);
163
164 std::vector<std::string> ids = prefs->GetAppIds();
165 EXPECT_EQ(ids.size(), GetArcItemCount());
166
167 // Process requested apps.
168 for (auto& app : apps) {
169 const std::string id = GetAppId(app);
170 std::vector<std::string>::iterator it_id = std::find(ids.begin(),
171 ids.end(),
172 id);
173 ASSERT_NE(it_id, ids.end());
174 ids.erase(it_id);
175
176 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
177 ASSERT_NE(nullptr, app_info.get());
178 EXPECT_EQ(ready, app_info->ready);
179 const ArcAppItem* app_item = FindArcItem(id);
180 ASSERT_NE(nullptr, app_item);
181 EXPECT_EQ(ready, app_item->ready());
182 }
183
184 // Process the rest of the apps.
185 for (auto& id : ids) {
186 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
187 ASSERT_NE(nullptr, app_info.get());
188 EXPECT_NE(ready, app_info->ready);
189 const ArcAppItem* app_item = FindArcItem(id);
190 ASSERT_NE(nullptr, app_item);
191 EXPECT_NE(ready, app_item->ready());
192 }
193
194 }
195
196 arc::FakeArcBridgeService* bridge_service() { return bridge_service_.get(); }
197
198 const std::vector<arc::AppInfo>& fake_apps() const { return fake_apps_; }
199
200 private:
201 scoped_ptr<app_list::AppListModel> model_;
202 scoped_ptr<test::TestAppListControllerDelegate> controller_;
203 scoped_ptr<ArcAppModelBuilder> builder_;
204 scoped_ptr<arc::FakeArcBridgeService> bridge_service_;
205 std::vector<arc::AppInfo> fake_apps_;
206
207 DISALLOW_COPY_AND_ASSIGN(ArcAppModelBuilderTest);
208 };
209
210 TEST_F(ArcAppModelBuilderTest, RefreshAllOnReady) {
211 EXPECT_EQ(0, bridge_service()->refresh_app_list_count());
212 bridge_service()->SetReady();
213 EXPECT_EQ(1, bridge_service()->refresh_app_list_count());
214 }
215
216 TEST_F(ArcAppModelBuilderTest, RefreshAllFillsContent) {
217 ValidateHaveApps(std::vector<arc::AppInfo>());
218 bridge_service()->SetReady();
219 bridge_service()->SendRefreshAppList(fake_apps());
220 ValidateHaveApps(fake_apps());
221 }
222
223 TEST_F(ArcAppModelBuilderTest, MultipleRefreshAll) {
224 ValidateHaveApps(std::vector<arc::AppInfo>());
225 bridge_service()->SetReady();
226 // Send info about all fake apps except last.
227 std::vector<arc::AppInfo> apps1(fake_apps().begin(), fake_apps().end() - 1);
228 bridge_service()->SendRefreshAppList(apps1);
229 // At this point all apps (except last) should exist and be ready.
230 ValidateHaveApps(apps1);
231 ValidateAppReadyState(apps1, true);
232
233 // Send info about all fake apps except first.
234 std::vector<arc::AppInfo> apps2(fake_apps().begin() + 1, fake_apps().end());
235 bridge_service()->SendRefreshAppList(apps2);
236 // At this point all apps should exist but first one should be non-ready.
237 ValidateHaveApps(fake_apps());
238 ValidateAppReadyState(apps2, true);
239
240 // Send info about all fake apps.
241 bridge_service()->SendRefreshAppList(fake_apps());
242 // At this point all apps should exist and be ready.
243 ValidateHaveApps(fake_apps());
244 ValidateAppReadyState(fake_apps(), true);
245
246 // Send info no app available.
247 bridge_service()->SendRefreshAppList(std::vector<arc::AppInfo>());
248 // At this point all apps should exist and be non-ready.
249 ValidateHaveApps(fake_apps());
250 ValidateAppReadyState(fake_apps(), false);
251 }
252
253 TEST_F(ArcAppModelBuilderTest, StopServiceDisablesApps) {
254 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
255 ASSERT_NE(nullptr, prefs);
256
257 bridge_service()->SetReady();
258 EXPECT_EQ(static_cast<size_t>(0), GetArcItemCount());
259 EXPECT_EQ(static_cast<size_t>(0), prefs->GetAppIds().size());
260
261 bridge_service()->SendRefreshAppList(fake_apps());
262 std::vector<std::string> ids = prefs->GetAppIds();
263 EXPECT_EQ(fake_apps().size(), ids.size());
264 ValidateAppReadyState(fake_apps(), true);
265
266 // Stopping service does not delete items. It makes them non-ready.
267 bridge_service()->SetStopped();
268 // Ids should be the same.
269 EXPECT_EQ(ids, prefs->GetAppIds());
270 ValidateAppReadyState(fake_apps(), false);
271 }
272
273 TEST_F(ArcAppModelBuilderTest, LaunchApps) {
274 bridge_service()->SetReady();
275 bridge_service()->SendRefreshAppList(fake_apps());
276
277 // Simulate item activate.
278 const arc::AppInfo& app_first = fake_apps()[0];
279 const arc::AppInfo& app_last = fake_apps()[0];
280 ArcAppItem* item_first = FindArcItem(GetAppId(app_first));
281 ArcAppItem* item_last = FindArcItem(GetAppId(app_last));
282 ASSERT_NE(nullptr, item_first);
283 ASSERT_NE(nullptr, item_last);
284 item_first->Activate(0);
285 item_last->Activate(0);
286 item_first->Activate(0);
287
288 const std::vector<arc::FakeArcBridgeService::Request>& launch_requests =
289 bridge_service()->launch_requests();
290 EXPECT_EQ(static_cast<size_t>(3), launch_requests.size());
291 EXPECT_EQ(true, launch_requests[0].IsForApp(app_first));
292 EXPECT_EQ(true, launch_requests[1].IsForApp(app_last));
293 EXPECT_EQ(true, launch_requests[2].IsForApp(app_first));
294 }
295
296 TEST_F(ArcAppModelBuilderTest, RequestIcons) {
297 // Make sure we are on UI thread.
298 ASSERT_EQ(true,
299 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
300
301 bridge_service()->SetReady();
302 bridge_service()->SendRefreshAppList(fake_apps());
303
304 // Validate that no icon exists at the beginning and request icon for
305 // each supported scale factor. This will start asynchronous loading.
306 uint32_t expected_mask = 0;
307 const std::vector<ui::ScaleFactor>& scale_factors =
308 ui::GetSupportedScaleFactors();
309 for (auto& scale_factor : scale_factors) {
310 expected_mask |= 1 << scale_factor;
311 for (auto& app : fake_apps()) {
312 ArcAppItem* app_item = FindArcItem(GetAppId(app));
313 ASSERT_NE(nullptr, app_item);
314 const float scale = ui::GetScaleForScaleFactor(scale_factor);
315 app_item->icon().GetRepresentation(scale);
316 }
317 }
318
319 // Process pending tasks.
320 content::BrowserThread::GetBlockingPool()->FlushForTesting();
321 base::RunLoop().RunUntilIdle();
322
323 // At this moment we should receive all requests for icon loading.
324 const std::vector<arc::FakeArcBridgeService::IconRequest>& icon_requests =
325 bridge_service()->icon_requests();
326 EXPECT_EQ(scale_factors.size() * fake_apps().size(), icon_requests.size());
327 std::map<std::string, uint32_t> app_masks;
328 for (size_t i = 0; i < icon_requests.size(); ++i) {
329 const arc::FakeArcBridgeService::IconRequest icon_request =
330 icon_requests[i];
331 const std::string id = ArcAppListPrefs::GetAppId(icon_request.package(),
332 icon_request.activity());
333 // Make sure no double requests.
334 EXPECT_NE(app_masks[id],
335 app_masks[id] | (1 << icon_request.scale_factor()));
336 app_masks[id] |= (1 << icon_request.scale_factor());
337 }
338
339 // Validate that we have a request for each icon for each supported scale
340 // factor.
341 EXPECT_EQ(fake_apps().size(), app_masks.size());
342 for (auto& app : fake_apps()) {
343 const std::string id = GetAppId(app);
344 ASSERT_NE(app_masks.find(id), app_masks.end());
345 EXPECT_EQ(app_masks[id], expected_mask);
346 }
347 }
348
349 TEST_F(ArcAppModelBuilderTest, InstallIcon) {
350 // Make sure we are on UI thread.
351 ASSERT_EQ(true,
352 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
353
354
355 bridge_service()->SetReady();
356 bridge_service()->SendRefreshAppList(std::vector<arc::AppInfo>(
357 fake_apps().begin(), fake_apps().begin() + 1));
358 const arc::AppInfo& app = fake_apps()[0];
359
360 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
361 ASSERT_NE(nullptr, prefs);
362
363 const ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactors()[0];
364 const float scale = ui::GetScaleForScaleFactor(scale_factor);
365 const base::FilePath icon_path = prefs->GetIconPath(GetAppId(app),
366 scale_factor);
367 EXPECT_EQ(true, !base::PathExists(icon_path));
368
369 const ArcAppItem* app_item = FindArcItem(GetAppId(app));
370 EXPECT_NE(nullptr, app_item);
371 // This initiates async loading.
372 app_item->icon().GetRepresentation(scale);
373
374 // Process pending tasks.
375 content::BrowserThread::GetBlockingPool()->FlushForTesting();
376 base::RunLoop().RunUntilIdle();
377
378 // Validating decoded content does not fit well for unit tests.
379 ArcAppIcon::DisableDecodingForTesting();
380
381 // Now send generated icon for the app.
382 std::string png_data;
383 EXPECT_EQ(true, bridge_service()->GenerateAndSendIcon(
384 app,
385 static_cast<arc::ScaleFactor>(scale_factor),
386 &png_data));
387
388 // Process pending tasks.
389 content::BrowserThread::GetBlockingPool()->FlushForTesting();
390 base::RunLoop().RunUntilIdle();
391
392 // Validate that icons are installed, have right content and icon is
393 // refreshed for ARC app item.
394 EXPECT_EQ(true, base::PathExists(icon_path));
395
396 std::string icon_data;
397 // Read the file from disk and compare with reference data.
398 EXPECT_EQ(true, base::ReadFileToString(icon_path, &icon_data));
399 ASSERT_EQ(icon_data, png_data);
400 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698