| Index: chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
|
| diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
|
| index a7582988caa445814a8962bd32c5fb25cdd45d15..0c729a9fcb1205bc179d8ace94be77aad9b93460 100644
|
| --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
|
| +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
|
| @@ -5,6 +5,7 @@
|
| #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
|
|
|
| #include "ash/multi_profile_uma.h"
|
| +#include "ash/public/cpp/remote_shelf_item_delegate.h"
|
| #include "ash/public/cpp/shelf_item.h"
|
| #include "ash/public/interfaces/constants.mojom.h"
|
| #include "ash/resources/grit/ash_resources.h"
|
| @@ -183,7 +184,10 @@ ChromeLauncherController* ChromeLauncherController::instance_ = nullptr;
|
|
|
| ChromeLauncherController::ChromeLauncherController(Profile* profile,
|
| ash::ShelfModel* model)
|
| - : model_(model), observer_binding_(this), weak_ptr_factory_(this) {
|
| + : model_(model),
|
| + observer_binding_(this),
|
| + shelf_model_observer_binding_(this),
|
| + weak_ptr_factory_(this) {
|
| DCHECK(!instance_);
|
| instance_ = this;
|
|
|
| @@ -280,6 +284,17 @@ void ChromeLauncherController::Init() {
|
| ash::mojom::ShelfObserverAssociatedPtrInfo ptr_info;
|
| observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
|
| shelf_controller_->AddObserver(std::move(ptr_info));
|
| + if (ash_util::IsRunningInMash()) {
|
| + // Mash synchronizes two ShelfModel instances, owned by Ash and Chrome.
|
| + // Delay binding Chrome's observer of Ash for now, to avoid handling Ash's
|
| + // shelf model changes before the initial states have been synchronized.
|
| + ash::mojom::ShelfModelObserverPtr observer_ptr;
|
| + shelf_model_observer_request_ = mojo::MakeRequest(&observer_ptr);
|
| + shelf_controller_->LinkShelfModels(
|
| + std::move(observer_ptr),
|
| + base::Bind(&ChromeLauncherController::LinkShelfModels,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + }
|
| }
|
|
|
| CreateBrowserShortcutLauncherItem();
|
| @@ -1237,6 +1252,31 @@ void ChromeLauncherController::ReleaseProfile() {
|
| PrefServiceSyncableFromProfile(profile())->RemoveObserver(this);
|
| }
|
|
|
| +void ChromeLauncherController::LinkShelfModels(
|
| + ash::mojom::ShelfModelObserverPtr observer,
|
| + const std::vector<ash::ShelfItem>& items) {
|
| + // Prepend Ash's shelf model items to the local (Chrome) shelf model.
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + for (size_t i = 0; i < items.size(); ++i)
|
| + model_->AddAt(i, items[i]);
|
| +
|
| + // Notify Ash of all the other existing local (Chrome) items and delegates.
|
| + for (int32_t i = items.size(); i < model_->item_count(); ++i) {
|
| + const ash::ShelfItem& item = model_->items()[i];
|
| + observer->OnShelfItemAdded(i, item);
|
| + ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(item.id);
|
| + observer->OnShelfItemDelegateChanged(
|
| + item.id, delegate ? delegate->CreateInterfacePtrAndBind()
|
| + : ash::mojom::ShelfItemDelegatePtr());
|
| + }
|
| +
|
| + // Delay binding Chrome's observer of Ash until now, to avoid handling Ash's
|
| + // shelf model changes before the initial states have been synchronized.
|
| + shelf_model_observer_binding_.Bind(std::move(shelf_model_observer_request_));
|
| + shelf_model_observers_.AddPtr(std::move(observer));
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // ash::mojom::ShelfObserver:
|
|
|
| @@ -1273,11 +1313,74 @@ void ChromeLauncherController::OnAutoHideBehaviorChanged(
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| +// ash::mojom::ShelfModelObserver:
|
| +
|
| +void ChromeLauncherController::OnShelfItemAdded(int32_t index,
|
| + const ash::ShelfItem& item) {
|
| + DCHECK(ash_util::IsRunningInMash()) << "Unexpected model synchronization";
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + DCHECK_GE(model_->item_count(), index) << "Models out of sync";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + model_->AddAt(index, item);
|
| +}
|
| +
|
| +void ChromeLauncherController::OnShelfItemRemoved(int32_t index,
|
| + const ash::ShelfItem& item) {
|
| + DCHECK(ash_util::IsRunningInMash()) << "Unexpected model synchronization";
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + DCHECK_GT(model_->item_count(), index) << "Models out of sync";
|
| + DCHECK_EQ(model_->items()[index].id, item.id) << "Models out of sync";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + model_->RemoveItemAt(index);
|
| +}
|
| +
|
| +void ChromeLauncherController::OnShelfItemMoved(int32_t start_index,
|
| + int32_t target_index) {
|
| + DCHECK(ash_util::IsRunningInMash()) << "Unexpected model synchronization";
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + DCHECK_GT(model_->item_count(), start_index) << "Models out of sync";
|
| + DCHECK_GT(model_->item_count(), target_index) << "Models out of sync";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + model_->Move(start_index, target_index);
|
| +}
|
| +
|
| +void ChromeLauncherController::OnShelfItemChanged(int32_t index,
|
| + const ash::ShelfItem& item) {
|
| + DCHECK(ash_util::IsRunningInMash()) << "Unexpected model synchronization";
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + DCHECK_GT(model_->item_count(), index) << "Models out of sync";
|
| + DCHECK_EQ(model_->items()[index].id, item.id) << "Models out of sync";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + model_->Set(index, item);
|
| +}
|
| +
|
| +void ChromeLauncherController::OnShelfItemDelegateChanged(
|
| + const ash::ShelfID& id,
|
| + ash::mojom::ShelfItemDelegatePtr delegate) {
|
| + DCHECK(ash_util::IsRunningInMash()) << "Unexpected model synchronization";
|
| + DCHECK(!applying_remote_shelf_model_changes_) << "Unexpected model change";
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, true);
|
| + if (delegate.is_bound())
|
| + model_->SetShelfItemDelegate(id,
|
| + base::MakeUnique<ash::RemoteShelfItemDelegate>(
|
| + id, std::move(delegate)));
|
| + else
|
| + model_->SetShelfItemDelegate(id, nullptr);
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| // ash::ShelfModelObserver:
|
|
|
| void ChromeLauncherController::ShelfItemAdded(int index) {
|
| - // Update the pin position preference as needed.
|
| ash::ShelfItem item = model_->items()[index];
|
| + if (!applying_remote_shelf_model_changes_) {
|
| + shelf_model_observers_.ForAllPtrs(
|
| + [index, item](ash::mojom::ShelfModelObserver* observer) {
|
| + observer->OnShelfItemAdded(index, item);
|
| + });
|
| + }
|
| +
|
| + // Update the pin position preference as needed.
|
| if (ItemTypeIsPinned(item) && should_sync_pin_changes_)
|
| SyncPinPosition(item.id);
|
|
|
| @@ -1305,12 +1408,17 @@ void ChromeLauncherController::ShelfItemAdded(int index) {
|
| needs_update = true;
|
| item.status = status;
|
| }
|
| - if (needs_update)
|
| + if (needs_update) {
|
| + // Ensure these changes are reported back to Ash.
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, false);
|
| model_->Set(index, item);
|
| + }
|
| }
|
|
|
| // Construct a ShelfItemDelegate for the item if one does not yet exist.
|
| if (!model_->GetShelfItemDelegate(item.id)) {
|
| + // Ensure these changes are reported back to Ash.
|
| + base::AutoReset<bool> reset(&applying_remote_shelf_model_changes_, false);
|
| model_->SetShelfItemDelegate(
|
| item.id, AppShortcutLauncherItemController::Create(item.id));
|
| }
|
| @@ -1319,6 +1427,13 @@ void ChromeLauncherController::ShelfItemAdded(int index) {
|
| void ChromeLauncherController::ShelfItemRemoved(
|
| int index,
|
| const ash::ShelfItem& old_item) {
|
| + if (!applying_remote_shelf_model_changes_) {
|
| + shelf_model_observers_.ForAllPtrs(
|
| + [index, old_item](ash::mojom::ShelfModelObserver* observer) {
|
| + observer->OnShelfItemRemoved(index, old_item);
|
| + });
|
| + }
|
| +
|
| // Remove the pin position from preferences as needed.
|
| if (ItemTypeIsPinned(old_item) && should_sync_pin_changes_)
|
| RemovePinPosition(profile(), old_item.id);
|
| @@ -1330,6 +1445,13 @@ void ChromeLauncherController::ShelfItemRemoved(
|
|
|
| void ChromeLauncherController::ShelfItemMoved(int start_index,
|
| int target_index) {
|
| + if (!applying_remote_shelf_model_changes_) {
|
| + shelf_model_observers_.ForAllPtrs(
|
| + [start_index, target_index](ash::mojom::ShelfModelObserver* observer) {
|
| + observer->OnShelfItemMoved(start_index, target_index);
|
| + });
|
| + }
|
| +
|
| // Update the pin position preference as needed.
|
| const ash::ShelfItem& item = model_->items()[target_index];
|
| DCHECK_NE(ash::TYPE_APP_LIST, item.type);
|
| @@ -1340,6 +1462,14 @@ void ChromeLauncherController::ShelfItemMoved(int start_index,
|
| void ChromeLauncherController::ShelfItemChanged(
|
| int index,
|
| const ash::ShelfItem& old_item) {
|
| + if (!applying_remote_shelf_model_changes_) {
|
| + const ash::ShelfItem& item = model_->items()[index];
|
| + shelf_model_observers_.ForAllPtrs(
|
| + [index, item](ash::mojom::ShelfModelObserver* observer) {
|
| + observer->OnShelfItemChanged(index, item);
|
| + });
|
| + }
|
| +
|
| if (!should_sync_pin_changes_)
|
| return;
|
|
|
| @@ -1351,6 +1481,20 @@ void ChromeLauncherController::ShelfItemChanged(
|
| RemovePinPosition(profile(), old_item.id);
|
| }
|
|
|
| +void ChromeLauncherController::ShelfItemDelegateChanged(
|
| + const ash::ShelfID& id,
|
| + ash::ShelfItemDelegate* delegate) {
|
| + if (applying_remote_shelf_model_changes_)
|
| + return;
|
| +
|
| + shelf_model_observers_.ForAllPtrs(
|
| + [id, delegate](ash::mojom::ShelfModelObserver* observer) {
|
| + observer->OnShelfItemDelegateChanged(
|
| + id, delegate ? delegate->CreateInterfacePtrAndBind()
|
| + : ash::mojom::ShelfItemDelegatePtr());
|
| + });
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // ash::WindowTreeHostManager::Observer:
|
|
|
|
|