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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/launcher/chrome_launcher_controller_impl.h" 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "ash/wm/window_util.h" 21 #include "ash/wm/window_util.h"
22 #include "base/command_line.h" 22 #include "base/command_line.h"
23 #include "base/macros.h" 23 #include "base/macros.h"
24 #include "base/strings/pattern.h" 24 #include "base/strings/pattern.h"
25 #include "base/strings/string_util.h" 25 #include "base/strings/string_util.h"
26 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
27 #include "base/values.h" 27 #include "base/values.h"
28 #include "build/build_config.h" 28 #include "build/build_config.h"
29 #include "chrome/browser/browser_process.h" 29 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/chrome_notification_types.h" 30 #include "chrome/browser/chrome_notification_types.h"
31 #include "chrome/browser/chromeos/arc/arc_support_host.h"
32 #include "chrome/browser/defaults.h" 31 #include "chrome/browser/defaults.h"
33 #include "chrome/browser/extensions/extension_app_icon_loader.h" 32 #include "chrome/browser/extensions/extension_app_icon_loader.h"
34 #include "chrome/browser/extensions/extension_util.h" 33 #include "chrome/browser/extensions/extension_util.h"
35 #include "chrome/browser/extensions/launch_util.h" 34 #include "chrome/browser/extensions/launch_util.h"
36 #include "chrome/browser/prefs/incognito_mode_prefs.h" 35 #include "chrome/browser/prefs/incognito_mode_prefs.h"
37 #include "chrome/browser/profiles/profile.h" 36 #include "chrome/browser/profiles/profile.h"
38 #include "chrome/browser/profiles/profile_manager.h" 37 #include "chrome/browser/profiles/profile_manager.h"
38 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
39 #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" 39 #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h"
40 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" 40 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
41 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" 41 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
42 #include "chrome/browser/ui/ash/app_sync_ui_state.h" 42 #include "chrome/browser/ui/ash/app_sync_ui_state.h"
43 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" 43 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
44 #include "chrome/browser/ui/ash/chrome_shell_delegate.h" 44 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
45 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h " 45 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h "
46 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h" 46 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h"
47 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h" 47 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h"
48 #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h" 48 #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 109
110 int64_t GetDisplayIDForShelf(ash::Shelf* shelf) { 110 int64_t GetDisplayIDForShelf(ash::Shelf* shelf) {
111 aura::Window* root_window = 111 aura::Window* root_window =
112 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); 112 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow();
113 display::Display display = 113 display::Display display =
114 display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); 114 display::Screen::GetScreen()->GetDisplayNearestWindow(root_window);
115 DCHECK(display.is_valid()); 115 DCHECK(display.is_valid());
116 return display.id(); 116 return display.id();
117 } 117 }
118 118
119 /*
120 * Return whether an app is pinned only by user.
121 * This function doesn't expect an app_id neither pinned by user nor by
122 * policy, the app_id in the arguments list MUST be pinned by either of
123 * those. Invalid input may lead to unexpected result.
124 * If this app is pinned by policy, but not by user, false is returned.
125 * If this app is pinned by both policy and user, false is returned.
126 * If this app is pinned not by policy, but by user, true is returned.
127 */
128 bool IsAppForUserPinned(const std::string& app_id,
129 const base::ListValue* pinned_apps_pref,
130 const base::ListValue* policy_pinned_apps_pref) {
131 for (size_t index = 0; index < pinned_apps_pref->GetSize(); ++index) {
132 const base::DictionaryValue* app;
133 if (pinned_apps_pref->GetDictionary(index, &app)) {
134 std::string current_app_id;
135 bool pinned_by_policy = false;
136 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, &current_app_id)) {
137 if (app_id == current_app_id) {
138 if (app->GetBoolean(ash::kPinnedAppsPrefPinnedByPolicy,
139 &pinned_by_policy) &&
140 pinned_by_policy) {
141 // Pinned by policy in the past or present.
142 // Need to check policy_pinned_apps to determine
143 break;
144 } else {
145 // User Preference Already Pinned
146 return true;
147 }
148 }
149 }
150 }
151 }
152 for (size_t index = 0; index < policy_pinned_apps_pref->GetSize(); ++index) {
153 const base::DictionaryValue* app;
154 if (policy_pinned_apps_pref->GetDictionary(index, &app)) {
155 std::string app_id_;
156 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id_)) {
157 // Only pinned by policy, which is not part of user-pinned
158 if (app_id == app_id_)
159 return false;
160 }
161 }
162 }
163 // Default, user added new pins
164 return true;
165 }
166
167 const char* const kPinProhibitedExtensionIds[] = {
168 ArcSupportHost::kHostAppId, arc::kPlayStoreAppId,
169 };
170
171 const size_t kPinProhibitedExtensionIdsLength =
172 arraysize(kPinProhibitedExtensionIds);
173
174 } // namespace 119 } // namespace
175 120
176 // A class to get events from ChromeOS when a user gets changed or added. 121 // A class to get events from ChromeOS when a user gets changed or added.
177 class ChromeLauncherControllerUserSwitchObserver 122 class ChromeLauncherControllerUserSwitchObserver
178 : public user_manager::UserManager::UserSessionStateObserver { 123 : public user_manager::UserManager::UserSessionStateObserver {
179 public: 124 public:
180 ChromeLauncherControllerUserSwitchObserver( 125 ChromeLauncherControllerUserSwitchObserver(
181 ChromeLauncherControllerImpl* controller) 126 ChromeLauncherControllerImpl* controller)
182 : controller_(controller) { 127 : controller_(controller) {
183 DCHECK(user_manager::UserManager::IsInitialized()); 128 DCHECK(user_manager::UserManager::IsInitialized());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) { 183 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) {
239 if (chrome::MultiUserWindowManager::GetMultiProfileMode() == 184 if (chrome::MultiUserWindowManager::GetMultiProfileMode() ==
240 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) 185 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED)
241 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile); 186 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
242 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile()); 187 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile());
243 } 188 }
244 189
245 ChromeLauncherControllerImpl::ChromeLauncherControllerImpl( 190 ChromeLauncherControllerImpl::ChromeLauncherControllerImpl(
246 Profile* profile, 191 Profile* profile,
247 ash::ShelfModel* model) 192 ash::ShelfModel* model)
248 : model_(model), 193 : model_(model), profile_(profile) {
249 item_delegate_manager_(NULL),
250 profile_(profile),
251 app_sync_ui_state_(NULL),
252 ignore_persist_pinned_state_change_(false) {
253 if (!profile_) { 194 if (!profile_) {
254 // If no profile was passed, we take the currently active profile and use it 195 // If no profile was passed, we take the currently active profile and use it
255 // as the owner of the current desktop. 196 // as the owner of the current desktop.
256 // Use the original profile as on chromeos we may get a temporary off the 197 // Use the original profile as on chromeos we may get a temporary off the
257 // record profile, unless in guest session (where off the record profile is 198 // record profile, unless in guest session (where off the record profile is
258 // the right one). 199 // the right one).
259 profile_ = ProfileManager::GetActiveUserProfile(); 200 profile_ = ProfileManager::GetActiveUserProfile();
260 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile()) 201 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile())
261 profile_ = profile_->GetOriginalProfile(); 202 profile_ = profile_->GetOriginalProfile();
262 203
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 309
369 void ChromeLauncherControllerImpl::Init() { 310 void ChromeLauncherControllerImpl::Init() {
370 CreateBrowserShortcutLauncherItem(); 311 CreateBrowserShortcutLauncherItem();
371 UpdateAppLaunchersFromPref(); 312 UpdateAppLaunchersFromPref();
372 313
373 // TODO(sky): update unit test so that this test isn't necessary. 314 // TODO(sky): update unit test so that this test isn't necessary.
374 if (ash::Shell::HasInstance()) 315 if (ash::Shell::HasInstance())
375 SetVirtualKeyboardBehaviorFromPrefs(); 316 SetVirtualKeyboardBehaviorFromPrefs();
376 317
377 prefs_observer_ = 318 prefs_observer_ =
378 ash::ChromeLauncherPrefsObserver::CreateIfNecessary(profile_); 319 ash::launcher::ChromeLauncherPrefsObserver::CreateIfNecessary(profile_);
379 } 320 }
380 321
381 ash::ShelfID ChromeLauncherControllerImpl::CreateAppLauncherItem( 322 ash::ShelfID ChromeLauncherControllerImpl::CreateAppLauncherItem(
382 LauncherItemController* controller, 323 LauncherItemController* controller,
383 const std::string& app_id, 324 const std::string& app_id,
384 ash::ShelfItemStatus status) { 325 ash::ShelfItemStatus status) {
385 CHECK(controller); 326 CHECK(controller);
386 int index = 0; 327 int index = 0;
387 // Panels are inserted on the left so as not to push all existing panels over. 328 // Panels are inserted on the left so as not to push all existing panels over.
388 if (controller->GetShelfItemType() != ash::TYPE_APP_PANEL) 329 if (controller->GetShelfItemType() != ash::TYPE_APP_PANEL)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 ash::ShelfItem item = model_->items()[index]; 383 ash::ShelfItem item = model_->items()[index];
443 384
444 if (item.type == ash::TYPE_PLATFORM_APP || 385 if (item.type == ash::TYPE_PLATFORM_APP ||
445 item.type == ash::TYPE_WINDOWED_APP) { 386 item.type == ash::TYPE_WINDOWED_APP) {
446 item.type = ash::TYPE_APP_SHORTCUT; 387 item.type = ash::TYPE_APP_SHORTCUT;
447 model_->Set(index, item); 388 model_->Set(index, item);
448 } else if (item.type != ash::TYPE_APP_SHORTCUT) { 389 } else if (item.type != ash::TYPE_APP_SHORTCUT) {
449 return; 390 return;
450 } 391 }
451 392
452 if (GetLauncherItemController(id)->CanPin()) 393 SyncPinPosition(id);
453 PersistPinnedState();
454 } 394 }
455 395
456 void ChromeLauncherControllerImpl::Unpin(ash::ShelfID id) { 396 void ChromeLauncherControllerImpl::Unpin(ash::ShelfID id) {
457 LauncherItemController* controller = GetLauncherItemController(id); 397 LauncherItemController* controller = GetLauncherItemController(id);
458 CHECK(controller); 398 CHECK(controller);
459 const bool can_pin = controller->CanPin(); 399
400 ash::launcher::RemovePinPosition(profile_, GetAppIDForShelfID(id));
460 401
461 if (controller->type() == LauncherItemController::TYPE_APP || 402 if (controller->type() == LauncherItemController::TYPE_APP ||
462 controller->locked()) { 403 controller->locked()) {
463 UnpinRunningAppInternal(model_->ItemIndexByID(id)); 404 UnpinRunningAppInternal(model_->ItemIndexByID(id));
464 } else { 405 } else {
465 LauncherItemClosed(id); 406 LauncherItemClosed(id);
466 } 407 }
467 if (can_pin)
468 PersistPinnedState();
469 } 408 }
470 409
471 bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) { 410 bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) {
472 int index = model_->ItemIndexByID(id); 411 int index = model_->ItemIndexByID(id);
473 if (index < 0) 412 if (index < 0)
474 return false; 413 return false;
475 ash::ShelfItemType type = model_->items()[index].type; 414 ash::ShelfItemType type = model_->items()[index].type;
476 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT); 415 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT);
477 } 416 }
478 417
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 void ChromeLauncherControllerImpl::SetLaunchType( 554 void ChromeLauncherControllerImpl::SetLaunchType(
616 ash::ShelfID id, 555 ash::ShelfID id,
617 extensions::LaunchType launch_type) { 556 extensions::LaunchType launch_type) {
618 LauncherItemController* controller = GetLauncherItemController(id); 557 LauncherItemController* controller = GetLauncherItemController(id);
619 if (!controller) 558 if (!controller)
620 return; 559 return;
621 560
622 extensions::SetLaunchType(profile_, controller->app_id(), launch_type); 561 extensions::SetLaunchType(profile_, controller->app_id(), launch_type);
623 } 562 }
624 563
625 void ChromeLauncherControllerImpl::PersistPinnedState() {
626 if (ignore_persist_pinned_state_change_)
627 return;
628 // It is a coding error to call PersistPinnedState() if the pinned apps are
629 // not user-editable. The code should check earlier and not perform any
630 // modification actions that trigger persisting the state.
631 // Mutating kPinnedLauncherApps is going to notify us and trigger us to
632 // process the change. We don't want that to happen so remove ourselves as a
633 // listener.
634 pref_change_registrar_.Remove(prefs::kPinnedLauncherApps);
635 {
636 std::unique_ptr<const base::ListValue> pinned_apps_pref =
637 profile_->GetPrefs()
638 ->GetList(prefs::kPinnedLauncherApps)
639 ->CreateDeepCopy();
640
641 const base::ListValue* policy_pinned_apps_pref =
642 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps);
643
644 ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps);
645 updater->Clear();
646 for (size_t i = 0; i < model_->items().size(); ++i) {
647 if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) {
648 ash::ShelfID id = model_->items()[i].id;
649 LauncherItemController* controller = GetLauncherItemController(id);
650 // Don't persist pinning state for apps that are handled internally and
651 // have pinnable state AppListControllerDelegate::NO_PIN.
652 if (controller && IsPinned(id) &&
653 GetPinnable(controller->app_id()) !=
654 AppListControllerDelegate::NO_PIN) {
655 base::DictionaryValue* app_value =
656 ash::CreateAppDict(controller->app_id());
657 if (app_value) {
658 if (!IsAppForUserPinned(controller->app_id(),
659 pinned_apps_pref.get(),
660 policy_pinned_apps_pref))
661 app_value->SetBoolean(ash::kPinnedAppsPrefPinnedByPolicy, true);
662 updater->Append(app_value);
663 }
664 }
665 } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) {
666 PersistChromeItemIndex(i);
667 } else if (model_->items()[i].type == ash::TYPE_APP_LIST) {
668 base::DictionaryValue* app_value =
669 ash::CreateAppDict(ash::kPinnedAppsPlaceholder);
670 if (app_value)
671 updater->Append(app_value);
672 }
673 }
674 }
675 pref_change_registrar_.Add(
676 prefs::kPinnedLauncherApps,
677 base::Bind(&ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref,
678 base::Unretained(this)));
679 }
680
681 Profile* ChromeLauncherControllerImpl::GetProfile() { 564 Profile* ChromeLauncherControllerImpl::GetProfile() {
682 return profile_; 565 return profile_;
683 } 566 }
684 567
685 void ChromeLauncherControllerImpl::UpdateAppState( 568 void ChromeLauncherControllerImpl::UpdateAppState(
686 content::WebContents* contents, 569 content::WebContents* contents,
687 AppState app_state) { 570 AppState app_state) {
688 std::string app_id = launcher_controller_helper_->GetAppID(contents); 571 std::string app_id = launcher_controller_helper_->GetAppID(contents);
689 572
690 // Check if the gMail app is loaded and it matches the given content. 573 // Check if the gMail app is loaded and it matches the given content.
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 AccountId::FromUserEmail(user_id)); 853 AccountId::FromUserEmail(user_id));
971 if (other_profile == profile_) 854 if (other_profile == profile_)
972 return false; 855 return false;
973 856
974 // Note: The Auto hide state from preferences is not the same as the actual 857 // Note: The Auto hide state from preferences is not the same as the actual
975 // visibility of the shelf. Depending on all the various states (full screen, 858 // visibility of the shelf. Depending on all the various states (full screen,
976 // no window on desktop, multi user, ..) the shelf could be shown - or not. 859 // no window on desktop, multi user, ..) the shelf could be shown - or not.
977 PrefService* prefs = profile_->GetPrefs(); 860 PrefService* prefs = profile_->GetPrefs();
978 PrefService* other_prefs = other_profile->GetPrefs(); 861 PrefService* other_prefs = other_profile->GetPrefs();
979 const int64_t display = GetDisplayIDForShelf(shelf); 862 const int64_t display = GetDisplayIDForShelf(shelf);
980 bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == 863 const bool currently_shown =
981 ash::GetShelfAutoHideBehaviorPref(prefs, display); 864 ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER ==
982 bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == 865 ash::launcher::GetShelfAutoHideBehaviorPref(prefs, display);
983 ash::GetShelfAutoHideBehaviorPref(other_prefs, display); 866 const bool other_shown =
867 ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER ==
868 ash::launcher::GetShelfAutoHideBehaviorPref(other_prefs, display);
984 869
985 return currently_shown != other_shown || 870 return currently_shown != other_shown ||
986 ash::GetShelfAlignmentPref(prefs, display) != 871 ash::launcher::GetShelfAlignmentPref(prefs, display) !=
987 ash::GetShelfAlignmentPref(other_prefs, display); 872 ash::launcher::GetShelfAlignmentPref(other_prefs, display);
988 } 873 }
989 874
990 void ChromeLauncherControllerImpl::OnUserProfileReadyToSwitch( 875 void ChromeLauncherControllerImpl::OnUserProfileReadyToSwitch(
991 Profile* profile) { 876 Profile* profile) {
992 if (user_switch_observer_.get()) 877 if (user_switch_observer_.get())
993 user_switch_observer_->OnUserProfileReadyToSwitch(profile); 878 user_switch_observer_->OnUserProfileReadyToSwitch(profile);
994 } 879 }
995 880
996 AppListControllerDelegate::Pinnable ChromeLauncherControllerImpl::GetPinnable( 881 AppListControllerDelegate::Pinnable ChromeLauncherControllerImpl::GetPinnable(
997 const std::string& app_id) { 882 const std::string& app_id) {
998 for (size_t i = 0; i < kPinProhibitedExtensionIdsLength; ++i) {
999 if (kPinProhibitedExtensionIds[i] == app_id)
1000 return AppListControllerDelegate::NO_PIN;
1001 }
1002
1003 const base::ListValue* pref = 883 const base::ListValue* pref =
1004 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps); 884 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps);
1005 if (!pref) 885 if (!pref)
1006 return AppListControllerDelegate::PIN_EDITABLE; 886 return AppListControllerDelegate::PIN_EDITABLE;
1007 887
1008 // Pinned ARC apps policy defines the package name of the apps, that must 888 // Pinned ARC apps policy defines the package name of the apps, that must
1009 // be pinned. All the launch activities of any package in policy are pinned. 889 // be pinned. All the launch activities of any package in policy are pinned.
1010 // In turn the input parameter to this function is app_id, which 890 // In turn the input parameter to this function is app_id, which
1011 // is 32 chars hash. In case of ARC app this is a hash of 891 // is 32 chars hash. In case of ARC app this is a hash of
1012 // (package name + activity). This means that we must identify the package 892 // (package name + activity). This means that we must identify the package
1013 // from the hash, and check if this package is pinned by policy. 893 // from the hash, and check if this package is pinned by policy.
1014 const ArcAppListPrefs* const arc_prefs = ArcAppListPrefs::Get(GetProfile()); 894 const ArcAppListPrefs* const arc_prefs = ArcAppListPrefs::Get(GetProfile());
1015 std::string arc_app_packege_name; 895 std::string arc_app_packege_name;
1016 if (arc_prefs) { 896 if (arc_prefs) {
1017 std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = 897 std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
1018 arc_prefs->GetApp(app_id); 898 arc_prefs->GetApp(app_id);
1019 if (app_info) 899 if (app_info)
1020 arc_app_packege_name = app_info->package_name; 900 arc_app_packege_name = app_info->package_name;
1021 } 901 }
1022 902
1023 for (size_t index = 0; index < pref->GetSize(); ++index) { 903 for (size_t index = 0; index < pref->GetSize(); ++index) {
1024 const base::DictionaryValue* app = nullptr; 904 const base::DictionaryValue* app = nullptr;
1025 std::string app_id_or_package; 905 std::string app_id_or_package;
1026 if (pref->GetDictionary(index, &app) && 906 if (pref->GetDictionary(index, &app) &&
1027 app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id_or_package) && 907 app->GetString(ash::launcher::kPinnedAppsPrefAppIDPath,
908 &app_id_or_package) &&
1028 (app_id == app_id_or_package || 909 (app_id == app_id_or_package ||
1029 arc_app_packege_name == app_id_or_package)) { 910 arc_app_packege_name == app_id_or_package)) {
1030 return AppListControllerDelegate::PIN_FIXED; 911 return AppListControllerDelegate::PIN_FIXED;
1031 } 912 }
1032 } 913 }
1033 return AppListControllerDelegate::PIN_EDITABLE; 914 return AppListControllerDelegate::PIN_EDITABLE;
1034 } 915 }
1035 916
1036 ArcAppDeferredLauncherController* 917 ArcAppDeferredLauncherController*
1037 ChromeLauncherControllerImpl::GetArcDeferredLauncher() { 918 ChromeLauncherControllerImpl::GetArcDeferredLauncher() {
1038 return arc_deferred_launcher_.get(); 919 return arc_deferred_launcher_.get();
1039 } 920 }
1040 921
1041 /////////////////////////////////////////////////////////////////////////////// 922 ///////////////////////////////////////////////////////////////////////////////
1042 // ash::ShelfDelegate: 923 // ash::ShelfDelegate:
1043 924
1044 void ChromeLauncherControllerImpl::OnShelfCreated(ash::Shelf* shelf) { 925 void ChromeLauncherControllerImpl::OnShelfCreated(ash::Shelf* shelf) {
1045 PrefService* prefs = profile_->GetPrefs(); 926 PrefService* prefs = profile_->GetPrefs();
1046 const int64_t display = GetDisplayIDForShelf(shelf); 927 const int64_t display = GetDisplayIDForShelf(shelf);
1047 928
1048 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref(prefs, display)); 929 shelf->SetAutoHideBehavior(
930 ash::launcher::GetShelfAutoHideBehaviorPref(prefs, display));
1049 931
1050 if (ash::ShelfWidget::ShelfAlignmentAllowed()) 932 if (ash::ShelfWidget::ShelfAlignmentAllowed())
1051 shelf->SetAlignment(ash::GetShelfAlignmentPref(prefs, display)); 933 shelf->SetAlignment(ash::launcher::GetShelfAlignmentPref(prefs, display));
1052 } 934 }
1053 935
1054 void ChromeLauncherControllerImpl::OnShelfDestroyed(ash::Shelf* shelf) {} 936 void ChromeLauncherControllerImpl::OnShelfDestroyed(ash::Shelf* shelf) {}
1055 937
1056 void ChromeLauncherControllerImpl::OnShelfAlignmentChanged(ash::Shelf* shelf) { 938 void ChromeLauncherControllerImpl::OnShelfAlignmentChanged(ash::Shelf* shelf) {
1057 ash::SetShelfAlignmentPref(profile_->GetPrefs(), GetDisplayIDForShelf(shelf), 939 ash::launcher::SetShelfAlignmentPref(
1058 shelf->alignment()); 940 profile_->GetPrefs(), GetDisplayIDForShelf(shelf), shelf->alignment());
1059 } 941 }
1060 942
1061 void ChromeLauncherControllerImpl::OnShelfAutoHideBehaviorChanged( 943 void ChromeLauncherControllerImpl::OnShelfAutoHideBehaviorChanged(
1062 ash::Shelf* shelf) { 944 ash::Shelf* shelf) {
1063 ash::SetShelfAutoHideBehaviorPref(profile_->GetPrefs(), 945 ash::launcher::SetShelfAutoHideBehaviorPref(profile_->GetPrefs(),
1064 GetDisplayIDForShelf(shelf), 946 GetDisplayIDForShelf(shelf),
1065 shelf->auto_hide_behavior()); 947 shelf->auto_hide_behavior());
1066 } 948 }
1067 949
1068 void ChromeLauncherControllerImpl::OnShelfAutoHideStateChanged( 950 void ChromeLauncherControllerImpl::OnShelfAutoHideStateChanged(
1069 ash::Shelf* shelf) {} 951 ash::Shelf* shelf) {}
1070 952
1071 void ChromeLauncherControllerImpl::OnShelfVisibilityStateChanged( 953 void ChromeLauncherControllerImpl::OnShelfVisibilityStateChanged(
1072 ash::Shelf* shelf) {} 954 ash::Shelf* shelf) {}
1073 955
1074 ash::ShelfID ChromeLauncherControllerImpl::GetShelfIDForAppID( 956 ash::ShelfID ChromeLauncherControllerImpl::GetShelfIDForAppID(
1075 const std::string& app_id) { 957 const std::string& app_id) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 if (IsAppPinned(app_id)) 1157 if (IsAppPinned(app_id))
1276 return; 1158 return;
1277 1159
1278 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); 1160 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id);
1279 if (shelf_id) { 1161 if (shelf_id) {
1280 // App item exists, pin it 1162 // App item exists, pin it
1281 Pin(shelf_id); 1163 Pin(shelf_id);
1282 } else { 1164 } else {
1283 // Otherwise, create a shortcut item for it. 1165 // Otherwise, create a shortcut item for it.
1284 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count()); 1166 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count());
1285 if (GetPinnable(app_id) == AppListControllerDelegate::PIN_EDITABLE) 1167 SyncPinPosition(shelf_id);
1286 PersistPinnedState();
1287 } 1168 }
1288 } 1169 }
1289 1170
1290 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id) { 1171 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id) {
1291 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); 1172 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id);
1292 if (shelf_id && IsPinned(shelf_id)) 1173 if (shelf_id && IsPinned(shelf_id))
1293 Unpin(shelf_id); 1174 Unpin(shelf_id);
1294 } 1175 }
1295 1176
1296 int ChromeLauncherControllerImpl::PinRunningAppInternal(int index, 1177 int ChromeLauncherControllerImpl::PinRunningAppInternal(int index,
(...skipping 20 matching lines...) Expand all
1317 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); 1198 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT);
1318 item.type = ash::TYPE_WINDOWED_APP; 1199 item.type = ash::TYPE_WINDOWED_APP;
1319 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such 1200 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such
1320 // we have to check here what this was before it got a shortcut. 1201 // we have to check here what this was before it got a shortcut.
1321 LauncherItemController* controller = GetLauncherItemController(item.id); 1202 LauncherItemController* controller = GetLauncherItemController(item.id);
1322 if (controller && controller->type() == LauncherItemController::TYPE_APP) 1203 if (controller && controller->type() == LauncherItemController::TYPE_APP)
1323 item.type = ash::TYPE_PLATFORM_APP; 1204 item.type = ash::TYPE_PLATFORM_APP;
1324 model_->Set(index, item); 1205 model_->Set(index, item);
1325 } 1206 }
1326 1207
1208 void ChromeLauncherControllerImpl::SyncPinPosition(ash::ShelfID shelf_id) {
1209 DCHECK(shelf_id);
1210 if (ignore_persist_pinned_state_change_)
1211 return;
1212
1213 const int max_index = model_->item_count();
1214 const int index = model_->ItemIndexByID(shelf_id);
1215 DCHECK_GT(index, 0);
1216
1217 const std::string& app_id = GetAppIDForShelfID(shelf_id);
1218 DCHECK(!app_id.empty());
1219
1220 std::string app_id_before;
1221 std::string app_id_after;
1222
1223 for (int i = index - 1; i > 0; --i) {
1224 const ash::ShelfID shelf_id_before = model_->items()[i].id;
1225 if (IsPinned(shelf_id_before)) {
1226 app_id_before = GetAppIDForShelfID(shelf_id_before);
1227 DCHECK(!app_id_before.empty());
1228 break;
1229 }
1230 }
1231
1232 for (int i = index + 1; i < max_index; ++i) {
1233 const ash::ShelfID shelf_id_after = model_->items()[i].id;
1234 if (IsPinned(shelf_id_after)) {
1235 app_id_after = GetAppIDForShelfID(shelf_id_after);
1236 DCHECK(!app_id_after.empty());
1237 break;
1238 }
1239 }
1240
1241 ash::launcher::SetPinPosition(profile_, app_id, app_id_before, app_id_after);
1242 }
1243
1244 void ChromeLauncherControllerImpl::OnSyncModelUpdated() {
1245 UpdateAppLaunchersFromPref();
1246 }
1247
1327 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { 1248 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() {
1328 // There are various functions which will trigger a |PersistPinnedState| call 1249 // There are various functions which will trigger a |SyncPinPosition| call
1329 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu 1250 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu
1330 // model which will use weights to re-arrange the icons to new positions. 1251 // model which will use weights to re-arrange the icons to new positions.
1331 // Since this function is meant to synchronize the "is state" with the 1252 // Since this function is meant to synchronize the "is state" with the
1332 // "sync state", it makes no sense to store any changes by this function back 1253 // "sync state", it makes no sense to store any changes by this function back
1333 // into the pref state. Therefore we tell |persistPinnedState| to ignore any 1254 // into the pref state. Therefore we tell |persistPinnedState| to ignore any
1334 // invocations while we are running. 1255 // invocations while we are running.
1335 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); 1256 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
1336 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs( 1257 std::vector<std::string> pinned_apps = ash::launcher::GetPinnedAppsFromPrefs(
1337 profile_->GetPrefs(), launcher_controller_helper_.get()); 1258 profile_->GetPrefs(), launcher_controller_helper_.get());
1338 1259
1339 int index = 0; 1260 int index = 0;
1340 int max_index = model_->item_count(); 1261 int max_index = model_->item_count();
1262 int seen_chrome_index = -1;
1341 1263
1342 // When one of the two special items cannot be moved (and we do not know where 1264 // At least chrome browser shortcut should exist.
1343 // yet), we remember the current location in one of these variables. 1265 DCHECK_GT(max_index, 0);
1344 int chrome_index = -1; 1266
1345 int app_list_index = -1; 1267 // Skip app list items if it exists.
1268 if (model_->items()[0].type == ash::TYPE_APP_LIST)
1269 ++index;
1346 1270
1347 // Walk the model and |pinned_apps| from the pref lockstep, adding and 1271 // Walk the model and |pinned_apps| from the pref lockstep, adding and
1348 // removing items as necessary. NB: This code uses plain old indexing instead 1272 // removing items as necessary. NB: This code uses plain old indexing instead
1349 // of iterators because of model mutations as part of the loop. 1273 // of iterators because of model mutations as part of the loop.
1350 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); 1274 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
1351 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { 1275 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) {
1352 // Check if we have an item which we need to handle. 1276 // Check if we have an item which we need to handle.
1353 if (*pref_app_id == extension_misc::kChromeAppId || 1277 if (IsAppPinned(*pref_app_id)) {
1354 *pref_app_id == ash::kPinnedAppsPlaceholder || 1278 if (seen_chrome_index >= 0 &&
1355 IsAppPinned(*pref_app_id)) { 1279 *pref_app_id == extension_misc::kChromeAppId) {
1280 // Current item is Chrome browser and we saw it before.
1281 model_->Move(seen_chrome_index, index);
1282 ++pref_app_id;
1283 --index;
1284 continue;
1285 }
1356 for (; index < max_index; ++index) { 1286 for (; index < max_index; ++index) {
1357 const ash::ShelfItem& item(model_->items()[index]); 1287 const ash::ShelfItem& item(model_->items()[index]);
1358 bool is_app_list = item.type == ash::TYPE_APP_LIST; 1288 if (item.type != ash::TYPE_APP_SHORTCUT &&
1359 bool is_chrome = item.type == ash::TYPE_BROWSER_SHORTCUT; 1289 item.type != ash::TYPE_BROWSER_SHORTCUT) {
1360 if (item.type != ash::TYPE_APP_SHORTCUT && !is_app_list && !is_chrome)
1361 continue; 1290 continue;
1291 }
1362 LauncherItemController* controller = GetLauncherItemController(item.id); 1292 LauncherItemController* controller = GetLauncherItemController(item.id);
1363 if ((ash::kPinnedAppsPlaceholder == *pref_app_id && is_app_list) || 1293 if (controller && controller->app_id() == *pref_app_id) {
1364 (extension_misc::kChromeAppId == *pref_app_id && is_chrome) ||
1365 (controller && controller->app_id() == *pref_app_id)) {
1366 // Check if an item needs to be moved here.
1367 MoveChromeOrApplistToFinalPosition(is_chrome, is_app_list, index,
1368 &chrome_index, &app_list_index);
1369 ++pref_app_id; 1294 ++pref_app_id;
1370 break; 1295 break;
1296 } else if (item.type == ash::TYPE_BROWSER_SHORTCUT) {
1297 // We cannot close browser shortcut. Remember its position.
1298 seen_chrome_index = index;
1371 } else { 1299 } else {
1372 if (is_chrome || is_app_list) { 1300 // Check if this is a platform or a windowed app.
1373 // We cannot delete any of these shortcuts. As such we remember 1301 if (item.type == ash::TYPE_APP_SHORTCUT && controller &&
1374 // their positions and move them later where they belong. 1302 (controller->locked() ||
1375 if (is_chrome) 1303 controller->type() == LauncherItemController::TYPE_APP)) {
1376 chrome_index = index; 1304 // Note: This will not change the amount of items (|max_index|).
1377 else 1305 // Even changes to the actual |index| due to item weighting
1378 app_list_index = index; 1306 // changes should be fine.
1379 // And skip the item - or exit the loop if end is reached (note that 1307 UnpinRunningAppInternal(index);
1380 // in that case we will reduce the index again by one and this only
1381 // compensates for it).
1382 if (index >= max_index - 1)
1383 break;
1384 ++index;
1385 } else { 1308 } else {
1386 // Check if this is a platform or a windowed app. 1309 if (controller)
1387 if (item.type == ash::TYPE_APP_SHORTCUT && controller && 1310 LauncherItemClosed(item.id);
1388 (controller->locked() || 1311 --max_index;
1389 controller->type() == LauncherItemController::TYPE_APP)) {
1390 // Note: This will not change the amount of items (|max_index|).
1391 // Even changes to the actual |index| due to item weighting
1392 // changes should be fine.
1393 UnpinRunningAppInternal(index);
1394 } else {
1395 if (controller)
1396 LauncherItemClosed(item.id);
1397 --max_index;
1398 }
1399 } 1312 }
1400 --index; 1313 --index;
1401 } 1314 }
1402 } 1315 }
1403 // If the item wasn't found, that means id_to_item_controller_map_ 1316 // If the item wasn't found, that means id_to_item_controller_map_
1404 // is out of sync. 1317 // is out of sync.
1405 DCHECK(index <= max_index); 1318 DCHECK(index <= max_index);
1406 } else { 1319 } else {
1407 // Check if the item was already running but not yet pinned. 1320 // Check if the item was already running but not yet pinned.
1408 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); 1321 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id);
(...skipping 17 matching lines...) Expand all
1426 LauncherItemController* controller = GetLauncherItemController(item.id); 1339 LauncherItemController* controller = GetLauncherItemController(item.id);
1427 if (controller) { 1340 if (controller) {
1428 if (controller->locked() || 1341 if (controller->locked() ||
1429 controller->type() == LauncherItemController::TYPE_APP) { 1342 controller->type() == LauncherItemController::TYPE_APP) {
1430 UnpinRunningAppInternal(index); 1343 UnpinRunningAppInternal(index);
1431 } else { 1344 } else {
1432 LauncherItemClosed(item.id); 1345 LauncherItemClosed(item.id);
1433 } 1346 }
1434 } 1347 }
1435 } else { 1348 } else {
1436 if (item.type == ash::TYPE_BROWSER_SHORTCUT)
1437 chrome_index = index;
1438 else if (item.type == ash::TYPE_APP_LIST)
1439 app_list_index = index;
1440 ++index; 1349 ++index;
1441 } 1350 }
1442 } 1351 }
1443 1352
1444 // Append unprocessed items from the pref to the end of the model. 1353 // Append unprocessed items from the pref to the end of the model.
1445 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { 1354 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) {
1446 // All items but the chrome and / or app list shortcut needs to be added. 1355 if (*pref_app_id == extension_misc::kChromeAppId) {
1447 bool is_chrome = *pref_app_id == extension_misc::kChromeAppId; 1356 int target_index = FindInsertionPoint();
1448 bool is_app_list = *pref_app_id == ash::kPinnedAppsPlaceholder; 1357 DCHECK(seen_chrome_index >= 0 && seen_chrome_index < target_index);
1449 // Coming here we know the next item which can be finalized, either the 1358 model_->Move(seen_chrome_index, target_index);
1450 // chrome item or the app launcher. The final position is the end of the 1359 } else {
1451 // list. The menu model will make sure that the item is grouped according
1452 // to its weight (which we do not know here).
1453 if (!is_chrome && !is_app_list) {
1454 DoPinAppWithID(*pref_app_id); 1360 DoPinAppWithID(*pref_app_id);
1455 int target_index = FindInsertionPoint(false); 1361 int target_index = FindInsertionPoint();
1456 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id); 1362 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id);
1457 int source_index = model_->ItemIndexByID(id); 1363 int source_index = model_->ItemIndexByID(id);
1458 if (source_index != target_index) 1364 if (source_index != target_index)
1459 model_->Move(source_index, target_index); 1365 model_->Move(source_index, target_index);
1460
1461 // Needed for the old layout - the weight might force it to be lower in
1462 // rank.
1463 if (app_list_index != -1 && target_index <= app_list_index)
1464 ++app_list_index;
1465 } else {
1466 int target_index = FindInsertionPoint(is_app_list);
1467 MoveChromeOrApplistToFinalPosition(is_chrome, is_app_list, target_index,
1468 &chrome_index, &app_list_index);
1469 } 1366 }
1470 } 1367 }
1471 } 1368 }
1472 1369
1473 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() { 1370 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() {
1474 for (auto* window : ash::Shell::GetAllRootWindows()) { 1371 for (auto* window : ash::Shell::GetAllRootWindows()) {
1475 ash::Shelf* shelf = ash::Shelf::ForWindow(window); 1372 ash::Shelf* shelf = ash::Shelf::ForWindow(window);
1476 if (shelf) { 1373 if (shelf) {
1477 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref( 1374 shelf->SetAutoHideBehavior(ash::launcher::GetShelfAutoHideBehaviorPref(
1478 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); 1375 profile_->GetPrefs(), GetDisplayIDForShelf(shelf)));
1479 } 1376 }
1480 } 1377 }
1481 } 1378 }
1482 1379
1483 void ChromeLauncherControllerImpl::SetShelfAlignmentFromPrefs() { 1380 void ChromeLauncherControllerImpl::SetShelfAlignmentFromPrefs() {
1484 if (!ash::ShelfWidget::ShelfAlignmentAllowed()) 1381 if (!ash::ShelfWidget::ShelfAlignmentAllowed())
1485 return; 1382 return;
1486 1383
1487 for (auto* window : ash::Shell::GetAllRootWindows()) { 1384 for (auto* window : ash::Shell::GetAllRootWindows()) {
1488 ash::Shelf* shelf = ash::Shelf::ForWindow(window); 1385 ash::Shelf* shelf = ash::Shelf::ForWindow(window);
1489 if (shelf) { 1386 if (shelf) {
1490 shelf->SetAlignment(ash::GetShelfAlignmentPref( 1387 shelf->SetAlignment(ash::launcher::GetShelfAlignmentPref(
1491 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); 1388 profile_->GetPrefs(), GetDisplayIDForShelf(shelf)));
1492 } 1389 }
1493 } 1390 }
1494 } 1391 }
1495 1392
1496 void ChromeLauncherControllerImpl::SetShelfBehaviorsFromPrefs() { 1393 void ChromeLauncherControllerImpl::SetShelfBehaviorsFromPrefs() {
1497 SetShelfAutoHideBehaviorFromPrefs(); 1394 SetShelfAutoHideBehaviorFromPrefs();
1498 SetShelfAlignmentFromPrefs(); 1395 SetShelfAlignmentFromPrefs();
1499 } 1396 }
1500 1397
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1584 static_cast<AppShortcutLauncherItemController*>(controller); 1481 static_cast<AppShortcutLauncherItemController*>(controller);
1585 return app_controller->GetRunningApplications(); 1482 return app_controller->GetRunningApplications();
1586 } 1483 }
1587 1484
1588 ash::ShelfID ChromeLauncherControllerImpl::CreateBrowserShortcutLauncherItem() { 1485 ash::ShelfID ChromeLauncherControllerImpl::CreateBrowserShortcutLauncherItem() {
1589 ash::ShelfItem browser_shortcut; 1486 ash::ShelfItem browser_shortcut;
1590 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; 1487 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT;
1591 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1488 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
1592 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); 1489 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
1593 ash::ShelfID id = model_->next_id(); 1490 ash::ShelfID id = model_->next_id();
1594 size_t index = GetChromeIconIndexForCreation(); 1491 model_->AddAt(0, browser_shortcut);
1595 model_->AddAt(index, browser_shortcut);
1596 id_to_item_controller_map_[id] = 1492 id_to_item_controller_map_[id] =
1597 new BrowserShortcutLauncherItemController(this, model_); 1493 new BrowserShortcutLauncherItemController(this, model_);
1598 id_to_item_controller_map_[id]->set_shelf_id(id); 1494 id_to_item_controller_map_[id]->set_shelf_id(id);
1599 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController. 1495 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController.
1600 SetShelfItemDelegate(id, id_to_item_controller_map_[id]); 1496 SetShelfItemDelegate(id, id_to_item_controller_map_[id]);
1601 return id; 1497 return id;
1602 } 1498 }
1603 1499
1604 bool ChromeLauncherControllerImpl::IsIncognito( 1500 bool ChromeLauncherControllerImpl::IsIncognito(
1605 const content::WebContents* web_contents) const { 1501 const content::WebContents* web_contents) const {
1606 const Profile* profile = 1502 const Profile* profile =
1607 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 1503 Profile::FromBrowserContext(web_contents->GetBrowserContext());
1608 return profile->IsOffTheRecord() && !profile->IsGuestSession() && 1504 return profile->IsOffTheRecord() && !profile->IsGuestSession() &&
1609 !profile->IsSystemProfile(); 1505 !profile->IsSystemProfile();
1610 } 1506 }
1611 1507
1612 void ChromeLauncherControllerImpl::PersistChromeItemIndex(int index) { 1508 int ChromeLauncherControllerImpl::FindInsertionPoint() {
1613 profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index); 1509 DCHECK_GT(model_->item_count(), 0);
1614 }
1615
1616 void ChromeLauncherControllerImpl::MoveChromeOrApplistToFinalPosition(
1617 bool is_chrome,
1618 bool is_app_list,
1619 int target_index,
1620 int* chrome_index,
1621 int* app_list_index) {
1622 if (is_chrome && *chrome_index != -1) {
1623 model_->Move(*chrome_index, target_index);
1624 if (*app_list_index != -1 && *chrome_index < *app_list_index &&
1625 target_index > *app_list_index)
1626 --(*app_list_index);
1627 *chrome_index = -1;
1628 } else if (is_app_list && *app_list_index != -1) {
1629 model_->Move(*app_list_index, target_index);
1630 if (*chrome_index != -1 && *app_list_index < *chrome_index &&
1631 target_index > *chrome_index)
1632 --(*chrome_index);
1633 *app_list_index = -1;
1634 }
1635 }
1636
1637 int ChromeLauncherControllerImpl::FindInsertionPoint(bool is_app_list) {
1638 // Keeping this change small to backport to M33&32 (see crbug.com/329597).
1639 // TODO(skuhne): With the removal of the legacy shelf layout we should remove
1640 // the ability to move the app list item since this was never used. We should
1641 // instead ask the ShelfModel::ValidateInsertionIndex or similir for an index.
1642 if (is_app_list)
1643 return 0;
1644
1645 for (int i = model_->item_count() - 1; i > 0; --i) { 1510 for (int i = model_->item_count() - 1; i > 0; --i) {
1646 ash::ShelfItemType type = model_->items()[i].type; 1511 ash::ShelfItemType type = model_->items()[i].type;
1512 DCHECK_NE(ash::TYPE_APP_LIST, type);
1647 if (type == ash::TYPE_APP_SHORTCUT || 1513 if (type == ash::TYPE_APP_SHORTCUT ||
1648 (is_app_list && type == ash::TYPE_APP_LIST) ||
1649 type == ash::TYPE_BROWSER_SHORTCUT) { 1514 type == ash::TYPE_BROWSER_SHORTCUT) {
1650 return i; 1515 return i;
1651 } 1516 }
1652 } 1517 }
1653 return 0; 1518 return 0;
1654 } 1519 }
1655 1520
1656 int ChromeLauncherControllerImpl::GetChromeIconIndexForCreation() {
1657 // We get the list of pinned apps as they currently would get pinned.
1658 // Within this list the chrome icon will be the correct location.
1659 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs(
1660 profile_->GetPrefs(), launcher_controller_helper_.get());
1661
1662 std::vector<std::string>::iterator it =
1663 std::find(pinned_apps.begin(), pinned_apps.end(),
1664 std::string(extension_misc::kChromeAppId));
1665 DCHECK(it != pinned_apps.end());
1666 int index = it - pinned_apps.begin();
1667
1668 // We should do here a comparison between the is state and the "want to be"
1669 // state since some apps might be able to pin but are not yet. Instead - for
1670 // the time being we clamp against the amount of known items and wait for the
1671 // next |UpdateAppLaunchersFromPref()| call to correct it - it will come since
1672 // the pinning will be done then.
1673 return std::min(model_->item_count(), index);
1674 }
1675
1676 void ChromeLauncherControllerImpl::CloseWindowedAppsFromRemovedExtension( 1521 void ChromeLauncherControllerImpl::CloseWindowedAppsFromRemovedExtension(
1677 const std::string& app_id, 1522 const std::string& app_id,
1678 const Profile* profile) { 1523 const Profile* profile) {
1679 // This function cannot rely on the controller's enumeration functionality 1524 // This function cannot rely on the controller's enumeration functionality
1680 // since the extension has already be unloaded. 1525 // since the extension has already be unloaded.
1681 const BrowserList* browser_list = BrowserList::GetInstance(); 1526 const BrowserList* browser_list = BrowserList::GetInstance();
1682 std::vector<Browser*> browser_to_close; 1527 std::vector<Browser*> browser_to_close;
1683 for (BrowserList::const_reverse_iterator it = 1528 for (BrowserList::const_reverse_iterator it =
1684 browser_list->begin_last_active(); 1529 browser_list->begin_last_active();
1685 it != browser_list->end_last_active(); ++it) { 1530 it != browser_list->end_last_active(); ++it) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1730 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { 1575 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) {
1731 DCHECK(arc_deferred_launcher_.get()); 1576 DCHECK(arc_deferred_launcher_.get());
1732 std::unique_ptr<AppIconLoader> arc_app_icon_loader( 1577 std::unique_ptr<AppIconLoader> arc_app_icon_loader(
1733 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL, 1578 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL,
1734 arc_deferred_launcher_.get(), this)); 1579 arc_deferred_launcher_.get(), this));
1735 app_icon_loaders_.push_back(std::move(arc_app_icon_loader)); 1580 app_icon_loaders_.push_back(std::move(arc_app_icon_loader));
1736 } 1581 }
1737 1582
1738 pref_change_registrar_.Init(profile_->GetPrefs()); 1583 pref_change_registrar_.Init(profile_->GetPrefs());
1739 pref_change_registrar_.Add( 1584 pref_change_registrar_.Add(
1740 prefs::kPinnedLauncherApps,
1741 base::Bind(&ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref,
1742 base::Unretained(this)));
1743 pref_change_registrar_.Add(
1744 prefs::kPolicyPinnedLauncherApps, 1585 prefs::kPolicyPinnedLauncherApps,
1745 base::Bind(&ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref, 1586 base::Bind(&ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref,
1746 base::Unretained(this))); 1587 base::Unretained(this)));
1747 pref_change_registrar_.Add( 1588 pref_change_registrar_.Add(
1748 prefs::kShelfAlignmentLocal, 1589 prefs::kShelfAlignmentLocal,
1749 base::Bind(&ChromeLauncherControllerImpl::SetShelfAlignmentFromPrefs, 1590 base::Bind(&ChromeLauncherControllerImpl::SetShelfAlignmentFromPrefs,
1750 base::Unretained(this))); 1591 base::Unretained(this)));
1751 pref_change_registrar_.Add( 1592 pref_change_registrar_.Add(
1752 prefs::kShelfAutoHideBehaviorLocal, 1593 prefs::kShelfAutoHideBehaviorLocal,
1753 base::Bind( 1594 base::Bind(
(...skipping 11 matching lines...) Expand all
1765 1606
1766 std::unique_ptr<LauncherAppUpdater> extension_app_updater( 1607 std::unique_ptr<LauncherAppUpdater> extension_app_updater(
1767 new LauncherExtensionAppUpdater(this, profile_)); 1608 new LauncherExtensionAppUpdater(this, profile_));
1768 app_updaters_.push_back(std::move(extension_app_updater)); 1609 app_updaters_.push_back(std::move(extension_app_updater));
1769 1610
1770 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { 1611 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) {
1771 std::unique_ptr<LauncherAppUpdater> arc_app_updater( 1612 std::unique_ptr<LauncherAppUpdater> arc_app_updater(
1772 new LauncherArcAppUpdater(this, profile_)); 1613 new LauncherArcAppUpdater(this, profile_));
1773 app_updaters_.push_back(std::move(arc_app_updater)); 1614 app_updaters_.push_back(std::move(arc_app_updater));
1774 } 1615 }
1616
1617 app_list::AppListSyncableService* app_service =
1618 app_list::AppListSyncableServiceFactory::GetForProfile(profile_);
1619 if (app_service)
1620 app_service->AddObserverAndStart(this);
1775 } 1621 }
1776 1622
1777 void ChromeLauncherControllerImpl::ReleaseProfile() { 1623 void ChromeLauncherControllerImpl::ReleaseProfile() {
1778 if (app_sync_ui_state_) 1624 if (app_sync_ui_state_)
1779 app_sync_ui_state_->RemoveObserver(this); 1625 app_sync_ui_state_->RemoveObserver(this);
1780 1626
1781 app_updaters_.clear(); 1627 app_updaters_.clear();
1782 1628
1783 prefs_observer_.reset(); 1629 prefs_observer_.reset();
1784 1630
1785 pref_change_registrar_.RemoveAll(); 1631 pref_change_registrar_.RemoveAll();
1632
1633 app_list::AppListSyncableService* app_service =
1634 app_list::AppListSyncableServiceFactory::GetForProfile(profile_);
1635 if (app_service)
1636 app_service->RemoveObserver(this);
1786 } 1637 }
1787 1638
1788 AppIconLoader* ChromeLauncherControllerImpl::GetAppIconLoaderForApp( 1639 AppIconLoader* ChromeLauncherControllerImpl::GetAppIconLoaderForApp(
1789 const std::string& app_id) { 1640 const std::string& app_id) {
1790 for (const auto& app_icon_loader : app_icon_loaders_) { 1641 for (const auto& app_icon_loader : app_icon_loaders_) {
1791 if (app_icon_loader->CanLoadImageForApp(app_id)) 1642 if (app_icon_loader->CanLoadImageForApp(app_id))
1792 return app_icon_loader.get(); 1643 return app_icon_loader.get();
1793 } 1644 }
1794 1645
1795 return nullptr; 1646 return nullptr;
(...skipping 11 matching lines...) Expand all
1807 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second) 1658 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second)
1808 return; 1659 return;
1809 LOG(ERROR) << "Unexpected change of shelf item id: " << id; 1660 LOG(ERROR) << "Unexpected change of shelf item id: " << id;
1810 id_to_item_controller_map_.erase(iter); 1661 id_to_item_controller_map_.erase(iter);
1811 } 1662 }
1812 1663
1813 /////////////////////////////////////////////////////////////////////////////// 1664 ///////////////////////////////////////////////////////////////////////////////
1814 // ash::ShelfModelObserver: 1665 // ash::ShelfModelObserver:
1815 1666
1816 void ChromeLauncherControllerImpl::ShelfItemAdded(int index) { 1667 void ChromeLauncherControllerImpl::ShelfItemAdded(int index) {
1817 // The app list launcher can get added to the shelf after we applied the
1818 // preferences. In that case the item might be at the wrong spot. As such we
1819 // call the function again.
1820 if (model_->items()[index].type == ash::TYPE_APP_LIST)
1821 UpdateAppLaunchersFromPref();
1822 } 1668 }
1823 1669
1824 void ChromeLauncherControllerImpl::ShelfItemRemoved(int index, 1670 void ChromeLauncherControllerImpl::ShelfItemRemoved(int index,
1825 ash::ShelfID id) { 1671 ash::ShelfID id) {
1826 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we 1672 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
1827 // get into this state in the first place. 1673 // get into this state in the first place.
1828 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); 1674 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
1829 if (iter == id_to_item_controller_map_.end()) 1675 if (iter == id_to_item_controller_map_.end())
1830 return; 1676 return;
1831 1677
1832 LOG(ERROR) << "Unexpected change of shelf item id: " << id; 1678 LOG(ERROR) << "Unexpected change of shelf item id: " << id;
1833 1679
1834 id_to_item_controller_map_.erase(iter); 1680 id_to_item_controller_map_.erase(iter);
1835 } 1681 }
1836 1682
1837 void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index, 1683 void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index,
1838 int target_index) { 1684 int target_index) {
1839 const ash::ShelfItem& item = model_->items()[target_index]; 1685 const ash::ShelfItem& item = model_->items()[target_index];
1840 // We remember the moved item position if it is either pinnable or 1686 // We remember the moved item position if it is either pinnable or
1841 // it is the app list with the alternate shelf layout. 1687 // it is the app list with the alternate shelf layout.
1842 if ((HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id)) || 1688 DCHECK_NE(ash::TYPE_APP_LIST, item.type);
1843 item.type == ash::TYPE_APP_LIST) 1689 if (HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id))
1844 PersistPinnedState(); 1690 SyncPinPosition(item.id);
1845 } 1691 }
1846 1692
1847 void ChromeLauncherControllerImpl::ShelfItemChanged( 1693 void ChromeLauncherControllerImpl::ShelfItemChanged(
1848 int index, 1694 int index,
1849 const ash::ShelfItem& old_item) {} 1695 const ash::ShelfItem& old_item) {}
1850 1696
1851 /////////////////////////////////////////////////////////////////////////////// 1697 ///////////////////////////////////////////////////////////////////////////////
1852 // ash::WindowTreeHostManager::Observer: 1698 // ash::WindowTreeHostManager::Observer:
1853 1699
1854 void ChromeLauncherControllerImpl::OnDisplayConfigurationChanged() { 1700 void ChromeLauncherControllerImpl::OnDisplayConfigurationChanged() {
(...skipping 27 matching lines...) Expand all
1882 continue; 1728 continue;
1883 int index = model_->ItemIndexByID(i->first); 1729 int index = model_->ItemIndexByID(i->first);
1884 if (index == -1) 1730 if (index == -1)
1885 continue; 1731 continue;
1886 ash::ShelfItem item = model_->items()[index]; 1732 ash::ShelfItem item = model_->items()[index];
1887 item.image = image; 1733 item.image = image;
1888 model_->Set(index, item); 1734 model_->Set(index, item);
1889 // It's possible we're waiting on more than one item, so don't break. 1735 // It's possible we're waiting on more than one item, so don't break.
1890 } 1736 }
1891 } 1737 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698