| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/crosapi/clipboard_history_ash.h" |
| |
| #include <utility> |
| |
| #include "ash/public/cpp/clipboard_history_controller.h" |
| #include "ash/shell.h" |
| #include "base/scoped_observation.h" |
| #include "base/unguessable_token.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "chromeos/crosapi/mojom/clipboard_history.mojom.h" |
| #include "chromeos/ui/clipboard_history/clipboard_history_util.h" |
| |
| namespace crosapi { |
| |
| namespace { |
| std::vector<crosapi::mojom::ClipboardHistoryItemDescriptorPtr> |
| GetCurrentDescriptors() { |
| std::vector<crosapi::mojom::ClipboardHistoryItemDescriptorPtr> |
| descriptor_ptrs; |
| for (const auto& descriptor : |
| chromeos::clipboard_history::QueryItemDescriptors()) { |
| descriptor_ptrs.push_back(descriptor.Clone()); |
| } |
| return descriptor_ptrs; |
| } |
| } // namespace |
| |
| // ClipboardHistoryAsh::ClientUpdater ------------------------------------------ |
| |
| // Updates the cached descriptors of the associated client. Used only when the |
| // clipboard history refresh feature is enabled. |
| class ClipboardHistoryAsh::ClientUpdater |
| : public ash::ClipboardHistoryController::Observer { |
| public: |
| explicit ClientUpdater(mojom::ClipboardHistoryClient* client) |
| : client_(client) { |
| CHECK(chromeos::features::IsClipboardHistoryRefreshEnabled()); |
| observation_.Observe(ash::ClipboardHistoryController::Get()); |
| } |
| ClientUpdater(const ClientUpdater&) = delete; |
| ClientUpdater& operator=(const ClientUpdater&) = delete; |
| ~ClientUpdater() override = default; |
| |
| // ash::ClipboardHistoryController::Observer: |
| void OnClipboardHistoryItemsUpdated() override { |
| client_->SetClipboardHistoryItemDescriptors(GetCurrentDescriptors()); |
| } |
| |
| private: |
| // The associated client. |
| const raw_ptr<mojom::ClipboardHistoryClient> client_; |
| |
| // The observation on the clipboard history controller. |
| base::ScopedObservation<ash::ClipboardHistoryController, |
| ash::ClipboardHistoryController::Observer> |
| observation_{this}; |
| }; |
| |
| // ClipboardHistoryAsh --------------------------------------------------------- |
| |
| ClipboardHistoryAsh::ClipboardHistoryAsh() { |
| // `ash::Shell` may not exist in tests. |
| if (ash::Shell::HasInstance()) { |
| shell_observation_.Observe(ash::Shell::Get()); |
| } |
| } |
| |
| ClipboardHistoryAsh::~ClipboardHistoryAsh() = default; |
| |
| void ClipboardHistoryAsh::ShowClipboard( |
| const gfx::Rect& anchor_point, |
| ui::MenuSourceType menu_source_type, |
| crosapi::mojom::ClipboardHistoryControllerShowSource show_source) { |
| if (auto* clipboard_history_controller = |
| ash::ClipboardHistoryController::Get()) { |
| clipboard_history_controller->ShowMenu(anchor_point, menu_source_type, |
| show_source); |
| } |
| } |
| |
| void ClipboardHistoryAsh::PasteClipboardItemById( |
| const base::UnguessableToken& item_id, |
| int event_flags, |
| mojom::ClipboardHistoryControllerShowSource paste_source) { |
| if (auto* clipboard_history_controller = |
| ash::ClipboardHistoryController::Get()) { |
| clipboard_history_controller->PasteClipboardItemById( |
| item_id.ToString(), event_flags, paste_source); |
| } |
| } |
| |
| void ClipboardHistoryAsh::RegisterClient( |
| mojo::PendingRemote<mojom::ClipboardHistoryClient> client) { |
| CHECK(chromeos::features::IsClipboardHistoryRefreshEnabled()); |
| |
| // In testing, `remote_client_` can be already bound when multiple Lacros |
| // tests run in parallel. This does not happen on real devices. |
| // TODO(http://b/294617428): Make `ClipboardHistoryAsh` support multiple |
| // clients then remove this code. |
| if (remote_client_.is_bound()) { |
| return; |
| } |
| |
| remote_client_.Bind(std::move(client)); |
| |
| // `remote_client_` is a class member so it is safe to use `this` here. |
| remote_client_.set_disconnect_handler(base::BindOnce( |
| &ClipboardHistoryAsh::OnRemoteDisconnected, base::Unretained(this))); |
| |
| // If there are clipboard history item descriptors, send the descriptors to |
| // `remote_client_` when connection is built. |
| if (auto descriptors = GetCurrentDescriptors(); !descriptors.empty()) { |
| remote_client_->SetClipboardHistoryItemDescriptors(std::move(descriptors)); |
| } |
| |
| client_updater_ = std::make_unique<ClientUpdater>(remote_client_.get()); |
| } |
| |
| void ClipboardHistoryAsh::UpdateRemoteDescriptorsForTesting() { |
| CHECK(chromeos::features::IsClipboardHistoryRefreshEnabled()); |
| CHECK(remote_client_.is_bound()); |
| CHECK(client_updater_); |
| |
| client_updater_->OnClipboardHistoryItemsUpdated(); |
| } |
| |
| void ClipboardHistoryAsh::BindReceiver( |
| mojo::PendingReceiver<mojom::ClipboardHistory> pending_receiver) { |
| receivers_.Add(this, std::move(pending_receiver)); |
| } |
| |
| void ClipboardHistoryAsh::FlushForTesting() { |
| remote_client_.FlushForTesting(); // IN-TEST |
| } |
| |
| void ClipboardHistoryAsh::OnShellDestroying() { |
| shell_observation_.Reset(); |
| ClearRemoteConnection(); |
| } |
| |
| void ClipboardHistoryAsh::OnRemoteDisconnected() { |
| ClearRemoteConnection(); |
| } |
| |
| void ClipboardHistoryAsh::ClearRemoteConnection() { |
| client_updater_.reset(); |
| remote_client_.reset(); |
| } |
| |
| } // namespace crosapi |