Home | History | Annotate | Download | only in html
      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