OLD | NEW |
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 <vector> | 7 #include <vector> |
8 | 8 |
9 #include "ash/ash_switches.h" | 9 #include "ash/ash_switches.h" |
10 #include "ash/desktop_background/desktop_background_controller.h" | 10 #include "ash/desktop_background/desktop_background_controller.h" |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 } | 429 } |
430 | 430 |
431 if (CanPin()) | 431 if (CanPin()) |
432 PersistPinnedState(); | 432 PersistPinnedState(); |
433 } | 433 } |
434 | 434 |
435 void ChromeLauncherController::Unpin(ash::LauncherID id) { | 435 void ChromeLauncherController::Unpin(ash::LauncherID id) { |
436 DCHECK(HasItemController(id)); | 436 DCHECK(HasItemController(id)); |
437 | 437 |
438 LauncherItemController* controller = id_to_item_controller_map_[id]; | 438 LauncherItemController* controller = id_to_item_controller_map_[id]; |
439 if (controller->type() == LauncherItemController::TYPE_APP || | 439 if (controller->type() == LauncherItemController::TYPE_APP) { |
440 controller->locked()) { | 440 int index = model_->ItemIndexByID(id); |
441 UnpinRunningAppInternal(model_->ItemIndexByID(id)); | 441 DCHECK_GE(index, 0); |
| 442 ash::LauncherItem item = model_->items()[index]; |
| 443 item.type = ash::TYPE_PLATFORM_APP; |
| 444 model_->Set(index, item); |
442 } else { | 445 } else { |
443 LauncherItemClosed(id); | 446 // Prevent the removal of items upon unpin if it is locked by a running |
| 447 // windowed V1 app. |
| 448 if (!controller->locked()) { |
| 449 LauncherItemClosed(id); |
| 450 } else { |
| 451 int index = model_->ItemIndexByID(id); |
| 452 DCHECK_GE(index, 0); |
| 453 ash::LauncherItem item = model_->items()[index]; |
| 454 item.type = ash::TYPE_WINDOWED_APP; |
| 455 model_->Set(index, item); |
| 456 } |
444 } | 457 } |
445 if (CanPin()) | 458 if (CanPin()) |
446 PersistPinnedState(); | 459 PersistPinnedState(); |
447 } | 460 } |
448 | 461 |
449 bool ChromeLauncherController::IsPinned(ash::LauncherID id) { | 462 bool ChromeLauncherController::IsPinned(ash::LauncherID id) { |
450 int index = model_->ItemIndexByID(id); | 463 int index = model_->ItemIndexByID(id); |
451 if (index < 0) | 464 if (index < 0) |
452 return false; | 465 return false; |
453 ash::LauncherItemType type = model_->items()[index].type; | 466 ash::LauncherItemType type = model_->items()[index].type; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 if (ignore_persist_pinned_state_change_) | 733 if (ignore_persist_pinned_state_change_) |
721 return; | 734 return; |
722 // It is a coding error to call PersistPinnedState() if the pinned apps are | 735 // It is a coding error to call PersistPinnedState() if the pinned apps are |
723 // not user-editable. The code should check earlier and not perform any | 736 // not user-editable. The code should check earlier and not perform any |
724 // modification actions that trigger persisting the state. | 737 // modification actions that trigger persisting the state. |
725 if (!CanPin()) { | 738 if (!CanPin()) { |
726 NOTREACHED() << "Can't pin but pinned state being updated"; | 739 NOTREACHED() << "Can't pin but pinned state being updated"; |
727 return; | 740 return; |
728 } | 741 } |
729 | 742 |
730 // With the alternate shelf layout, the app list is locked in position #0. | |
731 // Since the app list does not have any impact on the rest of the order, | |
732 // we need to keep track of its appearance so that the chrome icon position | |
733 // is at the proper location (backwards compatible). | |
734 size_t app_list_index_offset = 0; | |
735 | |
736 // Mutating kPinnedLauncherApps is going to notify us and trigger us to | 743 // Mutating kPinnedLauncherApps is going to notify us and trigger us to |
737 // process the change. We don't want that to happen so remove ourselves as a | 744 // process the change. We don't want that to happen so remove ourselves as a |
738 // listener. | 745 // listener. |
739 pref_change_registrar_.Remove(prefs::kPinnedLauncherApps); | 746 pref_change_registrar_.Remove(prefs::kPinnedLauncherApps); |
740 { | 747 { |
741 ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps); | 748 ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps); |
742 updater->Clear(); | 749 updater->Clear(); |
743 for (size_t i = 0; i < model_->items().size(); ++i) { | 750 for (size_t i = 0; i < model_->items().size(); ++i) { |
744 if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) { | 751 if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) { |
745 ash::LauncherID id = model_->items()[i].id; | 752 ash::LauncherID id = model_->items()[i].id; |
746 if (HasItemController(id) && IsPinned(id)) { | 753 if (HasItemController(id) && IsPinned(id)) { |
747 base::DictionaryValue* app_value = ash::CreateAppDict( | 754 base::DictionaryValue* app_value = ash::CreateAppDict( |
748 id_to_item_controller_map_[id]->app_id()); | 755 id_to_item_controller_map_[id]->app_id()); |
749 if (app_value) | 756 if (app_value) |
750 updater->Append(app_value); | 757 updater->Append(app_value); |
751 } | 758 } |
752 } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) { | 759 } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) { |
753 PersistChromeItemIndex(i - app_list_index_offset); | 760 PersistChromeItemIndex(i); |
754 } else if (model_->items()[i].type == ash::TYPE_APP_LIST && | |
755 ash::switches::UseAlternateShelfLayout()) { | |
756 // With the new alternate shelf layout the app list can be pinned to the | |
757 // position 0 and should not be taken into account. | |
758 app_list_index_offset = 1; | |
759 } | 761 } |
760 } | 762 } |
761 } | 763 } |
762 pref_change_registrar_.Add( | 764 pref_change_registrar_.Add( |
763 prefs::kPinnedLauncherApps, | 765 prefs::kPinnedLauncherApps, |
764 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, | 766 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, |
765 base::Unretained(this))); | 767 base::Unretained(this))); |
766 } | 768 } |
767 | 769 |
768 ash::LauncherModel* ChromeLauncherController::model() { | 770 ash::LauncherModel* ChromeLauncherController::model() { |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 PersistPinnedState(); | 1302 PersistPinnedState(); |
1301 } | 1303 } |
1302 } | 1304 } |
1303 | 1305 |
1304 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) { | 1306 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) { |
1305 ash::LauncherID launcher_id = GetLauncherIDForAppID(app_id); | 1307 ash::LauncherID launcher_id = GetLauncherIDForAppID(app_id); |
1306 if (launcher_id && IsPinned(launcher_id)) | 1308 if (launcher_id && IsPinned(launcher_id)) |
1307 Unpin(launcher_id); | 1309 Unpin(launcher_id); |
1308 } | 1310 } |
1309 | 1311 |
1310 int ChromeLauncherController::PinRunningAppInternal( | |
1311 int index, | |
1312 ash::LauncherID launcher_id) { | |
1313 int running_index = model_->ItemIndexByID(launcher_id); | |
1314 ash::LauncherItem item = model_->items()[running_index]; | |
1315 DCHECK(item.type == ash::TYPE_WINDOWED_APP || | |
1316 item.type == ash::TYPE_PLATFORM_APP); | |
1317 item.type = ash::TYPE_APP_SHORTCUT; | |
1318 model_->Set(running_index, item); | |
1319 // The |LauncherModel|'s weight system might reposition the item to a | |
1320 // new index, so we get the index again. | |
1321 running_index = model_->ItemIndexByID(launcher_id); | |
1322 if (running_index < index) | |
1323 --index; | |
1324 if (running_index != index) | |
1325 model_->Move(running_index, index); | |
1326 return index; | |
1327 } | |
1328 | |
1329 void ChromeLauncherController::UnpinRunningAppInternal(int index) { | |
1330 DCHECK_GE(index, 0); | |
1331 ash::LauncherItem item = model_->items()[index]; | |
1332 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); | |
1333 item.type = ash::TYPE_WINDOWED_APP; | |
1334 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such | |
1335 // we have to check here what this was before it got a shortcut. | |
1336 if (HasItemController(item.id) && | |
1337 id_to_item_controller_map_[item.id]->type() == | |
1338 LauncherItemController::TYPE_APP) | |
1339 item.type = ash::TYPE_PLATFORM_APP; | |
1340 model_->Set(index, item); | |
1341 } | |
1342 | |
1343 void ChromeLauncherController::UpdateAppLaunchersFromPref() { | 1312 void ChromeLauncherController::UpdateAppLaunchersFromPref() { |
1344 // There are various functions which will trigger a |PersistPinnedState| call | 1313 // Construct a vector representation of to-be-pinned apps from the pref. |
1345 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu | 1314 std::vector<std::string> pinned_apps; |
1346 // model which will use weights to re-arrange the icons to new positions. | 1315 int chrome_icon_index = GetChromeIconIndexFromPref(); |
1347 // Since this function is meant to synchronize the "is state" with the | |
1348 // "sync state", it makes no sense to store any changes by this function back | |
1349 // into the pref state. Therefore we tell |persistPinnedState| to ignore any | |
1350 // invocations while we are running. | |
1351 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); | |
1352 std::vector<std::string> pinned_apps = GetListOfPinnedAppsAndBrowser(); | |
1353 | |
1354 int index = 0; | 1316 int index = 0; |
1355 int max_index = model_->item_count(); | 1317 int max_index = model_->item_count(); |
1356 | 1318 // Using the alternate shelf layout the App Icon should be the first item in |
1357 // Using the alternate shelf layout the app list Icon should be the first item | 1319 // the list thus start adding items at slot 1 (instead of slot 0). |
1358 // in the list thus start adding items at slot 1 (instead of slot 0). | |
1359 if (ash::switches::UseAlternateShelfLayout()) { | 1320 if (ash::switches::UseAlternateShelfLayout()) { |
1360 ++index; | 1321 ++index; |
1361 ++max_index; | 1322 ++max_index; |
| 1323 // The alternate shelf layout's icon position will always include the |
| 1324 // AppLauncher which needs to be subtracted here. |
| 1325 if (chrome_icon_index > 0) |
| 1326 --chrome_icon_index; |
| 1327 } |
| 1328 const base::ListValue* pinned_apps_pref = |
| 1329 profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps); |
| 1330 for (base::ListValue::const_iterator it(pinned_apps_pref->begin()); |
| 1331 it != pinned_apps_pref->end(); ++it) { |
| 1332 // To preserve the Chrome icon position, we insert a dummy slot for it - if |
| 1333 // the model has a Chrome item. While initializing we can come here with no |
| 1334 // item in which case the count would be 1 or below. |
| 1335 if (it - pinned_apps_pref->begin() == chrome_icon_index && |
| 1336 model_->item_count() > 1) { |
| 1337 pinned_apps.push_back(extension_misc::kChromeAppId); |
| 1338 } |
| 1339 |
| 1340 DictionaryValue* app = NULL; |
| 1341 std::string app_id; |
| 1342 if ((*it)->GetAsDictionary(&app) && |
| 1343 app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id) && |
| 1344 std::find(pinned_apps.begin(), pinned_apps.end(), app_id) == |
| 1345 pinned_apps.end() && |
| 1346 app_tab_helper_->IsValidID(app_id)) { |
| 1347 pinned_apps.push_back(app_id); |
| 1348 } |
1362 } | 1349 } |
1363 | 1350 |
1364 // Walk the model and |pinned_apps| from the pref lockstep, adding and | 1351 // Walk the model and |pinned_apps| from the pref lockstep, adding and |
1365 // removing items as necessary. NB: This code uses plain old indexing instead | 1352 // removing items as necessary. NB: This code uses plain old indexing instead |
1366 // of iterators because of model mutations as part of the loop. | 1353 // of iterators because of model mutations as part of the loop. |
1367 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); | 1354 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); |
1368 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { | 1355 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { |
1369 // If the next app launcher according to the pref is present in the model, | 1356 // If the next app launcher according to the pref is present in the model, |
1370 // delete all app launcher entries in between. | 1357 // delete all app launcher entries in between. |
1371 if (*pref_app_id == extension_misc::kChromeAppId || | 1358 if (*pref_app_id == extension_misc::kChromeAppId || |
(...skipping 10 matching lines...) Expand all Loading... |
1382 item.type == ash::TYPE_BROWSER_SHORTCUT) || | 1369 item.type == ash::TYPE_BROWSER_SHORTCUT) || |
1383 (entry != id_to_item_controller_map_.end() && | 1370 (entry != id_to_item_controller_map_.end() && |
1384 entry->second->app_id() == *pref_app_id)) { | 1371 entry->second->app_id() == *pref_app_id)) { |
1385 ++pref_app_id; | 1372 ++pref_app_id; |
1386 break; | 1373 break; |
1387 } else { | 1374 } else { |
1388 if (item.type == ash::TYPE_BROWSER_SHORTCUT) { | 1375 if (item.type == ash::TYPE_BROWSER_SHORTCUT) { |
1389 // We cannot delete the browser shortcut. As such we move it up by | 1376 // We cannot delete the browser shortcut. As such we move it up by |
1390 // one. To avoid any side effects from our pinned state observer, we | 1377 // one. To avoid any side effects from our pinned state observer, we |
1391 // do not call the model directly. | 1378 // do not call the model directly. |
1392 model_->Move(index, index + 1); | 1379 MoveItemWithoutPinnedStateChangeNotification(index, index + 1); |
1393 } else { | 1380 } else { |
1394 // Check if this is a platform or a windowed app. | 1381 LauncherItemClosed(item.id); |
1395 if (item.type == ash::TYPE_APP_SHORTCUT && | 1382 --max_index; |
1396 (id_to_item_controller_map_[item.id]->locked() || | |
1397 id_to_item_controller_map_[item.id]->type() == | |
1398 LauncherItemController::TYPE_APP)) { | |
1399 // Note: This will not change the amount of items (|max_index|). | |
1400 // Even changes to the actual |index| due to item weighting | |
1401 // changes should be fine. | |
1402 UnpinRunningAppInternal(index); | |
1403 } else { | |
1404 LauncherItemClosed(item.id); | |
1405 --max_index; | |
1406 } | |
1407 } | 1383 } |
1408 --index; | 1384 --index; |
1409 } | 1385 } |
1410 } | 1386 } |
1411 // If the item wasn't found, that means id_to_item_controller_map_ | 1387 // If the item wasn't found, that means id_to_item_controller_map_ |
1412 // is out of sync. | 1388 // is out of sync. |
1413 DCHECK(index <= max_index); | 1389 DCHECK(index <= max_index); |
1414 } else { | 1390 } else { |
1415 // Check if the item was already running but not yet pinned. | 1391 // This app wasn't pinned before, insert a new entry. |
1416 ash::LauncherID launcher_id = GetLauncherIDForAppID(*pref_app_id); | 1392 ash::LauncherID id = CreateAppShortcutLauncherItem(*pref_app_id, index); |
1417 if (launcher_id) { | 1393 index = model_->ItemIndexByID(id); |
1418 // This app is running but not yet pinned. So pin and move it. | |
1419 index = PinRunningAppInternal(index, launcher_id); | |
1420 } else { | |
1421 // This app wasn't pinned before, insert a new entry. | |
1422 launcher_id = CreateAppShortcutLauncherItem(*pref_app_id, index); | |
1423 index = model_->ItemIndexByID(launcher_id); | |
1424 } | |
1425 ++pref_app_id; | 1394 ++pref_app_id; |
1426 } | 1395 } |
1427 } | 1396 } |
1428 | 1397 |
1429 // Since we are removing the currently existing shortcuts, but the chrome item | |
1430 // might be in the middle of that area, we need to keep track of it, so that | |
1431 // it can be shifted to the correct location afterwards. | |
1432 // Note: This might still produce location shifts with windowed V1 | |
1433 // applications since they will be grouped at the moment between shortcuts. | |
1434 // To address that problem we could either group them separately again - or | |
1435 // we will have to remember all shelf item locations. | |
1436 int chrome_index = -1; | |
1437 | |
1438 // Remove any trailing existing items. | 1398 // Remove any trailing existing items. |
1439 while (index < model_->item_count()) { | 1399 while (index < model_->item_count()) { |
1440 const ash::LauncherItem& item(model_->items()[index]); | 1400 const ash::LauncherItem& item(model_->items()[index]); |
1441 if (item.type == ash::TYPE_APP_SHORTCUT) { | 1401 if (item.type == ash::TYPE_APP_SHORTCUT) |
1442 if (id_to_item_controller_map_[item.id]->locked() || | 1402 LauncherItemClosed(item.id); |
1443 id_to_item_controller_map_[item.id]->type() == | 1403 else |
1444 LauncherItemController::TYPE_APP) | |
1445 UnpinRunningAppInternal(index); | |
1446 else | |
1447 LauncherItemClosed(item.id); | |
1448 } else { | |
1449 if (item.type == ash::TYPE_BROWSER_SHORTCUT) | |
1450 chrome_index = index; | |
1451 ++index; | 1404 ++index; |
1452 } | |
1453 } | 1405 } |
1454 | 1406 |
1455 // Append unprocessed items from the pref to the end of the model. | 1407 // Append unprocessed items from the pref to the end of the model. |
1456 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { | 1408 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { |
1457 // All items but the chrome shortcut needs to be added. | 1409 // Ignore the chrome icon. |
1458 if (*pref_app_id != extension_misc::kChromeAppId) { | 1410 if (*pref_app_id != extension_misc::kChromeAppId) |
1459 DoPinAppWithID(*pref_app_id); | 1411 DoPinAppWithID(*pref_app_id); |
1460 } else if (chrome_index != -1) { | |
1461 // The chrome item was in the middle of the to be removed items and needs | |
1462 // now to be moved to the last possible location. | |
1463 model_->Move(chrome_index, model_->item_count() - 1); | |
1464 } | |
1465 } | 1412 } |
| 1413 |
1466 } | 1414 } |
1467 | 1415 |
1468 void ChromeLauncherController::SetShelfAutoHideBehaviorPrefs( | 1416 void ChromeLauncherController::SetShelfAutoHideBehaviorPrefs( |
1469 ash::ShelfAutoHideBehavior behavior, | 1417 ash::ShelfAutoHideBehavior behavior, |
1470 aura::RootWindow* root_window) { | 1418 aura::RootWindow* root_window) { |
1471 const char* value = NULL; | 1419 const char* value = NULL; |
1472 switch (behavior) { | 1420 switch (behavior) { |
1473 case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: | 1421 case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: |
1474 value = ash::kShelfAutoHideBehaviorAlways; | 1422 value = ash::kShelfAutoHideBehaviorAlways; |
1475 break; | 1423 break; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1607 return static_cast<BrowserShortcutLauncherItemController*>( | 1555 return static_cast<BrowserShortcutLauncherItemController*>( |
1608 id_to_item_controller_map_[id]); | 1556 id_to_item_controller_map_[id]); |
1609 } | 1557 } |
1610 | 1558 |
1611 ash::LauncherID ChromeLauncherController::CreateBrowserShortcutLauncherItem() { | 1559 ash::LauncherID ChromeLauncherController::CreateBrowserShortcutLauncherItem() { |
1612 ash::LauncherItem browser_shortcut; | 1560 ash::LauncherItem browser_shortcut; |
1613 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; | 1561 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; |
1614 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1562 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
1615 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); | 1563 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); |
1616 ash::LauncherID id = model_->next_id(); | 1564 ash::LauncherID id = model_->next_id(); |
1617 size_t index = GetChromeIconIndexForCreation(); | 1565 size_t index = GetChromeIconIndexFromPref(); |
1618 model_->AddAt(index, browser_shortcut); | 1566 model_->AddAt(index, browser_shortcut); |
1619 browser_item_controller_.reset( | 1567 browser_item_controller_.reset( |
1620 new BrowserShortcutLauncherItemController(this, profile_)); | 1568 new BrowserShortcutLauncherItemController(this, profile_)); |
1621 id_to_item_controller_map_[id] = browser_item_controller_.get(); | 1569 id_to_item_controller_map_[id] = browser_item_controller_.get(); |
1622 id_to_item_controller_map_[id]->set_launcher_id(id); | 1570 id_to_item_controller_map_[id]->set_launcher_id(id); |
1623 return id; | 1571 return id; |
1624 } | 1572 } |
1625 | 1573 |
1626 void ChromeLauncherController::PersistChromeItemIndex(int index) { | 1574 void ChromeLauncherController::PersistChromeItemIndex(int index) { |
1627 profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index); | 1575 profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index); |
1628 } | 1576 } |
1629 | 1577 |
1630 int ChromeLauncherController::GetChromeIconIndexFromPref() const { | 1578 int ChromeLauncherController::GetChromeIconIndexFromPref() const { |
1631 size_t index = profile_->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex); | 1579 size_t index = profile_->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex); |
1632 const base::ListValue* pinned_apps_pref = | 1580 const base::ListValue* pinned_apps_pref = |
1633 profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps); | 1581 profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps); |
| 1582 if (ash::switches::UseAlternateShelfLayout()) |
| 1583 return std::max(static_cast<size_t>(1), |
| 1584 std::min(pinned_apps_pref->GetSize() + 1, index)); |
1634 return std::max(static_cast<size_t>(0), | 1585 return std::max(static_cast<size_t>(0), |
1635 std::min(pinned_apps_pref->GetSize(), index)); | 1586 std::min(pinned_apps_pref->GetSize(), index)); |
1636 } | 1587 } |
1637 | 1588 |
1638 int ChromeLauncherController::GetChromeIconIndexForCreation() { | |
1639 // We get the list of pinned apps as they currently would get pinned. | |
1640 // Within this list the chrome icon will be the correct location. | |
1641 std::vector<std::string> pinned_apps = GetListOfPinnedAppsAndBrowser(); | |
1642 | |
1643 std::vector<std::string>::iterator it = | |
1644 std::find(pinned_apps.begin(), | |
1645 pinned_apps.end(), | |
1646 std::string(extension_misc::kChromeAppId)); | |
1647 DCHECK(it != pinned_apps.end()); | |
1648 int index = it - pinned_apps.begin(); | |
1649 | |
1650 // Since this function returns the index of the item within the shelf, the | |
1651 // app list item must be taken into account and for now the app list is always | |
1652 // the left most item in the list. | |
1653 if (ash::switches::UseAlternateShelfLayout()) | |
1654 ++index; | |
1655 | |
1656 // We should do here a comparison between the is state and the "want to be" | |
1657 // state since some apps might be able to pin but are not yet. Instead - for | |
1658 // the time being we clamp against the amount of known items and wait for the | |
1659 // next |UpdateAppLaunchersFromPref()| call to correct it - it will come since | |
1660 // the pinning will be done then. | |
1661 return std::min(model_->item_count(), index); | |
1662 } | |
1663 | |
1664 std::vector<std::string> | |
1665 ChromeLauncherController::GetListOfPinnedAppsAndBrowser() { | |
1666 std::vector<std::string> pinned_apps; | |
1667 const base::ListValue* pinned_apps_pref = | |
1668 profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps); | |
1669 | |
1670 // Keep track of the addition of the chrome icon. | |
1671 bool chrome_icon_added = false; | |
1672 size_t chrome_icon_index = GetChromeIconIndexFromPref(); | |
1673 // Note: We do not need special handling for the app List here since it is | |
1674 // either always at the start or the end of the list and it is not part of | |
1675 // the pinned 'dynamic' items. | |
1676 for (size_t index = 0; index < pinned_apps_pref->GetSize(); ++index) { | |
1677 // We need to position the chrome icon relative to it's place in the pinned | |
1678 // preference list - even if an item of that list isn't shown yet. | |
1679 if (index == chrome_icon_index && model_->item_count() > 1) { | |
1680 pinned_apps.push_back(extension_misc::kChromeAppId); | |
1681 chrome_icon_added = true; | |
1682 } | |
1683 | |
1684 const DictionaryValue* app = NULL; | |
1685 std::string app_id; | |
1686 if (pinned_apps_pref->GetDictionary(index, &app) && | |
1687 app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id) && | |
1688 (std::find(pinned_apps.begin(), pinned_apps.end(), app_id) == | |
1689 pinned_apps.end()) && app_tab_helper_->IsValidID(app_id)) | |
1690 pinned_apps.push_back(app_id); | |
1691 } | |
1692 | |
1693 // If not added yet, the chrome item will be the final item in the list. | |
1694 if (!chrome_icon_added) | |
1695 pinned_apps.push_back(extension_misc::kChromeAppId); | |
1696 return pinned_apps; | |
1697 } | |
1698 | |
1699 bool ChromeLauncherController::IsIncognito( | 1589 bool ChromeLauncherController::IsIncognito( |
1700 const content::WebContents* web_contents) const { | 1590 content::WebContents* web_contents) const { |
1701 const Profile* profile = | 1591 const Profile* profile = |
1702 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 1592 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
1703 return profile->IsOffTheRecord() && !profile->IsGuestSession(); | 1593 return profile->IsOffTheRecord() && !profile->IsGuestSession(); |
1704 } | 1594 } |
1705 | 1595 |
1706 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension( | 1596 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension( |
1707 const std::string& app_id) { | 1597 const std::string& app_id) { |
1708 // This function cannot rely on the controller's enumeration functionality | 1598 // This function cannot rely on the controller's enumeration functionality |
1709 // since the extension has already be unloaded. | 1599 // since the extension has already be unloaded. |
1710 const BrowserList* ash_browser_list = | 1600 const BrowserList* ash_browser_list = |
(...skipping 11 matching lines...) Expand all Loading... |
1722 browser_to_close.push_back(browser); | 1612 browser_to_close.push_back(browser); |
1723 } | 1613 } |
1724 } | 1614 } |
1725 while (!browser_to_close.empty()) { | 1615 while (!browser_to_close.empty()) { |
1726 TabStripModel* tab_strip = browser_to_close.back()->tab_strip_model(); | 1616 TabStripModel* tab_strip = browser_to_close.back()->tab_strip_model(); |
1727 tab_strip->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE); | 1617 tab_strip->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE); |
1728 browser_to_close.pop_back(); | 1618 browser_to_close.pop_back(); |
1729 } | 1619 } |
1730 } | 1620 } |
1731 | 1621 |
| 1622 void |
| 1623 ChromeLauncherController::MoveItemWithoutPinnedStateChangeNotification( |
| 1624 int source_index, int target_index) { |
| 1625 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); |
| 1626 model_->Move(source_index, target_index); |
| 1627 } |
| 1628 |
1732 void ChromeLauncherController::RegisterLauncherItemDelegate() { | 1629 void ChromeLauncherController::RegisterLauncherItemDelegate() { |
1733 // TODO(simon.hong81): Register LauncherItemDelegate when LauncherItemDelegate | 1630 // TODO(simon.hong81): Register LauncherItemDelegate when LauncherItemDelegate |
1734 // is created. | 1631 // is created. |
1735 ash::LauncherItemDelegateManager* manager = | 1632 ash::LauncherItemDelegateManager* manager = |
1736 ash::Shell::GetInstance()->launcher_item_delegate_manager(); | 1633 ash::Shell::GetInstance()->launcher_item_delegate_manager(); |
1737 manager->RegisterLauncherItemDelegate(ash::TYPE_APP_PANEL, this); | 1634 manager->RegisterLauncherItemDelegate(ash::TYPE_APP_PANEL, this); |
1738 manager->RegisterLauncherItemDelegate(ash::TYPE_APP_SHORTCUT, this); | 1635 manager->RegisterLauncherItemDelegate(ash::TYPE_APP_SHORTCUT, this); |
1739 manager->RegisterLauncherItemDelegate(ash::TYPE_BROWSER_SHORTCUT, this); | 1636 manager->RegisterLauncherItemDelegate(ash::TYPE_BROWSER_SHORTCUT, this); |
1740 manager->RegisterLauncherItemDelegate(ash::TYPE_PLATFORM_APP, this); | 1637 manager->RegisterLauncherItemDelegate(ash::TYPE_PLATFORM_APP, this); |
1741 manager->RegisterLauncherItemDelegate(ash::TYPE_WINDOWED_APP, this); | 1638 manager->RegisterLauncherItemDelegate(ash::TYPE_WINDOWED_APP, this); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1777 } | 1674 } |
1778 | 1675 |
1779 void ChromeLauncherController::ReleaseProfile() { | 1676 void ChromeLauncherController::ReleaseProfile() { |
1780 if (app_sync_ui_state_) | 1677 if (app_sync_ui_state_) |
1781 app_sync_ui_state_->RemoveObserver(this); | 1678 app_sync_ui_state_->RemoveObserver(this); |
1782 | 1679 |
1783 PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this); | 1680 PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this); |
1784 | 1681 |
1785 pref_change_registrar_.RemoveAll(); | 1682 pref_change_registrar_.RemoveAll(); |
1786 } | 1683 } |
OLD | NEW |