Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / PluginDocument.cpp
1 /*
2  * Copyright (C) 2006, 2008 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 COMPUTER, 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 COMPUTER, 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 "core/html/PluginDocument.h"
27
28 #include "HTMLNames.h"
29 #include "bindings/v8/ExceptionStatePlaceholder.h"
30 #include "core/dom/RawDataDocumentParser.h"
31 #include "core/frame/FrameView.h"
32 #include "core/frame/LocalFrame.h"
33 #include "core/html/HTMLBodyElement.h"
34 #include "core/html/HTMLEmbedElement.h"
35 #include "core/html/HTMLHtmlElement.h"
36 #include "core/loader/DocumentLoader.h"
37 #include "core/loader/FrameLoader.h"
38 #include "core/loader/FrameLoaderClient.h"
39 #include "core/plugins/PluginView.h"
40 #include "core/rendering/RenderEmbeddedObject.h"
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 // FIXME: Share more code with MediaDocumentParser.
47 class PluginDocumentParser : 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(nullptr)
58     {
59     }
60
61     virtual void appendBytes(const char*, size_t) OVERRIDE;
62
63     virtual void finish() OVERRIDE;
64
65     void createDocumentStructure();
66
67     PluginView* pluginView() const;
68
69     RefPtr<HTMLEmbedElement> m_embedElement;
70 };
71
72 void PluginDocumentParser::createDocumentStructure()
73 {
74     // FIXME: Assert we have a loader to figure out why the original null checks
75     // and assert were added for the security bug in http://trac.webkit.org/changeset/87566
76     ASSERT(document());
77     RELEASE_ASSERT(document()->loader());
78
79     LocalFrame* frame = document()->frame();
80     if (!frame)
81         return;
82
83     // FIXME: Why does this check settings?
84     if (!frame->settings() || !frame->loader().allowPlugins(NotAboutToInstantiatePlugin))
85         return;
86
87     RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document());
88     rootElement->insertedByParser();
89     document()->appendChild(rootElement);
90     frame->loader().dispatchDocumentElementAvailable();
91
92     RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document());
93     body->setAttribute(marginwidthAttr, "0");
94     body->setAttribute(marginheightAttr, "0");
95     body->setAttribute(styleAttr, "background-color: rgb(38,38,38)");
96     rootElement->appendChild(body);
97
98     m_embedElement = HTMLEmbedElement::create(*document());
99     m_embedElement->setAttribute(widthAttr, "100%");
100     m_embedElement->setAttribute(heightAttr, "100%");
101     m_embedElement->setAttribute(nameAttr, "plugin");
102     m_embedElement->setAttribute(srcAttr, AtomicString(document()->url().string()));
103     m_embedElement->setAttribute(typeAttr, document()->loader()->mimeType());
104     body->appendChild(m_embedElement);
105
106     toPluginDocument(document())->setPluginNode(m_embedElement.get());
107
108     document()->updateLayout();
109
110     // We need the plugin to load synchronously so we can get the PluginView
111     // below so flush the layout tasks now instead of waiting on the timer.
112     frame->view()->flushAnyPendingPostLayoutTasks();
113
114     if (PluginView* view = pluginView())
115         view->didReceiveResponse(document()->loader()->response());
116 }
117
118 void PluginDocumentParser::appendBytes(const char* data, size_t length)
119 {
120     if (!m_embedElement)
121         createDocumentStructure();
122
123     if (!length)
124         return;
125     if (PluginView* view = pluginView())
126         view->didReceiveData(data, length);
127 }
128
129 void PluginDocumentParser::finish()
130 {
131     if (PluginView* view = pluginView()) {
132         const ResourceError& error = document()->loader()->mainDocumentError();
133         if (error.isNull())
134             view->didFinishLoading();
135         else
136             view->didFailLoading(error);
137         m_embedElement = nullptr;
138     }
139     RawDataDocumentParser::finish();
140 }
141
142 PluginView* PluginDocumentParser::pluginView() const
143 {
144     if (Widget* widget = toPluginDocument(document())->pluginWidget()) {
145         ASSERT_WITH_SECURITY_IMPLICATION(widget->isPluginContainer());
146         return toPluginView(widget);
147     }
148     return 0;
149 }
150
151 PluginDocument::PluginDocument(const DocumentInit& initializer)
152     : HTMLDocument(initializer, PluginDocumentClass)
153     , m_shouldLoadPluginManually(true)
154 {
155     setCompatibilityMode(QuirksMode);
156     lockCompatibilityMode();
157 }
158
159 PassRefPtr<DocumentParser> PluginDocument::createParser()
160 {
161     return PluginDocumentParser::create(this);
162 }
163
164 Widget* PluginDocument::pluginWidget()
165 {
166     if (m_pluginNode && m_pluginNode->renderer()) {
167         ASSERT(m_pluginNode->renderer()->isEmbeddedObject());
168         return toRenderEmbeddedObject(m_pluginNode->renderer())->widget();
169     }
170     return 0;
171 }
172
173 Node* PluginDocument::pluginNode()
174 {
175     return m_pluginNode.get();
176 }
177
178 void PluginDocument::detach(const AttachContext& context)
179 {
180     // Release the plugin node so that we don't have a circular reference.
181     m_pluginNode = nullptr;
182     HTMLDocument::detach(context);
183 }
184
185 void PluginDocument::trace(Visitor* visitor)
186 {
187     visitor->trace(m_pluginNode);
188     HTMLDocument::trace(visitor);
189 }
190
191 }