[Clipboard API] Refactor Pasteboard item reading functions to work on both iOS and...
[WebKit.git] / Source / WebCore / platform / PasteboardItemInfo.h
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #pragma once
27
28 #include <wtf/Optional.h>
29 #include <wtf/Vector.h>
30 #include <wtf/text/WTFString.h>
31
32 namespace WebCore {
33
34 enum class PasteboardItemPresentationStyle {
35     Unspecified,
36     Inline,
37     Attachment
38 };
39
40 struct PresentationSize {
41     Optional<double> width;
42     Optional<double> height;
43
44     template<class Encoder> void encode(Encoder&) const;
45     template<class Decoder> static Optional<PresentationSize> decode(Decoder&);
46 };
47
48 template<class Encoder>
49 void PresentationSize::encode(Encoder& encoder) const
50 {
51     encoder << width << height;
52 }
53
54 template<class Decoder>
55 Optional<PresentationSize> PresentationSize::decode(Decoder& decoder)
56 {
57     PresentationSize result;
58     if (!decoder.decode(result.width))
59         return WTF::nullopt;
60
61     if (!decoder.decode(result.height))
62         return WTF::nullopt;
63
64     return WTFMove(result);
65 }
66
67 struct PasteboardItemInfo {
68     Vector<String> pathsForFileUpload;
69     Vector<String> platformTypesForFileUpload;
70     Vector<String> platformTypesByFidelity;
71     String suggestedFileName;
72     PresentationSize preferredPresentationSize;
73     bool isNonTextType { false };
74     bool containsFileURLAndFileUploadContent { false };
75     Vector<String> webSafeTypesByFidelity;
76     int changeCount { 0 };
77     PasteboardItemPresentationStyle preferredPresentationStyle { PasteboardItemPresentationStyle::Unspecified };
78
79     String pathForContentType(const String& type) const
80     {
81         ASSERT(pathsForFileUpload.size() == platformTypesForFileUpload.size());
82         auto index = platformTypesForFileUpload.find(type);
83         if (index == notFound)
84             return { };
85
86         return pathsForFileUpload[index];
87     }
88
89     // The preferredPresentationStyle flag is platform API used by drag or copy sources to explicitly indicate
90     // that the data being written to the item provider should be treated as an attachment; unfortunately, not
91     // all clients attempt to set this flag, so we additionally take having a suggested filename as a strong
92     // indicator that the item should be treated as an attachment or file.
93     bool canBeTreatedAsAttachmentOrFile() const
94     {
95         switch (preferredPresentationStyle) {
96         case PasteboardItemPresentationStyle::Inline:
97             return false;
98         case PasteboardItemPresentationStyle::Attachment:
99             return true;
100         case PasteboardItemPresentationStyle::Unspecified:
101             return !suggestedFileName.isEmpty();
102         }
103         ASSERT_NOT_REACHED();
104         return false;
105     }
106
107     String contentTypeForHighestFidelityItem() const
108     {
109         if (platformTypesForFileUpload.isEmpty())
110             return { };
111
112         return platformTypesForFileUpload.first();
113     }
114
115     String pathForHighestFidelityItem() const
116     {
117         if (pathsForFileUpload.isEmpty())
118             return { };
119
120         return pathsForFileUpload.first();
121     }
122
123     template<class Encoder> void encode(Encoder&) const;
124     template<class Decoder> static Optional<PasteboardItemInfo> decode(Decoder&);
125 };
126
127 template<class Encoder>
128 void PasteboardItemInfo::encode(Encoder& encoder) const
129 {
130     encoder << pathsForFileUpload << platformTypesForFileUpload << platformTypesByFidelity << suggestedFileName << preferredPresentationSize << isNonTextType << containsFileURLAndFileUploadContent << webSafeTypesByFidelity << changeCount;
131     encoder.encodeEnum(preferredPresentationStyle);
132 }
133
134 template<class Decoder>
135 Optional<PasteboardItemInfo> PasteboardItemInfo::decode(Decoder& decoder)
136 {
137     PasteboardItemInfo result;
138     if (!decoder.decode(result.pathsForFileUpload))
139         return WTF::nullopt;
140
141     if (!decoder.decode(result.platformTypesForFileUpload))
142         return WTF::nullopt;
143
144     if (!decoder.decode(result.platformTypesByFidelity))
145         return WTF::nullopt;
146
147     if (!decoder.decode(result.suggestedFileName))
148         return WTF::nullopt;
149
150     if (!decoder.decode(result.preferredPresentationSize))
151         return WTF::nullopt;
152
153     if (!decoder.decode(result.isNonTextType))
154         return WTF::nullopt;
155
156     if (!decoder.decode(result.containsFileURLAndFileUploadContent))
157         return WTF::nullopt;
158
159     if (!decoder.decode(result.webSafeTypesByFidelity))
160         return WTF::nullopt;
161
162     if (!decoder.decode(result.changeCount))
163         return WTF::nullopt;
164
165     if (!decoder.decodeEnum(result.preferredPresentationStyle))
166         return WTF::nullopt;
167
168     return WTFMove(result);
169 }
170
171 }
172
173 namespace WTF {
174
175 template<> struct EnumTraits<WebCore::PasteboardItemPresentationStyle> {
176     using values = EnumValues<
177         WebCore::PasteboardItemPresentationStyle,
178         WebCore::PasteboardItemPresentationStyle::Unspecified,
179         WebCore::PasteboardItemPresentationStyle::Inline,
180         WebCore::PasteboardItemPresentationStyle::Attachment
181     >;
182 };
183
184 } // namespace WTF