void
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
    switch (why) {
    case AbnormalShutdown: {
#ifdef MOZ_CRASHREPORTER
        CrashReporterParent* crashReporter = CrashReporter();

        CrashReporter::AnnotationTable notes;
        notes.Init(4);
        WriteExtraDataForMinidump(notes);
        
        if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
            crashReporter->GenerateHangCrashReport(&notes);
        }
        else if (!mPluginDumpID.IsEmpty()) {
            // Nothing to do, we've already written this minidump in
            // PluginModuleParent::OnCrash
        }
        else if (crashReporter->GenerateCrashReport(this, &notes)) {
            mPluginDumpID = crashReporter->ChildDumpID();
            PLUGIN_LOG_DEBUG(("got child minidump: %s",
                              NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
        }
        else {
            NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
        }
#endif

        mShutdown = true;
        // Defer the PluginCrashed method so that we don't re-enter
        // and potentially modify the actor child list while enumerating it.
        if (mPlugin)
            MessageLoop::current()->PostTask(
                FROM_HERE,
                mTaskFactory.NewRunnableMethod(
                    &PluginModuleParent::NotifyPluginCrashed));
        break;
    }
    case NormalShutdown:
        mShutdown = true;
        break;

    default:
        NS_ERROR("Unexpected shutdown reason for toplevel actor.");
    }
}
void
ContentParent::ActorDestroy(ActorDestroyReason why)
{
    nsCOMPtr<nsIThreadObserver>
        kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    if (obs) {
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "xpcom-shutdown");
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "memory-pressure");
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-memory-reporter-request");
        obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC);
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-gc-request");
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-cc-request");
#ifdef ACCESSIBILITY
        obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
#endif
    }

    mMessageManager->Disconnect();

    // clear the child memory reporters
    InfallibleTArray<MemoryReport> empty;
    SetChildMemoryReporters(empty);

    // remove the global remote preferences observers
    nsCOMPtr<nsIPrefBranch2> prefs 
            (do_GetService(NS_PREFSERVICE_CONTRACTID));
    if (prefs) { 
        prefs->RemoveObserver("", this);
    }

    RecvRemoveGeolocationListener();
    RecvRemoveDeviceMotionListener();

    nsCOMPtr<nsIThreadInternal>
        threadInt(do_QueryInterface(NS_GetCurrentThread()));
    if (threadInt)
        threadInt->RemoveObserver(this);
    if (mRunToCompletionDepth)
        mRunToCompletionDepth = 0;

    if (gContentParents) {
        gContentParents->RemoveElement(this);
        if (!gContentParents->Length()) {
            delete gContentParents;
            gContentParents = NULL;
        }
    }

    mIsAlive = false;

    if (obs) {
        nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
        props->Init();

        if (AbnormalShutdown == why) {
            props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);

#ifdef MOZ_CRASHREPORTER
            MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0);
            CrashReporterParent* crashReporter =
                    static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);

            crashReporter->GenerateCrashReport(this, NULL);
 
            nsAutoString dumpID(crashReporter->ChildDumpID());
            props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
#endif

            obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull);
        }
    }

    MessageLoop::current()->
        PostTask(FROM_HERE,
                 NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
    mSubprocess = NULL;

    // IPDL rules require actors to live on past ActorDestroy, but it
    // may be that the kungFuDeathGrip above is the last reference to
    // |this|.  If so, when we go out of scope here, we're deleted and
    // all hell breaks loose.
    //
    // This runnable ensures that a reference to |this| lives on at
    // least until after the current task finishes running.
    NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
}