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