| 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 <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/common/system/tray/system_tray_delegate.h" | 14 #include "ash/common/system/tray/system_tray_delegate.h" |
| 15 #include "ash/desktop_background/desktop_background_controller.h" | 15 #include "ash/desktop_background/desktop_background_controller.h" |
| 16 #include "ash/multi_profile_uma.h" | 16 #include "ash/multi_profile_uma.h" |
| 17 #include "ash/root_window_controller.h" | 17 #include "ash/root_window_controller.h" |
| 18 #include "ash/shelf/shelf.h" | 18 #include "ash/shelf/shelf.h" |
| 19 #include "ash/shell.h" | 19 #include "ash/shell.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/profiles/profile.h" | 35 #include "chrome/browser/profiles/profile.h" |
| 37 #include "chrome/browser/profiles/profile_manager.h" | 36 #include "chrome/browser/profiles/profile_manager.h" |
| 37 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" |
| 38 #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" |
| 39 #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" |
| 40 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" | 40 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" |
| 41 #include "chrome/browser/ui/ash/app_sync_ui_state.h" | 41 #include "chrome/browser/ui/ash/app_sync_ui_state.h" |
| 42 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" | 42 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" |
| 43 #include "chrome/browser/ui/ash/chrome_shell_delegate.h" | 43 #include "chrome/browser/ui/ash/chrome_shell_delegate.h" |
| 44 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
" | 44 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
" |
| 45 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h" | 45 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h" |
| 46 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h" | 46 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h" |
| 47 #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h" | 47 #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 111 |
| 112 int64_t GetDisplayIDForShelf(ash::Shelf* shelf) { | 112 int64_t GetDisplayIDForShelf(ash::Shelf* shelf) { |
| 113 aura::Window* root_window = | 113 aura::Window* root_window = |
| 114 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); | 114 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); |
| 115 display::Display display = | 115 display::Display display = |
| 116 display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); | 116 display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); |
| 117 DCHECK(display.is_valid()); | 117 DCHECK(display.is_valid()); |
| 118 return display.id(); | 118 return display.id(); |
| 119 } | 119 } |
| 120 | 120 |
| 121 /* | |
| 122 * Return whether an app is pinned only by user. | |
| 123 * This function doesn't expect an app_id neither pinned by user nor by | |
| 124 * policy, the app_id in the arguments list MUST be pinned by either of | |
| 125 * those. Invalid input may lead to unexpected result. | |
| 126 * If this app is pinned by policy, but not by user, false is returned. | |
| 127 * If this app is pinned by both policy and user, false is returned. | |
| 128 * If this app is pinned not by policy, but by user, true is returned. | |
| 129 */ | |
| 130 bool IsAppForUserPinned(const std::string& app_id, | |
| 131 const base::ListValue* pinned_apps_pref, | |
| 132 const base::ListValue* policy_pinned_apps_pref) { | |
| 133 for (size_t index = 0; index < pinned_apps_pref->GetSize(); ++index) { | |
| 134 const base::DictionaryValue* app; | |
| 135 if (pinned_apps_pref->GetDictionary(index, &app)) { | |
| 136 std::string current_app_id; | |
| 137 bool pinned_by_policy = false; | |
| 138 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, ¤t_app_id)) { | |
| 139 if (app_id == current_app_id) { | |
| 140 if (app->GetBoolean(ash::kPinnedAppsPrefPinnedByPolicy, | |
| 141 &pinned_by_policy) && | |
| 142 pinned_by_policy) { | |
| 143 // Pinned by policy in the past or present. | |
| 144 // Need to check policy_pinned_apps to determine | |
| 145 break; | |
| 146 } else { | |
| 147 // User Preference Already Pinned | |
| 148 return true; | |
| 149 } | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 for (size_t index = 0; index < policy_pinned_apps_pref->GetSize(); ++index) { | |
| 155 const base::DictionaryValue* app; | |
| 156 if (policy_pinned_apps_pref->GetDictionary(index, &app)) { | |
| 157 std::string app_id_; | |
| 158 if (app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id_)) { | |
| 159 // Only pinned by policy, which is not part of user-pinned | |
| 160 if (app_id == app_id_) | |
| 161 return false; | |
| 162 } | |
| 163 } | |
| 164 } | |
| 165 // Default, user added new pins | |
| 166 return true; | |
| 167 } | |
| 168 | |
| 169 const char* const kPinProhibitedExtensionIds[] = { | |
| 170 ArcSupportHost::kHostAppId, arc::kPlayStoreAppId, | |
| 171 }; | |
| 172 | |
| 173 const size_t kPinProhibitedExtensionIdsLength = | |
| 174 arraysize(kPinProhibitedExtensionIds); | |
| 175 | |
| 176 } // namespace | 121 } // namespace |
| 177 | 122 |
| 178 // A class to get events from ChromeOS when a user gets changed or added. | 123 // A class to get events from ChromeOS when a user gets changed or added. |
| 179 class ChromeLauncherControllerUserSwitchObserver | 124 class ChromeLauncherControllerUserSwitchObserver |
| 180 : public user_manager::UserManager::UserSessionStateObserver { | 125 : public user_manager::UserManager::UserSessionStateObserver { |
| 181 public: | 126 public: |
| 182 ChromeLauncherControllerUserSwitchObserver( | 127 ChromeLauncherControllerUserSwitchObserver( |
| 183 ChromeLauncherController* controller) | 128 ChromeLauncherController* controller) |
| 184 : controller_(controller) { | 129 : controller_(controller) { |
| 185 DCHECK(user_manager::UserManager::IsInitialized()); | 130 DCHECK(user_manager::UserManager::IsInitialized()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 185 |
| 241 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) { | 186 void ChromeLauncherControllerUserSwitchObserver::AddUser(Profile* profile) { |
| 242 if (chrome::MultiUserWindowManager::GetMultiProfileMode() == | 187 if (chrome::MultiUserWindowManager::GetMultiProfileMode() == |
| 243 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) | 188 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) |
| 244 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile); | 189 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile); |
| 245 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile()); | 190 controller_->AdditionalUserAddedToSession(profile->GetOriginalProfile()); |
| 246 } | 191 } |
| 247 | 192 |
| 248 ChromeLauncherController::ChromeLauncherController(Profile* profile, | 193 ChromeLauncherController::ChromeLauncherController(Profile* profile, |
| 249 ash::ShelfModel* model) | 194 ash::ShelfModel* model) |
| 250 : model_(model), | 195 : model_(model), profile_(profile) { |
| 251 item_delegate_manager_(NULL), | |
| 252 profile_(profile), | |
| 253 app_sync_ui_state_(NULL), | |
| 254 ignore_persist_pinned_state_change_(false) { | |
| 255 if (!profile_) { | 196 if (!profile_) { |
| 256 // If no profile was passed, we take the currently active profile and use it | 197 // If no profile was passed, we take the currently active profile and use it |
| 257 // as the owner of the current desktop. | 198 // as the owner of the current desktop. |
| 258 // Use the original profile as on chromeos we may get a temporary off the | 199 // Use the original profile as on chromeos we may get a temporary off the |
| 259 // record profile, unless in guest session (where off the record profile is | 200 // record profile, unless in guest session (where off the record profile is |
| 260 // the right one). | 201 // the right one). |
| 261 profile_ = ProfileManager::GetActiveUserProfile(); | 202 profile_ = ProfileManager::GetActiveUserProfile(); |
| 262 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile()) | 203 if (!profile_->IsGuestSession() && !profile_->IsSystemProfile()) |
| 263 profile_ = profile_->GetOriginalProfile(); | 204 profile_ = profile_->GetOriginalProfile(); |
| 264 | 205 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 | 310 |
| 370 void ChromeLauncherController::Init() { | 311 void ChromeLauncherController::Init() { |
| 371 CreateBrowserShortcutLauncherItem(); | 312 CreateBrowserShortcutLauncherItem(); |
| 372 UpdateAppLaunchersFromPref(); | 313 UpdateAppLaunchersFromPref(); |
| 373 | 314 |
| 374 // TODO(sky): update unit test so that this test isn't necessary. | 315 // TODO(sky): update unit test so that this test isn't necessary. |
| 375 if (ash::Shell::HasInstance()) | 316 if (ash::Shell::HasInstance()) |
| 376 SetVirtualKeyboardBehaviorFromPrefs(); | 317 SetVirtualKeyboardBehaviorFromPrefs(); |
| 377 | 318 |
| 378 prefs_observer_ = | 319 prefs_observer_ = |
| 379 ash::ChromeLauncherPrefsObserver::CreateIfNecessary(profile_); | 320 ash::launcher::ChromeLauncherPrefsObserver::CreateIfNecessary(profile_); |
| 380 } | 321 } |
| 381 | 322 |
| 382 ash::ShelfID ChromeLauncherController::CreateAppLauncherItem( | 323 ash::ShelfID ChromeLauncherController::CreateAppLauncherItem( |
| 383 LauncherItemController* controller, | 324 LauncherItemController* controller, |
| 384 const std::string& app_id, | 325 const std::string& app_id, |
| 385 ash::ShelfItemStatus status) { | 326 ash::ShelfItemStatus status) { |
| 386 CHECK(controller); | 327 CHECK(controller); |
| 387 int index = 0; | 328 int index = 0; |
| 388 // Panels are inserted on the left so as not to push all existing panels over. | 329 // Panels are inserted on the left so as not to push all existing panels over. |
| 389 if (controller->GetShelfItemType() != ash::TYPE_APP_PANEL) | 330 if (controller->GetShelfItemType() != ash::TYPE_APP_PANEL) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 iter->second->set_shelf_id(id); | 373 iter->second->set_shelf_id(id); |
| 433 // Existing controller is destroyed and replaced by registering again. | 374 // Existing controller is destroyed and replaced by registering again. |
| 434 SetShelfItemDelegate(id, iter->second); | 375 SetShelfItemDelegate(id, iter->second); |
| 435 } else { | 376 } else { |
| 436 LauncherItemClosed(id); | 377 LauncherItemClosed(id); |
| 437 } | 378 } |
| 438 } | 379 } |
| 439 | 380 |
| 440 AppListControllerDelegate::Pinnable ChromeLauncherController::GetPinnable( | 381 AppListControllerDelegate::Pinnable ChromeLauncherController::GetPinnable( |
| 441 const std::string& app_id) { | 382 const std::string& app_id) { |
| 442 for (size_t i = 0; i < kPinProhibitedExtensionIdsLength; ++i) { | |
| 443 if (kPinProhibitedExtensionIds[i] == app_id) | |
| 444 return AppListControllerDelegate::NO_PIN; | |
| 445 } | |
| 446 | |
| 447 const base::ListValue* pref = | 383 const base::ListValue* pref = |
| 448 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps); | 384 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps); |
| 449 if (!pref) | 385 if (!pref) |
| 450 return AppListControllerDelegate::PIN_EDITABLE; | 386 return AppListControllerDelegate::PIN_EDITABLE; |
| 451 | 387 |
| 452 // Pinned ARC apps policy defines the package name of the apps, that must | 388 // Pinned ARC apps policy defines the package name of the apps, that must |
| 453 // be pinned. All the launch activities of any package in policy are pinned. | 389 // be pinned. All the launch activities of any package in policy are pinned. |
| 454 // In turn the input parameter to this function is app_id, which | 390 // In turn the input parameter to this function is app_id, which |
| 455 // is 32 chars hash. In case of ARC app this is a hash of | 391 // is 32 chars hash. In case of ARC app this is a hash of |
| 456 // (package name + activity). This means that we must identify the package | 392 // (package name + activity). This means that we must identify the package |
| 457 // from the hash, and check if this package is pinned by policy. | 393 // from the hash, and check if this package is pinned by policy. |
| 458 const ArcAppListPrefs* const arc_prefs = ArcAppListPrefs::Get(profile()); | 394 const ArcAppListPrefs* const arc_prefs = ArcAppListPrefs::Get(profile()); |
| 459 std::string arc_app_packege_name; | 395 std::string arc_app_packege_name; |
| 460 if (arc_prefs) { | 396 if (arc_prefs) { |
| 461 std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = | 397 std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = |
| 462 arc_prefs->GetApp(app_id); | 398 arc_prefs->GetApp(app_id); |
| 463 if (app_info) | 399 if (app_info) |
| 464 arc_app_packege_name = app_info->package_name; | 400 arc_app_packege_name = app_info->package_name; |
| 465 } | 401 } |
| 466 | 402 |
| 467 for (size_t index = 0; index < pref->GetSize(); ++index) { | 403 for (size_t index = 0; index < pref->GetSize(); ++index) { |
| 468 const base::DictionaryValue* app = nullptr; | 404 const base::DictionaryValue* app = nullptr; |
| 469 std::string app_id_or_package; | 405 std::string app_id_or_package; |
| 470 if (pref->GetDictionary(index, &app) && | 406 if (pref->GetDictionary(index, &app) && |
| 471 app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id_or_package) && | 407 app->GetString(ash::launcher::kPinnedAppsPrefAppIDPath, |
| 408 &app_id_or_package) && |
| 472 (app_id == app_id_or_package || | 409 (app_id == app_id_or_package || |
| 473 arc_app_packege_name == app_id_or_package)) { | 410 arc_app_packege_name == app_id_or_package)) { |
| 474 return AppListControllerDelegate::PIN_FIXED; | 411 return AppListControllerDelegate::PIN_FIXED; |
| 475 } | 412 } |
| 476 } | 413 } |
| 477 return AppListControllerDelegate::PIN_EDITABLE; | 414 return AppListControllerDelegate::PIN_EDITABLE; |
| 478 } | 415 } |
| 479 | 416 |
| 480 void ChromeLauncherController::Pin(ash::ShelfID id) { | 417 void ChromeLauncherController::Pin(ash::ShelfID id) { |
| 481 DCHECK(HasShelfIDToAppIDMapping(id)); | 418 DCHECK(HasShelfIDToAppIDMapping(id)); |
| 482 | 419 |
| 483 int index = model_->ItemIndexByID(id); | 420 int index = model_->ItemIndexByID(id); |
| 484 DCHECK_GE(index, 0); | 421 DCHECK_GE(index, 0); |
| 485 | 422 |
| 486 ash::ShelfItem item = model_->items()[index]; | 423 ash::ShelfItem item = model_->items()[index]; |
| 487 | 424 |
| 488 if (item.type == ash::TYPE_PLATFORM_APP || | 425 if (item.type == ash::TYPE_PLATFORM_APP || |
| 489 item.type == ash::TYPE_WINDOWED_APP) { | 426 item.type == ash::TYPE_WINDOWED_APP) { |
| 490 item.type = ash::TYPE_APP_SHORTCUT; | 427 item.type = ash::TYPE_APP_SHORTCUT; |
| 491 model_->Set(index, item); | 428 model_->Set(index, item); |
| 492 } else if (item.type != ash::TYPE_APP_SHORTCUT) { | 429 } else if (item.type != ash::TYPE_APP_SHORTCUT) { |
| 493 return; | 430 return; |
| 494 } | 431 } |
| 495 | 432 |
| 496 if (GetLauncherItemController(id)->CanPin()) | 433 SyncPinPosition(id); |
| 497 PersistPinnedState(); | |
| 498 } | 434 } |
| 499 | 435 |
| 500 void ChromeLauncherController::Unpin(ash::ShelfID id) { | 436 void ChromeLauncherController::Unpin(ash::ShelfID id) { |
| 501 LauncherItemController* controller = GetLauncherItemController(id); | 437 LauncherItemController* controller = GetLauncherItemController(id); |
| 502 CHECK(controller); | 438 CHECK(controller); |
| 503 const bool can_pin = controller->CanPin(); | 439 |
| 440 ash::launcher::RemovePinPosition(profile_, GetAppIDForShelfID(id)); |
| 504 | 441 |
| 505 if (controller->type() == LauncherItemController::TYPE_APP || | 442 if (controller->type() == LauncherItemController::TYPE_APP || |
| 506 controller->locked()) { | 443 controller->locked()) { |
| 507 UnpinRunningAppInternal(model_->ItemIndexByID(id)); | 444 UnpinRunningAppInternal(model_->ItemIndexByID(id)); |
| 508 } else { | 445 } else { |
| 509 LauncherItemClosed(id); | 446 LauncherItemClosed(id); |
| 510 } | 447 } |
| 511 if (can_pin) | |
| 512 PersistPinnedState(); | |
| 513 } | 448 } |
| 514 | 449 |
| 515 bool ChromeLauncherController::IsPinned(ash::ShelfID id) { | 450 bool ChromeLauncherController::IsPinned(ash::ShelfID id) { |
| 516 int index = model_->ItemIndexByID(id); | 451 int index = model_->ItemIndexByID(id); |
| 517 if (index < 0) | 452 if (index < 0) |
| 518 return false; | 453 return false; |
| 519 ash::ShelfItemType type = model_->items()[index].type; | 454 ash::ShelfItemType type = model_->items()[index].type; |
| 520 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT); | 455 return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT); |
| 521 } | 456 } |
| 522 | 457 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 ash::ShelfItemDelegate* item_delegate) { | 675 ash::ShelfItemDelegate* item_delegate) { |
| 741 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we | 676 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we |
| 742 // get into this state in the first place. | 677 // get into this state in the first place. |
| 743 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); | 678 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); |
| 744 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second) | 679 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second) |
| 745 return; | 680 return; |
| 746 LOG(ERROR) << "Unexpected change of shelf item id: " << id; | 681 LOG(ERROR) << "Unexpected change of shelf item id: " << id; |
| 747 id_to_item_controller_map_.erase(iter); | 682 id_to_item_controller_map_.erase(iter); |
| 748 } | 683 } |
| 749 | 684 |
| 750 void ChromeLauncherController::PersistPinnedState() { | |
| 751 if (ignore_persist_pinned_state_change_) | |
| 752 return; | |
| 753 // It is a coding error to call PersistPinnedState() if the pinned apps are | |
| 754 // not user-editable. The code should check earlier and not perform any | |
| 755 // modification actions that trigger persisting the state. | |
| 756 // Mutating kPinnedLauncherApps is going to notify us and trigger us to | |
| 757 // process the change. We don't want that to happen so remove ourselves as a | |
| 758 // listener. | |
| 759 pref_change_registrar_.Remove(prefs::kPinnedLauncherApps); | |
| 760 { | |
| 761 std::unique_ptr<const base::ListValue> pinned_apps_pref = | |
| 762 profile_->GetPrefs() | |
| 763 ->GetList(prefs::kPinnedLauncherApps) | |
| 764 ->CreateDeepCopy(); | |
| 765 | |
| 766 const base::ListValue* policy_pinned_apps_pref = | |
| 767 profile_->GetPrefs()->GetList(prefs::kPolicyPinnedLauncherApps); | |
| 768 | |
| 769 ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps); | |
| 770 updater->Clear(); | |
| 771 for (size_t i = 0; i < model_->items().size(); ++i) { | |
| 772 if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) { | |
| 773 ash::ShelfID id = model_->items()[i].id; | |
| 774 LauncherItemController* controller = GetLauncherItemController(id); | |
| 775 // Don't persist pinning state for apps that are handled internally and | |
| 776 // have pinnable state AppListControllerDelegate::NO_PIN. | |
| 777 if (controller && IsPinned(id) && | |
| 778 GetPinnable(controller->app_id()) != | |
| 779 AppListControllerDelegate::NO_PIN) { | |
| 780 base::DictionaryValue* app_value = ash::CreateAppDict( | |
| 781 controller->app_id()); | |
| 782 if (app_value) { | |
| 783 if (!IsAppForUserPinned(controller->app_id(), | |
| 784 pinned_apps_pref.get(), | |
| 785 policy_pinned_apps_pref)) | |
| 786 app_value->SetBoolean(ash::kPinnedAppsPrefPinnedByPolicy, true); | |
| 787 updater->Append(app_value); | |
| 788 } | |
| 789 } | |
| 790 } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) { | |
| 791 PersistChromeItemIndex(i); | |
| 792 } else if (model_->items()[i].type == ash::TYPE_APP_LIST) { | |
| 793 base::DictionaryValue* app_value = | |
| 794 ash::CreateAppDict(ash::kPinnedAppsPlaceholder); | |
| 795 if (app_value) | |
| 796 updater->Append(app_value); | |
| 797 } | |
| 798 } | |
| 799 } | |
| 800 pref_change_registrar_.Add( | |
| 801 prefs::kPinnedLauncherApps, | |
| 802 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, | |
| 803 base::Unretained(this))); | |
| 804 } | |
| 805 | |
| 806 Profile* ChromeLauncherController::profile() { | 685 Profile* ChromeLauncherController::profile() { |
| 807 return profile_; | 686 return profile_; |
| 808 } | 687 } |
| 809 | 688 |
| 810 void ChromeLauncherController::UpdateAppState(content::WebContents* contents, | 689 void ChromeLauncherController::UpdateAppState(content::WebContents* contents, |
| 811 AppState app_state) { | 690 AppState app_state) { |
| 812 std::string app_id = launcher_controller_helper_->GetAppID(contents); | 691 std::string app_id = launcher_controller_helper_->GetAppID(contents); |
| 813 | 692 |
| 814 // Check if the gMail app is loaded and it matches the given content. | 693 // Check if the gMail app is loaded and it matches the given content. |
| 815 // This special treatment is needed to address crbug.com/234268. | 694 // This special treatment is needed to address crbug.com/234268. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 | 798 |
| 920 window->Show(); | 799 window->Show(); |
| 921 window->Activate(); | 800 window->Activate(); |
| 922 return ash::ShelfItemDelegate::kExistingWindowActivated; | 801 return ash::ShelfItemDelegate::kExistingWindowActivated; |
| 923 } | 802 } |
| 924 | 803 |
| 925 void ChromeLauncherController::OnShelfCreated(ash::Shelf* shelf) { | 804 void ChromeLauncherController::OnShelfCreated(ash::Shelf* shelf) { |
| 926 PrefService* prefs = profile_->GetPrefs(); | 805 PrefService* prefs = profile_->GetPrefs(); |
| 927 const int64_t display = GetDisplayIDForShelf(shelf); | 806 const int64_t display = GetDisplayIDForShelf(shelf); |
| 928 | 807 |
| 929 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref(prefs, display)); | 808 shelf->SetAutoHideBehavior( |
| 809 ash::launcher::GetShelfAutoHideBehaviorPref(prefs, display)); |
| 930 | 810 |
| 931 if (ash::ShelfWidget::ShelfAlignmentAllowed()) | 811 if (ash::ShelfWidget::ShelfAlignmentAllowed()) |
| 932 shelf->SetAlignment(ash::GetShelfAlignmentPref(prefs, display)); | 812 shelf->SetAlignment(ash::launcher::GetShelfAlignmentPref(prefs, display)); |
| 933 } | 813 } |
| 934 | 814 |
| 935 void ChromeLauncherController::OnShelfDestroyed(ash::Shelf* shelf) {} | 815 void ChromeLauncherController::OnShelfDestroyed(ash::Shelf* shelf) {} |
| 936 | 816 |
| 937 void ChromeLauncherController::OnShelfAlignmentChanged(ash::Shelf* shelf) { | 817 void ChromeLauncherController::OnShelfAlignmentChanged(ash::Shelf* shelf) { |
| 938 ash::SetShelfAlignmentPref(profile_->GetPrefs(), GetDisplayIDForShelf(shelf), | 818 ash::launcher::SetShelfAlignmentPref( |
| 939 shelf->alignment()); | 819 profile_->GetPrefs(), GetDisplayIDForShelf(shelf), shelf->alignment()); |
| 940 } | 820 } |
| 941 | 821 |
| 942 void ChromeLauncherController::OnShelfAutoHideBehaviorChanged( | 822 void ChromeLauncherController::OnShelfAutoHideBehaviorChanged( |
| 943 ash::Shelf* shelf) { | 823 ash::Shelf* shelf) { |
| 944 ash::SetShelfAutoHideBehaviorPref(profile_->GetPrefs(), | 824 ash::launcher::SetShelfAutoHideBehaviorPref(profile_->GetPrefs(), |
| 945 GetDisplayIDForShelf(shelf), | 825 GetDisplayIDForShelf(shelf), |
| 946 shelf->auto_hide_behavior()); | 826 shelf->auto_hide_behavior()); |
| 947 } | 827 } |
| 948 | 828 |
| 949 void ChromeLauncherController::OnShelfAutoHideStateChanged(ash::Shelf* shelf) {} | 829 void ChromeLauncherController::OnShelfAutoHideStateChanged(ash::Shelf* shelf) {} |
| 950 | 830 |
| 951 void ChromeLauncherController::OnShelfVisibilityStateChanged( | 831 void ChromeLauncherController::OnShelfVisibilityStateChanged( |
| 952 ash::Shelf* shelf) {} | 832 ash::Shelf* shelf) {} |
| 953 | 833 |
| 954 void ChromeLauncherController::ShelfItemAdded(int index) { | 834 void ChromeLauncherController::ShelfItemAdded(int index) { |
| 955 // The app list launcher can get added to the shelf after we applied the | |
| 956 // preferences. In that case the item might be at the wrong spot. As such we | |
| 957 // call the function again. | |
| 958 if (model_->items()[index].type == ash::TYPE_APP_LIST) | |
| 959 UpdateAppLaunchersFromPref(); | |
| 960 } | 835 } |
| 961 | 836 |
| 962 void ChromeLauncherController::ShelfItemRemoved(int index, ash::ShelfID id) { | 837 void ChromeLauncherController::ShelfItemRemoved(int index, ash::ShelfID id) { |
| 963 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we | 838 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we |
| 964 // get into this state in the first place. | 839 // get into this state in the first place. |
| 965 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); | 840 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); |
| 966 if (iter == id_to_item_controller_map_.end()) | 841 if (iter == id_to_item_controller_map_.end()) |
| 967 return; | 842 return; |
| 968 | 843 |
| 969 LOG(ERROR) << "Unexpected change of shelf item id: " << id; | 844 LOG(ERROR) << "Unexpected change of shelf item id: " << id; |
| 970 | 845 |
| 971 id_to_item_controller_map_.erase(iter); | 846 id_to_item_controller_map_.erase(iter); |
| 972 } | 847 } |
| 973 | 848 |
| 974 void ChromeLauncherController::ShelfItemMoved(int start_index, | 849 void ChromeLauncherController::ShelfItemMoved(int start_index, |
| 975 int target_index) { | 850 int target_index) { |
| 976 const ash::ShelfItem& item = model_->items()[target_index]; | 851 const ash::ShelfItem& item = model_->items()[target_index]; |
| 977 // We remember the moved item position if it is either pinnable or | 852 // We remember the moved item position if it is either pinnable or |
| 978 // it is the app list with the alternate shelf layout. | 853 // it is the app list with the alternate shelf layout. |
| 979 if ((HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id)) || | 854 DCHECK_NE(ash::TYPE_APP_LIST, item.type); |
| 980 item.type == ash::TYPE_APP_LIST) | 855 if (HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id)) |
| 981 PersistPinnedState(); | 856 SyncPinPosition(item.id); |
| 982 } | 857 } |
| 983 | 858 |
| 984 void ChromeLauncherController::ShelfItemChanged( | 859 void ChromeLauncherController::ShelfItemChanged( |
| 985 int index, | 860 int index, |
| 986 const ash::ShelfItem& old_item) {} | 861 const ash::ShelfItem& old_item) {} |
| 987 | 862 |
| 988 void ChromeLauncherController::ActiveUserChanged( | 863 void ChromeLauncherController::ActiveUserChanged( |
| 989 const std::string& user_email) { | 864 const std::string& user_email) { |
| 990 // Store the order of running applications for the user which gets inactive. | 865 // Store the order of running applications for the user which gets inactive. |
| 991 RememberUnpinnedRunningApplicationOrder(); | 866 RememberUnpinnedRunningApplicationOrder(); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 AccountId::FromUserEmail(user_id)); | 1163 AccountId::FromUserEmail(user_id)); |
| 1289 if (other_profile == profile_) | 1164 if (other_profile == profile_) |
| 1290 return false; | 1165 return false; |
| 1291 | 1166 |
| 1292 // Note: The Auto hide state from preferences is not the same as the actual | 1167 // Note: The Auto hide state from preferences is not the same as the actual |
| 1293 // visibility of the shelf. Depending on all the various states (full screen, | 1168 // visibility of the shelf. Depending on all the various states (full screen, |
| 1294 // no window on desktop, multi user, ..) the shelf could be shown - or not. | 1169 // no window on desktop, multi user, ..) the shelf could be shown - or not. |
| 1295 PrefService* prefs = profile_->GetPrefs(); | 1170 PrefService* prefs = profile_->GetPrefs(); |
| 1296 PrefService* other_prefs = other_profile->GetPrefs(); | 1171 PrefService* other_prefs = other_profile->GetPrefs(); |
| 1297 const int64_t display = GetDisplayIDForShelf(shelf); | 1172 const int64_t display = GetDisplayIDForShelf(shelf); |
| 1298 bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == | 1173 bool currently_shown = |
| 1299 ash::GetShelfAutoHideBehaviorPref(prefs, display); | 1174 ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == |
| 1300 bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == | 1175 ash::launcher::GetShelfAutoHideBehaviorPref(prefs, display); |
| 1301 ash::GetShelfAutoHideBehaviorPref(other_prefs, display); | 1176 bool other_shown = |
| 1177 ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == |
| 1178 ash::launcher::GetShelfAutoHideBehaviorPref(other_prefs, display); |
| 1302 | 1179 |
| 1303 return currently_shown != other_shown || | 1180 return currently_shown != other_shown || |
| 1304 ash::GetShelfAlignmentPref(prefs, display) != | 1181 ash::launcher::GetShelfAlignmentPref(prefs, display) != |
| 1305 ash::GetShelfAlignmentPref(other_prefs, display); | 1182 ash::launcher::GetShelfAlignmentPref(other_prefs, display); |
| 1306 } | 1183 } |
| 1307 | 1184 |
| 1308 void ChromeLauncherController::OnUserProfileReadyToSwitch(Profile* profile) { | 1185 void ChromeLauncherController::OnUserProfileReadyToSwitch(Profile* profile) { |
| 1309 if (user_switch_observer_.get()) | 1186 if (user_switch_observer_.get()) |
| 1310 user_switch_observer_->OnUserProfileReadyToSwitch(profile); | 1187 user_switch_observer_->OnUserProfileReadyToSwitch(profile); |
| 1311 } | 1188 } |
| 1312 | 1189 |
| 1313 void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) { | 1190 void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) { |
| 1314 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); | 1191 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); |
| 1315 CHECK(iter != id_to_item_controller_map_.end()); | 1192 CHECK(iter != id_to_item_controller_map_.end()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1331 if (IsAppPinned(app_id)) | 1208 if (IsAppPinned(app_id)) |
| 1332 return; | 1209 return; |
| 1333 | 1210 |
| 1334 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 1211 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); |
| 1335 if (shelf_id) { | 1212 if (shelf_id) { |
| 1336 // App item exists, pin it | 1213 // App item exists, pin it |
| 1337 Pin(shelf_id); | 1214 Pin(shelf_id); |
| 1338 } else { | 1215 } else { |
| 1339 // Otherwise, create a shortcut item for it. | 1216 // Otherwise, create a shortcut item for it. |
| 1340 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count()); | 1217 shelf_id = CreateAppShortcutLauncherItem(app_id, model_->item_count()); |
| 1341 if (GetPinnable(app_id) == AppListControllerDelegate::PIN_EDITABLE) | 1218 SyncPinPosition(shelf_id); |
| 1342 PersistPinnedState(); | |
| 1343 } | 1219 } |
| 1344 } | 1220 } |
| 1345 | 1221 |
| 1346 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) { | 1222 void ChromeLauncherController::DoUnpinAppWithID(const std::string& app_id) { |
| 1347 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 1223 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); |
| 1348 if (shelf_id && IsPinned(shelf_id)) | 1224 if (shelf_id && IsPinned(shelf_id)) |
| 1349 Unpin(shelf_id); | 1225 Unpin(shelf_id); |
| 1350 } | 1226 } |
| 1351 | 1227 |
| 1352 int ChromeLauncherController::PinRunningAppInternal(int index, | 1228 int ChromeLauncherController::PinRunningAppInternal(int index, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1373 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); | 1249 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); |
| 1374 item.type = ash::TYPE_WINDOWED_APP; | 1250 item.type = ash::TYPE_WINDOWED_APP; |
| 1375 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such | 1251 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such |
| 1376 // we have to check here what this was before it got a shortcut. | 1252 // we have to check here what this was before it got a shortcut. |
| 1377 LauncherItemController* controller = GetLauncherItemController(item.id); | 1253 LauncherItemController* controller = GetLauncherItemController(item.id); |
| 1378 if (controller && controller->type() == LauncherItemController::TYPE_APP) | 1254 if (controller && controller->type() == LauncherItemController::TYPE_APP) |
| 1379 item.type = ash::TYPE_PLATFORM_APP; | 1255 item.type = ash::TYPE_PLATFORM_APP; |
| 1380 model_->Set(index, item); | 1256 model_->Set(index, item); |
| 1381 } | 1257 } |
| 1382 | 1258 |
| 1259 void ChromeLauncherController::SyncPinPosition(ash::ShelfID shelf_id) { |
| 1260 DCHECK(shelf_id); |
| 1261 if (ignore_persist_pinned_state_change_) |
| 1262 return; |
| 1263 |
| 1264 const int max_index = model_->item_count(); |
| 1265 const int index = model_->ItemIndexByID(shelf_id); |
| 1266 DCHECK_GT(index, 0); |
| 1267 |
| 1268 const std::string& app_id = GetAppIDForShelfID(shelf_id); |
| 1269 DCHECK(!app_id.empty()); |
| 1270 |
| 1271 std::string app_id_before; |
| 1272 std::string app_id_after; |
| 1273 |
| 1274 for (int i = index - 1; i > 0; --i) { |
| 1275 const ash::ShelfID shelf_id_before = model_->items()[i].id; |
| 1276 if (IsPinned(shelf_id_before)) { |
| 1277 app_id_before = GetAppIDForShelfID(shelf_id_before); |
| 1278 DCHECK(!app_id_before.empty()); |
| 1279 break; |
| 1280 } |
| 1281 } |
| 1282 |
| 1283 for (int i = index + 1; i < max_index; ++i) { |
| 1284 const ash::ShelfID shelf_id_after = model_->items()[i].id; |
| 1285 if (IsPinned(shelf_id_after)) { |
| 1286 app_id_after = GetAppIDForShelfID(shelf_id_after); |
| 1287 DCHECK(!app_id_after.empty()); |
| 1288 break; |
| 1289 } |
| 1290 } |
| 1291 |
| 1292 ash::launcher::SetPinPosition(profile_, app_id, app_id_before, app_id_after); |
| 1293 } |
| 1294 |
| 1295 void ChromeLauncherController::OnSyncModelUpdated() { |
| 1296 UpdateAppLaunchersFromPref(); |
| 1297 } |
| 1298 |
| 1383 void ChromeLauncherController::UpdateAppLaunchersFromPref() { | 1299 void ChromeLauncherController::UpdateAppLaunchersFromPref() { |
| 1384 // There are various functions which will trigger a |PersistPinnedState| call | 1300 // There are various functions which will trigger a |SyncPinPosition| call |
| 1385 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu | 1301 // like a direct call to |DoPinAppWithID|, or an indirect call to the |
| 1386 // model which will use weights to re-arrange the icons to new positions. | 1302 // menu model which will use weights to re-arrange the icons to new positions. |
| 1387 // Since this function is meant to synchronize the "is state" with the | 1303 // Since this function is meant to synchronize the "is state" with the |
| 1388 // "sync state", it makes no sense to store any changes by this function back | 1304 // "sync state", it makes no sense to store any changes by this function back |
| 1389 // into the pref state. Therefore we tell |persistPinnedState| to ignore any | 1305 // into the pref state. Therefore we tell |persistPinnedState| to ignore any |
| 1390 // invocations while we are running. | 1306 // invocations while we are running. |
| 1391 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); | 1307 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); |
| 1392 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs( | 1308 |
| 1309 std::vector<std::string> pinned_apps = ash::launcher::GetPinnedAppsFromPrefs( |
| 1393 profile_->GetPrefs(), launcher_controller_helper_.get()); | 1310 profile_->GetPrefs(), launcher_controller_helper_.get()); |
| 1394 | 1311 |
| 1395 int index = 0; | 1312 int index = 0; |
| 1396 int max_index = model_->item_count(); | 1313 int max_index = model_->item_count(); |
| 1314 int seen_chrome_index = -1; |
| 1397 | 1315 |
| 1398 // When one of the two special items cannot be moved (and we do not know where | 1316 // At least chrome browser shortcut should exist. |
| 1399 // yet), we remember the current location in one of these variables. | 1317 DCHECK_GT(max_index, 0); |
| 1400 int chrome_index = -1; | 1318 |
| 1401 int app_list_index = -1; | 1319 // Skip app list items if it exists. |
| 1320 if (model_->items()[0].type == ash::TYPE_APP_LIST) |
| 1321 ++index; |
| 1402 | 1322 |
| 1403 // Walk the model and |pinned_apps| from the pref lockstep, adding and | 1323 // Walk the model and |pinned_apps| from the pref lockstep, adding and |
| 1404 // removing items as necessary. NB: This code uses plain old indexing instead | 1324 // removing items as necessary. NB: This code uses plain old indexing instead |
| 1405 // of iterators because of model mutations as part of the loop. | 1325 // of iterators because of model mutations as part of the loop. |
| 1406 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); | 1326 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); |
| 1407 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { | 1327 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { |
| 1408 // Check if we have an item which we need to handle. | 1328 // Check if we have an item which we need to handle. |
| 1409 if (*pref_app_id == extension_misc::kChromeAppId || | 1329 if (IsAppPinned(*pref_app_id)) { |
| 1410 *pref_app_id == ash::kPinnedAppsPlaceholder || | 1330 if (seen_chrome_index >= 0 && |
| 1411 IsAppPinned(*pref_app_id)) { | 1331 *pref_app_id == extension_misc::kChromeAppId) { |
| 1332 // Current item is Chrome browser and we saw it before. |
| 1333 model_->Move(seen_chrome_index, index); |
| 1334 ++pref_app_id; |
| 1335 --index; |
| 1336 continue; |
| 1337 } |
| 1412 for (; index < max_index; ++index) { | 1338 for (; index < max_index; ++index) { |
| 1413 const ash::ShelfItem& item(model_->items()[index]); | 1339 const ash::ShelfItem& item(model_->items()[index]); |
| 1414 bool is_app_list = item.type == ash::TYPE_APP_LIST; | 1340 if (item.type != ash::TYPE_APP_SHORTCUT && |
| 1415 bool is_chrome = item.type == ash::TYPE_BROWSER_SHORTCUT; | 1341 item.type != ash::TYPE_BROWSER_SHORTCUT) |
| 1416 if (item.type != ash::TYPE_APP_SHORTCUT && !is_app_list && !is_chrome) | |
| 1417 continue; | 1342 continue; |
| 1418 LauncherItemController* controller = GetLauncherItemController(item.id); | 1343 LauncherItemController* controller = GetLauncherItemController(item.id); |
| 1419 if ((ash::kPinnedAppsPlaceholder == *pref_app_id && is_app_list) || | 1344 if (controller && controller->app_id() == *pref_app_id) { |
| 1420 (extension_misc::kChromeAppId == *pref_app_id && is_chrome) || | |
| 1421 (controller && controller->app_id() == *pref_app_id)) { | |
| 1422 // Check if an item needs to be moved here. | |
| 1423 MoveChromeOrApplistToFinalPosition( | |
| 1424 is_chrome, is_app_list, index, &chrome_index, &app_list_index); | |
| 1425 ++pref_app_id; | 1345 ++pref_app_id; |
| 1426 break; | 1346 break; |
| 1347 } else if (item.type == ash::TYPE_BROWSER_SHORTCUT) { |
| 1348 // We cannot close browser shortcut. Remember its position. |
| 1349 seen_chrome_index = index; |
| 1427 } else { | 1350 } else { |
| 1428 if (is_chrome || is_app_list) { | 1351 // Check if this is a platform or a windowed app. |
| 1429 // We cannot delete any of these shortcuts. As such we remember | 1352 if (item.type == ash::TYPE_APP_SHORTCUT && controller && |
| 1430 // their positions and move them later where they belong. | 1353 (controller->locked() || |
| 1431 if (is_chrome) | 1354 controller->type() == LauncherItemController::TYPE_APP)) { |
| 1432 chrome_index = index; | 1355 // Note: This will not change the amount of items (|max_index|). |
| 1433 else | 1356 // Even changes to the actual |index| due to item weighting |
| 1434 app_list_index = index; | 1357 // changes should be fine. |
| 1435 // And skip the item - or exit the loop if end is reached (note that | 1358 UnpinRunningAppInternal(index); |
| 1436 // in that case we will reduce the index again by one and this only | |
| 1437 // compensates for it). | |
| 1438 if (index >= max_index - 1) | |
| 1439 break; | |
| 1440 ++index; | |
| 1441 } else { | 1359 } else { |
| 1442 // Check if this is a platform or a windowed app. | 1360 if (controller) |
| 1443 if (item.type == ash::TYPE_APP_SHORTCUT && | 1361 LauncherItemClosed(item.id); |
| 1444 controller && | 1362 --max_index; |
| 1445 (controller->locked() || | |
| 1446 controller->type() == LauncherItemController::TYPE_APP)) { | |
| 1447 // Note: This will not change the amount of items (|max_index|). | |
| 1448 // Even changes to the actual |index| due to item weighting | |
| 1449 // changes should be fine. | |
| 1450 UnpinRunningAppInternal(index); | |
| 1451 } else { | |
| 1452 if (controller) | |
| 1453 LauncherItemClosed(item.id); | |
| 1454 --max_index; | |
| 1455 } | |
| 1456 } | 1363 } |
| 1457 --index; | 1364 --index; |
| 1458 } | 1365 } |
| 1459 } | 1366 } |
| 1460 // If the item wasn't found, that means id_to_item_controller_map_ | 1367 // If the item wasn't found, that means id_to_item_controller_map_ |
| 1461 // is out of sync. | 1368 // is out of sync. |
| 1462 DCHECK(index <= max_index); | 1369 DCHECK(index <= max_index); |
| 1463 } else { | 1370 } else { |
| 1464 // Check if the item was already running but not yet pinned. | 1371 // Check if the item was already running but not yet pinned. |
| 1465 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); | 1372 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1483 LauncherItemController* controller = GetLauncherItemController(item.id); | 1390 LauncherItemController* controller = GetLauncherItemController(item.id); |
| 1484 if (controller) { | 1391 if (controller) { |
| 1485 if (controller->locked() || | 1392 if (controller->locked() || |
| 1486 controller->type() == LauncherItemController::TYPE_APP) { | 1393 controller->type() == LauncherItemController::TYPE_APP) { |
| 1487 UnpinRunningAppInternal(index); | 1394 UnpinRunningAppInternal(index); |
| 1488 } else { | 1395 } else { |
| 1489 LauncherItemClosed(item.id); | 1396 LauncherItemClosed(item.id); |
| 1490 } | 1397 } |
| 1491 } | 1398 } |
| 1492 } else { | 1399 } else { |
| 1493 if (item.type == ash::TYPE_BROWSER_SHORTCUT) | |
| 1494 chrome_index = index; | |
| 1495 else if (item.type == ash::TYPE_APP_LIST) | |
| 1496 app_list_index = index; | |
| 1497 ++index; | 1400 ++index; |
| 1498 } | 1401 } |
| 1499 } | 1402 } |
| 1500 | 1403 |
| 1501 // Append unprocessed items from the pref to the end of the model. | 1404 // Append unprocessed items from the pref to the end of the model. |
| 1502 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { | 1405 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { |
| 1503 // All items but the chrome and / or app list shortcut needs to be added. | 1406 if (*pref_app_id == extension_misc::kChromeAppId) { |
| 1504 bool is_chrome = *pref_app_id == extension_misc::kChromeAppId; | 1407 int target_index = FindInsertionPoint(); |
| 1505 bool is_app_list = *pref_app_id == ash::kPinnedAppsPlaceholder; | 1408 DCHECK(seen_chrome_index >= 0 && seen_chrome_index < target_index); |
| 1506 // Coming here we know the next item which can be finalized, either the | 1409 model_->Move(seen_chrome_index, target_index); |
| 1507 // chrome item or the app launcher. The final position is the end of the | 1410 } else { |
| 1508 // list. The menu model will make sure that the item is grouped according | |
| 1509 // to its weight (which we do not know here). | |
| 1510 if (!is_chrome && !is_app_list) { | |
| 1511 DoPinAppWithID(*pref_app_id); | 1411 DoPinAppWithID(*pref_app_id); |
| 1512 int target_index = FindInsertionPoint(false); | 1412 int target_index = FindInsertionPoint(); |
| 1513 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id); | 1413 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id); |
| 1514 int source_index = model_->ItemIndexByID(id); | 1414 int source_index = model_->ItemIndexByID(id); |
| 1515 if (source_index != target_index) | 1415 if (source_index != target_index) |
| 1516 model_->Move(source_index, target_index); | 1416 model_->Move(source_index, target_index); |
| 1517 | |
| 1518 // Needed for the old layout - the weight might force it to be lower in | |
| 1519 // rank. | |
| 1520 if (app_list_index != -1 && target_index <= app_list_index) | |
| 1521 ++app_list_index; | |
| 1522 } else { | |
| 1523 int target_index = FindInsertionPoint(is_app_list); | |
| 1524 MoveChromeOrApplistToFinalPosition( | |
| 1525 is_chrome, is_app_list, target_index, &chrome_index, &app_list_index); | |
| 1526 } | 1417 } |
| 1527 } | 1418 } |
| 1528 } | 1419 } |
| 1529 | 1420 |
| 1530 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { | 1421 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { |
| 1531 for (auto* window : ash::Shell::GetAllRootWindows()) { | 1422 for (auto* window : ash::Shell::GetAllRootWindows()) { |
| 1532 ash::Shelf* shelf = ash::Shelf::ForWindow(window); | 1423 ash::Shelf* shelf = ash::Shelf::ForWindow(window); |
| 1533 if (shelf) { | 1424 if (shelf) { |
| 1534 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref( | 1425 shelf->SetAutoHideBehavior(ash::launcher::GetShelfAutoHideBehaviorPref( |
| 1535 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); | 1426 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); |
| 1536 } | 1427 } |
| 1537 } | 1428 } |
| 1538 } | 1429 } |
| 1539 | 1430 |
| 1540 void ChromeLauncherController::SetShelfAlignmentFromPrefs() { | 1431 void ChromeLauncherController::SetShelfAlignmentFromPrefs() { |
| 1541 if (!ash::ShelfWidget::ShelfAlignmentAllowed()) | 1432 if (!ash::ShelfWidget::ShelfAlignmentAllowed()) |
| 1542 return; | 1433 return; |
| 1543 | 1434 |
| 1544 for (auto* window : ash::Shell::GetAllRootWindows()) { | 1435 for (auto* window : ash::Shell::GetAllRootWindows()) { |
| 1545 ash::Shelf* shelf = ash::Shelf::ForWindow(window); | 1436 ash::Shelf* shelf = ash::Shelf::ForWindow(window); |
| 1546 if (shelf) { | 1437 if (shelf) { |
| 1547 shelf->SetAlignment(ash::GetShelfAlignmentPref( | 1438 shelf->SetAlignment(ash::launcher::GetShelfAlignmentPref( |
| 1548 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); | 1439 profile_->GetPrefs(), GetDisplayIDForShelf(shelf))); |
| 1549 } | 1440 } |
| 1550 } | 1441 } |
| 1551 } | 1442 } |
| 1552 | 1443 |
| 1553 void ChromeLauncherController::SetShelfBehaviorsFromPrefs() { | 1444 void ChromeLauncherController::SetShelfBehaviorsFromPrefs() { |
| 1554 SetShelfAutoHideBehaviorFromPrefs(); | 1445 SetShelfAutoHideBehaviorFromPrefs(); |
| 1555 SetShelfAlignmentFromPrefs(); | 1446 SetShelfAlignmentFromPrefs(); |
| 1556 } | 1447 } |
| 1557 | 1448 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 << "There should be always be a BrowserShortcutLauncherItemController."; | 1546 << "There should be always be a BrowserShortcutLauncherItemController."; |
| 1656 return nullptr; | 1547 return nullptr; |
| 1657 } | 1548 } |
| 1658 | 1549 |
| 1659 ash::ShelfID ChromeLauncherController::CreateBrowserShortcutLauncherItem() { | 1550 ash::ShelfID ChromeLauncherController::CreateBrowserShortcutLauncherItem() { |
| 1660 ash::ShelfItem browser_shortcut; | 1551 ash::ShelfItem browser_shortcut; |
| 1661 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; | 1552 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; |
| 1662 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1553 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 1663 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); | 1554 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); |
| 1664 ash::ShelfID id = model_->next_id(); | 1555 ash::ShelfID id = model_->next_id(); |
| 1665 size_t index = GetChromeIconIndexForCreation(); | 1556 model_->AddAt(0, browser_shortcut); |
| 1666 model_->AddAt(index, browser_shortcut); | |
| 1667 id_to_item_controller_map_[id] = | 1557 id_to_item_controller_map_[id] = |
| 1668 new BrowserShortcutLauncherItemController(this, model_); | 1558 new BrowserShortcutLauncherItemController(this, model_); |
| 1669 id_to_item_controller_map_[id]->set_shelf_id(id); | 1559 id_to_item_controller_map_[id]->set_shelf_id(id); |
| 1670 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController. | 1560 // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController. |
| 1671 SetShelfItemDelegate(id, id_to_item_controller_map_[id]); | 1561 SetShelfItemDelegate(id, id_to_item_controller_map_[id]); |
| 1672 return id; | 1562 return id; |
| 1673 } | 1563 } |
| 1674 | 1564 |
| 1675 void ChromeLauncherController::PersistChromeItemIndex(int index) { | 1565 int ChromeLauncherController::FindInsertionPoint() { |
| 1676 profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index); | 1566 DCHECK_GT(model_->item_count(), 0); |
| 1677 } | |
| 1678 | |
| 1679 void ChromeLauncherController::MoveChromeOrApplistToFinalPosition( | |
| 1680 bool is_chrome, | |
| 1681 bool is_app_list, | |
| 1682 int target_index, | |
| 1683 int* chrome_index, | |
| 1684 int* app_list_index) { | |
| 1685 if (is_chrome && *chrome_index != -1) { | |
| 1686 model_->Move(*chrome_index, target_index); | |
| 1687 if (*app_list_index != -1 && | |
| 1688 *chrome_index < *app_list_index && | |
| 1689 target_index > *app_list_index) | |
| 1690 --(*app_list_index); | |
| 1691 *chrome_index = -1; | |
| 1692 } else if (is_app_list && *app_list_index != -1) { | |
| 1693 model_->Move(*app_list_index, target_index); | |
| 1694 if (*chrome_index != -1 && | |
| 1695 *app_list_index < *chrome_index && | |
| 1696 target_index > *chrome_index) | |
| 1697 --(*chrome_index); | |
| 1698 *app_list_index = -1; | |
| 1699 } | |
| 1700 } | |
| 1701 | |
| 1702 int ChromeLauncherController::FindInsertionPoint(bool is_app_list) { | |
| 1703 // Keeping this change small to backport to M33&32 (see crbug.com/329597). | |
| 1704 // TODO(skuhne): With the removal of the legacy shelf layout we should remove | |
| 1705 // the ability to move the app list item since this was never used. We should | |
| 1706 // instead ask the ShelfModel::ValidateInsertionIndex or similir for an index. | |
| 1707 if (is_app_list) | |
| 1708 return 0; | |
| 1709 | 1567 |
| 1710 for (int i = model_->item_count() - 1; i > 0; --i) { | 1568 for (int i = model_->item_count() - 1; i > 0; --i) { |
| 1711 ash::ShelfItemType type = model_->items()[i].type; | 1569 ash::ShelfItemType type = model_->items()[i].type; |
| 1570 DCHECK_NE(ash::TYPE_APP_LIST, type); |
| 1712 if (type == ash::TYPE_APP_SHORTCUT || | 1571 if (type == ash::TYPE_APP_SHORTCUT || |
| 1713 (is_app_list && type == ash::TYPE_APP_LIST) || | |
| 1714 type == ash::TYPE_BROWSER_SHORTCUT) { | 1572 type == ash::TYPE_BROWSER_SHORTCUT) { |
| 1715 return i; | 1573 return i; |
| 1716 } | 1574 } |
| 1717 } | 1575 } |
| 1718 return 0; | 1576 return 0; |
| 1719 } | 1577 } |
| 1720 | 1578 |
| 1721 int ChromeLauncherController::GetChromeIconIndexForCreation() { | |
| 1722 // We get the list of pinned apps as they currently would get pinned. | |
| 1723 // Within this list the chrome icon will be the correct location. | |
| 1724 std::vector<std::string> pinned_apps = ash::GetPinnedAppsFromPrefs( | |
| 1725 profile_->GetPrefs(), launcher_controller_helper_.get()); | |
| 1726 | |
| 1727 std::vector<std::string>::iterator it = | |
| 1728 std::find(pinned_apps.begin(), | |
| 1729 pinned_apps.end(), | |
| 1730 std::string(extension_misc::kChromeAppId)); | |
| 1731 DCHECK(it != pinned_apps.end()); | |
| 1732 int index = it - pinned_apps.begin(); | |
| 1733 | |
| 1734 // We should do here a comparison between the is state and the "want to be" | |
| 1735 // state since some apps might be able to pin but are not yet. Instead - for | |
| 1736 // the time being we clamp against the amount of known items and wait for the | |
| 1737 // next |UpdateAppLaunchersFromPref()| call to correct it - it will come since | |
| 1738 // the pinning will be done then. | |
| 1739 return std::min(model_->item_count(), index); | |
| 1740 } | |
| 1741 | |
| 1742 bool ChromeLauncherController::IsIncognito( | 1579 bool ChromeLauncherController::IsIncognito( |
| 1743 const content::WebContents* web_contents) const { | 1580 const content::WebContents* web_contents) const { |
| 1744 const Profile* profile = | 1581 const Profile* profile = |
| 1745 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 1582 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 1746 return profile->IsOffTheRecord() && !profile->IsGuestSession() && | 1583 return profile->IsOffTheRecord() && !profile->IsGuestSession() && |
| 1747 !profile->IsSystemProfile(); | 1584 !profile->IsSystemProfile(); |
| 1748 } | 1585 } |
| 1749 | 1586 |
| 1750 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension( | 1587 void ChromeLauncherController::CloseWindowedAppsFromRemovedExtension( |
| 1751 const std::string& app_id, | 1588 const std::string& app_id, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1804 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { | 1641 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { |
| 1805 DCHECK(arc_deferred_launcher()); | 1642 DCHECK(arc_deferred_launcher()); |
| 1806 std::unique_ptr<AppIconLoader> arc_app_icon_loader( | 1643 std::unique_ptr<AppIconLoader> arc_app_icon_loader( |
| 1807 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL, | 1644 new ArcAppIconLoader(profile_, extension_misc::EXTENSION_ICON_SMALL, |
| 1808 arc_deferred_launcher(), this)); | 1645 arc_deferred_launcher(), this)); |
| 1809 app_icon_loaders_.push_back(std::move(arc_app_icon_loader)); | 1646 app_icon_loaders_.push_back(std::move(arc_app_icon_loader)); |
| 1810 } | 1647 } |
| 1811 | 1648 |
| 1812 pref_change_registrar_.Init(profile_->GetPrefs()); | 1649 pref_change_registrar_.Init(profile_->GetPrefs()); |
| 1813 pref_change_registrar_.Add( | 1650 pref_change_registrar_.Add( |
| 1814 prefs::kPinnedLauncherApps, | |
| 1815 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, | |
| 1816 base::Unretained(this))); | |
| 1817 pref_change_registrar_.Add( | |
| 1818 prefs::kPolicyPinnedLauncherApps, | 1651 prefs::kPolicyPinnedLauncherApps, |
| 1819 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, | 1652 base::Bind(&ChromeLauncherController::UpdateAppLaunchersFromPref, |
| 1820 base::Unretained(this))); | 1653 base::Unretained(this))); |
| 1821 pref_change_registrar_.Add( | 1654 pref_change_registrar_.Add( |
| 1822 prefs::kShelfAlignmentLocal, | 1655 prefs::kShelfAlignmentLocal, |
| 1823 base::Bind(&ChromeLauncherController::SetShelfAlignmentFromPrefs, | 1656 base::Bind(&ChromeLauncherController::SetShelfAlignmentFromPrefs, |
| 1824 base::Unretained(this))); | 1657 base::Unretained(this))); |
| 1825 pref_change_registrar_.Add( | 1658 pref_change_registrar_.Add( |
| 1826 prefs::kShelfAutoHideBehaviorLocal, | 1659 prefs::kShelfAutoHideBehaviorLocal, |
| 1827 base::Bind(&ChromeLauncherController:: | 1660 base::Bind(&ChromeLauncherController:: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1838 | 1671 |
| 1839 std::unique_ptr<LauncherAppUpdater> extension_app_updater( | 1672 std::unique_ptr<LauncherAppUpdater> extension_app_updater( |
| 1840 new LauncherExtensionAppUpdater(this, profile_)); | 1673 new LauncherExtensionAppUpdater(this, profile_)); |
| 1841 app_updaters_.push_back(std::move(extension_app_updater)); | 1674 app_updaters_.push_back(std::move(extension_app_updater)); |
| 1842 | 1675 |
| 1843 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { | 1676 if (arc::ArcAuthService::IsAllowedForProfile(profile_)) { |
| 1844 std::unique_ptr<LauncherAppUpdater> arc_app_updater( | 1677 std::unique_ptr<LauncherAppUpdater> arc_app_updater( |
| 1845 new LauncherArcAppUpdater(this, profile_)); | 1678 new LauncherArcAppUpdater(this, profile_)); |
| 1846 app_updaters_.push_back(std::move(arc_app_updater)); | 1679 app_updaters_.push_back(std::move(arc_app_updater)); |
| 1847 } | 1680 } |
| 1681 |
| 1682 app_list::AppListSyncableService* app_service = |
| 1683 app_list::AppListSyncableServiceFactory::GetForProfile(profile_); |
| 1684 if (app_service) |
| 1685 app_service->AddObserverAndStart(this); |
| 1848 } | 1686 } |
| 1849 | 1687 |
| 1850 void ChromeLauncherController::ReleaseProfile() { | 1688 void ChromeLauncherController::ReleaseProfile() { |
| 1851 if (app_sync_ui_state_) | 1689 if (app_sync_ui_state_) |
| 1852 app_sync_ui_state_->RemoveObserver(this); | 1690 app_sync_ui_state_->RemoveObserver(this); |
| 1853 | 1691 |
| 1854 app_updaters_.clear(); | 1692 app_updaters_.clear(); |
| 1855 | 1693 |
| 1856 prefs_observer_.reset(); | 1694 prefs_observer_.reset(); |
| 1857 | 1695 |
| 1858 pref_change_registrar_.RemoveAll(); | 1696 pref_change_registrar_.RemoveAll(); |
| 1697 |
| 1698 app_list::AppListSyncableService* app_service = |
| 1699 app_list::AppListSyncableServiceFactory::GetForProfile(profile_); |
| 1700 if (app_service) |
| 1701 app_service->RemoveObserver(this); |
| 1859 } | 1702 } |
| 1860 | 1703 |
| 1861 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp( | 1704 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp( |
| 1862 const std::string& app_id) { | 1705 const std::string& app_id) { |
| 1863 for (const auto& app_icon_loader : app_icon_loaders_) { | 1706 for (const auto& app_icon_loader : app_icon_loaders_) { |
| 1864 if (app_icon_loader->CanLoadImageForApp(app_id)) | 1707 if (app_icon_loader->CanLoadImageForApp(app_id)) |
| 1865 return app_icon_loader.get(); | 1708 return app_icon_loader.get(); |
| 1866 } | 1709 } |
| 1867 | 1710 |
| 1868 return nullptr; | 1711 return nullptr; |
| 1869 } | 1712 } |
| OLD | NEW |