summaryrefslogtreecommitdiff
path: root/Source/WebKit2/WebProcess/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/WebProcess/Plugins')
-rw-r--r--Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp36
-rw-r--r--Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h4
-rw-r--r--Source/WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm25
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h4
-rw-r--r--Source/WebKit2/WebProcess/Plugins/Plugin.h4
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginController.h15
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.cpp3
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h10
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProcessConnectionManager.cpp9
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp107
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProxy.h18
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in6
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginView.cpp50
-rw-r--r--Source/WebKit2/WebProcess/Plugins/PluginView.h8
14 files changed, 264 insertions, 35 deletions
diff --git a/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp b/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp
index 4d82cff01..b20743213 100644
--- a/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp
@@ -548,6 +548,38 @@ bool NetscapePlugin::allowPopups() const
return false;
}
+#if PLUGIN_ARCHITECTURE(MAC)
+static bool isTransparentSilverlightBackgroundValue(const String& lowercaseBackgroundValue)
+{
+ // This checks if the background color value is transparent, according to
+ // the forumat documented at http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx
+ if (lowercaseBackgroundValue.startsWith('#')) {
+ if (lowercaseBackgroundValue.length() == 5 && lowercaseBackgroundValue[1] != 'f') {
+ // An 8-bit RGB value with alpha transparency, in the form #ARGB.
+ return true;
+ }
+
+ if (lowercaseBackgroundValue.length() == 9 && !(lowercaseBackgroundValue[1] == 'f' && lowercaseBackgroundValue[2] == 'f')) {
+ // A 16-bit RGB value with alpha transparency, in the form #AARRGGBB.
+ return true;
+ }
+ } else if (lowercaseBackgroundValue.startsWith("sc#")) {
+ Vector<String> components;
+ lowercaseBackgroundValue.substring(3).split(",", components);
+
+ // An ScRGB value with alpha transparency, in the form sc#A,R,G,B.
+ if (components.size() == 4) {
+ if (components[0].toDouble() < 1)
+ return true;
+ }
+ } else if (lowercaseBackgroundValue == "transparent")
+ return true;
+
+ // This is an opaque color.
+ return false;
+}
+#endif
+
bool NetscapePlugin::initialize(const Parameters& parameters)
{
uint16_t mode = parameters.isFullFramePlugin ? NP_FULL : NP_EMBED;
@@ -581,10 +613,10 @@ bool NetscapePlugin::initialize(const Parameters& parameters)
}
#if PLUGIN_ARCHITECTURE(MAC)
- if (m_pluginModule->pluginQuirks().contains(PluginQuirks::MakeTransparentIfBackgroundAttributeExists)) {
+ if (m_pluginModule->pluginQuirks().contains(PluginQuirks::MakeOpaqueUnlessTransparentSilverlightBackgroundAttributeExists)) {
for (size_t i = 0; i < parameters.names.size(); ++i) {
if (equalIgnoringCase(parameters.names[i], "background")) {
- setIsTransparent(true);
+ setIsTransparent(isTransparentSilverlightBackgroundValue(parameters.values[i].lower()));
break;
}
}
diff --git a/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h b/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h
index 1c49c6032..8591892b8 100644
--- a/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h
+++ b/Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h
@@ -54,6 +54,10 @@ public:
static PassRefPtr<NetscapePlugin> fromNPP(NPP);
+ // In-process NetscapePlugins don't support asynchronous initialization.
+ virtual void waitForAsynchronousInitialization() { }
+ virtual bool isBeingAsynchronouslyInitialized() const { return false; }
+
#if PLATFORM(MAC)
NPError setDrawingModel(NPDrawingModel);
NPError setEventModel(NPEventModel);
diff --git a/Source/WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm b/Source/WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm
index f1fa2f646..8a447df31 100644
--- a/Source/WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm
+++ b/Source/WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm
@@ -1057,6 +1057,27 @@ PlatformLayer* NetscapePlugin::pluginLayer()
return static_cast<PlatformLayer*>(m_pluginLayer.get());
}
+static void makeCGLPresentLayerOpaque(CALayer *pluginRootLayer)
+{
+ // We look for a layer that's the only sublayer of the root layer that is an instance
+ // of the CGLPresentLayer class which in turn is a subclass of CAOpenGLLayer and make
+ // it opaque if all these conditions hold.
+
+ NSArray *sublayers = [pluginRootLayer sublayers];
+ if ([sublayers count] != 1)
+ return;
+
+ Class cglPresentLayerClass = NSClassFromString(@"CGLPresentLayer");
+ if (![cglPresentLayerClass isSubclassOfClass:[CAOpenGLLayer class]])
+ return;
+
+ CALayer *layer = [sublayers objectAtIndex:0];
+ if (![layer isKindOfClass:cglPresentLayerClass])
+ return;
+
+ [layer setOpaque:YES];
+}
+
void NetscapePlugin::updatePluginLayer()
{
if (m_drawingModel != NPDrawingModelCoreAnimation)
@@ -1086,6 +1107,10 @@ void NetscapePlugin::updatePluginLayer()
m_pluginLayer = reinterpret_cast<CALayer *>(value);
else
m_pluginLayer.adoptNS(reinterpret_cast<CALayer *>(value));
+
+ if (m_pluginModule->pluginQuirks().contains(PluginQuirks::MakeOpaqueUnlessTransparentSilverlightBackgroundAttributeExists) &&
+ !m_isTransparent)
+ makeCGLPresentLayerOpaque(m_pluginLayer.get());
}
#ifndef NP_NO_CARBON
diff --git a/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h b/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h
index 6d11c8552..8a7c28a5b 100644
--- a/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h
+++ b/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h
@@ -50,6 +50,10 @@ public:
static WebCore::PluginInfo pluginInfo();
+ // In-process PDFViews don't support asynchronous initialization.
+ virtual void waitForAsynchronousInitialization() { }
+ virtual bool isBeingAsynchronouslyInitialized() const { return false; }
+
private:
explicit BuiltInPDFView(WebFrame*);
diff --git a/Source/WebKit2/WebProcess/Plugins/Plugin.h b/Source/WebKit2/WebProcess/Plugins/Plugin.h
index 5be84f476..b91174f9e 100644
--- a/Source/WebKit2/WebProcess/Plugins/Plugin.h
+++ b/Source/WebKit2/WebProcess/Plugins/Plugin.h
@@ -83,6 +83,10 @@ public:
// Sets the active plug-in controller and initializes the plug-in.
bool initialize(PluginController*, const Parameters&);
+ // Forces synchronous initialization of a plugin previously initialized asynchronously.
+ virtual void waitForAsynchronousInitialization() = 0;
+ virtual bool isBeingAsynchronouslyInitialized() const = 0;
+
// Destroys the plug-in.
void destroyPlugin();
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginController.h b/Source/WebKit2/WebProcess/Plugins/PluginController.h
index 42c29595e..6682ba020 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginController.h
+++ b/Source/WebKit2/WebProcess/Plugins/PluginController.h
@@ -138,6 +138,15 @@ public:
// Returns whether private browsing is enabled.
virtual bool isPrivateBrowsingEnabled() = 0;
+
+ // Returns whether or not asynchronous plugin initialization is enabled.
+ virtual bool asynchronousPluginInitializationEnabled() const { return false; }
+
+ // Returns whether or not asynchronous plugin initialization should be attempted for all plugins.
+ virtual bool asynchronousPluginInitializationEnabledForAllPlugins() const { return false; }
+
+ // Returns the articifical plugin delay to use for testing of asynchronous plugin initialization.
+ virtual bool artificialPluginInitializationDelayEnabled() const { return false; }
// Increments a counter that prevents the plug-in from being destroyed.
virtual void protectPluginFromDestruction() = 0;
@@ -151,6 +160,12 @@ public:
virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) = 0;
#endif
+ // Called when the a plug-in instance is successfully initialized, either synchronously or asynchronously.
+ virtual void didInitializePlugin() = 0;
+
+ // Called when the a plug-in instance fails to initialized, either synchronously or asynchronously.
+ virtual void didFailToInitializePlugin() = 0;
+
// Helper class for delaying destruction of a plug-in.
class PluginDestructionProtector {
public:
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.cpp b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.cpp
index 8339ad45c..cc313d2e4 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.cpp
@@ -73,9 +73,10 @@ static double defaultSyncMessageTimeout(const String& pluginPath)
return syncMessageTimeout;
}
-PluginProcessConnection::PluginProcessConnection(PluginProcessConnectionManager* pluginProcessConnectionManager, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier)
+PluginProcessConnection::PluginProcessConnection(PluginProcessConnectionManager* pluginProcessConnectionManager, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier, bool supportsAsynchronousPluginInitialization)
: m_pluginProcessConnectionManager(pluginProcessConnectionManager)
, m_pluginPath(pluginPath)
+ , m_supportsAsynchronousPluginInitialization(supportsAsynchronousPluginInitialization)
{
m_connection = CoreIPC::Connection::createClientConnection(connectionIdentifier, this, WebProcess::shared().runLoop());
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h
index 61c4ac2a5..bc866d10c 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h
@@ -43,9 +43,9 @@ class PluginProxy;
class PluginProcessConnection : public RefCounted<PluginProcessConnection>, CoreIPC::Connection::Client {
public:
- static PassRefPtr<PluginProcessConnection> create(PluginProcessConnectionManager* pluginProcessConnectionManager, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier)
+ static PassRefPtr<PluginProcessConnection> create(PluginProcessConnectionManager* pluginProcessConnectionManager, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier, bool supportsAsynchronousPluginInitialization)
{
- return adoptRef(new PluginProcessConnection(pluginProcessConnectionManager, pluginPath, connectionIdentifier));
+ return adoptRef(new PluginProcessConnection(pluginProcessConnectionManager, pluginPath, connectionIdentifier, supportsAsynchronousPluginInitialization));
}
~PluginProcessConnection();
@@ -58,8 +58,10 @@ public:
NPRemoteObjectMap* npRemoteObjectMap() const { return m_npRemoteObjectMap.get(); }
+ bool supportsAsynchronousPluginInitialization() const { return m_supportsAsynchronousPluginInitialization; }
+
private:
- PluginProcessConnection(PluginProcessConnectionManager* pluginProcessConnectionManager, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier);
+ PluginProcessConnection(PluginProcessConnectionManager*, const String& pluginPath, CoreIPC::Connection::Identifier connectionIdentifier, bool supportsAsynchronousInitialization);
// CoreIPC::Connection::Client
virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
@@ -82,6 +84,8 @@ private:
HashMap<uint64_t, PluginProxy*> m_plugins;
RefPtr<NPRemoteObjectMap> m_npRemoteObjectMap;
+
+ bool m_supportsAsynchronousPluginInitialization;
};
} // namespace WebKit
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnectionManager.cpp b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnectionManager.cpp
index fd1906d7a..b77050992 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProcessConnectionManager.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProcessConnectionManager.cpp
@@ -57,13 +57,14 @@ PluginProcessConnection* PluginProcessConnectionManager::getPluginProcessConnect
}
CoreIPC::Attachment encodedConnectionIdentifier;
+ bool supportsAsynchronousInitialization;
if (!WebProcess::shared().connection()->sendSync(Messages::WebProcessProxy::GetPluginProcessConnection(pluginPath),
- Messages::WebProcessProxy::GetPluginProcessConnection::Reply(encodedConnectionIdentifier), 0))
+ Messages::WebProcessProxy::GetPluginProcessConnection::Reply(encodedConnectionIdentifier, supportsAsynchronousInitialization), 0))
return 0;
#if PLATFORM(MAC)
- CoreIPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.port();
- if (!connectionIdentifier)
+ CoreIPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
+ if (CoreIPC::Connection::identifierIsNull(connectionIdentifier))
return 0;
#elif USE(UNIX_DOMAIN_SOCKETS)
CoreIPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.fileDescriptor();
@@ -71,7 +72,7 @@ PluginProcessConnection* PluginProcessConnectionManager::getPluginProcessConnect
return 0;
#endif
- RefPtr<PluginProcessConnection> pluginProcessConnection = PluginProcessConnection::create(this, pluginPath, connectionIdentifier);
+ RefPtr<PluginProcessConnection> pluginProcessConnection = PluginProcessConnection::create(this, pluginPath, connectionIdentifier, supportsAsynchronousInitialization);
m_pluginProcessConnections.append(pluginProcessConnection);
{
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp b/Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp
index d4a3549f4..17db25708 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp
@@ -68,6 +68,7 @@ PluginProxy::PluginProxy(const String& pluginPath)
, m_waitingForPaintInResponseToUpdate(false)
, m_wantsWheelEvents(false)
, m_remoteLayerClientID(0)
+ , m_waitingOnAsynchronousInitialization(false)
{
}
@@ -93,38 +94,112 @@ bool PluginProxy::initialize(const Parameters& parameters)
m_connection->addPluginProxy(this);
// Ask the plug-in process to create a plug-in.
- PluginCreationParameters creationParameters;
- creationParameters.pluginInstanceID = m_pluginInstanceID;
- creationParameters.windowNPObjectID = windowNPObjectID();
- creationParameters.parameters = parameters;
- creationParameters.userAgent = controller()->userAgent();
- creationParameters.contentsScaleFactor = contentsScaleFactor();
- creationParameters.isPrivateBrowsingEnabled = controller()->isPrivateBrowsingEnabled();
+ m_pendingPluginCreationParameters = adoptPtr(new PluginCreationParameters);
+
+ m_pendingPluginCreationParameters->pluginInstanceID = m_pluginInstanceID;
+ m_pendingPluginCreationParameters->windowNPObjectID = windowNPObjectID();
+ m_pendingPluginCreationParameters->parameters = parameters;
+ m_pendingPluginCreationParameters->userAgent = controller()->userAgent();
+ m_pendingPluginCreationParameters->contentsScaleFactor = contentsScaleFactor();
+ m_pendingPluginCreationParameters->isPrivateBrowsingEnabled = controller()->isPrivateBrowsingEnabled();
+ m_pendingPluginCreationParameters->artificialPluginInitializationDelayEnabled = controller()->artificialPluginInitializationDelayEnabled();
+
#if USE(ACCELERATED_COMPOSITING)
- creationParameters.isAcceleratedCompositingEnabled = controller()->isAcceleratedCompositingEnabled();
+ m_pendingPluginCreationParameters->isAcceleratedCompositingEnabled = controller()->isAcceleratedCompositingEnabled();
#endif
+ if (!canInitializeAsynchronously())
+ return initializeSynchronously();
+
+ // Remember that we tried to create this plug-in asynchronously in case we need to create it synchronously later.
+ m_waitingOnAsynchronousInitialization = true;
+ PluginCreationParameters creationParameters(*m_pendingPluginCreationParameters.get());
+ m_connection->connection()->send(Messages::WebProcessConnection::CreatePluginAsynchronously(creationParameters), m_pluginInstanceID);
+ return true;
+}
+
+bool PluginProxy::canInitializeAsynchronously() const
+{
+ return controller()->asynchronousPluginInitializationEnabled() && (m_connection->supportsAsynchronousPluginInitialization() || controller()->asynchronousPluginInitializationEnabledForAllPlugins());
+}
+
+void PluginProxy::waitForAsynchronousInitialization()
+{
+ ASSERT(!m_isStarted);
+ ASSERT(m_waitingOnAsynchronousInitialization);
+
+ initializeSynchronously();
+}
+
+bool PluginProxy::initializeSynchronously()
+{
+ ASSERT(m_pendingPluginCreationParameters);
+
+ m_pendingPluginCreationParameters->asynchronousCreationIncomplete = m_waitingOnAsynchronousInitialization;
bool result = false;
bool wantsWheelEvents = false;
uint32_t remoteLayerClientID = 0;
+
+ PluginCreationParameters parameters(*m_pendingPluginCreationParameters.get());
- if (!m_connection->connection()->sendSync(Messages::WebProcessConnection::CreatePlugin(creationParameters), Messages::WebProcessConnection::CreatePlugin::Reply(result, wantsWheelEvents, remoteLayerClientID), 0) || !result) {
- m_connection->removePluginProxy(this);
- return false;
- }
+ if (!m_connection->connection()->sendSync(Messages::WebProcessConnection::CreatePlugin(parameters), Messages::WebProcessConnection::CreatePlugin::Reply(result, wantsWheelEvents, remoteLayerClientID), 0) || !result)
+ didFailToCreatePluginInternal();
+ else
+ didCreatePluginInternal(wantsWheelEvents, remoteLayerClientID);
+
+ return result;
+}
+void PluginProxy::didCreatePlugin(bool wantsWheelEvents, uint32_t remoteLayerClientID)
+{
+ // We might have tried to create the plug-in sychronously while waiting on the asynchronous reply,
+ // in which case we should ignore this message.
+ if (!m_waitingOnAsynchronousInitialization)
+ return;
+
+ didCreatePluginInternal(wantsWheelEvents, remoteLayerClientID);
+}
+
+void PluginProxy::didFailToCreatePlugin()
+{
+ // We might have tried to create the plug-in sychronously while waiting on the asynchronous reply,
+ // in which case we should ignore this message.
+ if (!m_waitingOnAsynchronousInitialization)
+ return;
+
+ didFailToCreatePluginInternal();
+}
+
+void PluginProxy::didCreatePluginInternal(bool wantsWheelEvents, uint32_t remoteLayerClientID)
+{
m_wantsWheelEvents = wantsWheelEvents;
m_remoteLayerClientID = remoteLayerClientID;
m_isStarted = true;
+ controller()->didInitializePlugin();
- return true;
+ // Whether synchronously or asynchronously, this plug-in was created and we shouldn't need to remember
+ // anything about how.
+ m_pendingPluginCreationParameters.clear();
+ m_waitingOnAsynchronousInitialization = false;
}
-void PluginProxy::destroy()
+void PluginProxy::didFailToCreatePluginInternal()
{
- ASSERT(m_isStarted);
+ // Calling out to the connection and the controller could potentially cause the plug-in proxy to go away, so protect it here.
+ RefPtr<PluginProxy> protect(this);
+
+ m_connection->removePluginProxy(this);
+ controller()->didFailToInitializePlugin();
+
+ // Whether synchronously or asynchronously, this plug-in failed to create and we shouldn't need to remember
+ // anything about how.
+ m_pendingPluginCreationParameters.clear();
+ m_waitingOnAsynchronousInitialization = false;
+}
- m_connection->connection()->sendSync(Messages::WebProcessConnection::DestroyPlugin(m_pluginInstanceID), Messages::WebProcessConnection::DestroyPlugin::Reply(), 0);
+void PluginProxy::destroy()
+{
+ m_connection->connection()->sendSync(Messages::WebProcessConnection::DestroyPlugin(m_pluginInstanceID, m_waitingOnAsynchronousInitialization), Messages::WebProcessConnection::DestroyPlugin::Reply(), 0);
m_isStarted = false;
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProxy.h b/Source/WebKit2/WebProcess/Plugins/PluginProxy.h
index be07caa85..c0ca116b0 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProxy.h
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProxy.h
@@ -49,6 +49,8 @@ class ShareableBitmap;
class NPVariantData;
class PluginProcessConnection;
+struct PluginCreationParameters;
+
class PluginProxy : public Plugin {
public:
static PassRefPtr<PluginProxy> create(const String& pluginPath);
@@ -60,11 +62,16 @@ public:
void didReceivePluginProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments);
void didReceiveSyncPluginProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&);
+ bool isBeingAsynchronouslyInitialized() const { return m_waitingOnAsynchronousInitialization; }
+
private:
explicit PluginProxy(const String& pluginPath);
// Plugin
virtual bool initialize(const Parameters&);
+ bool initializeSynchronously();
+
+ virtual void waitForAsynchronousInitialization();
virtual void destroy();
virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
virtual PassRefPtr<ShareableBitmap> snapshot();
@@ -141,6 +148,14 @@ private:
void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
#endif
+ bool canInitializeAsynchronously() const;
+
+ void didCreatePlugin(bool wantsWheelEvents, uint32_t remoteLayerClientID);
+ void didFailToCreatePlugin();
+
+ void didCreatePluginInternal(bool wantsWheelEvents, uint32_t remoteLayerClientID);
+ void didFailToCreatePluginInternal();
+
String m_pluginPath;
RefPtr<PluginProcessConnection> m_connection;
@@ -174,6 +189,9 @@ private:
// The client ID for the CA layer in the plug-in process. Will be 0 if the plug-in is not a CA plug-in.
uint32_t m_remoteLayerClientID;
+
+ OwnPtr<PluginCreationParameters> m_pendingPluginCreationParameters;
+ bool m_waitingOnAsynchronousInitialization;
#if PLATFORM(MAC)
RetainPtr<CALayer> m_pluginLayer;
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in b/Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in
index a2ef31965..453c0f1d2 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in
+++ b/Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in
@@ -74,6 +74,12 @@ messages -> PluginProxy {
# Update geometry of windowed plugin widget
WindowedPluginGeometryDidChange(WebCore::IntRect frameRect, WebCore::IntRect clipRect, uint64_t windowID)
#endif
+
+ # Tells the WebProcess that the plug-in was successfully initialized asynchronously
+ DidCreatePlugin(bool wantsWheelEvents, uint32_t remoteLayerClientID) -> ()
+
+ # Tells the WebProcess that the plug-in failed to initialize.
+ DidFailToCreatePlugin() -> ()
}
#endif
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
index 072a69c9c..d07f8b79d 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
@@ -260,6 +260,7 @@ PluginView::PluginView(PassRefPtr<HTMLPlugInElement> pluginElement, PassRefPtr<P
, m_webPage(webPage(m_pluginElement.get()))
, m_parameters(parameters)
, m_isInitialized(false)
+ , m_isWaitingForSynchronousInitialization(false)
, m_isWaitingUntilMediaCanStart(false)
, m_isBeingDestroyed(false)
, m_pendingURLRequestsTimer(RunLoop::main(), this, &PluginView::pendingURLRequestsTimerFired)
@@ -285,7 +286,7 @@ PluginView::~PluginView()
for (FrameLoadMap::iterator it = m_pendingFrameLoads.begin(), end = m_pendingFrameLoads.end(); it != end; ++it)
it->first->setLoadListener(0);
- if (m_plugin && m_isInitialized) {
+ if (m_plugin) {
m_isBeingDestroyed = true;
m_plugin->destroyPlugin();
m_isBeingDestroyed = false;
@@ -487,15 +488,20 @@ void PluginView::initializePlugin()
}
}
}
-
- if (!m_plugin->initialize(this, m_parameters)) {
- // We failed to initialize the plug-in.
- m_plugin = 0;
- m_webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(m_parameters.mimeType));
- return;
- }
+ m_plugin->initialize(this, m_parameters);
+ // Plug-in initialization continued in didFailToInitializePlugin() or didInitializePlugin().
+}
+
+void PluginView::didFailToInitializePlugin()
+{
+ m_plugin = 0;
+ m_webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(m_parameters.mimeType));
+}
+
+void PluginView::didInitializePlugin()
+{
m_isInitialized = true;
#if PLATFORM(MAC)
@@ -539,6 +545,19 @@ PlatformLayer* PluginView::platformLayer() const
JSObject* PluginView::scriptObject(JSGlobalObject* globalObject)
{
+ // If we're already waiting for synchronous initialization of the plugin,
+ // calls to scriptObject() are from the plug-in itself and need to return 0;
+ if (m_isWaitingForSynchronousInitialization)
+ return 0;
+
+ // If the plug-in exists but is not initialized then we're still initializing asynchronously.
+ // We need to wait here until initialization has either succeeded or failed.
+ if (m_plugin->isBeingAsynchronouslyInitialized()) {
+ m_isWaitingForSynchronousInitialization = true;
+ m_plugin->waitForAsynchronousInitialization();
+ m_isWaitingForSynchronousInitialization = false;
+ }
+
// The plug-in can be null here if it failed to initialize.
if (!m_isInitialized || !m_plugin)
return 0;
@@ -1250,6 +1269,21 @@ bool PluginView::isPrivateBrowsingEnabled()
return settings->privateBrowsingEnabled();
}
+bool PluginView::asynchronousPluginInitializationEnabled() const
+{
+ return m_webPage->asynchronousPluginInitializationEnabled();
+}
+
+bool PluginView::asynchronousPluginInitializationEnabledForAllPlugins() const
+{
+ return m_webPage->asynchronousPluginInitializationEnabledForAllPlugins();
+}
+
+bool PluginView::artificialPluginInitializationDelayEnabled() const
+{
+ return m_webPage->artificialPluginInitializationDelayEnabled();
+}
+
void PluginView::protectPluginFromDestruction()
{
if (!m_isBeingDestroyed)
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginView.h b/Source/WebKit2/WebProcess/Plugins/PluginView.h
index f101b2f4f..a6a056ccd 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginView.h
+++ b/Source/WebKit2/WebProcess/Plugins/PluginView.h
@@ -80,7 +80,6 @@ private:
virtual ~PluginView();
void initializePlugin();
- void destroyPlugin();
void viewGeometryDidChange();
void viewVisibilityDidChange();
@@ -164,6 +163,9 @@ private:
virtual void setCookiesForURL(const String& urlString, const String& cookieString);
virtual bool getAuthenticationInfo(const WebCore::ProtectionSpace&, String& username, String& password);
virtual bool isPrivateBrowsingEnabled();
+ virtual bool asynchronousPluginInitializationEnabled() const;
+ virtual bool asynchronousPluginInitializationEnabledForAllPlugins() const;
+ virtual bool artificialPluginInitializationDelayEnabled() const;
virtual void protectPluginFromDestruction();
virtual void unprotectPluginFromDestruction();
#if PLUGIN_ARCHITECTURE(X11)
@@ -171,6 +173,9 @@ private:
virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
#endif
+ virtual void didInitializePlugin();
+ virtual void didFailToInitializePlugin();
+
// WebFrame::LoadListener
virtual void didFinishLoad(WebFrame*);
virtual void didFailLoad(WebFrame*, bool wasCancelled);
@@ -181,6 +186,7 @@ private:
Plugin::Parameters m_parameters;
bool m_isInitialized;
+ bool m_isWaitingForSynchronousInitialization;
bool m_isWaitingUntilMediaCanStart;
bool m_isBeingDestroyed;