Related: cool#8648 clipboard: use JSON when requesting HTML only

Visit the
/cool/clipboard?WOPISrc=...&MimeType=text/html,text/plain;charset=utf-8
endpoint, you get a JSON with HTML and plain text. Visit
/cool/clipboard?WOPISrc=...&MimeType=text/html, you get HTML with a
custom header that is only possibly to skip easily because HTML itself
has as well-known header.

This is decied in ChildSession::getClipboard(), which has 3 cases: 1)
single specific format 2) multiple specific formats and 3) all formats.
So far only 2) used JSON, but the new async clipboard copy will want to
(als) request just plain text, where skipping our own custom header is
hard, given that the text itself has no well-known header (unlike HTML).

Solve the problem by always using JSON when a specific format is
requested, so both the HTML and HTML+plaintext case gives JSON.

The client side of this is the recently introduced Clipboard.js
parseClipboard(), which can cope with JSON already.

Signed-off-by: Miklos Vajna <vmiklos@collabora.com>
Change-Id: I8298f3f82d2a3871777c369f5aee6bb81d66a553
This commit is contained in:
Miklos Vajna 2024-04-02 16:06:45 +02:00 committed by Caolán McNamara
parent 5b6042f896
commit ea8202268c
2 changed files with 32 additions and 15 deletions

View file

@ -1273,7 +1273,7 @@ bool ChildSession::getClipboard(const StringVector& tokens)
// FIXME: extra 'content' is necessary for Message parsing.
Util::vectorAppend(output, "clipboardcontent: content\n");
bool json = specifics.size() > 1;
bool json = !specifics.empty();
Poco::JSON::Object selectionObject;
LOG_TRC("Building clipboardcontent: " << nOutCount << " items");
for (size_t i = 0; i < nOutCount; ++i)

View file

@ -77,20 +77,37 @@ public:
// Then make sure asking for multiple, specific formats results in a JSON answer, it's what
// JS expects:
std::string clipURI = getSessionClipboardURI(0);
clipURI += "&MimeType=text/html,text/plain;charset=utf-8";
std::shared_ptr<http::Session> httpSession = http::Session::create(clipURI);
std::shared_ptr<const http::Response> httpResponse =
httpSession->syncRequest(http::Request(Poco::URI(clipURI).getPathAndQuery()));
LOK_ASSERT_EQUAL(http::StatusCode::OK, httpResponse->statusLine().statusCode());
std::string body = httpResponse->getBody();
Poco::JSON::Object::Ptr object;
// This failed, we didn't return JSON.
LOK_ASSERT(JsonUtil::parseJSON(body, object));
LOK_ASSERT(object->has("text/html"));
std::string expectedPlainText(" • first\n • second\n • third");
std::string actualPlainText = object->get("text/plain;charset=utf-8").toString();
LOK_ASSERT_EQUAL(actualPlainText, expectedPlainText);
{
std::string clipURI = getSessionClipboardURI(0);
clipURI += "&MimeType=text/html,text/plain;charset=utf-8";
std::shared_ptr<http::Session> httpSession = http::Session::create(clipURI);
std::shared_ptr<const http::Response> httpResponse =
httpSession->syncRequest(http::Request(Poco::URI(clipURI).getPathAndQuery()));
LOK_ASSERT_EQUAL(http::StatusCode::OK, httpResponse->statusLine().statusCode());
std::string body = httpResponse->getBody();
Poco::JSON::Object::Ptr object;
// This failed, we didn't return JSON.
LOK_ASSERT(JsonUtil::parseJSON(body, object));
LOK_ASSERT(object->has("text/html"));
std::string expectedPlainText(" • first\n • second\n • third");
std::string actualPlainText = object->get("text/plain;charset=utf-8").toString();
LOK_ASSERT_EQUAL(actualPlainText, expectedPlainText);
}
// Now also test HTML only:
{
std::string clipURI = getSessionClipboardURI(0);
clipURI += "&MimeType=text/html";
std::shared_ptr<http::Session> httpSession = http::Session::create(clipURI);
std::shared_ptr<const http::Response> httpResponse =
httpSession->syncRequest(http::Request(Poco::URI(clipURI).getPathAndQuery()));
LOK_ASSERT_EQUAL(http::StatusCode::OK, httpResponse->statusLine().statusCode());
std::string body = httpResponse->getBody();
Poco::JSON::Object::Ptr object;
LOK_ASSERT(JsonUtil::parseJSON(body, object));
LOK_ASSERT(object->has("text/html"));
}
TRANSITION_STATE(_phase, Phase::WaitDocClose);
socket->asyncShutdown();
LOK_ASSERT(socket->waitForDisconnection(std::chrono::seconds(5)));