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

Side by Side Diff: chrome/browser/ui/ash/chrome_launcher_prefs.cc

Issue 2055553004: arc: Support pinned apps across Arc-enabled and Arc-disabled platforms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased, comments addressed, add policy pins movable, add and extends unit tests Created 4 years, 6 months 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" 5 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <set>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/app_mode/app_mode_utils.h" 14 #include "chrome/browser/app_mode/app_mode_utils.h"
15 #include "chrome/browser/chromeos/arc/arc_auth_service.h" 15 #include "chrome/browser/chromeos/arc/arc_auth_service.h"
16 #include "chrome/browser/chromeos/arc/arc_support_host.h" 16 #include "chrome/browser/chromeos/arc/arc_support_host.h"
17 #include "chrome/browser/prefs/pref_service_syncable_util.h" 17 #include "chrome/browser/prefs/pref_service_syncable_util.h"
18 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
19 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
18 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" 20 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
19 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" 21 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
20 #include "chrome/common/extensions/extension_constants.h" 22 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/pref_names.h" 23 #include "chrome/common/pref_names.h"
22 #include "components/pref_registry/pref_registry_syncable.h" 24 #include "components/pref_registry/pref_registry_syncable.h"
23 #include "components/prefs/pref_service.h" 25 #include "components/prefs/pref_service.h"
24 #include "components/prefs/scoped_user_pref_update.h" 26 #include "components/prefs/scoped_user_pref_update.h"
25 #include "components/syncable_prefs/pref_service_syncable.h" 27 #include "components/syncable_prefs/pref_service_syncable.h"
28 #include "sync/api/string_ordinal.h"
26 #include "ui/display/display.h" 29 #include "ui/display/display.h"
27 #include "ui/display/screen.h" 30 #include "ui/display/screen.h"
28 31
29 namespace ash { 32 namespace ash {
33 namespace launcher {
30 34
31 namespace { 35 namespace {
32 36
33 // App ID of default pinned apps. 37 // App ID of default pinned apps.
34 const char* kDefaultPinnedApps[] = { 38 const char* kDefaultPinnedApps[] = {
35 extension_misc::kGmailAppId, 39 extension_misc::kGmailAppId,
36 extension_misc::kGoogleDocAppId, 40 extension_misc::kGoogleDocAppId,
37 extension_misc::kYoutubeAppId, 41 extension_misc::kYoutubeAppId,
38 }; 42 };
39 43
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 // If no user-set value exists at |local_path|, the value from |synced_path| is 200 // If no user-set value exists at |local_path|, the value from |synced_path| is
197 // copied to |local_path|. 201 // copied to |local_path|.
198 void PropagatePrefToLocalIfNotSet( 202 void PropagatePrefToLocalIfNotSet(
199 syncable_prefs::PrefServiceSyncable* pref_service, 203 syncable_prefs::PrefServiceSyncable* pref_service,
200 const char* local_path, 204 const char* local_path,
201 const char* synced_path) { 205 const char* synced_path) {
202 if (!pref_service->FindPreference(local_path)->HasUserSetting()) 206 if (!pref_service->FindPreference(local_path)->HasUserSetting())
203 pref_service->SetString(local_path, pref_service->GetString(synced_path)); 207 pref_service->SetString(local_path, pref_service->GetString(synced_path));
204 } 208 }
205 209
210 struct PinInfo {
211 PinInfo(const std::string& app_id, const syncer::StringOrdinal& item_ordinal)
212 : app_id(app_id), item_ordinal(item_ordinal) {}
213
214 std::string app_id;
215 syncer::StringOrdinal item_ordinal;
216 };
217
218 struct ComparePinInfo {
219 bool operator()(const PinInfo& pin1, const PinInfo& pin2) {
220 return pin1.item_ordinal.LessThan(pin2.item_ordinal);
221 }
222 };
223
224 // Helper class to keep apps in order of appearance and to provide fast way
225 // to check if app exists in the list.
226 class AppTracker {
227 public:
228 bool HasApp(const std::string& app_id) const {
229 return app_set_.find(app_id) != app_set_.end();
230 }
231
232 void AddApp(const std::string& app_id) {
233 if (HasApp(app_id))
234 return;
235 app_list_.push_back(app_id);
236 app_set_.insert(app_id);
237 }
238
239 void MaybeAddApp(const std::string& app_id,
240 const LauncherControllerHelper* helper) {
241 DCHECK_NE(kPinnedAppsPlaceholder, app_id);
242 if (!helper->IsValidIDForCurrentUser(app_id))
243 return;
244 AddApp(app_id);
245 }
246
247 void MaybeAddAppFromPref(const base::DictionaryValue* app_pref,
248 const LauncherControllerHelper* helper) {
249 std::string app_id;
250 if (!app_pref->GetString(kPinnedAppsPrefAppIDPath, &app_id)) {
251 LOG(ERROR) << "Cannot get app id from app pref entry.";
252 return;
253 }
254
255 if (app_id == kPinnedAppsPlaceholder)
256 return;
257
258 bool pinned_by_policy = false;
259 if (app_pref->GetBoolean(kPinnedAppsPrefPinnedByPolicy,
260 &pinned_by_policy) &&
261 pinned_by_policy) {
262 return;
263 }
264
265 MaybeAddApp(app_id, helper);
266 }
267
268 const std::vector<std::string>& app_list() const { return app_list_; }
269
270 private:
271 std::vector<std::string> app_list_;
272 std::set<std::string> app_set_;
273 };
274
206 } // namespace 275 } // namespace
207 276
208 const char kPinnedAppsPrefAppIDPath[] = "id"; 277 const char kPinnedAppsPrefAppIDPath[] = "id";
209 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy"; 278 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy";
210 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------"; 279 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------";
211 280
212 const char kShelfAutoHideBehaviorAlways[] = "Always"; 281 const char kShelfAutoHideBehaviorAlways[] = "Always";
213 const char kShelfAutoHideBehaviorNever[] = "Never"; 282 const char kShelfAutoHideBehaviorNever[] = "Never";
214 283
215 const char kShelfAlignmentBottom[] = "Bottom"; 284 const char kShelfAlignmentBottom[] = "Bottom";
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 return; 366 return;
298 367
299 SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value); 368 SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value);
300 if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { 369 if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) {
301 // See comment in |kShelfAlignment| as to why we consider two prefs. 370 // See comment in |kShelfAlignment| as to why we consider two prefs.
302 prefs->SetString(prefs::kShelfAlignmentLocal, value); 371 prefs->SetString(prefs::kShelfAlignmentLocal, value);
303 prefs->SetString(prefs::kShelfAlignment, value); 372 prefs->SetString(prefs::kShelfAlignment, value);
304 } 373 }
305 } 374 }
306 375
307 std::vector<std::string> GetPinnedAppsFromPrefs( 376 // Helper that extracts app list from policy preferences.
377 void GetAppsPinnedByPolicy(const PrefService* prefs,
378 const LauncherControllerHelper* helper,
379 AppTracker* apps) {
380 DCHECK(apps);
381 DCHECK(apps->app_list().empty());
382
383 const auto* policy_apps = prefs->GetList(prefs::kPolicyPinnedLauncherApps);
384 if (!policy_apps)
385 return;
386
387 // Obtain here all ids of ARC apps because it takes linear time, and getting
388 // them in the loop bellow would lead to quadratic complexity.
389 const ArcAppListPrefs* const arc_app_list_pref = helper->GetArcAppListPrefs();
390 const std::vector<std::string> all_arc_app_ids(
391 arc_app_list_pref ? arc_app_list_pref->GetAppIds()
392 : std::vector<std::string>());
393
394 std::string app_id;
395 for (size_t i = 0; i < policy_apps->GetSize(); ++i) {
396 const base::DictionaryValue* dictionary = nullptr;
397 if (!policy_apps->GetDictionary(i, &dictionary) ||
398 !dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id)) {
399 LOG(ERROR) << "Cannot extract policy app info from prefs.";
400 continue;
401 }
402 if (IsAppIdArcPackage(app_id)) {
403 if (!arc_app_list_pref)
404 continue;
405
406 // We are dealing with package name, not with 32 characters ID.
407 const std::string& arc_package = app_id;
408 const std::vector<std::string> activities = GetActivitiesForPackage(
409 arc_package, all_arc_app_ids, *arc_app_list_pref);
410 for (const auto& activity : activities) {
411 const std::string arc_app_id =
412 ArcAppListPrefs::GetAppId(arc_package, activity);
413 apps->MaybeAddApp(arc_app_id, helper);
414 }
415 } else {
416 apps->MaybeAddApp(app_id, helper);
417 }
418 }
419 }
420
421 std::vector<std::string> GetPinnedAppsFromPrefsLegacy(
308 const PrefService* prefs, 422 const PrefService* prefs,
309 const LauncherControllerHelper* helper) { 423 const LauncherControllerHelper* helper) {
310 // Adding the app list item to the list of items requires that the ID is not 424 // Adding the app list item to the list of items requires that the ID is not
311 // a valid and known ID for the extension system. The ID was constructed that 425 // a valid and known ID for the extension system. The ID was constructed that
312 // way - but just to make sure... 426 // way - but just to make sure...
313 DCHECK(!helper->IsValidIDForCurrentUser(kPinnedAppsPlaceholder)); 427 DCHECK(!helper->IsValidIDForCurrentUser(kPinnedAppsPlaceholder));
314 428
315 std::vector<std::string> apps; 429 const auto* pinned_apps = prefs->GetList(prefs::kPinnedLauncherApps);
316 const auto* pinned = prefs->GetList(prefs::kPinnedLauncherApps);
317 const auto* policy = prefs->GetList(prefs::kPolicyPinnedLauncherApps);
318 430
319 // Get the sanitized preference value for the index of the Chrome app icon. 431 // Get the sanitized preference value for the index of the Chrome app icon.
320 const size_t chrome_icon_index = std::max<size_t>( 432 const size_t chrome_icon_index = std::max<size_t>(
321 0, std::min<size_t>(pinned->GetSize(), 433 0, std::min<size_t>(pinned_apps->GetSize(),
322 prefs->GetInteger(prefs::kShelfChromeIconIndex))); 434 prefs->GetInteger(prefs::kShelfChromeIconIndex)));
323 435
324 // Check if Chrome is in either of the the preferences lists. 436 // Check if Chrome is in either of the the preferences lists.
325 std::unique_ptr<base::Value> chrome_app( 437 std::unique_ptr<base::Value> chrome_app(
326 ash::CreateAppDict(extension_misc::kChromeAppId)); 438 CreateAppDict(extension_misc::kChromeAppId));
327 bool chrome_listed =
328 (pinned->Find(*chrome_app.get()) != pinned->end() ||
329 (policy && policy->Find(*chrome_app.get()) != policy->end()));
330 439
331 // Obtain here all ids of ARC apps because it takes linear time, and getting 440 AppTracker apps;
332 // them in the loop bellow would lead to quadratic complexity. 441 GetAppsPinnedByPolicy(prefs, helper, &apps);
333 const ArcAppListPrefs* const arc_app_list_pref = helper->GetArcAppListPrefs();
334 const std::vector<std::string> all_arc_app_ids(
335 arc_app_list_pref ? arc_app_list_pref->GetAppIds()
336 : std::vector<std::string>());
337 442
338 std::string app_id; 443 std::string app_id;
339 for (size_t i = 0; policy && (i < policy->GetSize()); ++i) { 444 for (size_t i = 0; i < pinned_apps->GetSize(); ++i) {
340 const base::DictionaryValue* dictionary = nullptr;
341 if (policy->GetDictionary(i, &dictionary) &&
342 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) &&
343 std::find(apps.begin(), apps.end(), app_id) == apps.end()) {
344 if (IsAppIdArcPackage(app_id)) {
345 if (!arc_app_list_pref)
346 continue;
347
348 // We are dealing with package name, not with 32 characters ID.
349 const std::string& arc_package = app_id;
350 const std::vector<std::string> activities = GetActivitiesForPackage(
351 arc_package, all_arc_app_ids, *arc_app_list_pref);
352 for (const auto& activity : activities) {
353 const std::string arc_app_id =
354 ArcAppListPrefs::GetAppId(arc_package, activity);
355 if (helper->IsValidIDForCurrentUser(arc_app_id))
356 apps.push_back(arc_app_id);
357 }
358 } else if (helper->IsValidIDForCurrentUser(app_id)) {
359 apps.push_back(app_id);
360 }
361 }
362 }
363
364 for (size_t i = 0; i < pinned->GetSize(); ++i) {
365 // We need to position the chrome icon relative to its place in the pinned 445 // We need to position the chrome icon relative to its place in the pinned
366 // preference list - even if an item of that list isn't shown yet. 446 // preference list - even if an item of that list isn't shown yet.
367 if (i == chrome_icon_index && !chrome_listed) { 447 if (i == chrome_icon_index)
368 apps.push_back(extension_misc::kChromeAppId); 448 apps.AddApp(extension_misc::kChromeAppId);
369 chrome_listed = true; 449 const base::DictionaryValue* app_pref = nullptr;
450 if (!pinned_apps->GetDictionary(i, &app_pref)) {
451 LOG(ERROR) << "There is no dictionary for app entry.";
452 continue;
370 } 453 }
371 bool pinned_by_policy = false; 454 apps.MaybeAddAppFromPref(app_pref, helper);
372 const base::DictionaryValue* dictionary = nullptr;
373 if (pinned->GetDictionary(i, &dictionary) &&
374 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) &&
375 helper->IsValidIDForCurrentUser(app_id) &&
376 std::find(apps.begin(), apps.end(), app_id) == apps.end() &&
377 (!dictionary->GetBoolean(kPinnedAppsPrefPinnedByPolicy,
378 &pinned_by_policy) ||
379 !pinned_by_policy)) {
380 apps.push_back(app_id);
381 }
382 }
383
384 if (arc::ArcAuthService::IsAllowedForProfile(helper->profile()) &&
385 helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) {
386 apps.push_back(ArcSupportHost::kHostAppId);
387 } 455 }
388 456
389 // If not added yet, the chrome item will be the last item in the list. 457 // If not added yet, the chrome item will be the last item in the list.
390 if (!chrome_listed) 458 apps.AddApp(extension_misc::kChromeAppId);
391 apps.push_back(extension_misc::kChromeAppId); 459 return apps.app_list();
392
393 // If not added yet, place the app list item at the beginning of the list.
394 if (std::find(apps.begin(), apps.end(), kPinnedAppsPlaceholder) == apps.end())
395 apps.insert(apps.begin(), kPinnedAppsPlaceholder);
396
397 return apps;
398 } 460 }
399 461
400 // static 462 // static
401 std::unique_ptr<ChromeLauncherPrefsObserver> 463 std::unique_ptr<ChromeLauncherPrefsObserver>
402 ChromeLauncherPrefsObserver::CreateIfNecessary(Profile* profile) { 464 ChromeLauncherPrefsObserver::CreateIfNecessary(Profile* profile) {
403 syncable_prefs::PrefServiceSyncable* prefs = 465 syncable_prefs::PrefServiceSyncable* prefs =
404 PrefServiceSyncableFromProfile(profile); 466 PrefServiceSyncableFromProfile(profile);
405 if (!prefs->FindPreference(prefs::kShelfAlignmentLocal)->HasUserSetting() || 467 if (!prefs->FindPreference(prefs::kShelfAlignmentLocal)->HasUserSetting() ||
406 !prefs->FindPreference(prefs::kShelfAutoHideBehaviorLocal) 468 !prefs->FindPreference(prefs::kShelfAutoHideBehaviorLocal)
407 ->HasUserSetting()) { 469 ->HasUserSetting()) {
(...skipping 10 matching lines...) Expand all
418 syncable_prefs::PrefServiceSyncable* prefs) 480 syncable_prefs::PrefServiceSyncable* prefs)
419 : prefs_(prefs) { 481 : prefs_(prefs) {
420 // This causes OnIsSyncingChanged to be called when the value of 482 // This causes OnIsSyncingChanged to be called when the value of
421 // PrefService::IsSyncing() changes. 483 // PrefService::IsSyncing() changes.
422 prefs_->AddObserver(this); 484 prefs_->AddObserver(this);
423 } 485 }
424 486
425 void ChromeLauncherPrefsObserver::OnIsSyncingChanged() { 487 void ChromeLauncherPrefsObserver::OnIsSyncingChanged() {
426 // If prefs have synced, copy the values from |synced_path| to |local_path| 488 // If prefs have synced, copy the values from |synced_path| to |local_path|
427 // if the local values haven't already been set. 489 // if the local values haven't already been set.
428 if (prefs_->IsSyncing()) { 490 if (!prefs_->IsSyncing())
429 PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAlignmentLocal, 491 return;
430 prefs::kShelfAlignment); 492 PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAlignmentLocal,
431 PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAutoHideBehaviorLocal, 493 prefs::kShelfAlignment);
432 prefs::kShelfAutoHideBehavior); 494 PropagatePrefToLocalIfNotSet(prefs_, prefs::kShelfAutoHideBehaviorLocal,
433 prefs_->RemoveObserver(this); 495 prefs::kShelfAutoHideBehavior);
434 } 496 prefs_->RemoveObserver(this);
435 } 497 }
436 498
499 // Helper to create pin position that stays before any synced app, even if
500 // app is not currently visible on a device.
501 syncer::StringOrdinal GetFirstPinPosition(Profile* profile) {
502 syncer::StringOrdinal position;
503 app_list::AppListSyncableService* app_service =
504 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
505 for (const auto& sync_peer : app_service->sync_items()) {
506 if (!sync_peer.second->item_pin_ordinal.IsValid())
507 continue;
508 if (!position.IsValid() ||
509 sync_peer.second->item_pin_ordinal.LessThan(position)) {
510 position = sync_peer.second->item_pin_ordinal;
511 }
512 }
513
514 return position.IsValid() ? position.CreateBefore()
515 : syncer::StringOrdinal::CreateInitialOrdinal();
516 }
517
518 // Helper to creates pin position that stays before any synced app, even if
519 // app is not currently visible on a device.
520 syncer::StringOrdinal GetLastPinPosition(Profile* profile) {
521 syncer::StringOrdinal position;
522 app_list::AppListSyncableService* app_service =
523 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
524 for (const auto& sync_peer : app_service->sync_items()) {
525 if (!sync_peer.second->item_pin_ordinal.IsValid())
526 continue;
527 if (!position.IsValid() ||
528 sync_peer.second->item_pin_ordinal.GreaterThan(position)) {
529 position = sync_peer.second->item_pin_ordinal;
530 }
531 }
532
533 return position.IsValid() ? position.CreateAfter()
534 : syncer::StringOrdinal::CreateInitialOrdinal();
535 }
536
537 std::vector<std::string> ImportLegacyPinnedApps(
538 const PrefService* prefs,
539 LauncherControllerHelper* helper,
540 const AppTracker& policy_apps) {
541 std::vector<std::string> legacy_pins =
542 GetPinnedAppsFromPrefsLegacy(prefs, helper);
543 DCHECK(!legacy_pins.empty());
544
545 app_list::AppListSyncableService* app_service =
546 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile());
547
548 syncer::StringOrdinal last_position =
549 syncer::StringOrdinal::CreateInitialOrdinal();
550 // Convert to sync item record.
551 for (const auto& app_id : legacy_pins) {
552 DCHECK_NE(kPinnedAppsPlaceholder, app_id);
553 app_service->SetPinPosition(app_id, last_position);
554 last_position = last_position.CreateAfter();
555 }
556
557 // Now process default apps.
558 for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i) {
559 const std::string& app_id = kDefaultPinnedApps[i];
560 // Check if it is already imported.
561 if (app_service->GetPinPosition(app_id).IsValid())
562 continue;
563 // Check if it is present but not in legacy pin.
564 if (helper->IsValidIDForCurrentUser(app_id))
565 continue;
566 app_service->SetPinPosition(app_id, last_position);
567 last_position = last_position.CreateAfter();
568 }
569
570 return legacy_pins;
571 }
572
573 std::vector<std::string> GetPinnedAppsFromPrefs(
574 const PrefService* prefs,
575 LauncherControllerHelper* helper) {
576 app_list::AppListSyncableService* app_service =
577 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile());
578 // Some unit tests may not have it.
579 if (!app_service)
580 return std::vector<std::string>();
581
582 std::vector<PinInfo> pin_infos;
583
584 AppTracker policy_apps;
585 GetAppsPinnedByPolicy(prefs, helper, &policy_apps);
586
587 // Empty pins indicates that sync based pin model is used for the first
588 // time. In normal workflow we have at least Chrome browser pin info.
589 bool first_run = true;
590
591 for (const auto& sync_peer : app_service->sync_items()) {
592 if (!sync_peer.second->item_pin_ordinal.IsValid())
593 continue;
594
595 first_run = false;
596 // Don't include apps that currently do not exist on device.
597 if (sync_peer.first != extension_misc::kChromeAppId &&
598 !helper->IsValidIDForCurrentUser(sync_peer.first)) {
599 continue;
600 }
601
602 pin_infos.push_back(
603 PinInfo(sync_peer.first, sync_peer.second->item_pin_ordinal));
604 }
605
606 if (first_run) {
607 // We need to import legacy pins model and convert it to sync based
608 // model.
609 return ImportLegacyPinnedApps(prefs, helper, policy_apps);
610 }
611
612 // Sort pins according their ordinals.
613 std::sort(pin_infos.begin(), pin_infos.end(), ComparePinInfo());
614
615 // Pinned by policy apps appear first, if they were not shown before.
616 syncer::StringOrdinal front_position = GetFirstPinPosition(helper->profile());
617 std::vector<std::string>::const_reverse_iterator it;
618 for (it = policy_apps.app_list().rbegin();
619 it != policy_apps.app_list().rend(); ++it) {
620 const std::string& app_id = *it;
621 if (app_id == kPinnedAppsPlaceholder)
622 continue;
623
624 // Check if we already processed current app.
625 if (app_service->GetPinPosition(app_id).IsValid()) {
626 DCHECK(pin_infos.end() != std::find_if(pin_infos.begin(), pin_infos.end(),
627 [app_id](const PinInfo& pin_info) {
628 return (pin_info.app_id ==
629 app_id);
630 }));
stevenjb 2016/06/15 17:53:52 This is a bit lengthy and expensive for a DCHECK.
khmel 2016/06/15 18:26:22 agree, removed.
631 continue;
632 }
633
634 // Now put it to the front.
stevenjb 2016/06/15 17:53:52 nit: s/put/move/
khmel 2016/06/15 18:26:22 Done.
635 pin_infos.insert(pin_infos.begin(), PinInfo(app_id, front_position));
636 app_service->SetPinPosition(app_id, front_position);
637 front_position = front_position.CreateBefore();
638 }
639
640 // Now insert Chrome browser app if needed.
641 if (!app_service->GetPinPosition(extension_misc::kChromeAppId).IsValid()) {
642 pin_infos.insert(pin_infos.begin(),
643 PinInfo(extension_misc::kChromeAppId, front_position));
644 app_service->SetPinPosition(extension_misc::kChromeAppId, front_position);
645 }
646
647 if (arc::ArcAuthService::IsAllowedForProfile(helper->profile()) &&
648 helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) {
649 if (!app_service->GetSyncItem(ArcSupportHost::kHostAppId)) {
650 const syncer::StringOrdinal arc_host_position =
651 GetLastPinPosition(helper->profile());
652 pin_infos.insert(pin_infos.begin(),
653 PinInfo(ArcSupportHost::kHostAppId, arc_host_position));
654 app_service->SetPinPosition(ArcSupportHost::kHostAppId,
655 arc_host_position);
656 }
657 }
658
659 // Convert to string array.
660 std::vector<std::string> pins(pin_infos.size());
661 for (size_t i = 0; i < pin_infos.size(); ++i)
662 pins[i] = pin_infos[i].app_id;
663
664 return pins;
665 }
666
667 void RemovePinPosition(Profile* profile, const std::string& app_id) {
668 DCHECK(profile);
669 DCHECK(!app_id.empty());
670 app_list::AppListSyncableService* app_service =
671 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
672 app_service->SetPinPosition(app_id, syncer::StringOrdinal());
673 }
674
675 void SetPinPosition(Profile* profile,
676 const std::string& app_id,
677 const std::string& app_id_before,
678 const std::string& app_id_after) {
679 DCHECK(profile);
680 DCHECK(!app_id.empty());
681 DCHECK_NE(app_id, app_id_before);
682 DCHECK_NE(app_id, app_id_after);
683 DCHECK(app_id_before.empty() || app_id_before != app_id_after);
684
685 app_list::AppListSyncableService* app_service =
686 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
687 // Some unit tests may not have this service.
688 if (!app_service)
689 return;
690
691 syncer::StringOrdinal position_before =
692 app_id_before.empty() ? syncer::StringOrdinal()
693 : app_service->GetPinPosition(app_id_before);
694 syncer::StringOrdinal position_after =
695 app_id_after.empty() ? syncer::StringOrdinal()
696 : app_service->GetPinPosition(app_id_after);
697
698 syncer::StringOrdinal pin_position;
699 if (position_before.IsValid() && position_after.IsValid())
700 pin_position = position_before.CreateBetween(position_after);
701 else if (position_before.IsValid())
702 pin_position = position_before.CreateAfter();
703 else if (position_after.IsValid())
704 pin_position = position_after.CreateBefore();
705 else
706 pin_position = syncer::StringOrdinal::CreateInitialOrdinal();
707 app_service->SetPinPosition(app_id, pin_position);
708 }
709
710 } // namespace launcher
437 } // namespace ash 711 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698