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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc

Issue 2385753002: [Merge-M54] Fix possible overlapping icons in shelf on sync. (Closed)
Patch Set: Created 4 years, 2 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 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 } 1117 }
1118 } 1118 }
1119 1119
1120 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id, 1120 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id,
1121 bool update_prefs) { 1121 bool update_prefs) {
1122 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); 1122 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id);
1123 if (shelf_id && IsPinned(shelf_id)) 1123 if (shelf_id && IsPinned(shelf_id))
1124 UnpinAndUpdatePrefs(shelf_id, update_prefs); 1124 UnpinAndUpdatePrefs(shelf_id, update_prefs);
1125 } 1125 }
1126 1126
1127 int ChromeLauncherControllerImpl::PinRunningAppInternal(int index, 1127 void ChromeLauncherControllerImpl::PinRunningAppInternal(
1128 ash::ShelfID shelf_id) { 1128 int index,
1129 ash::ShelfID shelf_id) {
1129 int running_index = model_->ItemIndexByID(shelf_id); 1130 int running_index = model_->ItemIndexByID(shelf_id);
1130 ash::ShelfItem item = model_->items()[running_index]; 1131 ash::ShelfItem item = model_->items()[running_index];
1131 DCHECK(item.type == ash::TYPE_WINDOWED_APP || 1132 DCHECK(item.type == ash::TYPE_WINDOWED_APP ||
1132 item.type == ash::TYPE_PLATFORM_APP); 1133 item.type == ash::TYPE_PLATFORM_APP);
1133 item.type = ash::TYPE_APP_SHORTCUT; 1134 item.type = ash::TYPE_APP_SHORTCUT;
1134 model_->Set(running_index, item); 1135 model_->Set(running_index, item);
1135 // The |ShelfModel|'s weight system might reposition the item to a 1136 // The |ShelfModel|'s weight system might reposition the item to a
1136 // new index, so we get the index again. 1137 // new index, so we get the index again.
1137 running_index = model_->ItemIndexByID(shelf_id); 1138 running_index = model_->ItemIndexByID(shelf_id);
1138 if (running_index < index) 1139 if (running_index < index)
1139 --index; 1140 --index;
1140 if (running_index != index) 1141 if (running_index != index)
1141 model_->Move(running_index, index); 1142 model_->Move(running_index, index);
1142 return index;
1143 } 1143 }
1144 1144
1145 void ChromeLauncherControllerImpl::UnpinRunningAppInternal(int index) { 1145 void ChromeLauncherControllerImpl::UnpinRunningAppInternal(int index) {
1146 DCHECK_GE(index, 0); 1146 DCHECK_GE(index, 0);
1147 ash::ShelfItem item = model_->items()[index]; 1147 ash::ShelfItem item = model_->items()[index];
1148 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); 1148 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT);
1149 item.type = ash::TYPE_WINDOWED_APP; 1149 item.type = ash::TYPE_WINDOWED_APP;
1150 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such 1150 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such
1151 // we have to check here what this was before it got a shortcut. 1151 // we have to check here what this was before it got a shortcut.
1152 LauncherItemController* controller = GetLauncherItemController(item.id); 1152 LauncherItemController* controller = GetLauncherItemController(item.id);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 1204
1205 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { 1205 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() {
1206 // There are various functions which will trigger a |SyncPinPosition| call 1206 // There are various functions which will trigger a |SyncPinPosition| call
1207 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu 1207 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu
1208 // model which will use weights to re-arrange the icons to new positions. 1208 // model which will use weights to re-arrange the icons to new positions.
1209 // Since this function is meant to synchronize the "is state" with the 1209 // Since this function is meant to synchronize the "is state" with the
1210 // "sync state", it makes no sense to store any changes by this function back 1210 // "sync state", it makes no sense to store any changes by this function back
1211 // into the pref state. Therefore we tell |persistPinnedState| to ignore any 1211 // into the pref state. Therefore we tell |persistPinnedState| to ignore any
1212 // invocations while we are running. 1212 // invocations while we are running.
1213 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); 1213 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
1214 std::vector<std::string> pinned_apps = ash::launcher::GetPinnedAppsFromPrefs( 1214 const std::vector<std::string> pinned_apps =
1215 profile_->GetPrefs(), launcher_controller_helper_.get()); 1215 ash::launcher::GetPinnedAppsFromPrefs(profile_->GetPrefs(),
1216 launcher_controller_helper_.get());
1216 1217
1217 int index = 0; 1218 int index = 0;
1218 int max_index = model_->item_count();
1219 int seen_chrome_index = -1;
1220
1221 // At least chrome browser shortcut should exist.
1222 DCHECK_GT(max_index, 0);
1223
1224 // Skip app list items if it exists. 1219 // Skip app list items if it exists.
1225 if (model_->items()[0].type == ash::TYPE_APP_LIST) 1220 if (model_->items()[0].type == ash::TYPE_APP_LIST)
1226 ++index; 1221 ++index;
1227 1222
1228 // Walk the model and |pinned_apps| from the pref lockstep, adding and 1223 // Apply pins in two steps. At the first step, go through the list of apps to
1229 // removing items as necessary. NB: This code uses plain old indexing instead 1224 // pin, move existing pin to current position specified by |index| or create
1230 // of iterators because of model mutations as part of the loop. 1225 // the new pin at that position.
1231 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); 1226 for (const auto& pref_app_id : pinned_apps) {
1232 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { 1227 // Filter out apps that may be mapped wrongly.
1228 // TODO(khmel): b/31703859 is to refactore shelf mapping.
1229 const std::string shelf_app_id =
1230 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(pref_app_id);
1231 if (shelf_app_id != pref_app_id)
1232 continue;
1233
1233 // Update apps icon if applicable. 1234 // Update apps icon if applicable.
1234 OnAppUpdated(profile_, *pref_app_id); 1235 OnAppUpdated(profile_, pref_app_id);
1235 // Check if we have an item which we need to handle. 1236
1236 if (IsAppPinned(*pref_app_id)) { 1237 // Find existing pin or app from the right of current |index|.
1237 if (seen_chrome_index >= 0 && 1238 int app_index = index;
1238 *pref_app_id == extension_misc::kChromeAppId) { 1239 for (; app_index < model_->item_count(); ++app_index) {
1239 // Current item is Chrome browser and we saw it before. 1240 const ash::ShelfItem& item = model_->items()[app_index];
1240 model_->Move(seen_chrome_index, index); 1241 const IDToItemControllerMap::iterator it =
1241 ++pref_app_id; 1242 id_to_item_controller_map_.find(item.id);
1242 --index; 1243 if (it != id_to_item_controller_map_.end() &&
1243 continue; 1244 it->second->app_id() == pref_app_id) {
1245 break;
1244 } 1246 }
1245 for (; index < max_index; ++index) { 1247 }
1246 const ash::ShelfItem& item(model_->items()[index]); 1248 if (app_index < model_->item_count()) {
1247 if (item.type != ash::TYPE_APP_SHORTCUT && 1249 // Found existing pin or running app.
1248 item.type != ash::TYPE_BROWSER_SHORTCUT) { 1250 const ash::ShelfItem item = model_->items()[app_index];
1249 continue; 1251 if (item.type == ash::TYPE_APP_SHORTCUT ||
1250 } 1252 item.type == ash::TYPE_BROWSER_SHORTCUT) {
1251 LauncherItemController* controller = GetLauncherItemController(item.id); 1253 // Just move to required position or keep it inplace.
1252 if (controller && controller->app_id() == *pref_app_id) { 1254 model_->Move(app_index, index);
1253 ++pref_app_id; 1255 } else {
1254 break; 1256 PinRunningAppInternal(index, item.id);
1255 } else if (item.type == ash::TYPE_BROWSER_SHORTCUT) {
1256 // We cannot close browser shortcut. Remember its position.
1257 seen_chrome_index = index;
1258 } else {
1259 // Check if this is a platform or a windowed app.
1260 if (item.type == ash::TYPE_APP_SHORTCUT && controller &&
1261 (controller->locked() ||
1262 controller->type() == LauncherItemController::TYPE_APP)) {
1263 // Note: This will not change the amount of items (|max_index|).
1264 // Even changes to the actual |index| due to item weighting
1265 // changes should be fine.
1266 UnpinRunningAppInternal(index);
1267 } else {
1268 if (controller)
1269 LauncherItemClosed(item.id);
1270 --max_index;
1271 }
1272 --index;
1273 }
1274 } 1257 }
1275 // If the item wasn't found, that means id_to_item_controller_map_ 1258 DCHECK_EQ(model_->ItemIndexByID(item.id), index);
1276 // is out of sync.
1277 DCHECK(index <= max_index);
1278 } else { 1259 } else {
1279 // Check if the item was already running but not yet pinned. 1260 // This is fresh pin. Create new one.
1280 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); 1261 DCHECK_NE(pref_app_id, extension_misc::kChromeAppId);
1281 if (shelf_id) { 1262 CreateAppShortcutLauncherItem(pref_app_id, index);
1282 // This app is running but not yet pinned. So pin and move it.
1283 index = PinRunningAppInternal(index, shelf_id);
1284 } else {
1285 // This app wasn't pinned before, insert a new entry.
1286 shelf_id = CreateAppShortcutLauncherItem(*pref_app_id, index);
1287 ++max_index;
1288 index = model_->ItemIndexByID(shelf_id);
1289 }
1290 ++pref_app_id;
1291 } 1263 }
1264 ++index;
1292 } 1265 }
1293 1266
1294 // Remove any trailing existing items. 1267 // At second step remove any pin to the right from the current index.
1295 while (index < model_->item_count()) { 1268 while (index < model_->item_count()) {
1296 const ash::ShelfItem& item(model_->items()[index]); 1269 const ash::ShelfItem item = model_->items()[index];
1297 if (item.type == ash::TYPE_APP_SHORTCUT) { 1270 if (item.type != ash::TYPE_APP_SHORTCUT) {
1298 LauncherItemController* controller = GetLauncherItemController(item.id); 1271 ++index;
1299 if (controller) { 1272 continue;
1300 if (controller->locked() || 1273 }
1301 controller->type() == LauncherItemController::TYPE_APP) { 1274
1302 UnpinRunningAppInternal(index); 1275 const LauncherItemController* controller =
1303 } else { 1276 GetLauncherItemController(item.id);
1304 LauncherItemClosed(item.id); 1277 DCHECK(controller);
1305 } 1278 DCHECK_NE(controller->app_id(), extension_misc::kChromeAppId);
1306 } 1279
1280 if (controller->locked() ||
1281 controller->type() == LauncherItemController::TYPE_APP) {
1282 UnpinRunningAppInternal(index);
1283 // Note, item can be moved to the right due weighting in shelf model.
1284 DCHECK_GE(model_->ItemIndexByID(item.id), index);
1307 } else { 1285 } else {
1308 ++index; 1286 LauncherItemClosed(item.id);
1309 }
1310 }
1311
1312 // Append unprocessed items from the pref to the end of the model.
1313 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) {
1314 // Update apps icon if applicable.
1315 OnAppUpdated(profile_, *pref_app_id);
1316 if (*pref_app_id == extension_misc::kChromeAppId) {
1317 int target_index = FindInsertionPoint();
1318 DCHECK(seen_chrome_index >= 0 && seen_chrome_index < target_index);
1319 model_->Move(seen_chrome_index, target_index);
1320 } else {
1321 DoPinAppWithID(*pref_app_id);
1322 int target_index = FindInsertionPoint();
1323 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id);
1324 int source_index = model_->ItemIndexByID(id);
1325 if (source_index != target_index)
1326 model_->Move(source_index, target_index);
1327 } 1287 }
1328 } 1288 }
1329 } 1289 }
1330 1290
1331 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() { 1291 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() {
1332 for (ash::WmWindow* window : ash::WmShell::Get()->GetAllRootWindows()) { 1292 for (ash::WmWindow* window : ash::WmShell::Get()->GetAllRootWindows()) {
1333 ash::Shelf* shelf = ash::Shelf::ForWindow(window); 1293 ash::Shelf* shelf = ash::Shelf::ForWindow(window);
1334 if (shelf) { 1294 if (shelf) {
1335 shelf->wm_shelf()->SetAutoHideBehavior( 1295 shelf->wm_shelf()->SetAutoHideBehavior(
1336 ash::launcher::GetShelfAutoHideBehaviorPref( 1296 ash::launcher::GetShelfAutoHideBehaviorPref(
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 if (index == -1) 1665 if (index == -1)
1706 continue; 1666 continue;
1707 ash::ShelfItem item = model_->items()[index]; 1667 ash::ShelfItem item = model_->items()[index];
1708 item.image = image; 1668 item.image = image;
1709 if (arc_deferred_launcher_) 1669 if (arc_deferred_launcher_)
1710 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image); 1670 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image);
1711 model_->Set(index, item); 1671 model_->Set(index, item);
1712 // It's possible we're waiting on more than one item, so don't break. 1672 // It's possible we're waiting on more than one item, so don't break.
1713 } 1673 }
1714 } 1674 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698