Use is<>() / downcast<>() for all remaining RenderObject subclasses
[WebKit-https.git] / Source / WebCore / html / PluginDocument.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2013 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 "DocumentLoader.h"
29 #include "ExceptionCodePlaceholder.h"
30 #include "Frame.h"
31 #include "FrameLoader.h"
32 #include "FrameLoaderClient.h"
33 #include "FrameView.h"
34 #include "HTMLEmbedElement.h"
35 #include "HTMLHtmlElement.h"
36 #include "HTMLNames.h"
37 #include "Page.h"
38 #include "RawDataDocumentParser.h"
39 #include "RenderEmbeddedObject.h"
40 #include "Settings.h"
41
42 namespace WebCore {
43     
44 using namespace HTMLNames;
45
46 // FIXME: Share more code with MediaDocumentParser.
47 class PluginDocumentParser final : public RawDataDocumentParser {
48 public:
49     static PassRefPtr<PluginDocumentParser> create(PluginDocument& document)
50     {
51         return adoptRef(new PluginDocumentParser(document));
52     }
53
54 private:
55     PluginDocumentParser(Document& document)
56         : RawDataDocumentParser(document)
57         , m_embedElement(0)
58     {
59     }
60
61     virtual void appendBytes(DocumentWriter&, const char*, size_t) override;
62
63     void createDocumentStructure();
64
65     HTMLEmbedElement* m_embedElement;
66 };
67
68 void PluginDocumentParser::createDocumentStructure()
69 {
70     RefPtr<Element> rootElement = document()->createElement(htmlTag, false);
71     document()->appendChild(rootElement, IGNORE_EXCEPTION);
72     downcast<HTMLHtmlElement>(*rootElement).insertedByParser();
73
74     if (document()->frame())
75         document()->frame()->injectUserScripts(InjectAtDocumentStart);
76
77 #if PLATFORM(IOS)
78     // Should not be able to zoom into standalone plug-in documents.
79     document()->processViewport(ASCIILiteral("user-scalable=no"), ViewportArguments::PluginDocument);
80 #endif
81
82     RefPtr<Element> body = document()->createElement(bodyTag, false);
83     body->setAttribute(marginwidthAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
84     body->setAttribute(marginheightAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
85 #if PLATFORM(IOS)
86     body->setAttribute(styleAttr, AtomicString("background-color: rgb(217,224,233)", AtomicString::ConstructFromLiteral));
87 #else
88     body->setAttribute(styleAttr, AtomicString("background-color: rgb(38,38,38)", AtomicString::ConstructFromLiteral));
89 #endif
90
91     rootElement->appendChild(body, IGNORE_EXCEPTION);
92         
93     RefPtr<Element> embedElement = document()->createElement(embedTag, false);
94         
95     m_embedElement = downcast<HTMLEmbedElement>(embedElement.get());
96     m_embedElement->setAttribute(widthAttr, "100%");
97     m_embedElement->setAttribute(heightAttr, "100%");
98     
99     m_embedElement->setAttribute(nameAttr, "plugin");
100     m_embedElement->setAttribute(srcAttr, document()->url().string());
101     
102     DocumentLoader* loader = document()->loader();
103     ASSERT(loader);
104     if (loader)
105         m_embedElement->setAttribute(typeAttr, loader->writer().mimeType());
106
107     downcast<PluginDocument>(*document()).setPluginElement(m_embedElement);
108
109     body->appendChild(embedElement, IGNORE_EXCEPTION);
110 }
111
112 void PluginDocumentParser::appendBytes(DocumentWriter&, const char*, size_t)
113 {
114     if (m_embedElement)
115         return;
116
117     createDocumentStructure();
118
119     Frame* frame = document()->frame();
120     if (!frame)
121         return;
122
123     document()->updateLayout();
124
125     // Below we assume that renderer->widget() to have been created by
126     // document()->updateLayout(). However, in some cases, updateLayout() will 
127     // recurse too many times and delay its post-layout tasks (such as creating
128     // the widget). Here we kick off the pending post-layout tasks so that we
129     // can synchronously redirect data to the plugin.
130     frame->view()->flushAnyPendingPostLayoutTasks();
131
132     if (RenderWidget* renderer = m_embedElement->renderWidget()) {
133         if (Widget* widget = renderer->widget()) {
134             frame->loader().client().redirectDataToPlugin(widget);
135             // In a plugin document, the main resource is the plugin. If we have a null widget, that means
136             // the loading of the plugin was cancelled, which gives us a null mainResourceLoader(), so we
137             // need to have this call in a null check of the widget or of mainResourceLoader().
138             frame->loader().activeDocumentLoader()->setMainResourceDataBufferingPolicy(DoNotBufferData);
139         }
140     }
141 }
142
143 PluginDocument::PluginDocument(Frame* frame, const URL& url)
144     : HTMLDocument(frame, url, PluginDocumentClass)
145     , m_shouldLoadPluginManually(true)
146 {
147     setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
148     lockCompatibilityMode();
149 }
150
151 PassRefPtr<DocumentParser> PluginDocument::createParser()
152 {
153     return PluginDocumentParser::create(*this);
154 }
155
156 Widget* PluginDocument::pluginWidget()
157 {
158     if (m_pluginElement && m_pluginElement->renderer())
159         return downcast<RenderEmbeddedObject>(*m_pluginElement->renderer()).widget();
160     return nullptr;
161 }
162
163 void PluginDocument::setPluginElement(PassRefPtr<HTMLPlugInElement> element)
164 {
165     m_pluginElement = element;
166 }
167
168 void PluginDocument::detachFromPluginElement()
169 {
170     // Release the plugin Element so that we don't have a circular reference.
171     m_pluginElement = 0;
172     frame()->loader().client().redirectDataToPlugin(0);
173 }
174
175 void PluginDocument::cancelManualPluginLoad()
176 {
177     // PluginDocument::cancelManualPluginLoad should only be called once, but there are issues
178     // with how many times we call beforeload on object elements. <rdar://problem/8441094>.
179     if (!shouldLoadPluginManually())
180         return;
181
182     DocumentLoader* documentLoader = frame()->loader().activeDocumentLoader();
183     documentLoader->cancelMainResourceLoad(frame()->loader().cancelledError(documentLoader->request()));
184     setShouldLoadPluginManually(false);
185 }
186
187 }