Sent "PluginCrashed" notification when a plugin crashes. b=519541 r=jst r=bsmedberg

This commit is contained in:
Josh Aas 2010-01-13 11:42:41 -05:00
parent 1d3e09c88b
commit 9f1683fecf
6 changed files with 93 additions and 15 deletions

View File

@ -46,7 +46,7 @@ interface nsIDOMClientRect;
/**
* This interface represents a content node that loads objects.
*/
[scriptable, uuid(7749d965-92f3-473e-b12d-de1e342acf1c)]
[scriptable, uuid(1d89f35e-8f4b-4b79-b622-7be812a8babe)]
interface nsIObjectLoadingContent : nsISupports
{
const unsigned long TYPE_LOADING = 0;
@ -81,7 +81,6 @@ interface nsIObjectLoadingContent : nsISupports
*/
[noscript] readonly attribute nsIPluginInstance pluginInstance;
/**
* Makes sure that a frame for this object exists, and that the plugin is
* instantiated. This method does nothing if the type is not #TYPE_PLUGIN.
@ -124,4 +123,6 @@ interface nsIObjectLoadingContent : nsISupports
* not in the static clone.
*/
[noscript] nsIFrame getPrintFrame();
[noscript] void pluginCrashed();
};

View File

@ -200,6 +200,9 @@ nsPluginErrorEvent::Run()
case ePluginOutdated:
type = NS_LITERAL_STRING("PluginOutdated");
break;
case ePluginCrashed:
type = NS_LITERAL_STRING("PluginCrashed");
break;
default:
return NS_OK;
}
@ -255,7 +258,7 @@ class AutoFallback {
LOG(("OBJLC [%p]: rv=%08x, falling back\n", mContent, *mResult));
mContent->Fallback(PR_FALSE);
if (mPluginState != ePluginOtherState) {
mContent->mPluginState = mPluginState;
mContent->mFallbackReason = mPluginState;
}
}
}
@ -358,7 +361,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mInstantiating(PR_FALSE)
, mUserDisabled(PR_FALSE)
, mSuppressed(PR_FALSE)
, mPluginState(ePluginOtherState)
, mFallbackReason(ePluginOtherState)
{
}
@ -597,7 +600,7 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
case eType_Null:
LOG(("OBJLC [%p]: Unsupported type, falling back\n", this));
// Need to fallback here (instead of using the case below), so that we can
// set mPluginState without it being overwritten. This is also why we
// set mFallbackReason without it being overwritten. This is also why we
// return early.
Fallback(PR_FALSE);
@ -605,8 +608,8 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
mContentType);
// Do nothing, but fire the plugin not found event if needed
if (pluginState != ePluginOtherState) {
mFallbackReason = pluginState;
FirePluginError(thisContent, pluginState);
mPluginState = pluginState;
}
return NS_BINDING_ABORTED;
}
@ -945,7 +948,7 @@ nsObjectLoadingContent::ObjectState() const
// Otherwise, broken
PRInt32 state = NS_EVENT_STATE_BROKEN;
switch (mPluginState) {
switch (mFallbackReason) {
case ePluginDisabled:
state |= NS_EVENT_STATE_HANDLER_DISABLED;
break;
@ -1502,7 +1505,7 @@ nsObjectLoadingContent::UnloadContent()
}
mType = eType_Null;
mUserDisabled = mSuppressed = PR_FALSE;
mPluginState = ePluginOtherState;
mFallbackReason = ePluginOtherState;
}
void
@ -1925,4 +1928,12 @@ nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
return frame->SetAbsoluteScreenPosition(element, position, clip);
}
NS_IMETHODIMP
nsObjectLoadingContent::PluginCrashed()
{
UnloadContent();
mFallbackReason = ePluginCrashed;
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
FirePluginError(thisContent, mFallbackReason);
return NS_OK;
}

View File

@ -61,13 +61,12 @@ class AutoFallback;
class AutoSetInstantiatingToFalse;
enum PluginSupportState {
ePluginUnsupported, // The plugin is not supported (not installed, say)
ePluginDisabled, // The plugin has been explicitly disabled by the
// user.
ePluginUnsupported, // The plugin is not supported (e.g. not installed)
ePluginDisabled, // The plugin has been explicitly disabled by the user
ePluginBlocklisted, // The plugin is blocklisted and disabled
ePluginOutdated, // The plugin is considered outdated, but not disabled
ePluginOtherState // Something else (e.g. not a plugin at all as far
// as we can tell).
ePluginOtherState, // Something else (e.g. uninitialized or not a plugin)
ePluginCrashed
};
/**
@ -422,7 +421,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
PRPackedBool mUserDisabled : 1;
PRPackedBool mSuppressed : 1;
// A specific state that caused us to fallback
PluginSupportState mPluginState;
PluginSupportState mFallbackReason;
nsWeakFrame mPrintFrame;

View File

@ -88,6 +88,7 @@
#include "nsIBlocklistService.h"
#include "nsVersionComparator.h"
#include "nsIPrivateBrowsingService.h"
#include "nsIObjectLoadingContent.h"
#include "nsEnumeratorUtils.h"
#include "nsXPCOM.h"
@ -5177,6 +5178,14 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
while (*pinstancetag) {
nsPluginInstanceTag* instancetag = *pinstancetag;
if (instancetag->mPluginTag == plugin) {
// notify the content node (nsIObjectLoadingContent) that the plugin has crashed
nsCOMPtr<nsIDOMElement> domElement;
instancetag->mInstance->GetDOMElement(getter_AddRefs(domElement));
nsCOMPtr<nsIObjectLoadingContent> objectContent(do_QueryInterface(domElement));
if (objectContent) {
objectContent->PluginCrashed();
}
*pinstancetag = (*pinstancetag)->mNext;
delete instancetag;
}

View File

@ -100,6 +100,12 @@ _MOCHICHROME_FILES += \
$(NULL)
endif
ifdef MOZ_IPC
_MOCHICHROME_FILES += \
test_crash_notify.xul \
$(NULL)
endif
libs:: $(_MOCHICHROME_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

View File

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Basic Plugin Tests"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Plugin Crash Notification Test</title>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
var success = false;
function onPluginCrashed(aEvent) {
ok(true, "Plugin crashed notification received");
var pluginElement = document.getElementById("plugin1");
is (pluginElement, aEvent.target, "Plugin crashed event target is plugin element");
SimpleTest.finish();
}
function runTests() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var prefs = Components.classes['@mozilla.org/preferences-service;1']
.getService(Components.interfaces.nsIPrefBranch);
if (!prefs.getBoolPref('dom.ipc.plugins.enabled')) {
ok(true, "Skipping this test when IPC plugins are not enabled.");
SimpleTest.finish();
return;
}
document.addEventListener("PluginCrashed", onPluginCrashed, false);
var pluginElement = document.getElementById("plugin1");
try {
pluginElement.crash();
} catch (e) {
}
}
]]>
</script>
</window>