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; |
} |