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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller.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: cleanup and update 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.h" 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
11 #include "ash/ash_switches.h" 11 #include "ash/ash_switches.h"
12 #include "ash/common/shelf/shelf_item_delegate_manager.h" 12 #include "ash/common/shelf/shelf_item_delegate_manager.h"
13 #include "ash/common/shelf/shelf_model.h" 13 #include "ash/common/shelf/shelf_model.h"
14 #include "ash/desktop_background/desktop_background_controller.h" 14 #include "ash/desktop_background/desktop_background_controller.h"
15 #include "ash/multi_profile_uma.h" 15 #include "ash/multi_profile_uma.h"
16 #include "ash/root_window_controller.h" 16 #include "ash/root_window_controller.h"
17 #include "ash/shelf/shelf.h" 17 #include "ash/shelf/shelf.h"
18 #include "ash/shell.h" 18 #include "ash/shell.h"
19 #include "ash/system/tray/system_tray_delegate.h" 19 #include "ash/system/tray/system_tray_delegate.h"
20 #include "ash/wm/window_util.h" 20 #include "ash/wm/window_util.h"
21 #include "base/command_line.h" 21 #include "base/command_line.h"
22 #include "base/macros.h" 22 #include "base/macros.h"
23 #include "base/strings/pattern.h" 23 #include "base/strings/pattern.h"
24 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
25 #include "base/strings/utf_string_conversions.h" 25 #include "base/strings/utf_string_conversions.h"
26 #include "base/values.h" 26 #include "base/values.h"
27 #include "build/build_config.h" 27 #include "build/build_config.h"
28 #include "chrome/browser/browser_process.h" 28 #include "chrome/browser/browser_process.h"
29 #include "chrome/browser/chrome_notification_types.h" 29 #include "chrome/browser/chrome_notification_types.h"
30 #include "chrome/browser/chromeos/arc/arc_support_host.h"
31 #include "chrome/browser/defaults.h" 30 #include "chrome/browser/defaults.h"
32 #include "chrome/browser/extensions/extension_app_icon_loader.h" 31 #include "chrome/browser/extensions/extension_app_icon_loader.h"
33 #include "chrome/browser/extensions/extension_util.h" 32 #include "chrome/browser/extensions/extension_util.h"
34 #include "chrome/browser/extensions/launch_util.h" 33 #include "chrome/browser/extensions/launch_util.h"
35 #include "chrome/browser/prefs/incognito_mode_prefs.h" 34 #include "chrome/browser/prefs/incognito_mode_prefs.h"
36 #include "chrome/browser/prefs/pref_service_syncable_util.h" 35 #include "chrome/browser/prefs/pref_service_syncable_util.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"
39 #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" 38 #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" 39 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 const char* local_path, 127 const char* local_path,
129 const char* synced_path) { 128 const char* synced_path) {
130 if (!pref_service->FindPreference(local_path)->HasUserSetting() && 129 if (!pref_service->FindPreference(local_path)->HasUserSetting() &&
131 pref_service->IsSyncing()) { 130 pref_service->IsSyncing()) {
132 // First time the user is using this machine, propagate from remote to 131 // First time the user is using this machine, propagate from remote to
133 // local. 132 // local.
134 pref_service->SetString(local_path, pref_service->GetString(synced_path)); 133 pref_service->SetString(local_path, pref_service->GetString(synced_path));
135 } 134 }
136 } 135 }
137 136
138 /*
139 * Return whether an app is pinned only by user.
140 * This function doesn't expect an app_id neither pinned by user nor by
141 * policy, the app_id in the arguments list MUST be pinned by either of
142 * those. Invalid input may lead to unexpected result.
143 * If this app is pinned by policy, but not by user, false is returned.
144 * If this app is pinned by both policy and user, false is returned.
145 * If this app is pinned not by policy, but by user, true is returned.
146 */
147 bool IsAppForUserPinned(const std::string& app_id,
148 const base::ListValue* pinned_apps_pref,
149 const base::ListValue* policy_pinned_apps_pref) {
150 for (size_t index = 0; index < pinned_apps_pref->GetSize(); ++index) {
151 const base::DictionaryValue* app;
152 if (pinned_apps_pref->GetDictionary(index, &app)) {
153 std::string current_app_id;
154 bool pinned_by_policy = false;
155 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, &current_app_id)) {
156 if (app_id == current_app_id) {
157 if (app->GetBoolean(ash::kPinnedAppsPrefPinnedByPolicy,
158 &pinned_by_policy) &&
159 pinned_by_policy) {
160 // Pinned by policy in the past or present.
161 // Need to check policy_pinned_apps to determine
162 break;
163 } else {
164 // User Preference Already Pinned
165 return true;
166 }
167 }
168 }
169 }
170 }
171 for (size_t index = 0; index < policy_pinned_apps_pref->GetSize(); ++index) {
172 const base::DictionaryValue* app;
173 if (policy_pinned_apps_pref->GetDictionary(index, &app)) {
174 std::string app_id_;
175 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id_)) {
176 // Only pinned by policy, which is not part of user-pinned
177 if (app_id == app_id_)
178 return false;
179 }
180 }
181 }
182 // Default, user added new pins
183 return true;
184 }
185
186 const char* const kPinProhibitedExtensionIds[] = {
187 ArcSupportHost::kHostAppId, arc::kPlayStoreAppId,
188 };
189
190 const size_t kPinProhibitedExtensionIdsLength =
191 arraysize(kPinProhibitedExtensionIds);
192
193 } // namespace 137 } // namespace
194 138
195 // A class to get events from ChromeOS when a user gets changed or added. 139 // A class to get events from ChromeOS when a user gets changed or added.
196 class ChromeLauncherControllerUserSwitchObserver 140 class ChromeLauncherControllerUserSwitchObserver
197 : public user_manager::UserManager::UserSessionStateObserver { 141 : public user_manager::UserManager::UserSessionStateObserver {
198 public: 142 public:
199 ChromeLauncherControllerUserSwitchObserver( 143 ChromeLauncherControllerUserSwitchObserver(
200 ChromeLauncherController* controller) 144 ChromeLauncherController* controller)
201 : controller_(controller) { 145 : controller_(controller) {
202 DCHECK(user_manager::UserManager::IsInitialized()); 146 DCHECK(user_manager::UserManager::IsInitialized());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 201
258 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) { 202 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) {
259 if (chrome::MultiUserWindowManager::GetMultiProfileMode() == 203 if (chrome::MultiUserWindowManager::GetMultiProfileMode() ==
260 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) 204 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED)
261 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile); 205 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
262 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile()); 206 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile());
263 } 207 }
264 208
265 ChromeLauncherController::ChromeLauncherController(Profile* profile, 209 ChromeLauncherController::ChromeLauncherController(Profile* profile,
266 ash::ShelfModel* model) 210 ash::ShelfModel* model)
267 : model_(model), 211 : model_(model), profile_(profile) {
268 item_delegate_manager_(NULL),
269 profile_(profile),
270 app_sync_ui_state_(NULL),
271 ignore_persist_pinned_state_change_(false) {
272 if (!profile_) { 212 if (!profile_) {
273 // If no profile was passed, we take the currently active profile and use it 213 // If no profile was passed, we take the currently active profile and use it
274 // as the owner of the current desktop. 214 // as the owner of the current desktop.
275 // Use the original profile as on chromeos we may get a temporary off the 215 // Use the original profile as on chromeos we may get a temporary off the
276 // record profile, unless in guest session (where off the record profile is 216 // record profile, unless in guest session (where off the record profile is
277 // the right one). 217 // the right one).
278 profile_ = ProfileManager::GetActiveUserProfile(); 218 profile_ = ProfileManager::GetActiveUserProfile();
279 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile()) 219 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile())
280 profile_ = profile_->GetOriginalProfile(); 220 profile_ = profile_->GetOriginalProfile();
281 221
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 iter->second->set_shelf_id(id); 396 iter->second->set_shelf_id(id);
457 // Existing controller is destroyed and replaced by registering again. 397 // Existing controller is destroyed and replaced by registering again.
458 SetShelfItemDelegate(id, iter->second); 398 SetShelfItemDelegate(id, iter->second);
459 } else { 399 } else {
460 LauncherItemClosed(id); 400 LauncherItemClosed(id);
461 } 401 }
462 } 402 }
463 403
464 AppListControllerDelegate::Pinnable ChromeLauncherController::GetPinnable( 404 AppListControllerDelegate::Pinnable ChromeLauncherController::GetPinnable(
465 const std::string& app_id) { 405 const std::string& app_id) {
466 for (size_t i = 0; i < kPinProhibitedExtensionIdsLength; ++i) {
467 if (kPinProhibitedExtensionIds[i] == app_id)
468 return AppListControllerDelegate::NO_PIN;
469 }
470
471 const base::ListValue* pref = 406 const base::ListValue* pref =
472 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps); 407 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps);
473 if (!pref) 408 if (!pref)
474 return AppListControllerDelegate::PIN_EDITABLE; 409 return AppListControllerDelegate::PIN_EDITABLE;
475 410
476 // Pinned ARC apps policy defines the package name of the apps, that must 411 // Pinned ARC apps policy defines the package name of the apps, that must
477 // be pinned. All the launch activities of any package in policy are pinned. 412 // be pinned. All the launch activities of any package in policy are pinned.
478 // In turn the input parameter to this function is app_id, which 413 // In turn the input parameter to this function is app_id, which
479 // is 32 chars hash. In case of ARC app this is a hash of 414 // is 32 chars hash. In case of ARC app this is a hash of
480 // (package name + activity). This means that we must identify the package 415 // (package name + activity). This means that we must identify the package
(...skipping 29 matching lines...) Expand all
510 ash::ShelfItem item = model_->items()[index]; 445 ash::ShelfItem item = model_->items()[index];
511 446
512 if (item.type == ash::TYPE_PLATFORM_APP || 447 if (item.type == ash::TYPE_PLATFORM_APP ||
513 item.type == ash::TYPE_WINDOWED_APP) { 448 item.type == ash::TYPE_WINDOWED_APP) {
514 item.type = ash::TYPE_APP_SHORTCUT; 449 item.type = ash::TYPE_APP_SHORTCUT;
515 model_->Set(index, item); 450 model_->Set(index, item);
516 } else if (item.type != ash::TYPE_APP_SHORTCUT) { 451 } else if (item.type != ash::TYPE_APP_SHORTCUT) {
517 return; 452 return;
518 } 453 }
519 454
520 if (GetLauncherItemController(id)->CanPin()) 455 SyncPinPosition(id);
521 PersistPinnedState();
522 } 456 }
523 457
524 void ChromeLauncherController::Unpin(ash::ShelfID id) { 458 void ChromeLauncherController::Unpin(ash::ShelfID id) {
525 LauncherItemController* controller = GetLauncherItemController(id); 459 LauncherItemController* controller = GetLauncherItemController(id);
526 CHECK(controller); 460 CHECK(controller);
527 const bool can_pin = controller->CanPin(); 461
462 ash::RemovePinPosition(profile_, GetAppIDForShelfID(id));
528 463
529 if (controller->type() == LauncherItemController::TYPE_APP || 464 if (controller->type() == LauncherItemController::TYPE_APP ||
530 controller->locked()) { 465 controller->locked()) {
531 UnpinRunningAppInternal(model_->ItemIndexByID(id)); 466 UnpinRunningAppInternal(model_->ItemIndexByID(id));
532 } else { 467 } else {
533 LauncherItemClosed(id); 468 LauncherItemClosed(id);
534 } 469 }
535 if (can_pin)
536 PersistPinnedState();
537 } 470 }
538 471
539 bool ChromeLauncherController::IsPinned(ash::ShelfID id) { 472 bool ChromeLauncherController::IsPinned(ash::ShelfID id) {
540 int index = model_->ItemIndexByID(id); 473 int index = model_->ItemIndexByID(id);
541 if (index < 0) 474 if (index < 0)
542 return false; 475 return false;
543 ash::ShelfItemType type = model_->items()[index].type; 476 ash::ShelfItemType type = model_->items()[index].type;
544 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT); 477 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT);
545 } 478 }
546 479
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 void ChromeLauncherController::CreateNewWindow() { 711 void ChromeLauncherController::CreateNewWindow() {
779 // Use the currently active user. 712 // Use the currently active user.
780 chrome::NewEmptyWindow(profile_); 713 chrome::NewEmptyWindow(profile_);
781 } 714 }
782 715
783 void ChromeLauncherController::CreateNewIncognitoWindow() { 716 void ChromeLauncherController::CreateNewIncognitoWindow() {
784 // Use the currently active user. 717 // Use the currently active user.
785 chrome::NewEmptyWindow(profile_->GetOffTheRecordProfile()); 718 chrome::NewEmptyWindow(profile_->GetOffTheRecordProfile());
786 } 719 }
787 720
788 void ChromeLauncherController::PersistPinnedState() {
789 if (ignore_persist_pinned_state_change_)
790 return;
791 // It is a coding error to call PersistPinnedState() if the pinned apps are
792 // not user-editable. The code should check earlier and not perform any
793 // modification actions that trigger persisting the state.
794 // Mutating kPinnedLauncherApps is going to notify us and trigger us to
795 // process the change. We don't want that to happen so remove ourselves as a
796 // listener.
797 pref_change_registrar_.Remove(prefs::kPinnedLauncherApps);
798 {
799 std::unique_ptr<const base::ListValue> pinned_apps_pref =
800 profile_->GetPrefs()
801 ->GetList(prefs::kPinnedLauncherApps)
802 ->CreateDeepCopy();
803
804 const base::ListValue* policy_pinned_apps_pref =
805 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps);
806
807 ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps);
808 updater->Clear();
809 for (size_t i = 0; i < model_->items().size(); ++i) {
810 if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) {
811 ash::ShelfID id = model_->items()[i].id;
812 LauncherItemController* controller = GetLauncherItemController(id);
813 // Don't persist pinning state for apps that are handled internally and
814 // have pinnable state AppListControllerDelegate::NO_PIN.
815 if (controller && IsPinned(id) &&
816 GetPinnable(controller->app_id()) !=
817 AppListControllerDelegate::NO_PIN) {
818 base::DictionaryValue* app_value = ash::CreateAppDict(
819 controller->app_id());
820 if (app_value) {
821 if (!IsAppForUserPinned(controller->app_id(),
822 pinned_apps_pref.get(),
823 policy_pinned_apps_pref))
824 app_value->SetBoolean(ash::kPinnedAppsPrefPinnedByPolicy, true);
825 updater->Append(app_value);
826 }
827 }
828 } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) {
829 PersistChromeItemIndex(i);
830 } else if (model_->items()[i].type == ash::TYPE_APP_LIST) {
831 base::DictionaryValue* app_value =
832 ash::CreateAppDict(ash::kPinnedAppsPlaceholder);
833 if (app_value)
834 updater->Append(app_value);
835 }
836 }
837 }
838 pref_change_registrar_.Add(
839 prefs::kPinnedLauncherApps,
840 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref,
841 base::Unretained(this)));
842 }
843
844 Profile* ChromeLauncherController::profile() { 721 Profile* ChromeLauncherController::profile() {
845 return profile_; 722 return profile_;
846 } 723 }
847 724
848 void ChromeLauncherController::UpdateAppState(content::WebContents* contents, 725 void ChromeLauncherController::UpdateAppState(content::WebContents* contents,
849 AppState app_state) { 726 AppState app_state) {
850 std::string app_id = launcher_controller_helper_->GetAppID(contents); 727 std::string app_id = launcher_controller_helper_->GetAppID(contents);
851 728
852 // Check if the gMail app is loaded and it matches the given content. 729 // Check if the gMail app is loaded and it matches the given content.
853 // This special treatment is needed to address crbug.com/234268. 730 // This special treatment is needed to address crbug.com/234268.
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 GetDisplayIDForShelf(shelf), 860 GetDisplayIDForShelf(shelf),
984 shelf->auto_hide_behavior()); 861 shelf->auto_hide_behavior());
985 } 862 }
986 863
987 void ChromeLauncherController::OnShelfAutoHideStateChanged(ash::Shelf* shelf) {} 864 void ChromeLauncherController::OnShelfAutoHideStateChanged(ash::Shelf* shelf) {}
988 865
989 void ChromeLauncherController::OnShelfVisibilityStateChanged( 866 void ChromeLauncherController::OnShelfVisibilityStateChanged(
990 ash::Shelf* shelf) {} 867 ash::Shelf* shelf) {}
991 868
992 void ChromeLauncherController::ShelfItemAdded(int index) { 869 void ChromeLauncherController::ShelfItemAdded(int index) {
993 // The app list launcher can get added to the shelf after we applied the
994 // preferences. In that case the item might be at the wrong spot. As such we
995 // call the function again.
996 if (model_->items()[index].type == ash::TYPE_APP_LIST)
997 UpdateAppLaunchersFromPref();
998 } 870 }
999 871
1000 void ChromeLauncherController::ShelfItemRemoved(int index, ash::ShelfID id) { 872 void ChromeLauncherController::ShelfItemRemoved(int index, ash::ShelfID id) {
1001 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we 873 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
1002 // get into this state in the first place. 874 // get into this state in the first place.
1003 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); 875 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
1004 if (iter == id_to_item_controller_map_.end()) 876 if (iter == id_to_item_controller_map_.end())
1005 return; 877 return;
1006 878
1007 LOG(ERROR) << "Unexpected change of shelf item id: " << id; 879 LOG(ERROR) << "Unexpected change of shelf item id: " << id;
1008 880
1009 id_to_item_controller_map_.erase(iter); 881 id_to_item_controller_map_.erase(iter);
1010 } 882 }
1011 883
1012 void ChromeLauncherController::ShelfItemMoved(int start_index, 884 void ChromeLauncherController::ShelfItemMoved(int start_index,
1013 int target_index) { 885 int target_index) {
1014 const ash::ShelfItem& item = model_->items()[target_index]; 886 const ash::ShelfItem& item = model_->items()[target_index];
1015 // We remember the moved item position if it is either pinnable or 887 // We remember the moved item position if it is either pinnable or
1016 // it is the app list with the alternate shelf layout. 888 // it is the app list with the alternate shelf layout.
1017 if ((HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id)) || 889 DCHECK_NE(ash::TYPE_APP_LIST, item.type);
1018 item.type == ash::TYPE_APP_LIST) 890 if (HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id))
1019 PersistPinnedState(); 891 SyncPinPosition(item.id);
1020 } 892 }
1021 893
1022 void ChromeLauncherController::ShelfItemChanged( 894 void ChromeLauncherController::ShelfItemChanged(
1023 int index, 895 int index,
1024 const ash::ShelfItem& old_item) {} 896 const ash::ShelfItem& old_item) {}
1025 897
1026 void ChromeLauncherController::ActiveUserChanged( 898 void ChromeLauncherController::ActiveUserChanged(
1027 const std::string& user_email) { 899 const std::string& user_email) {
1028 // Store the order of running applications for the user which gets inactive. 900 // Store the order of running applications for the user which gets inactive.
1029 RememberUnpinnedRunningApplicationOrder(); 901 RememberUnpinnedRunningApplicationOrder();
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 if (IsAppPinned(app_id)) 1252 if (IsAppPinned(app_id))
1381 return; 1253 return;
1382 1254
1383 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); 1255 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id);
1384 if (shelf_id) { 1256 if (shelf_id) {
1385 // App item exists, pin it 1257 // App item exists, pin it
1386 Pin(shelf_id); 1258 Pin(shelf_id);
1387 } else { 1259 } else {
1388 // Otherwise, create a shortcut item for it. 1260 // Otherwise, create a shortcut item for it.
1389 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count()); 1261 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count());
1390 if (GetPinnable(app_id) == AppListControllerDelegate::PIN_EDITABLE) 1262 SyncPinPosition(shelf_id);
1391 PersistPinnedState();
1392 } 1263 }
1393 } 1264 }
1394 1265
1395 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) { 1266 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) {
1396 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); 1267 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id);
1397 if (shelf_id && IsPinned(shelf_id)) 1268 if (shelf_id && IsPinned(shelf_id))
1398 Unpin(shelf_id); 1269 Unpin(shelf_id);
1399 } 1270 }
1400 1271
1401 int ChromeLauncherController::PinRunningAppInternal(int index, 1272 int ChromeLauncherController::PinRunningAppInternal(int index,
(...skipping 20 matching lines...) Expand all
1422 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); 1293 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT);
1423 item.type = ash::TYPE_WINDOWED_APP; 1294 item.type = ash::TYPE_WINDOWED_APP;
1424 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such 1295 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such
1425 // we have to check here what this was before it got a shortcut. 1296 // we have to check here what this was before it got a shortcut.
1426 LauncherItemController* controller = GetLauncherItemController(item.id); 1297 LauncherItemController* controller = GetLauncherItemController(item.id);
1427 if (controller && controller->type() == LauncherItemController::TYPE_APP) 1298 if (controller && controller->type() == LauncherItemController::TYPE_APP)
1428 item.type = ash::TYPE_PLATFORM_APP; 1299 item.type = ash::TYPE_PLATFORM_APP;
1429 model_->Set(index, item); 1300 model_->Set(index, item);
1430 } 1301 }
1431 1302
1303 void ChromeLauncherController::SyncPinPosition(ash::ShelfID shelf_id) {
1304 DCHECK(shelf_id);
1305 if (ignore_persist_pinned_state_change_)
1306 return;
1307
1308 const int max_index = model_->item_count();
1309 const int index = model_->ItemIndexByID(shelf_id);
1310 DCHECK_GT(index, 0);
1311
1312 const std::string& app_id = GetAppIDForShelfID(shelf_id);
1313 DCHECK(!app_id.empty());
1314
1315 std::string app_id_before;
1316 std::string app_id_after;
1317
1318 for (int i = index - 1; i > 0; --i) {
1319 const ash::ShelfID shelf_id_before = model_->items()[i].id;
1320 if (IsPinned(shelf_id_before)) {
1321 app_id_before = GetAppIDForShelfID(shelf_id_before);
1322 DCHECK(!app_id_before.empty());
1323 break;
1324 }
1325 }
1326
1327 for (int i = index + 1; i < max_index; ++i) {
1328 const ash::ShelfID shelf_id_after = model_->items()[i].id;
1329 if (IsPinned(shelf_id_after)) {
1330 app_id_after = GetAppIDForShelfID(shelf_id_after);
1331 DCHECK(!app_id_after.empty());
1332 break;
1333 }
1334 }
1335
1336 ash::SetPinPosition(profile_, app_id, app_id_before, app_id_after);
1337 }
1338
1339 void ChromeLauncherController::OnSyncModelUpdated() {
1340 UpdateAppLaunchersFromPref();
1341 }
1342
1432 void ChromeLauncherController::UpdateAppLaunchersFromPref() { 1343 void ChromeLauncherController::UpdateAppLaunchersFromPref() {
1433 // There are various functions which will trigger a |PersistPinnedState| call 1344 // There are various functions which will trigger a |SyncPinPosition| call
1434 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu 1345 // like a direct call to |DoPinAppWithID|, or an indirect call to the
1435 // model which will use weights to re-arrange the icons to new positions. 1346 // menu model which will use weights to re-arrange the icons to new positions.
1436 // Since this function is meant to synchronize the "is state" with the 1347 // Since this function is meant to synchronize the "is state" with the
1437 // "sync state", it makes no sense to store any changes by this function back 1348 // "sync state", it makes no sense to store any changes by this function back
1438 // into the pref state. Therefore we tell |persistPinnedState| to ignore any 1349 // into the pref state. Therefore we tell |persistPinnedState| to ignore any
1439 // invocations while we are running. 1350 // invocations while we are running.
1440 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); 1351 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
1352
1441 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs( 1353 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs(
1442 profile_->GetPrefs(), launcher_controller_helper_.get()); 1354 profile_->GetPrefs(), launcher_controller_helper_.get());
1443 1355
1444 int index = 0; 1356 int index = 0;
1445 int max_index = model_->item_count(); 1357 int max_index = model_->item_count();
1358 int seen_chrome_index = -1;
1446 1359
1447 // When one of the two special items cannot be moved (and we do not know where 1360 // At least chrome browser shortcut should exist.
1448 // yet), we remember the current location in one of these variables. 1361 DCHECK_GT(max_index, 0);
1449 int chrome_index = -1; 1362
1450 int app_list_index = -1; 1363 // Skip app list items if it exists.
1364 if (model_->items()[0].type == ash::TYPE_APP_LIST)
1365 ++index;
1451 1366
1452 // Walk the model and |pinned_apps| from the pref lockstep, adding and 1367 // Walk the model and |pinned_apps| from the pref lockstep, adding and
1453 // removing items as necessary. NB: This code uses plain old indexing instead 1368 // removing items as necessary. NB: This code uses plain old indexing instead
1454 // of iterators because of model mutations as part of the loop. 1369 // of iterators because of model mutations as part of the loop.
1455 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); 1370 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
1456 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { 1371 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) {
1457 // Check if we have an item which we need to handle. 1372 // Check if we have an item which we need to handle.
1458 if (*pref_app_id == extension_misc::kChromeAppId || 1373 if (IsAppPinned(*pref_app_id)) {
1459 *pref_app_id == ash::kPinnedAppsPlaceholder || 1374 if (seen_chrome_index >= 0 &&
1460 IsAppPinned(*pref_app_id)) { 1375 *pref_app_id == extension_misc::kChromeAppId) {
1376 // Current item is Chrome browser and we saw it before.
1377 model_->Move(seen_chrome_index, index);
1378 ++pref_app_id;
1379 --index;
1380 continue;
1381 }
1461 for (; index < max_index; ++index) { 1382 for (; index < max_index; ++index) {
1462 const ash::ShelfItem& item(model_->items()[index]); 1383 const ash::ShelfItem& item(model_->items()[index]);
1463 bool is_app_list = item.type == ash::TYPE_APP_LIST; 1384 if (item.type != ash::TYPE_APP_SHORTCUT &&
1464 bool is_chrome = item.type == ash::TYPE_BROWSER_SHORTCUT; 1385 item.type != ash::TYPE_BROWSER_SHORTCUT)
1465 if (item.type != ash::TYPE_APP_SHORTCUT && !is_app_list && !is_chrome)
1466 continue; 1386 continue;
1467 LauncherItemController* controller = GetLauncherItemController(item.id); 1387 LauncherItemController* controller = GetLauncherItemController(item.id);
1468 if ((ash::kPinnedAppsPlaceholder == *pref_app_id && is_app_list) || 1388 if (controller && controller->app_id() == *pref_app_id) {
1469 (extension_misc::kChromeAppId == *pref_app_id && is_chrome) ||
1470 (controller && controller->app_id() == *pref_app_id)) {
1471 // Check if an item needs to be moved here.
1472 MoveChromeOrApplistToFinalPosition(
1473 is_chrome, is_app_list, index, &chrome_index, &app_list_index);
1474 ++pref_app_id; 1389 ++pref_app_id;
1475 break; 1390 break;
1391 } else if (item.type == ash::TYPE_BROWSER_SHORTCUT) {
1392 // We cannot close browser shortcut. Remember its position.
1393 seen_chrome_index = index;
1476 } else { 1394 } else {
1477 if (is_chrome || is_app_list) { 1395 // Check if this is a platform or a windowed app.
1478 // We cannot delete any of these shortcuts. As such we remember 1396 if (item.type == ash::TYPE_APP_SHORTCUT && controller &&
1479 // their positions and move them later where they belong. 1397 (controller->locked() ||
1480 if (is_chrome) 1398 controller->type() == LauncherItemController::TYPE_APP)) {
1481 chrome_index = index; 1399 // Note: This will not change the amount of items (|max_index|).
1482 else 1400 // Even changes to the actual |index| due to item weighting
1483 app_list_index = index; 1401 // changes should be fine.
1484 // And skip the item - or exit the loop if end is reached (note that 1402 UnpinRunningAppInternal(index);
1485 // in that case we will reduce the index again by one and this only
1486 // compensates for it).
1487 if (index >= max_index - 1)
1488 break;
1489 ++index;
1490 } else { 1403 } else {
1491 // Check if this is a platform or a windowed app. 1404 if (controller)
1492 if (item.type == ash::TYPE_APP_SHORTCUT && 1405 LauncherItemClosed(item.id);
1493 controller && 1406 --max_index;
1494 (controller->locked() ||
1495 controller->type() == LauncherItemController::TYPE_APP)) {
1496 // Note: This will not change the amount of items (|max_index|).
1497 // Even changes to the actual |index| due to item weighting
1498 // changes should be fine.
1499 UnpinRunningAppInternal(index);
1500 } else {
1501 if (controller)
1502 LauncherItemClosed(item.id);
1503 --max_index;
1504 }
1505 } 1407 }
1506 --index; 1408 --index;
1507 } 1409 }
1508 } 1410 }
1509 // If the item wasn't found, that means id_to_item_controller_map_ 1411 // If the item wasn't found, that means id_to_item_controller_map_
1510 // is out of sync. 1412 // is out of sync.
1511 DCHECK(index <= max_index); 1413 DCHECK(index <= max_index);
1512 } else { 1414 } else {
1513 // Check if the item was already running but not yet pinned. 1415 // Check if the item was already running but not yet pinned.
1514 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); 1416 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id);
(...skipping 17 matching lines...) Expand all
1532 LauncherItemController* controller = GetLauncherItemController(item.id); 1434 LauncherItemController* controller = GetLauncherItemController(item.id);
1533 if (controller) { 1435 if (controller) {
1534 if (controller->locked() || 1436 if (controller->locked() ||
1535 controller->type() == LauncherItemController::TYPE_APP) { 1437 controller->type() == LauncherItemController::TYPE_APP) {
1536 UnpinRunningAppInternal(index); 1438 UnpinRunningAppInternal(index);
1537 } else { 1439 } else {
1538 LauncherItemClosed(item.id); 1440 LauncherItemClosed(item.id);
1539 } 1441 }
1540 } 1442 }
1541 } else { 1443 } else {
1542 if (item.type == ash::TYPE_BROWSER_SHORTCUT)
1543 chrome_index = index;
1544 else if (item.type == ash::TYPE_APP_LIST)
1545 app_list_index = index;
1546 ++index; 1444 ++index;
1547 } 1445 }
1548 } 1446 }
1549 1447
1550 // Append unprocessed items from the pref to the end of the model. 1448 // Append unprocessed items from the pref to the end of the model.
1551 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { 1449 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) {
1552 // All items but the chrome and / or app list shortcut needs to be added. 1450 if (*pref_app_id == extension_misc::kChromeAppId) {
1553 bool is_chrome = *pref_app_id == extension_misc::kChromeAppId; 1451 int target_index = FindInsertionPoint();
1554 bool is_app_list = *pref_app_id == ash::kPinnedAppsPlaceholder; 1452 DCHECK(seen_chrome_index >= 0 && seen_chrome_index < target_index);
1555 // Coming here we know the next item which can be finalized, either the 1453 model_->Move(seen_chrome_index, target_index);
1556 // chrome item or the app launcher. The final position is the end of the 1454 } else {
1557 // list. The menu model will make sure that the item is grouped according
1558 // to its weight (which we do not know here).
1559 if (!is_chrome && !is_app_list) {
1560 DoPinAppWithID(*pref_app_id); 1455 DoPinAppWithID(*pref_app_id);
1561 int target_index = FindInsertionPoint(false); 1456 int target_index = FindInsertionPoint();
1562 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id); 1457 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id);
1563 int source_index = model_->ItemIndexByID(id); 1458 int source_index = model_->ItemIndexByID(id);
1564 if (source_index != target_index) 1459 if (source_index != target_index)
1565 model_->Move(source_index, target_index); 1460 model_->Move(source_index, target_index);
1566
1567 // Needed for the old layout - the weight might force it to be lower in
1568 // rank.
1569 if (app_list_index != -1 && target_index <= app_list_index)
1570 ++app_list_index;
1571 } else {
1572 int target_index = FindInsertionPoint(is_app_list);
1573 MoveChromeOrApplistToFinalPosition(
1574 is_chrome, is_app_list, target_index, &chrome_index, &app_list_index);
1575 } 1461 }
1576 } 1462 }
1577 } 1463 }
1578 1464
1579 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { 1465 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() {
1580 for (auto* window : ash::Shell::GetAllRootWindows()) { 1466 for (auto* window : ash::Shell::GetAllRootWindows()) {
1581 ash::Shelf* shelf = ash::Shelf::ForWindow(window); 1467 ash::Shelf* shelf = ash::Shelf::ForWindow(window);
1582 if (shelf) { 1468 if (shelf) {
1583 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref( 1469 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref(
1584 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); 1470 profile_->GetPrefs(), GetDisplayIDForShelf(shelf)));
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1704 << "There should be always be a BrowserShortcutLauncherItemController."; 1590 << "There should be always be a BrowserShortcutLauncherItemController.";
1705 return nullptr; 1591 return nullptr;
1706 } 1592 }
1707 1593
1708 ash::ShelfID ChromeLauncherController::CreateBrowserShortcutLauncherItem() { 1594 ash::ShelfID ChromeLauncherController::CreateBrowserShortcutLauncherItem() {
1709 ash::ShelfItem browser_shortcut; 1595 ash::ShelfItem browser_shortcut;
1710 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; 1596 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT;
1711 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1597 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
1712 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); 1598 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
1713 ash::ShelfID id = model_->next_id(); 1599 ash::ShelfID id = model_->next_id();
1714 size_t index = GetChromeIconIndexForCreation(); 1600 model_->AddAt(0, browser_shortcut);
1715 model_->AddAt(index, browser_shortcut);
1716 id_to_item_controller_map_[id] = 1601 id_to_item_controller_map_[id] =
1717 new BrowserShortcutLauncherItemController(this, model_); 1602 new BrowserShortcutLauncherItemController(this, model_);
1718 id_to_item_controller_map_[id]->set_shelf_id(id); 1603 id_to_item_controller_map_[id]->set_shelf_id(id);
1719 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController. 1604 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController.
1720 SetShelfItemDelegate(id, id_to_item_controller_map_[id]); 1605 SetShelfItemDelegate(id, id_to_item_controller_map_[id]);
1721 return id; 1606 return id;
1722 } 1607 }
1723 1608
1724 void ChromeLauncherController::PersistChromeItemIndex(int index) { 1609 int ChromeLauncherController::FindInsertionPoint() {
1725 profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index); 1610 DCHECK_GT(model_->item_count(), 0);
1726 }
1727
1728 void ChromeLauncherController::MoveChromeOrApplistToFinalPosition(
1729 bool is_chrome,
1730 bool is_app_list,
1731 int target_index,
1732 int* chrome_index,
1733 int* app_list_index) {
1734 if (is_chrome && *chrome_index != -1) {
1735 model_->Move(*chrome_index, target_index);
1736 if (*app_list_index != -1 &&
1737 *chrome_index < *app_list_index &&
1738 target_index > *app_list_index)
1739 --(*app_list_index);
1740 *chrome_index = -1;
1741 } else if (is_app_list && *app_list_index != -1) {
1742 model_->Move(*app_list_index, target_index);
1743 if (*chrome_index != -1 &&
1744 *app_list_index < *chrome_index &&
1745 target_index > *chrome_index)
1746 --(*chrome_index);
1747 *app_list_index = -1;
1748 }
1749 }
1750
1751 int ChromeLauncherController::FindInsertionPoint(bool is_app_list) {
1752 // Keeping this change small to backport to M33&32 (see crbug.com/329597).
1753 // TODO(skuhne): With the removal of the legacy shelf layout we should remove
1754 // the ability to move the app list item since this was never used. We should
1755 // instead ask the ShelfModel::ValidateInsertionIndex or similir for an index.
1756 if (is_app_list)
1757 return 0;
1758 1611
1759 for (int i = model_->item_count() - 1; i > 0; --i) { 1612 for (int i = model_->item_count() - 1; i > 0; --i) {
1760 ash::ShelfItemType type = model_->items()[i].type; 1613 ash::ShelfItemType type = model_->items()[i].type;
1614 DCHECK_NE(ash::TYPE_APP_LIST, type);
1761 if (type == ash::TYPE_APP_SHORTCUT || 1615 if (type == ash::TYPE_APP_SHORTCUT ||
1762 (is_app_list && type == ash::TYPE_APP_LIST) ||
1763 type == ash::TYPE_BROWSER_SHORTCUT) { 1616 type == ash::TYPE_BROWSER_SHORTCUT) {
1764 return i; 1617 return i;
1765 } 1618 }
1766 } 1619 }
1767 return 0; 1620 return 0;
1768 } 1621 }
1769 1622
1770 int ChromeLauncherController::GetChromeIconIndexForCreation() {
1771 // We get the list of pinned apps as they currently would get pinned.
1772 // Within this list the chrome icon will be the correct location.
1773 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs(
1774 profile_->GetPrefs(), launcher_controller_helper_.get());
1775
1776 std::vector<std::string>::iterator it =
1777 std::find(pinned_apps.begin(),
1778 pinned_apps.end(),
1779 std::string(extension_misc::kChromeAppId));
1780 DCHECK(it != pinned_apps.end());
1781 int index = it - pinned_apps.begin();
1782
1783 // We should do here a comparison between the is state and the "want to be"
1784 // state since some apps might be able to pin but are not yet. Instead - for
1785 // the time being we clamp against the amount of known items and wait for the
1786 // next |UpdateAppLaunchersFromPref()| call to correct it - it will come since
1787 // the pinning will be done then.
1788 return std::min(model_->item_count(), index);
1789 }
1790
1791 bool ChromeLauncherController::IsIncognito( 1623 bool ChromeLauncherController::IsIncognito(
1792 const content::WebContents* web_contents) const { 1624 const content::WebContents* web_contents) const {
1793 const Profile* profile = 1625 const Profile* profile =
1794 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 1626 Profile::FromBrowserContext(web_contents->GetBrowserContext());
1795 return profile->IsOffTheRecord() && !profile->IsGuestSession() && 1627 return profile->IsOffTheRecord() && !profile->IsGuestSession() &&
1796 !profile->IsSystemProfile(); 1628 !profile->IsSystemProfile();
1797 } 1629 }
1798 1630
1799 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension( 1631 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension(
1800 const std::string& app_id, 1632 const std::string& app_id,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { 1685 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) {
1854 DCHECK(arc_deferred_launcher()); 1686 DCHECK(arc_deferred_launcher());
1855 std::unique_ptr<AppIconLoader> arc_app_icon_loader( 1687 std::unique_ptr<AppIconLoader> arc_app_icon_loader(
1856 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL, 1688 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL,
1857 arc_deferred_launcher(), this)); 1689 arc_deferred_launcher(), this));
1858 app_icon_loaders_.push_back(std::move(arc_app_icon_loader)); 1690 app_icon_loaders_.push_back(std::move(arc_app_icon_loader));
1859 } 1691 }
1860 1692
1861 pref_change_registrar_.Init(profile_->GetPrefs()); 1693 pref_change_registrar_.Init(profile_->GetPrefs());
1862 pref_change_registrar_.Add( 1694 pref_change_registrar_.Add(
1863 prefs::kPinnedLauncherApps,
1864 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref,
1865 base::Unretained(this)));
1866 pref_change_registrar_.Add(
1867 prefs::kPolicyPinnedLauncherApps, 1695 prefs::kPolicyPinnedLauncherApps,
1868 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, 1696 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref,
1869 base::Unretained(this))); 1697 base::Unretained(this)));
1870 pref_change_registrar_.Add( 1698 pref_change_registrar_.Add(
1871 prefs::kShelfAlignmentLocal, 1699 prefs::kShelfAlignmentLocal,
1872 base::Bind(&ChromeLauncherController::SetShelfAlignmentFromPrefs, 1700 base::Bind(&ChromeLauncherController::SetShelfAlignmentFromPrefs,
1873 base::Unretained(this))); 1701 base::Unretained(this)));
1874 pref_change_registrar_.Add( 1702 pref_change_registrar_.Add(
1875 prefs::kShelfAutoHideBehaviorLocal, 1703 prefs::kShelfAutoHideBehaviorLocal,
1876 base::Bind(&ChromeLauncherController:: 1704 base::Bind(&ChromeLauncherController::
(...skipping 10 matching lines...) Expand all
1887 1715
1888 std::unique_ptr<LauncherAppUpdater> extension_app_updater( 1716 std::unique_ptr<LauncherAppUpdater> extension_app_updater(
1889 new LauncherExtensionAppUpdater(this, profile_)); 1717 new LauncherExtensionAppUpdater(this, profile_));
1890 app_updaters_.push_back(std::move(extension_app_updater)); 1718 app_updaters_.push_back(std::move(extension_app_updater));
1891 1719
1892 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { 1720 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) {
1893 std::unique_ptr<LauncherAppUpdater> arc_app_updater( 1721 std::unique_ptr<LauncherAppUpdater> arc_app_updater(
1894 new LauncherArcAppUpdater(this, profile_)); 1722 new LauncherArcAppUpdater(this, profile_));
1895 app_updaters_.push_back(std::move(arc_app_updater)); 1723 app_updaters_.push_back(std::move(arc_app_updater));
1896 } 1724 }
1725
1726 app_list::AppListSyncableService* app_service =
1727 app_list::AppListSyncableService::Get(profile_);
1728 if (app_service)
1729 app_service->AddObserverAndStart(this);
1897 } 1730 }
1898 1731
1899 void ChromeLauncherController::ReleaseProfile() { 1732 void ChromeLauncherController::ReleaseProfile() {
1900 if (app_sync_ui_state_) 1733 if (app_sync_ui_state_)
1901 app_sync_ui_state_->RemoveObserver(this); 1734 app_sync_ui_state_->RemoveObserver(this);
1902 1735
1903 app_updaters_.clear(); 1736 app_updaters_.clear();
1904 1737
1905 PrefServiceSyncableFromProfile(profile_)->RemoveObserver(this); 1738 PrefServiceSyncableFromProfile(profile_)->RemoveObserver(this);
1906 1739
1907 pref_change_registrar_.RemoveAll(); 1740 pref_change_registrar_.RemoveAll();
1741
1742 app_list::AppListSyncableService* app_service =
1743 app_list::AppListSyncableService::Get(profile_);
1744 if (app_service)
1745 app_service->RemoveObserver(this);
1908 } 1746 }
1909 1747
1910 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp( 1748 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp(
1911 const std::string& app_id) { 1749 const std::string& app_id) {
1912 for (const auto& app_icon_loader : app_icon_loaders_) { 1750 for (const auto& app_icon_loader : app_icon_loaders_) {
1913 if (app_icon_loader->CanLoadImageForApp(app_id)) 1751 if (app_icon_loader->CanLoadImageForApp(app_id))
1914 return app_icon_loader.get(); 1752 return app_icon_loader.get();
1915 } 1753 }
1916 1754
1917 return nullptr; 1755 return nullptr;
1918 } 1756 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698