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/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 WebCore { 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 } 198