| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANNOTATION_ANNOTATION_TEST_UTILS_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_ANNOTATION_ANNOTATION_TEST_UTILS_H_ |
| |
| #include <optional> |
| |
| #include "base/check_op.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "third_party/blink/public/mojom/annotation/annotation.mojom-blink-forward.h" |
| #include "third_party/blink/public/mojom/annotation/annotation.mojom-blink.h" |
| #include "third_party/blink/renderer/core/annotation/annotation_agent_impl.h" |
| #include "third_party/blink/renderer/core/annotation/annotation_selector.h" |
| #include "third_party/blink/renderer/core/editing/position.h" |
| #include "third_party/blink/renderer/core/editing/range_in_flat_tree.h" |
| #include "third_party/blink/renderer/platform/wtf/functional.h" |
| |
| namespace blink { |
| |
| // A selector type for returning a predetermined range in tests. The empty |
| // constructor will simply return the entire Document tree as a range. |
| // Otherwise, the caller can specify a range in the constructor that will be |
| // returned. Specifying a null Range will simulate a "not found" result. |
| class MockAnnotationSelector : public AnnotationSelector { |
| public: |
| MockAnnotationSelector() = default; |
| explicit MockAnnotationSelector(RangeInFlatTree& mock_result) |
| : mock_result_(&mock_result) {} |
| |
| String Serialize() const override { return ""; } |
| |
| void FindRange(Range& search_range, |
| SearchType type, |
| FinishedCallback finished_cb) override { |
| RangeInFlatTree* range; |
| |
| if (mock_result_) { |
| if (mock_result_->IsNull()) { |
| range = nullptr; |
| } else { |
| range = mock_result_; |
| |
| DCHECK_EQ(mock_result_->StartPosition().GetDocument(), |
| &search_range.OwnerDocument()); |
| } |
| } else { |
| // Just select the whole document. |
| auto range_start = |
| PositionInFlatTree::FirstPositionInNode(search_range.OwnerDocument()); |
| auto range_end = |
| PositionInFlatTree::LastPositionInNode(search_range.OwnerDocument()); |
| range = MakeGarbageCollected<RangeInFlatTree>(range_start, range_end); |
| } |
| |
| std::move(finished_cb).Run(range); |
| } |
| |
| void Trace(Visitor* visitor) const override { |
| visitor->Trace(mock_result_); |
| AnnotationSelector::Trace(visitor); |
| } |
| |
| private: |
| Member<RangeInFlatTree> mock_result_; |
| }; |
| |
| class ScopedUseMockAnnotationSelector { |
| public: |
| ScopedUseMockAnnotationSelector() { |
| AnnotationSelector::SetGeneratorForTesting(BindRepeating( |
| &ScopedUseMockAnnotationSelector::Generate, Unretained(this))); |
| } |
| |
| ~ScopedUseMockAnnotationSelector() { |
| AnnotationSelector::UnsetGeneratorForTesting(); |
| } |
| |
| private: |
| AnnotationSelector* Generate(const String& serialized) { |
| return MakeGarbageCollected<MockAnnotationSelector>(); |
| } |
| }; |
| |
| class MockAnnotationAgentHost : public mojom::blink::AnnotationAgentHost { |
| public: |
| MockAnnotationAgentHost() : receiver_(this) {} |
| ~MockAnnotationAgentHost() override = default; |
| void DidFinishAttachment(const gfx::Rect& rect, |
| mojom::blink::AttachmentResult result) override { |
| did_finish_attachment_rect_ = rect; |
| attachment_result_ = result; |
| } |
| |
| void BindToAgent(AnnotationAgentImpl& agent) { |
| // Receivers have no way to query is_connected so we use a disconnect |
| // handler. |
| auto pending_remote = receiver_.BindNewPipeAndPassRemote(); |
| DCHECK(receiver_.is_bound()); |
| receiver_.set_disconnect_handler( |
| BindRepeating([](bool* did_disconnect) { *did_disconnect = true; }, |
| Unretained(&did_disconnect_))); |
| |
| agent.Bind(std::move(pending_remote), agent_.BindNewPipeAndPassReceiver()); |
| } |
| |
| void Bind( |
| mojo::PendingReceiver<mojom::blink::AnnotationAgentHost> host_receiver, |
| mojo::PendingRemote<mojom::blink::AnnotationAgent> agent_remote) { |
| agent_.Bind(std::move(agent_remote)); |
| receiver_.Bind(std::move(host_receiver)); |
| } |
| |
| using RemoteHostReceiverAgentPair = |
| std::pair<mojo::PendingRemote<mojom::blink::AnnotationAgentHost>, |
| mojo::PendingReceiver<mojom::blink::AnnotationAgent>>; |
| |
| RemoteHostReceiverAgentPair BindForCreateAgent() { |
| auto pending_remote = receiver_.BindNewPipeAndPassRemote(); |
| receiver_.set_disconnect_handler( |
| BindRepeating([](bool* did_disconnect) { *did_disconnect = true; }, |
| Unretained(&did_disconnect_))); |
| |
| return std::make_pair(std::move(pending_remote), |
| agent_.BindNewPipeAndPassReceiver()); |
| } |
| |
| // Flushes both the receiver and remote mojo connections. |
| void FlushForTesting() { |
| receiver_.FlushForTesting(); |
| if (agent_) |
| agent_.FlushForTesting(); |
| } |
| |
| // Public to allow inspection. |
| mojo::Receiver<mojom::blink::AnnotationAgentHost> receiver_; |
| mojo::Remote<mojom::blink::AnnotationAgent> agent_; |
| std::optional<gfx::Rect> did_finish_attachment_rect_; |
| std::optional<mojom::blink::AttachmentResult> attachment_result_; |
| bool did_disconnect_ = false; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANNOTATION_ANNOTATION_TEST_UTILS_H_ |