[WPE][GTK] Build failure with ENABLE_ACCESSIBILITY=OFF
[WebKit-https.git] / Source / WebCore / html / HTMLAttachmentElement.cpp
1 /*
2  * Copyright (C) 2015-2018 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 #include "config.h"
27 #include "HTMLAttachmentElement.h"
28
29 #if ENABLE(ATTACHMENT_ELEMENT)
30
31 #include "DOMURL.h"
32 #include "Document.h"
33 #include "Editor.h"
34 #include "File.h"
35 #include "Frame.h"
36 #include "HTMLImageElement.h"
37 #include "HTMLNames.h"
38 #include "MIMETypeRegistry.h"
39 #include "RenderAttachment.h"
40 #include "SharedBuffer.h"
41 #include <pal/FileSizeFormatter.h>
42 #include <wtf/IsoMallocInlines.h>
43 #include <wtf/UUID.h>
44 #include <wtf/URLParser.h>
45
46 #if PLATFORM(COCOA)
47 #include "UTIUtilities.h"
48 #endif
49
50 namespace WebCore {
51
52 WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLAttachmentElement);
53
54 using namespace HTMLNames;
55
56 HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document)
57     : HTMLElement(tagName, document)
58 {
59     ASSERT(hasTagName(attachmentTag));
60 }
61
62 HTMLAttachmentElement::~HTMLAttachmentElement() = default;
63
64 Ref<HTMLAttachmentElement> HTMLAttachmentElement::create(const QualifiedName& tagName, Document& document)
65 {
66     return adoptRef(*new HTMLAttachmentElement(tagName, document));
67 }
68
69 RenderPtr<RenderElement> HTMLAttachmentElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
70 {
71     return createRenderer<RenderAttachment>(*this, WTFMove(style));
72 }
73
74 const String& HTMLAttachmentElement::getAttachmentIdentifier(HTMLImageElement& image)
75 {
76     if (auto attachment = image.attachmentElement())
77         return attachment->uniqueIdentifier();
78
79     auto& document = image.document();
80     auto attachment = create(HTMLNames::attachmentTag, document);
81     auto& identifier = attachment->ensureUniqueIdentifier();
82
83     document.registerAttachmentIdentifier(identifier);
84     image.setAttachmentElement(WTFMove(attachment));
85
86     return identifier;
87 }
88
89 void HTMLAttachmentElement::copyNonAttributePropertiesFromElement(const Element& source)
90 {
91     m_uniqueIdentifier = downcast<HTMLAttachmentElement>(source).uniqueIdentifier();
92     HTMLElement::copyNonAttributePropertiesFromElement(source);
93 }
94
95 URL HTMLAttachmentElement::archiveResourceURL(const String& identifier)
96 {
97     auto resourceURL = URL({ }, "applewebdata://attachment/"_s);
98     resourceURL.setPath(identifier);
99     return resourceURL;
100 }
101
102 File* HTMLAttachmentElement::file() const
103 {
104     return m_file.get();
105 }
106
107 URL HTMLAttachmentElement::blobURL() const
108 {
109     return { { }, attributeWithoutSynchronization(HTMLNames::webkitattachmentbloburlAttr).string() };
110 }
111
112 void HTMLAttachmentElement::setFile(RefPtr<File>&& file, UpdateDisplayAttributes updateAttributes)
113 {
114     m_file = WTFMove(file);
115
116     if (updateAttributes == UpdateDisplayAttributes::Yes) {
117         if (m_file) {
118             setAttributeWithoutSynchronization(HTMLNames::titleAttr, m_file->name());
119             setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(m_file->size()));
120             setAttributeWithoutSynchronization(HTMLNames::typeAttr, m_file->type());
121         } else {
122             removeAttribute(HTMLNames::titleAttr);
123             removeAttribute(HTMLNames::subtitleAttr);
124             removeAttribute(HTMLNames::typeAttr);
125         }
126     }
127
128     if (auto* renderer = this->renderer())
129         renderer->invalidate();
130 }
131
132 Node::InsertedIntoAncestorResult HTMLAttachmentElement::insertedIntoAncestor(InsertionType type, ContainerNode& ancestor)
133 {
134     auto result = HTMLElement::insertedIntoAncestor(type, ancestor);
135     if (type.connectedToDocument)
136         document().didInsertAttachmentElement(*this);
137     return result;
138 }
139
140 void HTMLAttachmentElement::removedFromAncestor(RemovalType type, ContainerNode& ancestor)
141 {
142     HTMLElement::removedFromAncestor(type, ancestor);
143     if (type.disconnectedFromDocument)
144         document().didRemoveAttachmentElement(*this);
145 }
146
147 const String& HTMLAttachmentElement::ensureUniqueIdentifier()
148 {
149     if (m_uniqueIdentifier.isEmpty())
150         m_uniqueIdentifier = createCanonicalUUIDString();
151     return m_uniqueIdentifier;
152 }
153
154 bool HTMLAttachmentElement::hasEnclosingImage() const
155 {
156     return is<HTMLImageElement>(shadowHost());
157 }
158
159 void HTMLAttachmentElement::parseAttribute(const QualifiedName& name, const AtomString& value)
160 {
161     if (name == progressAttr || name == subtitleAttr || name == titleAttr || name == typeAttr) {
162         if (auto* renderer = this->renderer())
163             renderer->invalidate();
164     }
165
166     HTMLElement::parseAttribute(name, value);
167 }
168
169 String HTMLAttachmentElement::attachmentTitle() const
170 {
171     auto& title = attributeWithoutSynchronization(titleAttr);
172     if (!title.isEmpty())
173         return title;
174     return m_file ? m_file->name() : String();
175 }
176
177 String HTMLAttachmentElement::attachmentTitleForDisplay() const
178 {
179     auto title = attachmentTitle();
180
181     auto indexOfLastDot = title.reverseFind('.');
182     if (indexOfLastDot == notFound)
183         return title;
184
185     String name = title.left(indexOfLastDot);
186     String extension = title.substring(indexOfLastDot);
187
188     StringBuilder builder;
189     builder.append(leftToRightMark);
190     builder.append(firstStrongIsolate);
191     builder.append(name);
192     builder.append(popDirectionalIsolate);
193     builder.append(extension);
194
195     return builder.toString();
196 }
197
198 String HTMLAttachmentElement::attachmentType() const
199 {
200     return attributeWithoutSynchronization(typeAttr);
201 }
202
203 String HTMLAttachmentElement::attachmentPath() const
204 {
205     return attributeWithoutSynchronization(webkitattachmentpathAttr);
206 }
207
208 void HTMLAttachmentElement::updateAttributes(Optional<uint64_t>&& newFileSize, const String& newContentType, const String& newFilename)
209 {
210     if (!newFilename.isNull())
211         setAttributeWithoutSynchronization(HTMLNames::titleAttr, newFilename);
212     else
213         removeAttribute(HTMLNames::titleAttr);
214
215     if (!newContentType.isNull())
216         setAttributeWithoutSynchronization(HTMLNames::typeAttr, newContentType);
217     else
218         removeAttribute(HTMLNames::typeAttr);
219
220     if (newFileSize)
221         setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(*newFileSize));
222     else
223         removeAttribute(HTMLNames::subtitleAttr);
224
225     if (auto* renderer = this->renderer())
226         renderer->invalidate();
227 }
228
229 static bool mimeTypeIsSuitableForInlineImageAttachment(const String& mimeType)
230 {
231     return MIMETypeRegistry::isSupportedImageMIMEType(mimeType) || MIMETypeRegistry::isPDFMIMEType(mimeType);
232 }
233
234 void HTMLAttachmentElement::updateEnclosingImageWithData(const String& contentType, Ref<SharedBuffer>&& data)
235 {
236     auto* hostElement = shadowHost();
237     if (!is<HTMLImageElement>(hostElement) || !data->size())
238         return;
239
240     String mimeType = contentType;
241 #if PLATFORM(COCOA)
242     if (isDeclaredUTI(contentType))
243         mimeType = MIMETypeFromUTI(contentType);
244 #endif
245
246     if (!mimeTypeIsSuitableForInlineImageAttachment(mimeType))
247         return;
248
249     hostElement->setAttributeWithoutSynchronization(HTMLNames::srcAttr, DOMURL::createObjectURL(document(), Blob::create(WTFMove(data), mimeType)));
250 }
251
252 } // namespace WebCore
253
254 #endif // ENABLE(ATTACHMENT_ELEMENT)