Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(960)

Unified Diff: Source/core/html/HTMLPlugInElement.cpp

Issue 23618022: BrowserPlugin/WebView - Move plugin lifetime to DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Revised method for widget lifetime management. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698