[WPE][GTK] Build failure with ENABLE_ACCESSIBILITY=OFF
[WebKit-https.git] / Source / WebCore / html / PluginDocument.cpp
1 /*
2  * Copyright (C) 2006-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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
23  */
24
25 #include "config.h"
26 #include "PluginDocument.h"
27
28 #include "CustomHeaderFields.h"
29 #include "DocumentLoader.h"
30 #include "Frame.h"
31 #include "FrameLoader.h"
32 #include "FrameLoaderClient.h"
33 #include "FrameView.h"
34 #include "HTMLBodyElement.h"
35 #include "HTMLEmbedElement.h"
36 #include "HTMLHtmlElement.h"
37 #include "HTMLNames.h"
38 #include "RawDataDocumentParser.h"
39 #include "RenderEmbeddedObject.h"
40 #include <wtf/IsoMallocInlines.h>
41
42 namespace WebCore {
43
44 WTF_MAKE_ISO_ALLOCATED_IMPL(PluginDocument);
45
46 using namespace HTMLNames;
47
48 // FIXME: Share more code with MediaDocumentParser.
49 class PluginDocumentParser final : public RawDataDocumentParser {
50 public:
51     static Ref<PluginDocumentParser> create(PluginDocument& document)
52     {
53         return adoptRef(*new PluginDocumentParser(document));
54     }
55
56 private:
57     PluginDocumentParser(Document& document)
58         : RawDataDocumentParser(document)
59     {
60     }
61
62     void appendBytes(DocumentWriter&, const char*, size_t) final;
63     void createDocumentStructure();
64
65     HTMLEmbedElement* m_embedElement { nullptr };
66 };
67
68 void PluginDocumentParser::createDocumentStructure()
69 {
70     auto& document = downcast<PluginDocument>(*this->document());
71
72     auto rootElement = HTMLHtmlElement::create(document);
73     document.appendChild(rootElement);
74     rootElement->insertedByParser();
75
76     if (document.frame())
77         document.frame()->injectUserScripts(InjectAtDocumentStart);
78
79 #if PLATFORM(IOS_FAMILY)
80     // Should not be able to zoom into standalone plug-in documents.
81     document.processViewport("user-scalable=no"_s, ViewportArguments::PluginDocument);
82 #endif
83
84     auto body = HTMLBodyElement::create(document);
85     body->setAttributeWithoutSynchronization(marginwidthAttr, AtomString("0", AtomString::ConstructFromLiteral));
86     body->setAttributeWithoutSynchronization(marginheightAttr, AtomString("0", AtomString::ConstructFromLiteral));
87 #if PLATFORM(IOS_FAMILY)
88     body->setAttribute(styleAttr, AtomString("background-color: rgb(217,224,233)", AtomString::ConstructFromLiteral));
89 #else
90     body->setAttribute(styleAttr, AtomString("background-color: rgb(38,38,38)", AtomString::ConstructFromLiteral));
91 #endif
92
93     rootElement->appendChild(body);
94         
95     auto embedElement = HTMLEmbedElement::create(document);
96         
97     m_embedElement = embedElement.ptr();
98     embedElement->setAttributeWithoutSynchronization(widthAttr, AtomString("100%", AtomString::ConstructFromLiteral));
99     embedElement->setAttributeWithoutSynchronization(heightAttr, AtomString("100%", AtomString::ConstructFromLiteral));
100     
101     embedElement->setAttributeWithoutSynchronization(nameAttr, AtomString("plugin", AtomString::ConstructFromLiteral));
102     embedElement->setAttributeWithoutSynchronization(srcAttr, document.url().string());
103     
104     ASSERT(document.loader());
105     if (auto loader = makeRefPtr(document.loader()))
106         m_embedElement->setAttributeWithoutSynchronization(typeAttr, loader->writer().mimeType());
107
108     document.setPluginElement(*m_embedElement);
109
110     body->appendChild(embedElement);
111 }
112
113 void PluginDocumentParser::appendBytes(DocumentWriter&, const char*, size_t)
114 {
115     if (m_embedElement)
116         return;
117
118     createDocumentStructure();
119
120     auto frame = makeRefPtr(document()->frame());
121     if (!frame)
122         return;
123
124     document()->updateLayout();
125
126     // Below we assume that renderer->widget() to have been created by
127     // document()->updateLayout(). However, in some cases, updateLayout() will 
128     // recurse too many times and delay its post-layout tasks (such as creating
129     // the widget). Here we kick off the pending post-layout tasks so that we
130     // can synchronously redirect data to the plugin.
131     frame->view()->flushAnyPendingPostLayoutTasks();
132
133     if (RenderWidget* renderer = m_embedElement->renderWidget()) {
134         if (RefPtr<Widget> widget = renderer->widget()) {
135             frame->loader().client().redirectDataToPlugin(*widget);
136             // In a plugin document, the main resource is the plugin. If we have a null widget, that means
137             // the loading of the plugin was cancelled, which gives us a null mainResourceLoader(), so we
138             // need to have this call in a null check of the widget or of mainResourceLoader().
139             frame->loader().activeDocumentLoader()->setMainResourceDataBufferingPolicy(DataBufferingPolicy::DoNotBufferData);
140         }
141     }
142 }
143
144 PluginDocument::PluginDocument(Frame* frame, const URL& url)
145     : HTMLDocument(frame, url, PluginDocumentClass)
146 {
147     setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
148     lockCompatibilityMode();
149 }
150
151 Ref<DocumentParser> PluginDocument::createParser()
152 {
153     return PluginDocumentParser::create(*this);
154 }
155
156 Widget* PluginDocument::pluginWidget()
157 {
158     if (!m_pluginElement)
159         return nullptr;
160     auto* renderer = m_pluginElement->renderer();
161     if (!renderer)
162         return nullptr;
163     return downcast<RenderEmbeddedObject>(*m_pluginElement->renderer()).widget();
164 }
165
166 void PluginDocument::setPluginElement(HTMLPlugInElement& element)
167 {
168     m_pluginElement = &element;
169 }
170
171 void PluginDocument::detachFromPluginElement()
172 {
173     // Release the plugin Element so that we don't have a circular reference.
174     m_pluginElement = nullptr;
175 }
176
177 void PluginDocument::cancelManualPluginLoad()
178 {
179     // PluginDocument::cancelManualPluginLoad should only be called once, but there are issues
180     // with how many times we call beforeload on object elements. <rdar://problem/8441094>.
181     if (!shouldLoadPluginManually())
182         return;
183
184     auto& frameLoader = frame()->loader();
185     auto& documentLoader = *frameLoader.activeDocumentLoader();
186     documentLoader.cancelMainResourceLoad(frameLoader.cancelledError(documentLoader.request()));
187     m_shouldLoadPluginManually = false;
188 }
189
190 }