mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-04 07:40:42 +00:00
Bug 541076 - add minidump id and plugin name to PluginCrashed event. p=ted+dolske, r=jst, r=ted
This commit is contained in:
parent
5dc97f65d8
commit
2a33518c3c
@ -124,5 +124,6 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
[noscript] nsIFrame getPrintFrame();
|
||||
|
||||
[noscript] void pluginCrashed();
|
||||
[noscript] void pluginCrashed(in AString pluginName,
|
||||
in boolean submittedCrashReport);
|
||||
};
|
||||
|
@ -44,9 +44,13 @@
|
||||
|
||||
// Interface headers
|
||||
#include "imgILoader.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDataContainerEvent.h"
|
||||
#include "nsIDOMDocumentEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIExternalProtocolHandler.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
@ -54,6 +58,7 @@
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
@ -79,6 +84,7 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
// Concrete classes
|
||||
#include "nsFrameLoader.h"
|
||||
@ -200,9 +206,6 @@ nsPluginErrorEvent::Run()
|
||||
case ePluginOutdated:
|
||||
type = NS_LITERAL_STRING("PluginOutdated");
|
||||
break;
|
||||
case ePluginCrashed:
|
||||
type = NS_LITERAL_STRING("PluginCrashed");
|
||||
break;
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
@ -212,6 +215,79 @@ nsPluginErrorEvent::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* A task for firing PluginCrashed DOM Events.
|
||||
*/
|
||||
class nsPluginCrashedEvent : public nsRunnable {
|
||||
public:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsString mPluginName;
|
||||
PRBool mSubmittedCrashReport;
|
||||
|
||||
nsPluginCrashedEvent(nsIContent* aContent,
|
||||
const nsAString& aPluginName,
|
||||
PRBool submittedCrashReport)
|
||||
: mContent(aContent),
|
||||
mPluginName(aPluginName),
|
||||
mSubmittedCrashReport(submittedCrashReport)
|
||||
{}
|
||||
|
||||
~nsPluginCrashedEvent() {}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginCrashedEvent::Run()
|
||||
{
|
||||
LOG(("OBJLC []: Firing plugin crashed event for content %p\n",
|
||||
mContent.get()));
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentEvent> domEventDoc =
|
||||
do_QueryInterface(mContent->GetDocument());
|
||||
if (!domEventDoc) {
|
||||
NS_WARNING("Couldn't get document for PluginCrashed event!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
domEventDoc->CreateEvent(NS_LITERAL_STRING("datacontainerevents"),
|
||||
getter_AddRefs(event));
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
|
||||
nsCOMPtr<nsIDOMDataContainerEvent> containerEvent(do_QueryInterface(event));
|
||||
if (!privateEvent || !containerEvent) {
|
||||
NS_WARNING("Couldn't QI event for PluginCrashed event!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
event->InitEvent(NS_LITERAL_STRING("PluginCrashed"), PR_TRUE, PR_TRUE);
|
||||
privateEvent->SetTrusted(PR_TRUE);
|
||||
privateEvent->GetInternalNSEvent()->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> variant;
|
||||
|
||||
// add a "pluginName" property to this event
|
||||
variant = do_CreateInstance("@mozilla.org/variant;1");
|
||||
if (!variant) {
|
||||
NS_WARNING("Couldn't create pluginName variant for PluginCrashed event!");
|
||||
return NS_OK;
|
||||
}
|
||||
variant->SetAsAString(mPluginName);
|
||||
containerEvent->SetData(NS_LITERAL_STRING("pluginName"), variant);
|
||||
|
||||
// add a "submittedCrashReport" property to this event
|
||||
variant = do_CreateInstance("@mozilla.org/variant;1");
|
||||
if (!variant) {
|
||||
NS_WARNING("Couldn't create crashSubmit variant for PluginCrashed event!");
|
||||
return NS_OK;
|
||||
}
|
||||
variant->SetAsBool(mSubmittedCrashReport);
|
||||
containerEvent->SetData(NS_LITERAL_STRING("submittedCrashReport"), variant);
|
||||
|
||||
nsEventDispatcher::DispatchDOMEvent(mContent, nsnull, event, nsnull, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class AutoNotifier {
|
||||
public:
|
||||
AutoNotifier(nsObjectLoadingContent* aContent, PRBool aNotify) :
|
||||
@ -1932,12 +2008,19 @@ nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::PluginCrashed()
|
||||
nsObjectLoadingContent::PluginCrashed(const nsAString& pluginName,
|
||||
PRBool submittedCrashReport)
|
||||
{
|
||||
AutoNotifier notifier(this, PR_TRUE);
|
||||
UnloadContent();
|
||||
mFallbackReason = ePluginCrashed;
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
FirePluginError(thisContent, mFallbackReason);
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginCrashedEvent(thisContent,
|
||||
pluginName,
|
||||
submittedCrashReport);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsPluginCrashedEvent");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -50,6 +50,24 @@ using namespace mozilla::plugins;
|
||||
|
||||
PR_STATIC_ASSERT(sizeof(NPIdentifier) == sizeof(void*));
|
||||
|
||||
class PluginCrashed : public nsRunnable
|
||||
{
|
||||
public:
|
||||
PluginCrashed(nsNPAPIPlugin* plugin,
|
||||
const nsString& dumpID)
|
||||
: mDumpID(dumpID),
|
||||
mPlugin(plugin) { }
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mPlugin->PluginCrashed(mDumpID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsNPAPIPlugin* mPlugin;
|
||||
nsString mDumpID;
|
||||
};
|
||||
|
||||
// static
|
||||
PluginLibrary*
|
||||
PluginModuleParent::LoadModule(const char* aFilePath)
|
||||
@ -160,8 +178,13 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
|
||||
switch (why) {
|
||||
case AbnormalShutdown: {
|
||||
nsCOMPtr<nsIFile> dump;
|
||||
nsAutoString dumpID;
|
||||
if (GetMinidump(getter_AddRefs(dump))) {
|
||||
WriteExtraDataForMinidump(dump);
|
||||
if (NS_SUCCEEDED(dump->GetLeafName(dumpID))) {
|
||||
dumpID.Replace(dumpID.Length() - 4, 4,
|
||||
NS_LITERAL_STRING(""));
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
|
||||
@ -172,8 +195,7 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
|
||||
// and potentially modify the actor child list while enumerating it.
|
||||
if (mPlugin) {
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
new nsRunnableMethod<nsNPAPIPlugin>(
|
||||
mPlugin, &nsNPAPIPlugin::PluginCrashed);
|
||||
new PluginCrashed(mPlugin, dumpID);
|
||||
NS_DispatchToMainThread(r);
|
||||
}
|
||||
break;
|
||||
|
@ -300,10 +300,10 @@ nsNPAPIPlugin::SetPluginRefNum(short aRefNum)
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
void
|
||||
nsNPAPIPlugin::PluginCrashed()
|
||||
nsNPAPIPlugin::PluginCrashed(const nsAString& dumpID)
|
||||
{
|
||||
nsRefPtr<nsPluginHost> host = dont_AddRef(nsPluginHost::GetInst());
|
||||
host->PluginCrashed(this);
|
||||
host->PluginCrashed(this, dumpID);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -93,8 +93,9 @@ public:
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
// The IPC mechanism notifies the nsNPAPIPlugin if the plugin crashes and is
|
||||
// no longer usable.
|
||||
void PluginCrashed();
|
||||
// no longer usable. dumpID is the ID of a minidump that was written,
|
||||
// or empty if no minidump was written.
|
||||
void PluginCrashed(const nsAString& dumpID);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "nsVersionComparator.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
@ -5207,7 +5208,7 @@ NS_IMETHODIMP nsPluginHost::Notify(nsITimer* timer)
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
void
|
||||
nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
|
||||
nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin, const nsAString& dumpID)
|
||||
{
|
||||
nsPluginTag* pluginTag = FindTagForPlugin(aPlugin);
|
||||
if (!pluginTag) {
|
||||
@ -5215,6 +5216,17 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the app's observer that a plugin crashed so it can submit a crashreport.
|
||||
PRBool submittedCrashReport = PR_FALSE;
|
||||
nsCOMPtr<nsIObserverService> obsService = do_GetService("@mozilla.org/observer-service;1");
|
||||
nsCOMPtr<nsIWritablePropertyBag2> propbag = do_CreateInstance("@mozilla.org/hash-property-bag;1");
|
||||
if (obsService && propbag) {
|
||||
propbag->SetPropertyAsAString(NS_LITERAL_STRING("minidumpID"), dumpID);
|
||||
obsService->NotifyObservers(propbag, "plugin-crashed", nsnull);
|
||||
// see if an observer submitted a crash report.
|
||||
propbag->GetPropertyAsBool(NS_LITERAL_STRING("submittedCrashReport"), &submittedCrashReport);
|
||||
}
|
||||
|
||||
// Invalidate each nsPluginInstanceTag for the crashed plugin
|
||||
|
||||
for (PRUint32 i = mInstanceTags.Length(); i > 0; i--) {
|
||||
@ -5225,7 +5237,8 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
|
||||
instanceTag->mInstance->GetDOMElement(getter_AddRefs(domElement));
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectContent(do_QueryInterface(domElement));
|
||||
if (objectContent) {
|
||||
objectContent->PluginCrashed();
|
||||
objectContent->PluginCrashed(NS_ConvertUTF8toUTF16(pluginTag->mName),
|
||||
submittedCrashReport);
|
||||
}
|
||||
|
||||
instanceTag->mInstance->Stop();
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame);
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
void PluginCrashed(nsNPAPIPlugin* plugin);
|
||||
void PluginCrashed(nsNPAPIPlugin* plugin, const nsAString& dumpID);
|
||||
#endif
|
||||
|
||||
nsPluginInstanceTag *FindInstanceTag(nsIPluginInstance *instance);
|
||||
|
@ -19,12 +19,71 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var success = false;
|
||||
|
||||
var observerFired = false;
|
||||
|
||||
var testObserver = {
|
||||
observe: function(subject, topic, data) {
|
||||
observerFired = true;
|
||||
ok(true, "Observer fired");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
is(topic, "plugin-crashed", "Checking correct topic");
|
||||
is(data, null, "Checking null data");
|
||||
ok((subject instanceof Components.interfaces.nsIPropertyBag2), "got Propbag");
|
||||
ok((subject instanceof Components.interfaces.nsIWritablePropertyBag2),
|
||||
"got writable Propbag");
|
||||
|
||||
var id = subject.getPropertyAsAString("minidumpID");
|
||||
isnot(id, "", "got a non-empty crash id");
|
||||
let directoryService =
|
||||
Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties);
|
||||
let profD = directoryService.get("ProfD", Components.interfaces.nsIFile);
|
||||
profD.append("minidumps");
|
||||
let dumpFile = profD.clone();
|
||||
dumpFile.append(id + ".dmp");
|
||||
ok(dumpFile.exists(), "minidump exists");
|
||||
let extraFile = profD.clone();
|
||||
extraFile.append(id + ".extra");
|
||||
ok(extraFile.exists(), "extra file exists");
|
||||
// cleanup, to be nice
|
||||
dumpFile.remove(false);
|
||||
extraFile.remove(false);
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
if (iid.equals(Components.interfaces.nsIObserver) ||
|
||||
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
iid.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function onPluginCrashed(aEvent) {
|
||||
ok(true, "Plugin crashed notification received");
|
||||
ok(observerFired, "Observer should have fired first");
|
||||
is(aEvent.type, "PluginCrashed", "event is correct type");
|
||||
|
||||
var pluginElement = document.getElementById("plugin1");
|
||||
is (pluginElement, aEvent.target, "Plugin crashed event target is plugin element");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
ok(aEvent instanceof Components.interfaces.nsIDOMDataContainerEvent,
|
||||
"plugin crashed event has the right interface");
|
||||
var pluginName = aEvent.getData("pluginName");
|
||||
is(pluginName, "Test Plug-in");
|
||||
var didReport = aEvent.getData("submittedCrashReport");
|
||||
// The app itself may or may not have decided to submit the report, so
|
||||
// allow either true or false here.
|
||||
ok((didReport == true || didReport == false), "event said crash report was submitted");
|
||||
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(testObserver, "plugin-crashed");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -38,6 +97,10 @@ function runTests() {
|
||||
return;
|
||||
}
|
||||
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService);
|
||||
os.addObserver(testObserver, "plugin-crashed", true);
|
||||
|
||||
document.addEventListener("PluginCrashed", onPluginCrashed, false);
|
||||
|
||||
var pluginElement = document.getElementById("plugin1");
|
||||
|
Loading…
x
Reference in New Issue
Block a user