| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "peridot/bin/agents/clipboard/clipboard_storage.h" |
| |
| #include <lib/fsl/vmo/strings.h> |
| #include <lib/fxl/functional/make_copyable.h> |
| |
| namespace modular { |
| namespace { |
| |
| fidl::VectorPtr<uint8_t> ToArray(const std::string& str) { |
| auto array = fidl::VectorPtr<uint8_t>::New(str.size()); |
| memcpy(array->data(), str.data(), str.size()); |
| return array; |
| } |
| |
| std::string ToString(fuchsia::mem::Buffer value) { |
| fsl::SizedVmo vmo; |
| std::string parsed_string; |
| if (!fsl::SizedVmo::FromTransport(std::move(value), &vmo)) { |
| FXL_LOG(ERROR) << "Could not decode clipboard value."; |
| return ""; |
| } |
| if (!fsl::StringFromVmo(vmo, &parsed_string)) { |
| FXL_LOG(ERROR) |
| << "fuchsia::modular::Clipboard vmo could not be decoded to string."; |
| return ""; |
| } |
| return parsed_string; |
| } |
| |
| // The Ledger key that is used to store the current value. |
| constexpr char kCurrentValueKey[] = "current_value"; |
| |
| } // namespace |
| |
| class ClipboardStorage::PushCall : public Operation<> { |
| public: |
| PushCall(ClipboardStorage* const impl, const fidl::StringPtr& text) |
| : Operation("ClipboardStorage::PushCall", [] {}), |
| impl_(impl), |
| text_(text) {} |
| |
| private: |
| void Run() override { |
| FlowToken flow{this}; |
| impl_->page()->Put(ToArray(kCurrentValueKey), ToArray(text_), |
| [this, flow](fuchsia::ledger::Status status) { |
| if (status != fuchsia::ledger::Status::OK) { |
| FXL_LOG(ERROR) << "Failed to put text: " << text_; |
| } |
| }); |
| } |
| |
| ClipboardStorage* const impl_; // not owned |
| const fidl::StringPtr text_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(PushCall); |
| }; |
| |
| class ClipboardStorage::PeekCall : public Operation<fidl::StringPtr> { |
| public: |
| PeekCall(ClipboardStorage* const impl, |
| std::function<void(fidl::StringPtr)> result) |
| : Operation("ClipboardStorage::PeekCall", std::move(result)), |
| impl_(impl) { |
| // No error checking: Absent ledger value yields "", not |
| // null. TODO(mesch): Once we support types, distinction of |
| // null may make sense. |
| text_.reset(""); |
| } |
| |
| private: |
| void Run() override { |
| FlowToken flow{this, &text_}; |
| impl_->page()->GetSnapshot( |
| snapshot_.NewRequest(), fidl::VectorPtr<uint8_t>::New(0), nullptr, |
| [](fuchsia::ledger::Status status) { |
| if (status != fuchsia::ledger::Status::OK) { |
| FXL_LOG(ERROR) << "Failed to get page snapshot"; |
| } |
| }); |
| |
| snapshot_->Get(ToArray(kCurrentValueKey), |
| [this, flow](fuchsia::ledger::Status status, |
| fuchsia::mem::BufferPtr value) { |
| if (value) { |
| text_ = ToString(std::move(*value)); |
| } |
| }); |
| } |
| |
| ClipboardStorage* const impl_; // not owned |
| fuchsia::ledger::PageSnapshotPtr snapshot_; |
| fidl::StringPtr text_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(PeekCall); |
| }; |
| |
| ClipboardStorage::ClipboardStorage(LedgerClient* ledger_client, |
| LedgerPageId page_id) |
| : PageClient("ClipboardStorage", ledger_client, std::move(page_id)) {} |
| |
| ClipboardStorage::~ClipboardStorage() = default; |
| |
| void ClipboardStorage::Push(const fidl::StringPtr& text) { |
| operation_queue_.Add(new PushCall(this, text)); |
| } |
| |
| void ClipboardStorage::Peek( |
| const std::function<void(fidl::StringPtr)>& callback) { |
| operation_queue_.Add(new PeekCall(this, callback)); |
| } |
| |
| } // namespace modular |