Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <memory> |
| 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/ui/app_list/app_list_syncable_service.h" | |
| 17 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" | 18 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" |
| 18 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" | 19 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" |
| 19 #include "chrome/common/extensions/extension_constants.h" | 20 #include "chrome/common/extensions/extension_constants.h" |
| 20 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
| 21 #include "components/pref_registry/pref_registry_syncable.h" | 22 #include "components/pref_registry/pref_registry_syncable.h" |
| 22 #include "components/prefs/pref_service.h" | 23 #include "components/prefs/pref_service.h" |
| 23 #include "components/prefs/scoped_user_pref_update.h" | 24 #include "components/prefs/scoped_user_pref_update.h" |
| 25 #include "sync/api/string_ordinal.h" | |
| 24 #include "ui/display/display.h" | 26 #include "ui/display/display.h" |
| 25 #include "ui/display/screen.h" | 27 #include "ui/display/screen.h" |
| 26 | 28 |
| 27 namespace ash { | 29 namespace ash { |
| 28 | 30 |
| 29 namespace { | 31 namespace { |
| 30 | 32 |
| 31 // App ID of default pinned apps. | 33 // App ID of default pinned apps. |
| 32 const char* kDefaultPinnedApps[] = { | 34 const char* kDefaultPinnedApps[] = { |
| 33 extension_misc::kGmailAppId, | 35 extension_misc::kGmailAppId, |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 for (const std::string& app_id : all_arc_app_ids) { | 186 for (const std::string& app_id : all_arc_app_ids) { |
| 185 const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = | 187 const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = |
| 186 app_list_pref.GetApp(app_id); | 188 app_list_pref.GetApp(app_id); |
| 187 if (app_info->package_name == package) { | 189 if (app_info->package_name == package) { |
| 188 activities.push_back(app_info->activity); | 190 activities.push_back(app_info->activity); |
| 189 } | 191 } |
| 190 } | 192 } |
| 191 return activities; | 193 return activities; |
| 192 } | 194 } |
| 193 | 195 |
| 196 struct PinInfo { | |
| 197 PinInfo(const std::string& app_id, const syncer::StringOrdinal& item_ordinal) | |
| 198 : app_id(app_id), item_ordinal(item_ordinal) {} | |
| 199 | |
| 200 std::string app_id; | |
| 201 syncer::StringOrdinal item_ordinal; | |
| 202 }; | |
| 203 | |
| 204 struct ComparePinInfo { | |
| 205 bool operator()(const PinInfo& pin1, const PinInfo& pin2) { | |
| 206 return pin1.item_ordinal.LessThan(pin2.item_ordinal); | |
| 207 } | |
| 208 }; | |
| 209 | |
| 194 } // namespace | 210 } // namespace |
| 195 | 211 |
| 196 const char kPinnedAppsPrefAppIDPath[] = "id"; | 212 const char kPinnedAppsPrefAppIDPath[] = "id"; |
| 197 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy"; | 213 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy"; |
| 198 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------"; | 214 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------"; |
| 199 | 215 |
| 200 const char kShelfAutoHideBehaviorAlways[] = "Always"; | 216 const char kShelfAutoHideBehaviorAlways[] = "Always"; |
| 201 const char kShelfAutoHideBehaviorNever[] = "Never"; | 217 const char kShelfAutoHideBehaviorNever[] = "Never"; |
| 202 | 218 |
| 203 const char kShelfAlignmentBottom[] = "Bottom"; | 219 const char kShelfAlignmentBottom[] = "Bottom"; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 return; | 301 return; |
| 286 | 302 |
| 287 SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value); | 303 SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value); |
| 288 if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { | 304 if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) { |
| 289 // See comment in |kShelfAlignment| as to why we consider two prefs. | 305 // See comment in |kShelfAlignment| as to why we consider two prefs. |
| 290 prefs->SetString(prefs::kShelfAlignmentLocal, value); | 306 prefs->SetString(prefs::kShelfAlignmentLocal, value); |
| 291 prefs->SetString(prefs::kShelfAlignment, value); | 307 prefs->SetString(prefs::kShelfAlignment, value); |
| 292 } | 308 } |
| 293 } | 309 } |
| 294 | 310 |
| 295 std::vector<std::string> GetPinnedAppsFromPrefs( | 311 // Helper that extracts app list from policy preferences. |
| 312 std::vector<std::string> GetAppsPinnedByPolicy( | |
| 296 const PrefService* prefs, | 313 const PrefService* prefs, |
| 297 const LauncherControllerHelper* helper) { | 314 const LauncherControllerHelper* helper) { |
| 298 // Adding the app list item to the list of items requires that the ID is not | |
| 299 // a valid and known ID for the extension system. The ID was constructed that | |
| 300 // way - but just to make sure... | |
| 301 DCHECK(!helper->IsValidIDForCurrentUser(kPinnedAppsPlaceholder)); | |
| 302 | |
| 303 std::vector<std::string> apps; | 315 std::vector<std::string> apps; |
| 304 const auto* pinned = prefs->GetList(prefs::kPinnedLauncherApps); | |
| 305 const auto* policy = prefs->GetList(prefs::kPolicyPinnedLauncherApps); | 316 const auto* policy = prefs->GetList(prefs::kPolicyPinnedLauncherApps); |
| 306 | 317 if (!policy) |
| 307 // Get the sanitized preference value for the index of the Chrome app icon. | 318 return apps; |
| 308 const size_t chrome_icon_index = std::max<size_t>( | |
| 309 0, std::min<size_t>(pinned->GetSize(), | |
| 310 prefs->GetInteger(prefs::kShelfChromeIconIndex))); | |
| 311 | |
| 312 // Check if Chrome is in either of the the preferences lists. | |
| 313 std::unique_ptr<base::Value> chrome_app( | |
| 314 ash::CreateAppDict(extension_misc::kChromeAppId)); | |
| 315 bool chrome_listed = | |
| 316 (pinned->Find(*chrome_app.get()) != pinned->end() || | |
| 317 (policy && policy->Find(*chrome_app.get()) != policy->end())); | |
| 318 | 319 |
| 319 // Obtain here all ids of ARC apps because it takes linear time, and getting | 320 // Obtain here all ids of ARC apps because it takes linear time, and getting |
| 320 // them in the loop bellow would lead to quadratic complexity. | 321 // them in the loop bellow would lead to quadratic complexity. |
| 321 const ArcAppListPrefs* const arc_app_list_pref = helper->GetArcAppListPrefs(); | 322 const ArcAppListPrefs* const arc_app_list_pref = helper->GetArcAppListPrefs(); |
| 322 const std::vector<std::string> all_arc_app_ids( | 323 const std::vector<std::string> all_arc_app_ids( |
| 323 arc_app_list_pref ? arc_app_list_pref->GetAppIds() | 324 arc_app_list_pref ? arc_app_list_pref->GetAppIds() |
| 324 : std::vector<std::string>()); | 325 : std::vector<std::string>()); |
| 325 | 326 |
| 326 std::string app_id; | 327 std::string app_id; |
| 327 for (size_t i = 0; policy && (i < policy->GetSize()); ++i) { | 328 for (size_t i = 0; i < policy->GetSize(); ++i) { |
| 328 const base::DictionaryValue* dictionary = nullptr; | 329 const base::DictionaryValue* dictionary = nullptr; |
| 329 if (policy->GetDictionary(i, &dictionary) && | 330 if (policy->GetDictionary(i, &dictionary) && |
| 330 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) && | 331 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) && |
| 331 std::find(apps.begin(), apps.end(), app_id) == apps.end()) { | 332 std::find(apps.begin(), apps.end(), app_id) == apps.end()) { |
| 332 if (IsAppIdArcPackage(app_id)) { | 333 if (IsAppIdArcPackage(app_id)) { |
| 333 if (!arc_app_list_pref) | 334 if (!arc_app_list_pref) |
| 334 continue; | 335 continue; |
| 335 | 336 |
| 336 // We are dealing with package name, not with 32 characters ID. | 337 // We are dealing with package name, not with 32 characters ID. |
| 337 const std::string& arc_package = app_id; | 338 const std::string& arc_package = app_id; |
| 338 const std::vector<std::string> activities = GetActivitiesForPackage( | 339 const std::vector<std::string> activities = GetActivitiesForPackage( |
| 339 arc_package, all_arc_app_ids, *arc_app_list_pref); | 340 arc_package, all_arc_app_ids, *arc_app_list_pref); |
| 340 for (const auto& activity : activities) { | 341 for (const auto& activity : activities) { |
| 341 const std::string arc_app_id = | 342 const std::string arc_app_id = |
| 342 ArcAppListPrefs::GetAppId(arc_package, activity); | 343 ArcAppListPrefs::GetAppId(arc_package, activity); |
| 343 if (helper->IsValidIDForCurrentUser(arc_app_id)) | 344 if (helper->IsValidIDForCurrentUser(arc_app_id)) |
| 344 apps.push_back(arc_app_id); | 345 apps.push_back(arc_app_id); |
| 345 } | 346 } |
| 346 } else if (helper->IsValidIDForCurrentUser(app_id)) { | 347 } else if (helper->IsValidIDForCurrentUser(app_id)) { |
| 347 apps.push_back(app_id); | 348 apps.push_back(app_id); |
| 348 } | 349 } |
| 349 } | 350 } |
| 350 } | 351 } |
| 351 | 352 |
| 353 return apps; | |
| 354 } | |
| 355 | |
| 356 std::vector<std::string> GetPinnedAppsFromPrefsDepricated( | |
|
stevenjb
2016/06/10 18:00:41
s/Depricated/Deprecated/, but also maybe use Legac
khmel
2016/06/10 22:08:10
Legacy sounds better, thanks
| |
| 357 const PrefService* prefs, | |
| 358 const LauncherControllerHelper* helper) { | |
| 359 // Adding the app list item to the list of items requires that the ID is not | |
| 360 // a valid and known ID for the extension system. The ID was constructed that | |
| 361 // way - but just to make sure... | |
| 362 DCHECK(!helper->IsValidIDForCurrentUser(kPinnedAppsPlaceholder)); | |
| 363 | |
| 364 const auto* pinned = prefs->GetList(prefs::kPinnedLauncherApps); | |
| 365 const auto* policy = prefs->GetList(prefs::kPolicyPinnedLauncherApps); | |
| 366 | |
| 367 // Get the sanitized preference value for the index of the Chrome app icon. | |
| 368 const size_t chrome_icon_index = std::max<size_t>( | |
| 369 0, std::min<size_t>(pinned->GetSize(), | |
| 370 prefs->GetInteger(prefs::kShelfChromeIconIndex))); | |
| 371 | |
| 372 // Check if Chrome is in either of the the preferences lists. | |
| 373 std::unique_ptr<base::Value> chrome_app( | |
| 374 ash::CreateAppDict(extension_misc::kChromeAppId)); | |
| 375 bool chrome_listed = | |
| 376 (pinned->Find(*chrome_app.get()) != pinned->end() || | |
| 377 (policy && policy->Find(*chrome_app.get()) != policy->end())); | |
| 378 | |
| 379 std::vector<std::string> apps = GetAppsPinnedByPolicy(prefs, helper); | |
| 380 | |
| 381 std::string app_id; | |
| 352 for (size_t i = 0; i < pinned->GetSize(); ++i) { | 382 for (size_t i = 0; i < pinned->GetSize(); ++i) { |
| 353 // We need to position the chrome icon relative to its place in the pinned | 383 // We need to position the chrome icon relative to its place in the pinned |
| 354 // preference list - even if an item of that list isn't shown yet. | 384 // preference list - even if an item of that list isn't shown yet. |
| 355 if (i == chrome_icon_index && !chrome_listed) { | 385 if (i == chrome_icon_index && !chrome_listed) { |
| 356 apps.push_back(extension_misc::kChromeAppId); | 386 apps.push_back(extension_misc::kChromeAppId); |
| 357 chrome_listed = true; | 387 chrome_listed = true; |
| 358 } | 388 } |
| 359 bool pinned_by_policy = false; | 389 bool pinned_by_policy = false; |
| 360 const base::DictionaryValue* dictionary = nullptr; | 390 const base::DictionaryValue* dictionary = nullptr; |
| 361 if (pinned->GetDictionary(i, &dictionary) && | 391 if (pinned->GetDictionary(i, &dictionary) && |
| 362 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) && | 392 dictionary->GetString(kPinnedAppsPrefAppIDPath, &app_id) && |
| 363 helper->IsValidIDForCurrentUser(app_id) && | 393 helper->IsValidIDForCurrentUser(app_id) && |
| 364 std::find(apps.begin(), apps.end(), app_id) == apps.end() && | 394 std::find(apps.begin(), apps.end(), app_id) == apps.end() && |
| 365 (!dictionary->GetBoolean(kPinnedAppsPrefPinnedByPolicy, | 395 (!dictionary->GetBoolean(kPinnedAppsPrefPinnedByPolicy, |
| 366 &pinned_by_policy) || | 396 &pinned_by_policy) || |
| 367 !pinned_by_policy)) { | 397 !pinned_by_policy)) { |
| 368 apps.push_back(app_id); | 398 apps.push_back(app_id); |
| 369 } | 399 } |
| 370 } | 400 } |
| 371 | 401 |
| 372 if (arc::ArcAuthService::IsAllowedForProfile(helper->profile()) && | |
| 373 helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) { | |
| 374 apps.push_back(ArcSupportHost::kHostAppId); | |
| 375 } | |
| 376 | |
| 377 // If not added yet, the chrome item will be the last item in the list. | 402 // If not added yet, the chrome item will be the last item in the list. |
| 378 if (!chrome_listed) | 403 if (!chrome_listed) |
| 379 apps.push_back(extension_misc::kChromeAppId); | 404 apps.push_back(extension_misc::kChromeAppId); |
| 380 | 405 |
| 381 // If not added yet, place the app list item at the beginning of the list. | 406 // If not added yet, place the app list item at the beginning of the list. |
| 382 if (std::find(apps.begin(), apps.end(), kPinnedAppsPlaceholder) == apps.end()) | 407 if (std::find(apps.begin(), apps.end(), kPinnedAppsPlaceholder) == apps.end()) |
| 383 apps.insert(apps.begin(), kPinnedAppsPlaceholder); | 408 apps.insert(apps.begin(), kPinnedAppsPlaceholder); |
| 384 | 409 |
| 385 return apps; | 410 return apps; |
| 386 } | 411 } |
| 387 | 412 |
| 413 // Helper to creates pin position that stays before any synced app, even if | |
|
stevenjb
2016/06/10 18:00:40
s/creates/create/
khmel
2016/06/10 22:08:10
Done.
| |
| 414 // app is not currently visbile on a device. | |
| 415 syncer::StringOrdinal CreateFirstPinPosition(Profile* profile) { | |
| 416 syncer::StringOrdinal position; | |
| 417 app_list::AppListSyncableService* app_service = | |
| 418 app_list::AppListSyncableService::Get(profile); | |
| 419 for (const auto& sync_peer : app_service->sync_items()) { | |
| 420 if (!sync_peer.second->item_pin_ordinal.IsValid()) | |
| 421 continue; | |
| 422 if (!position.IsValid() || | |
| 423 sync_peer.second->item_pin_ordinal.LessThan(position)) { | |
| 424 position = sync_peer.second->item_pin_ordinal; | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 return position.IsValid() ? position.CreateBefore() | |
| 429 : syncer::StringOrdinal::CreateInitialOrdinal(); | |
| 430 } | |
| 431 | |
| 432 // Helper to creates pin position that stays before any synced app, even if | |
| 433 // app is not currently visbile on a device. | |
| 434 syncer::StringOrdinal CreateLastPinPosition(Profile* profile) { | |
| 435 syncer::StringOrdinal position; | |
| 436 app_list::AppListSyncableService* app_service = | |
| 437 app_list::AppListSyncableService::Get(profile); | |
| 438 for (const auto& sync_peer : app_service->sync_items()) { | |
| 439 if (!sync_peer.second->item_pin_ordinal.IsValid()) | |
| 440 continue; | |
| 441 if (!position.IsValid() || | |
| 442 sync_peer.second->item_pin_ordinal.GreaterThan(position)) { | |
| 443 position = sync_peer.second->item_pin_ordinal; | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 return position.IsValid() ? position.CreateAfter() | |
| 448 : syncer::StringOrdinal::CreateInitialOrdinal(); | |
| 449 } | |
| 450 | |
| 451 std::vector<std::string> GetPinnedAppsFromPrefs( | |
| 452 const PrefService* prefs, | |
| 453 LauncherControllerHelper* helper) { | |
| 454 app_list::AppListSyncableService* app_service = | |
| 455 app_list::AppListSyncableService::Get(helper->profile()); | |
| 456 // Some unit tests may not have it. | |
| 457 if (!app_service) | |
| 458 return std::vector<std::string>(); | |
| 459 | |
| 460 const std::vector<std::string> policy_apps = | |
| 461 GetAppsPinnedByPolicy(prefs, helper); | |
| 462 | |
| 463 std::vector<PinInfo> pin_infos; | |
| 464 | |
| 465 // Empty pins indicates that sync based pin model is used for the first | |
| 466 // time. In normal workflow we have at least Chrom browser pin info. | |
|
stevenjb
2016/06/10 18:00:41
Chrome
khmel
2016/06/10 22:08:10
Done.
| |
| 467 bool first_run = true; | |
| 468 | |
| 469 for (const auto& sync_peer : app_service->sync_items()) { | |
| 470 if (!sync_peer.second->item_pin_ordinal.IsValid()) | |
| 471 continue; | |
| 472 | |
| 473 first_run = false; | |
| 474 // Don't include apps that are currently do not exist on device. | |
|
stevenjb
2016/06/10 18:00:40
s/are//
khmel
2016/06/10 22:08:10
Done.
| |
| 475 if (sync_peer.first != extension_misc::kChromeAppId && | |
| 476 !helper->IsValidIDForCurrentUser(sync_peer.first)) { | |
| 477 continue; | |
| 478 } | |
| 479 | |
| 480 const bool pin_by_policy = std::find(policy_apps.begin(), policy_apps.end(), | |
| 481 sync_peer.first) != policy_apps.end(); | |
|
stevenjb
2016/06/10 18:00:40
If the app list gets large this could be expensive
| |
| 482 // Check if item was pinned by policy only and currently is not in policy. | |
| 483 if (!pin_by_policy && sync_peer.second->item_pin_by_policy) | |
| 484 continue; | |
| 485 | |
| 486 pin_infos.push_back( | |
| 487 PinInfo(sync_peer.first, sync_peer.second->item_pin_ordinal)); | |
| 488 } | |
| 489 | |
| 490 if (first_run) { | |
|
stevenjb
2016/06/10 18:00:41
We should wrap this into a separate function, e.g.
khmel
2016/06/10 22:08:10
Done.
| |
| 491 // We need to import legacy pins model and convert it to sync based | |
| 492 // model. | |
| 493 std::vector<std::string> legacy_pins = | |
| 494 GetPinnedAppsFromPrefsDepricated(prefs, helper); | |
| 495 DCHECK(!legacy_pins.empty()); | |
| 496 | |
| 497 legacy_pins.erase( | |
| 498 std::remove_if(legacy_pins.begin(), legacy_pins.end(), | |
| 499 [](const std::string& app_id) { | |
| 500 return (app_id == kPinnedAppsPlaceholder); | |
| 501 }), | |
| 502 legacy_pins.end()); | |
|
stevenjb
2016/06/10 18:00:41
We are already iterating over legacy_pins below, w
khmel
2016/06/10 22:08:10
Done.
Refactored GetPinnedAppsFromPrefsLegacy not
| |
| 503 DCHECK(!legacy_pins.empty()); | |
| 504 | |
| 505 syncer::StringOrdinal last_position; | |
| 506 // Convert to sync item record. | |
| 507 for (const auto& app_id : legacy_pins) { | |
| 508 last_position = last_position.IsValid() | |
| 509 ? last_position.CreateAfter() | |
| 510 : syncer::StringOrdinal::CreateInitialOrdinal(); | |
|
stevenjb
2016/06/10 18:00:40
nit: Just initialize last_position to syncer::Stri
khmel
2016/06/10 22:08:11
That is nicer, thanks
| |
| 511 const bool pin_by_policy = | |
| 512 std::find(policy_apps.begin(), policy_apps.end(), app_id) != | |
| 513 policy_apps.end(); | |
|
stevenjb
2016/06/10 18:00:41
This will also avoid an N^2 operation if policy_ap
khmel
2016/06/10 22:08:10
Done.
| |
| 514 app_service->SetPinPosition(app_id, last_position, pin_by_policy); | |
| 515 } | |
| 516 | |
| 517 // Now process default apps. | |
| 518 for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i) { | |
| 519 const std::string& app_id = kDefaultPinnedApps[i]; | |
| 520 // Check if it is already imported. | |
| 521 if (app_service->GetPinPosition(app_id).IsValid()) | |
| 522 continue; | |
| 523 // Check if it is present but not in legacy pin. | |
| 524 if (helper->IsValidIDForCurrentUser(app_id)) | |
| 525 continue; | |
| 526 DCHECK(last_position.IsValid()); | |
|
stevenjb
2016/06/10 18:00:41
Just check this once above.
khmel
2016/06/10 22:08:10
Done.
| |
| 527 last_position = last_position.CreateAfter(); | |
| 528 app_service->SetPinPosition(app_id, last_position, false); | |
| 529 } | |
| 530 | |
| 531 return legacy_pins; | |
| 532 } | |
| 533 | |
| 534 // Sort pins according its ordinals. | |
|
stevenjb
2016/06/10 18:00:40
s/its/their/
khmel
2016/06/10 22:08:10
Done.
| |
| 535 std::sort(pin_infos.begin(), pin_infos.end(), ComparePinInfo()); | |
| 536 | |
| 537 // Now insert Chrome browser app if needed. | |
| 538 syncer::StringOrdinal chrome_position = | |
| 539 app_service->GetPinPosition(extension_misc::kChromeAppId); | |
| 540 if (!chrome_position.IsValid()) { | |
| 541 chrome_position = CreateFirstPinPosition(helper->profile()); | |
| 542 pin_infos.insert(pin_infos.begin(), | |
| 543 PinInfo(extension_misc::kChromeAppId, chrome_position)); | |
| 544 app_service->SetPinPosition(extension_misc::kChromeAppId, chrome_position, | |
| 545 false); | |
| 546 } | |
| 547 | |
| 548 // Policy apps must preserve order of appearance and be first app in the list. | |
| 549 // Validate that there have correct position and fix if needed. | |
|
stevenjb
2016/06/10 18:00:40
s/there have correct/they have a correct/
khmel
2016/06/10 22:08:10
Done.
khmel
2016/06/10 22:08:11
Done.
| |
| 550 size_t shelf_index = 0; | |
| 551 for (const auto& app_id : policy_apps) { | |
| 552 if (app_id == kPinnedAppsPlaceholder) | |
| 553 continue; | |
| 554 if (app_id == extension_misc::kChromeAppId) | |
| 555 continue; | |
| 556 | |
| 557 // Chrome browser app has right to appear between pinned by policy apps. | |
| 558 if (shelf_index < pin_infos.size() && | |
| 559 pin_infos[shelf_index].app_id == extension_misc::kChromeAppId) { | |
| 560 ++shelf_index; | |
| 561 } | |
| 562 | |
| 563 const bool need_position_item = shelf_index >= pin_infos.size() || | |
| 564 app_id != pin_infos[shelf_index].app_id; | |
| 565 if (need_position_item) { | |
| 566 // Remove existing app that breaks the order from the list. | |
| 567 if (shelf_index < pin_infos.size()) { | |
| 568 pin_infos.erase( | |
| 569 std::remove_if(pin_infos.begin() + shelf_index + 1, pin_infos.end(), | |
| 570 [app_id](const PinInfo& pin_info) { | |
| 571 return (pin_info.app_id == app_id); | |
| 572 }), | |
| 573 pin_infos.end()); | |
| 574 } | |
| 575 | |
| 576 syncer::StringOrdinal new_shelf_ordinal; | |
| 577 if (shelf_index == 0) { | |
| 578 // First app. | |
| 579 new_shelf_ordinal = pin_infos.empty() | |
| 580 ? syncer::StringOrdinal::CreateInitialOrdinal() | |
| 581 : pin_infos.front().item_ordinal.CreateBefore(); | |
| 582 } else if (shelf_index == pin_infos.size()) { | |
| 583 new_shelf_ordinal = pin_infos.back().item_ordinal.CreateAfter(); | |
| 584 } else { | |
| 585 new_shelf_ordinal = | |
| 586 pin_infos[shelf_index - 1].item_ordinal.CreateBetween( | |
| 587 pin_infos[shelf_index].item_ordinal); | |
| 588 } | |
| 589 pin_infos.insert(pin_infos.begin() + shelf_index, | |
| 590 PinInfo(app_id, new_shelf_ordinal)); | |
| 591 const bool pin_by_policy = | |
| 592 !app_service->GetPinPosition(app_id).IsValid() || | |
| 593 app_service->GetPinByPolicy(app_id); | |
| 594 app_service->SetPinPosition(app_id, new_shelf_ordinal, pin_by_policy); | |
| 595 } | |
| 596 ++shelf_index; | |
| 597 } | |
| 598 | |
| 599 if (arc::ArcAuthService::IsAllowedForProfile(helper->profile()) && | |
| 600 helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) { | |
| 601 if (!app_service->GetSyncItem(ArcSupportHost::kHostAppId)) { | |
| 602 const syncer::StringOrdinal arc_host_position = | |
| 603 CreateLastPinPosition(helper->profile()); | |
| 604 pin_infos.insert(pin_infos.begin(), | |
| 605 PinInfo(ArcSupportHost::kHostAppId, arc_host_position)); | |
| 606 app_service->SetPinPosition(ArcSupportHost::kHostAppId, arc_host_position, | |
| 607 false); | |
| 608 } | |
| 609 } | |
| 610 | |
| 611 // Convert to string array. | |
| 612 std::vector<std::string> pins(pin_infos.size()); | |
| 613 for (size_t i = 0; i < pin_infos.size(); ++i) | |
| 614 pins[i] = pin_infos[i].app_id; | |
| 615 | |
| 616 return pins; | |
| 617 } | |
| 618 | |
| 619 void RemovePinPosition(Profile* profile, const std::string& app_id) { | |
| 620 DCHECK(profile); | |
| 621 DCHECK(!app_id.empty()); | |
| 622 app_list::AppListSyncableService* app_service = | |
| 623 app_list::AppListSyncableService::Get(profile); | |
| 624 app_service->SetPinPosition(app_id, syncer::StringOrdinal(), false); | |
| 625 } | |
| 626 | |
| 627 void SetPinPosition(Profile* profile, | |
| 628 const std::string& app_id, | |
| 629 const std::string& app_id_before, | |
| 630 const std::string& app_id_after) { | |
| 631 DCHECK(profile); | |
| 632 DCHECK(!app_id.empty()); | |
| 633 DCHECK_NE(app_id, app_id_before); | |
| 634 DCHECK_NE(app_id, app_id_after); | |
| 635 DCHECK(app_id_before.empty() || app_id_before != app_id_after); | |
| 636 | |
| 637 app_list::AppListSyncableService* app_service = | |
| 638 app_list::AppListSyncableService::Get(profile); | |
| 639 // Some unit tests may not have this service. | |
| 640 if (!app_service) | |
| 641 return; | |
| 642 | |
| 643 syncer::StringOrdinal position_before = | |
| 644 app_id_before.empty() ? syncer::StringOrdinal() | |
| 645 : app_service->GetPinPosition(app_id_before); | |
| 646 syncer::StringOrdinal position_after = | |
| 647 app_id_after.empty() ? syncer::StringOrdinal() | |
| 648 : app_service->GetPinPosition(app_id_after); | |
| 649 | |
| 650 syncer::StringOrdinal pin_position; | |
| 651 if (position_before.IsValid() && position_after.IsValid()) | |
| 652 pin_position = position_before.CreateBetween(position_after); | |
| 653 else if (position_before.IsValid()) | |
| 654 pin_position = position_before.CreateAfter(); | |
| 655 else if (position_after.IsValid()) | |
| 656 pin_position = position_after.CreateBefore(); | |
| 657 else | |
| 658 pin_position = syncer::StringOrdinal::CreateInitialOrdinal(); | |
| 659 app_service->SetPinPosition(app_id, pin_position, false); | |
| 660 } | |
| 661 | |
| 388 } // namespace ash | 662 } // namespace ash |
| OLD | NEW |