Chromium Code Reviews| Index: Source/core/html/HTMLPlugInElement.cpp |
| diff --git a/Source/core/html/HTMLPlugInElement.cpp b/Source/core/html/HTMLPlugInElement.cpp |
| index ebbbdd8bfaca2ce0bf9ed10d389d7796e00871be..c6d1a4698dc96017a18dc00a7f5b890a5dca6418 100644 |
| --- a/Source/core/html/HTMLPlugInElement.cpp |
| +++ b/Source/core/html/HTMLPlugInElement.cpp |
| @@ -82,7 +82,7 @@ HTMLPlugInElement::~HTMLPlugInElement() |
| bool HTMLPlugInElement::canProcessDrag() const |
| { |
| - return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->canProcessDrag(); |
| + return widget() && widget()->isPluginView() && toPluginView(widget())->canProcessDrag(); |
| } |
| bool HTMLPlugInElement::willRespondToMouseClickEvents() |
| @@ -136,12 +136,46 @@ void HTMLPlugInElement::updateWidgetIfNecessary() |
| if (!needsWidgetUpdate() || useFallbackContent() || isImageType()) |
| return; |
| + |
| + if (!renderEmbeddedObject() && !m_serviceType.isEmpty()) { |
| + createPluginWithoutRenderer(m_serviceType); |
| + return; |
| + } |
| + |
| if (!renderEmbeddedObject() || renderEmbeddedObject()->showsUnavailablePluginIndicator()) |
| return; |
| updateWidget(CreateOnlyNonNetscapePlugins); |
| } |
| +void HTMLPlugInElement::createPluginWithoutRenderer(const String& mimeType) |
| +{ |
| + KURL url; |
| + Vector<String> paramNames; |
| + Vector<String> paramValues; |
| + |
| + paramNames.append("type"); |
| + paramValues.append(mimeType); |
| + |
| + bool useFallback = false; |
| + if (loadPlugin(url, mimeType, paramNames, paramValues, useFallback)) { |
| + // Register the bindings with V8 as a scriptable object; normally this |
| + // as done in getInstance(), but that is only called after a renderer |
| + // has been assigned. |
| + // If we've created a plugin without a renderer, it may want to be able |
| + // to configure itself before attach, so make sure it has a script |
| + // object. |
| + // FIXME: Do we need a new script object and plugin wrapper when we |
| + // create a plugin? Or can we re-use any existing ones? |
| + Widget* plugin = widget(); |
| + ASSERT(plugin); |
| + Frame* frame = document().frame(); |
| + if (!m_NPObject) |
| + m_NPObject = frame->script().createScriptObjectForPluginElement(this); |
| + m_pluginWrapper = frame->script().createPluginWrapper(plugin); |
| + } |
| +} |
| + |
| void HTMLPlugInElement::detach(const AttachContext& context) |
| { |
| // Update the widget the next time we attach (detaching destroys the plugin). |
| @@ -149,7 +183,13 @@ void HTMLPlugInElement::detach(const AttachContext& context) |
| if (renderer() && !useFallbackContent()) |
| setNeedsWidgetUpdate(true); |
| - resetInstance(); |
| + Widget* plugin = widget(); |
| + if (plugin) { |
|
eseidel
2013/12/02 16:28:34
Just combine these two ifs into one line?
wjmaclean
2013/12/02 21:51:55
This disappears in the new patch :-)
|
| + if (!plugin->pluginShouldPersist()) { |
| + setWidget(0); |
| + resetInstance(); |
| + } |
| + } |
| if (m_isCapturingMouseEvents) { |
| if (Frame* frame = document().frame()) |
| @@ -215,8 +255,8 @@ SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() |
| // return the cached allocated Bindings::Instance. Not supporting this |
| // edge-case is OK. |
| if (!m_pluginWrapper) { |
| - if (Widget* widget = pluginWidget()) |
| - m_pluginWrapper = frame->script().createPluginWrapper(widget); |
| + if (Widget* plugin = widget()) |
| + m_pluginWrapper = frame->script().createPluginWrapper(plugin); |
| } |
| return m_pluginWrapper.get(); |
| } |
| @@ -234,20 +274,6 @@ bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) |
| return beforeLoadAllowedLoad; |
| } |
| -Widget* HTMLPlugInElement::pluginWidget() const |
| -{ |
| - if (m_inBeforeLoadEventHandler) { |
| - // The plug-in hasn't loaded yet, and it makes no sense to try to load |
| - // if beforeload handler happened to touch the plug-in element. That |
| - // would recursively call beforeload for the same element. |
| - return 0; |
| - } |
| - |
| - if (RenderWidget* renderWidget = renderWidgetForJSBindings()) |
| - return renderWidget->widget(); |
| - return 0; |
| -} |
| - |
| bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const |
| { |
| if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr) |
| @@ -317,7 +343,7 @@ bool HTMLPlugInElement::isKeyboardFocusable() const |
| { |
| if (!document().page()) |
| return false; |
| - return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->supportsKeyboardFocus(); |
| + return widget() && widget()->isPluginView() && toPluginView(widget())->supportsKeyboardFocus(); |
| } |
| bool HTMLPlugInElement::isPluginElement() const |
| @@ -429,28 +455,43 @@ bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons |
| if (!pluginIsLoadable(url, mimeType)) |
| return false; |
| + bool canCreateWithoutRenderer = frame->loader().client()->canCreatePluginWithoutRenderer(mimeType); |
| + |
| RenderEmbeddedObject* renderer = renderEmbeddedObject(); |
| // FIXME: This code should not depend on renderer! |
| - if (!renderer || useFallback) |
| + if ((!renderer && !canCreateWithoutRenderer) || useFallback) |
| return false; |
| + FrameLoaderClient::PluginLoadType loadType = renderer ? FrameLoaderClient::PluginLoadRequiresRenderer : FrameLoaderClient::PluginLoadWithoutRenderer; |
| + |
| LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); |
| LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); |
| m_loadedUrl = url; |
| - IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); |
| - bool loadManually = document().isPluginDocument() && !document().containsPlugins() && toPluginDocument(document()).shouldLoadPluginManually(); |
| - RefPtr<Widget> widget = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually); |
| + IntSize contentSize; |
| + if (renderer) |
| + contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); |
| + RefPtr<Widget> plugin = widget(); |
| + |
| + if (!plugin) { |
| + bool loadManually = document().isPluginDocument() && !document().containsPlugins() && toPluginDocument(document()).shouldLoadPluginManually(); |
| + plugin = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually, loadType); |
| + } |
| - if (!widget) { |
| - if (!renderer->showsUnavailablePluginIndicator()) |
| + if (!plugin) { |
| + if (renderer && !renderer->showsUnavailablePluginIndicator()) |
| renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing); |
| return false; |
| } |
| - renderer->setWidget(widget); |
| + ASSERT(plugin->isPluginContainer()); |
| + setWidget(plugin); |
| + |
| + if (renderer) { |
| + // FIXME: We assume we don't layout without a renderer, but check this assumption. |
|
eseidel
2013/12/02 16:28:34
style recalc creates/destroys renderers. I doubt
wjmaclean
2013/12/02 21:51:55
Thanks, that's useful to know. I'll remove the if(
|
| + setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); |
| + } |
| document().setContainsPlugins(); |
| - setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); |
| return true; |
| } |