diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp | 265 |
1 files changed, 50 insertions, 215 deletions
diff --git a/chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp b/chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp index d72d4b17128..bbe66c9ea36 100644 --- a/chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp +++ b/chromium/third_party/WebKit/Source/web/WebHelperPluginImpl.cpp @@ -29,249 +29,84 @@ */ #include "config.h" -#include "WebHelperPluginImpl.h" +#include "web/WebHelperPluginImpl.h" -#include "PageWidgetDelegate.h" -#include "WebDocument.h" -#include "WebFrameClient.h" -#include "WebFrameImpl.h" -#include "WebPlugin.h" -#include "WebPluginContainerImpl.h" -#include "WebViewClient.h" -#include "WebViewImpl.h" -#include "WebWidgetClient.h" -#include "core/dom/NodeList.h" -#include "core/html/HTMLPlugInElement.h" -#include "core/loader/DocumentLoader.h" -#include "core/loader/EmptyClients.h" -#include "core/page/FocusController.h" -#include "core/frame/FrameView.h" -#include "core/page/Page.h" -#include "core/frame/Settings.h" +#include "core/html/HTMLObjectElement.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "public/web/WebPlugin.h" +#include "web/WebLocalFrameImpl.h" +#include "web/WebPluginContainerImpl.h" using namespace WebCore; namespace blink { -#define addLiteral(literal, writer) writer->addData(literal, sizeof(literal) - 1) +DEFINE_TYPE_CASTS(WebHelperPluginImpl, WebHelperPlugin, plugin, true, true); -static inline void addString(const String& str, DocumentWriter* writer) +WebHelperPlugin* WebHelperPlugin::create(const WebString& pluginType, WebLocalFrame* frame) { - CString str8 = str.utf8(); - writer->addData(str8.data(), str8.length()); -} - -static void writeDocument(const String& pluginType, const WebDocument& hostDocument, WebCore::DocumentLoader* loader) -{ - // Give the new document the same URL as the hose document so that content - // settings and other decisions can be made based on the correct origin. - const WebURL& url = hostDocument.url(); - - DocumentWriter* writer = loader->beginWriting("text/html", "UTF-8", url); - - addLiteral("<!DOCTYPE html><head><meta charset='UTF-8'></head><body>\n", writer); - String objectTag = "<object type=\"" + pluginType + "\"></object>"; - addString(objectTag, writer); - addLiteral("</body>\n", writer); - - loader->endWriting(writer); + OwnPtr<WebHelperPlugin> plugin = adoptPtr<WebHelperPlugin>(new WebHelperPluginImpl()); + if (!toWebHelperPluginImpl(plugin.get())->initialize(pluginType, toWebLocalFrameImpl(frame))) + return 0; + return plugin.leakPtr(); } -class HelperPluginChromeClient : public EmptyChromeClient { - WTF_MAKE_NONCOPYABLE(HelperPluginChromeClient); - WTF_MAKE_FAST_ALLOCATED; - -public: - explicit HelperPluginChromeClient(WebHelperPluginImpl* widget) - : m_widget(widget) - { - ASSERT(m_widget->m_widgetClient); - } - -private: - virtual void closeWindowSoon() OVERRIDE - { - // This should never be called since the only way to close the - // invisible page is via closeHelperPlugin(). - ASSERT_NOT_REACHED(); - m_widget->closeHelperPlugin(); - } - - virtual void* webView() const OVERRIDE - { - return m_widget->m_webView; - } - - WebHelperPluginImpl* m_widget; -}; - -// HelperPluginFrameClient acts as a filter to only forward messages onto the -// main render frame that WebHelperPlugin actually needs. This prevents -// having the WebHelperPlugin's frame accidentally signaling events on the -// client that are meant only for WebFrames which are part of the main DOM. -class HelperPluginFrameClient : public WebFrameClient { -public: - HelperPluginFrameClient(WebFrameClient* hostWebFrameClient) - : m_hostWebFrameClient(hostWebFrameClient) - { - } - - virtual ~HelperPluginFrameClient() - { - } - - virtual WebPlugin* createPlugin(blink::WebFrame* frame, const WebPluginParams& params) - { - return m_hostWebFrameClient->createPlugin(frame, params); - } - -private: - WebFrameClient* m_hostWebFrameClient; -}; - - -// WebHelperPluginImpl ---------------------------------------------------------------- - -WebHelperPluginImpl::WebHelperPluginImpl(WebWidgetClient* client) - : m_widgetClient(client) - , m_webView(0) - , m_mainFrame(0) +WebHelperPluginImpl::WebHelperPluginImpl() + : m_destructionTimer(this, &WebHelperPluginImpl::reallyDestroy) { - ASSERT(client); } WebHelperPluginImpl::~WebHelperPluginImpl() { - ASSERT(!m_page); } -bool WebHelperPluginImpl::initialize(const String& pluginType, const WebDocument& hostDocument, WebViewImpl* webView) +bool WebHelperPluginImpl::initialize(const String& pluginType, WebLocalFrameImpl* frame) { - ASSERT(webView); - m_webView = webView; - - return initializePage(pluginType, hostDocument); + ASSERT(!m_objectElement && !m_pluginContainer); + if (!frame->frame()->loader().client()) + return false; + + m_objectElement = HTMLObjectElement::create(*frame->frame()->document(), 0, false); + Vector<String> attributeNames; + Vector<String> attributeValues; + ASSERT(frame->frame()->document()->url().isValid()); + m_pluginContainer = adoptRef(toWebPluginContainerImpl(frame->frame()->loader().client()->createPlugin( + m_objectElement.get(), + frame->frame()->document()->url(), + attributeNames, + attributeValues, + pluginType, + false, + FrameLoaderClient::AllowDetachedPlugin).leakRef())); + + if (!m_pluginContainer) + return false; + + // Getting a placeholder plugin is also failure, since it's not the plugin the caller needed. + return !getPlugin()->isPlaceholder(); } -void WebHelperPluginImpl::closeHelperPlugin() +void WebHelperPluginImpl::reallyDestroy(Timer<WebHelperPluginImpl>*) { - if (m_page) { - m_page->clearPageGroup(); - m_page->mainFrame()->loader().stopAllLoaders(); - } - - // We must destroy the page now in case the host page is being destroyed, in - // which case some of the objects the page depends on may have been - // destroyed by the time this->close() is called asynchronously. - destroyPage(); - - // m_widgetClient might be 0 because this widget might be already closed. - if (m_widgetClient) { - // closeWidgetSoon() will call this->close() later. - m_widgetClient->closeWidgetSoon(); - } - m_mainFrame->close(); + delete this; } -void WebHelperPluginImpl::initializeFrame(WebFrameClient* client) +void WebHelperPluginImpl::destroy() { - ASSERT(m_page); - ASSERT(!m_frameClient); - m_frameClient = adoptPtr(new HelperPluginFrameClient(client)); - m_mainFrame = WebFrameImpl::create(m_frameClient.get()); - m_mainFrame->initializeAsMainFrame(m_page.get()); + // Defer deletion so we don't do too much work when called via stopActiveDOMObjects(). + // FIXME: It's not clear why we still need this. The original code held a Page and a + // WebFrame, and destroying it would cause JavaScript triggered by frame detach to run, + // which isn't allowed inside stopActiveDOMObjects(). Removing this causes one Chrome test + // to fail with a timeout. + m_destructionTimer.startOneShot(0, FROM_HERE); } -// Returns a pointer to the WebPlugin by finding the single <object> tag in the page. WebPlugin* WebHelperPluginImpl::getPlugin() { - ASSERT(m_page); - - RefPtr<NodeList> objectElements = m_page->mainFrame()->document()->getElementsByTagName(WebCore::HTMLNames::objectTag.localName()); - ASSERT(objectElements && objectElements->length() == 1); - if (!objectElements || objectElements->length() < 1) - return 0; - Node* node = objectElements->item(0); - ASSERT(node->hasTagName(WebCore::HTMLNames::objectTag)); - WebCore::Widget* widget = toHTMLPlugInElement(node)->pluginWidget(); - if (!widget) - return 0; - WebPlugin* plugin = toPluginContainerImpl(widget)->plugin(); - ASSERT(plugin); - // If the plugin is a placeholder, it is not useful to the caller, and it - // could be replaced at any time. Therefore, do not return it. - if (plugin->isPlaceholder()) - return 0; - - // The plugin was instantiated and will outlive this object. - return plugin; -} - -bool WebHelperPluginImpl::initializePage(const String& pluginType, const WebDocument& hostDocument) -{ - Page::PageClients pageClients; - fillWithEmptyClients(pageClients); - m_chromeClient = adoptPtr(new HelperPluginChromeClient(this)); - pageClients.chromeClient = m_chromeClient.get(); - - m_page = adoptPtr(new Page(pageClients)); - ASSERT(!m_page->settings().isScriptEnabled()); - m_page->settings().setPluginsEnabled(true); - - m_webView->client()->initializeHelperPluginWebFrame(this); - - // The page's main frame was set in initializeFrame() as a result of the above call. - Frame* frame = m_page->mainFrame(); - ASSERT(frame); - frame->loader().forceSandboxFlags(SandboxAll & ~SandboxPlugins); - frame->setView(FrameView::create(frame)); - // No need to set a size or make it not transparent. - - writeDocument(pluginType, hostDocument, frame->loader().activeDocumentLoader()); - - return true; -} - -void WebHelperPluginImpl::destroyPage() -{ - if (!m_page) - return; - - if (m_page->mainFrame()) - m_page->mainFrame()->loader().frameDetached(); - - m_page.clear(); -} - -void WebHelperPluginImpl::layout() -{ - PageWidgetDelegate::layout(m_page.get()); -} - -void WebHelperPluginImpl::setFocus(bool) -{ - ASSERT_NOT_REACHED(); -} - -void WebHelperPluginImpl::close() -{ - ASSERT(!m_page); // Should only be called via closePopup(). - m_widgetClient = 0; - deref(); -} - -// WebHelperPlugin ---------------------------------------------------------------- - -WebHelperPlugin* WebHelperPlugin::create(WebWidgetClient* client) -{ - RELEASE_ASSERT(client); - // A WebHelperPluginImpl instance usually has two references. - // - One owned by the instance itself. It represents the visible widget. - // - One owned by the hosting element. It's released when the hosting - // element asks the WebHelperPluginImpl to close. - // We need them because the closing operation is asynchronous and the widget - // can be closed while the hosting element is unaware of it. - return adoptRef(new WebHelperPluginImpl(client)).leakRef(); + ASSERT(m_pluginContainer); + ASSERT(m_pluginContainer->plugin()); + return m_pluginContainer->plugin(); } } // namespace blink |