2
* Copyright (C) 2019 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
* THE POSSIBILITY OF SUCH DAMAGE.
27
#include "PasteboardCustomData.h"
29
#include "SharedBuffer.h"
30
#include <wtf/URLParser.h>
31
#include <wtf/persistence/PersistentCoders.h>
32
#include <wtf/text/StringHash.h>
36
static Variant<String, Ref<SharedBuffer>> copyPlatformData(const Variant<String, Ref<SharedBuffer>>& other)
38
if (WTF::holds_alternative<String>(other))
39
return { WTF::get<String>(other) };
41
if (WTF::holds_alternative<Ref<SharedBuffer>>(other))
42
return { WTF::get<Ref<SharedBuffer>>(other).copyRef() };
47
PasteboardCustomData::Entry::Entry(const Entry& entry)
49
, customData(entry.customData)
50
, platformData(copyPlatformData(entry.platformData))
54
PasteboardCustomData::Entry::Entry(const String& dataType)
59
PasteboardCustomData::Entry::Entry() = default;
60
PasteboardCustomData::Entry::Entry(Entry&&) = default;
62
PasteboardCustomData::Entry& PasteboardCustomData::Entry::operator=(const Entry& entry)
65
customData = entry.customData;
66
platformData = copyPlatformData(entry.platformData);
70
PasteboardCustomData::Entry& PasteboardCustomData::Entry::operator=(Entry&&) = default;
72
PasteboardCustomData::PasteboardCustomData() = default;
73
PasteboardCustomData::PasteboardCustomData(const PasteboardCustomData&) = default;
74
PasteboardCustomData::PasteboardCustomData(PasteboardCustomData&&) = default;
75
PasteboardCustomData::~PasteboardCustomData() = default;
77
PasteboardCustomData::PasteboardCustomData(String&& origin, Vector<Entry>&& data)
78
: m_origin(WTFMove(origin))
79
, m_data(WTFMove(data))
83
Ref<SharedBuffer> PasteboardCustomData::createSharedBuffer() const
85
constexpr unsigned currentCustomDataSerializationVersion = 1;
87
WTF::Persistence::Encoder encoder;
88
encoder << currentCustomDataSerializationVersion;
90
encoder << sameOriginCustomStringData();
91
encoder << orderedTypes();
92
return SharedBuffer::create(encoder.buffer(), encoder.bufferSize());
95
PasteboardCustomData PasteboardCustomData::fromSharedBuffer(const SharedBuffer& buffer)
97
constexpr unsigned maxSupportedDataSerializationVersionNumber = 1;
99
PasteboardCustomData result;
100
auto decoder = buffer.decoder();
102
if (!decoder.decode(version) || version > maxSupportedDataSerializationVersionNumber)
105
if (!decoder.decode(result.m_origin))
108
HashMap<String, String> sameOriginCustomStringData;
109
if (!decoder.decode(sameOriginCustomStringData))
112
Vector<String> orderedTypes;
113
if (!decoder.decode(orderedTypes))
116
for (auto& type : orderedTypes)
117
result.writeStringInCustomData(type, sameOriginCustomStringData.get(type));
122
void PasteboardCustomData::writeString(const String& type, const String& value)
124
addOrMoveEntryToEnd(type).platformData = { value };
127
void PasteboardCustomData::writeData(const String& type, Ref<SharedBuffer>&& data)
129
addOrMoveEntryToEnd(type).platformData = { WTFMove(data) };
132
void PasteboardCustomData::writeStringInCustomData(const String& type, const String& value)
134
addOrMoveEntryToEnd(type).customData = value;
137
PasteboardCustomData::Entry& PasteboardCustomData::addOrMoveEntryToEnd(const String& type)
139
auto index = m_data.findMatching([&] (auto& entry) {
140
return entry.type == type;
142
auto entry = index == notFound ? Entry(type) : m_data[index];
143
if (index != notFound)
144
m_data.remove(index);
145
m_data.append(WTFMove(entry));
146
return m_data.last();
149
void PasteboardCustomData::clear()
154
void PasteboardCustomData::clear(const String& type)
156
m_data.removeFirstMatching([&] (auto& entry) {
157
return entry.type == type;
161
PasteboardCustomData& PasteboardCustomData::operator=(const PasteboardCustomData& other)
163
m_origin = other.origin();
164
m_data = other.m_data;
168
Vector<String> PasteboardCustomData::orderedTypes() const
170
return m_data.map([&] (auto& entry) {
175
bool PasteboardCustomData::hasData() const
177
return !m_data.isEmpty();
180
bool PasteboardCustomData::hasSameOriginCustomData() const
182
return notFound != m_data.findMatching([&] (auto& entry) {
183
return !entry.customData.isNull();
187
HashMap<String, String> PasteboardCustomData::sameOriginCustomStringData() const
189
HashMap<String, String> customData;
190
for (auto& entry : m_data)
191
customData.set(entry.type, entry.customData);
195
RefPtr<SharedBuffer> PasteboardCustomData::readBuffer(const String& type) const
197
for (auto& entry : m_data) {
198
if (entry.type != type)
201
if (WTF::holds_alternative<Ref<SharedBuffer>>(entry.platformData))
202
return makeRefPtr(WTF::get<Ref<SharedBuffer>>(entry.platformData).get());
209
String PasteboardCustomData::readString(const String& type) const
211
for (auto& entry : m_data) {
212
if (entry.type != type)
215
if (WTF::holds_alternative<String>(entry.platformData))
216
return WTF::get<String>(entry.platformData);
223
String PasteboardCustomData::readStringInCustomData(const String& type) const
225
for (auto& entry : m_data) {
226
if (entry.type == type)
227
return entry.customData;
232
void PasteboardCustomData::forEachType(Function<void(const String&)>&& function) const
234
for (auto& entry : m_data)
235
function(entry.type);
238
void PasteboardCustomData::forEachPlatformString(Function<void(const String& type, const String& data)>&& function) const
240
for (auto& entry : m_data) {
241
if (!WTF::holds_alternative<String>(entry.platformData))
244
auto string = WTF::get<String>(entry.platformData);
245
if (!string.isNull())
246
function(entry.type, string);
250
void PasteboardCustomData::forEachCustomString(Function<void(const String& type, const String& data)>&& function) const
252
for (auto& entry : m_data) {
253
if (!entry.customData.isNull())
254
function(entry.type, entry.customData);
258
void PasteboardCustomData::forEachPlatformStringOrBuffer(Function<void(const String& type, const Variant<String, Ref<SharedBuffer>>& data)>&& function) const
260
for (auto& entry : m_data) {
261
auto& data = entry.platformData;
262
if ((WTF::holds_alternative<String>(data) && !WTF::get<String>(data).isNull()) || WTF::holds_alternative<Ref<SharedBuffer>>(data))
263
function(entry.type, data);
267
} // namespace WebCore