15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/PluginDocument.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/RawDataDocumentParser.h"
31d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/FrameView.h"
32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h"
33e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/html/HTMLBodyElement.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLEmbedElement.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLHtmlElement.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/DocumentLoader.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoader.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoaderClient.h"
39591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/plugins/PluginView.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderEmbeddedObject.h"
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
4302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Share more code with MediaDocumentParser.
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class PluginDocumentParser : public RawDataDocumentParser {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
49d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    static PassRefPtrWillBeRawPtr<PluginDocumentParser> create(PluginDocument* document)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
51d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return adoptRefWillBeNoop(new PluginDocumentParser(document));
52d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
53d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
54d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    virtual void trace(Visitor* visitor) OVERRIDE
55d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    {
56d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        visitor->trace(m_embedElement);
57d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        RawDataDocumentParser::trace(visitor);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PluginDocumentParser(Document* document)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        : RawDataDocumentParser(document)
63d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        , m_embedElement(nullptr)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    virtual void appendBytes(const char*, size_t) OVERRIDE;
68591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
69591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    virtual void finish() OVERRIDE;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void createDocumentStructure();
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
73591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    PluginView* pluginView() const;
74591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
75d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RefPtrWillBeMember<HTMLEmbedElement> m_embedElement;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PluginDocumentParser::createDocumentStructure()
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
80e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // FIXME: Assert we have a loader to figure out why the original null checks
81e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // and assert were added for the security bug in http://trac.webkit.org/changeset/87566
828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(document());
83e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    RELEASE_ASSERT(document()->loader());
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
85d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    LocalFrame* frame = document()->frame();
86e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (!frame)
87e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return;
88e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
89e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // FIXME: Why does this check settings?
90f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    if (!frame->settings() || !frame->loader().allowPlugins(NotAboutToInstantiatePlugin))
91e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return;
92e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
93323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document());
94e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    rootElement->insertedByParser();
95e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    document()->appendChild(rootElement);
96f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    frame->loader().dispatchDocumentElementAvailable();
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
98323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document());
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    body->setAttribute(marginwidthAttr, "0");
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    body->setAttribute(marginheightAttr, "0");
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    body->setAttribute(styleAttr, "background-color: rgb(38,38,38)");
102e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    rootElement->appendChild(body);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_embedElement = HTMLEmbedElement::create(*document());
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_embedElement->setAttribute(widthAttr, "100%");
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_embedElement->setAttribute(heightAttr, "100%");
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_embedElement->setAttribute(nameAttr, "plugin");
108a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_embedElement->setAttribute(srcAttr, AtomicString(document()->url().string()));
109e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    m_embedElement->setAttribute(typeAttr, document()->loader()->mimeType());
110e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    body->appendChild(m_embedElement);
11102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
112e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    toPluginDocument(document())->setPluginNode(m_embedElement.get());
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayout();
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
116e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // We need the plugin to load synchronously so we can get the PluginView
117e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // below so flush the layout tasks now instead of waiting on the timer.
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    frame->view()->flushAnyPendingPostLayoutTasks();
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
120591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (PluginView* view = pluginView())
121591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        view->didReceiveResponse(document()->loader()->response());
122591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
12451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void PluginDocumentParser::appendBytes(const char* data, size_t length)
125591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
126591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!m_embedElement)
127591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        createDocumentStructure();
128591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
129591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!length)
13051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return;
131591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (PluginView* view = pluginView())
132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        view->didReceiveData(data, length);
133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
134591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
135591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid PluginDocumentParser::finish()
136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
137591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (PluginView* view = pluginView()) {
138591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const ResourceError& error = document()->loader()->mainDocumentError();
139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (error.isNull())
140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            view->didFinishLoading();
141591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else
142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            view->didFailLoading(error);
143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_embedElement = nullptr;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
145591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RawDataDocumentParser::finish();
146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
147591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
148591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPluginView* PluginDocumentParser::pluginView() const
149591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
1508abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (Widget* widget = toPluginDocument(document())->pluginWidget()) {
151591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ASSERT_WITH_SECURITY_IMPLICATION(widget->isPluginContainer());
1528abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        return toPluginView(widget);
153591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
154591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return 0;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
157e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochPluginDocument::PluginDocument(const DocumentInit& initializer)
158e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    : HTMLDocument(initializer, PluginDocumentClass)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setCompatibilityMode(QuirksMode);
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lockCompatibilityMode();
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
164d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)PassRefPtrWillBeRawPtr<DocumentParser> PluginDocument::createParser()
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return PluginDocumentParser::create(this);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Widget* PluginDocument::pluginWidget()
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_pluginNode && m_pluginNode->renderer()) {
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_pluginNode->renderer()->isEmbeddedObject());
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return toRenderEmbeddedObject(m_pluginNode->renderer())->widget();
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node* PluginDocument::pluginNode()
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_pluginNode.get();
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
183521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void PluginDocument::detach(const AttachContext& context)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Release the plugin node so that we don't have a circular reference.
186d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_pluginNode = nullptr;
187521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    HTMLDocument::detach(context);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
190323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void PluginDocument::trace(Visitor* visitor)
191323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
192323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    visitor->trace(m_pluginNode);
193323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    HTMLDocument::trace(visitor);
194323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
195323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
197