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

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

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

Powered by Google App Engine
This is Rietveld 408576698