dom/plugins/ipc/PluginModuleParent.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/plugins/ipc/PluginModuleParent.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1804 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: sw=4 ts=4 et :
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifdef MOZ_WIDGET_QT
    1.11 +// Must be included first to avoid conflicts.
    1.12 +#include <QtCore/QCoreApplication>
    1.13 +#include <QtCore/QEventLoop>
    1.14 +#include "NestedLoopTimer.h"
    1.15 +#endif
    1.16 +
    1.17 +#include "mozilla/plugins/PluginModuleParent.h"
    1.18 +
    1.19 +#include "base/process_util.h"
    1.20 +#include "mozilla/Attributes.h"
    1.21 +#include "mozilla/dom/PCrashReporterParent.h"
    1.22 +#include "mozilla/ipc/MessageChannel.h"
    1.23 +#include "mozilla/plugins/BrowserStreamParent.h"
    1.24 +#include "mozilla/plugins/PluginInstanceParent.h"
    1.25 +#include "mozilla/Preferences.h"
    1.26 +#include "mozilla/Services.h"
    1.27 +#include "mozilla/unused.h"
    1.28 +#include "nsAutoPtr.h"
    1.29 +#include "nsCRT.h"
    1.30 +#include "nsIFile.h"
    1.31 +#include "nsIObserverService.h"
    1.32 +#include "nsNPAPIPlugin.h"
    1.33 +#include "nsPrintfCString.h"
    1.34 +#include "PluginIdentifierParent.h"
    1.35 +#include "prsystem.h"
    1.36 +#include "GeckoProfiler.h"
    1.37 +
    1.38 +#ifdef XP_WIN
    1.39 +#include "PluginHangUIParent.h"
    1.40 +#include "mozilla/widget/AudioSession.h"
    1.41 +#endif
    1.42 +
    1.43 +#ifdef MOZ_ENABLE_PROFILER_SPS
    1.44 +#include "nsIProfileSaveEvent.h"
    1.45 +#endif
    1.46 +
    1.47 +#ifdef MOZ_WIDGET_GTK
    1.48 +#include <glib.h>
    1.49 +#elif XP_MACOSX
    1.50 +#include "PluginInterposeOSX.h"
    1.51 +#include "PluginUtilsOSX.h"
    1.52 +#endif
    1.53 +
    1.54 +using base::KillProcess;
    1.55 +
    1.56 +using mozilla::PluginLibrary;
    1.57 +using mozilla::ipc::MessageChannel;
    1.58 +using mozilla::dom::PCrashReporterParent;
    1.59 +using mozilla::dom::CrashReporterParent;
    1.60 +
    1.61 +using namespace mozilla;
    1.62 +using namespace mozilla::plugins;
    1.63 +using namespace mozilla::plugins::parent;
    1.64 +
    1.65 +#ifdef MOZ_CRASHREPORTER
    1.66 +#include "mozilla/dom/CrashReporterParent.h"
    1.67 +
    1.68 +using namespace CrashReporter;
    1.69 +#endif
    1.70 +
    1.71 +static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
    1.72 +static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs";
    1.73 +static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
    1.74 +#ifdef XP_WIN
    1.75 +static const char kHangUITimeoutPref[] = "dom.ipc.plugins.hangUITimeoutSecs";
    1.76 +static const char kHangUIMinDisplayPref[] = "dom.ipc.plugins.hangUIMinDisplaySecs";
    1.77 +#define CHILD_TIMEOUT_PREF kHangUITimeoutPref
    1.78 +#else
    1.79 +#define CHILD_TIMEOUT_PREF kChildTimeoutPref
    1.80 +#endif
    1.81 +
    1.82 +template<>
    1.83 +struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
    1.84 +{
    1.85 +    typedef mozilla::plugins::PluginModuleParent Class;
    1.86 +    static void RetainCallee(Class* obj) { }
    1.87 +    static void ReleaseCallee(Class* obj) { }
    1.88 +};
    1.89 +
    1.90 +// static
    1.91 +PluginLibrary*
    1.92 +PluginModuleParent::LoadModule(const char* aFilePath)
    1.93 +{
    1.94 +    PLUGIN_LOG_DEBUG_FUNCTION;
    1.95 +
    1.96 +    int32_t prefSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
    1.97 +
    1.98 +    // Block on the child process being launched and initialized.
    1.99 +    nsAutoPtr<PluginModuleParent> parent(new PluginModuleParent(aFilePath));
   1.100 +    bool launched = parent->mSubprocess->Launch(prefSecs * 1000);
   1.101 +    if (!launched) {
   1.102 +        // We never reached open
   1.103 +        parent->mShutdown = true;
   1.104 +        return nullptr;
   1.105 +    }
   1.106 +    parent->Open(parent->mSubprocess->GetChannel(),
   1.107 +                 parent->mSubprocess->GetChildProcessHandle());
   1.108 +
   1.109 +    // Request Windows message deferral behavior on our channel. This
   1.110 +    // applies to the top level and all sub plugin protocols since they
   1.111 +    // all share the same channel.
   1.112 +    parent->GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
   1.113 +
   1.114 +    TimeoutChanged(CHILD_TIMEOUT_PREF, parent);
   1.115 +
   1.116 +#ifdef MOZ_CRASHREPORTER
   1.117 +    // If this fails, we're having IPC troubles, and we're doomed anyways.
   1.118 +    if (!CrashReporterParent::CreateCrashReporter(parent.get())) {
   1.119 +        parent->Close();
   1.120 +        return nullptr;
   1.121 +    }
   1.122 +#ifdef XP_WIN
   1.123 +    mozilla::MutexAutoLock lock(parent->mCrashReporterMutex);
   1.124 +    parent->mCrashReporter = parent->CrashReporter();
   1.125 +#endif
   1.126 +#endif
   1.127 +
   1.128 +    return parent.forget();
   1.129 +}
   1.130 +
   1.131 +
   1.132 +PluginModuleParent::PluginModuleParent(const char* aFilePath)
   1.133 +    : mSubprocess(new PluginProcessParent(aFilePath))
   1.134 +    , mShutdown(false)
   1.135 +    , mClearSiteDataSupported(false)
   1.136 +    , mGetSitesWithDataSupported(false)
   1.137 +    , mNPNIface(nullptr)
   1.138 +    , mPlugin(nullptr)
   1.139 +    , mTaskFactory(MOZ_THIS_IN_INITIALIZER_LIST())
   1.140 +#ifdef XP_WIN
   1.141 +    , mPluginCpuUsageOnHang()
   1.142 +    , mHangUIParent(nullptr)
   1.143 +    , mHangUIEnabled(true)
   1.144 +    , mIsTimerReset(true)
   1.145 +#ifdef MOZ_CRASHREPORTER
   1.146 +    , mCrashReporterMutex("PluginModuleParent::mCrashReporterMutex")
   1.147 +    , mCrashReporter(nullptr)
   1.148 +#endif
   1.149 +#endif
   1.150 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.151 +    , mFlashProcess1(0)
   1.152 +    , mFlashProcess2(0)
   1.153 +#endif
   1.154 +{
   1.155 +    NS_ASSERTION(mSubprocess, "Out of memory!");
   1.156 +
   1.157 +    Preferences::RegisterCallback(TimeoutChanged, kChildTimeoutPref, this);
   1.158 +    Preferences::RegisterCallback(TimeoutChanged, kParentTimeoutPref, this);
   1.159 +#ifdef XP_WIN
   1.160 +    Preferences::RegisterCallback(TimeoutChanged, kHangUITimeoutPref, this);
   1.161 +    Preferences::RegisterCallback(TimeoutChanged, kHangUIMinDisplayPref, this);
   1.162 +#endif
   1.163 +
   1.164 +#ifdef MOZ_ENABLE_PROFILER_SPS
   1.165 +    InitPluginProfiling();
   1.166 +#endif
   1.167 +}
   1.168 +
   1.169 +PluginModuleParent::~PluginModuleParent()
   1.170 +{
   1.171 +    if (!OkToCleanup()) {
   1.172 +        NS_RUNTIMEABORT("unsafe destruction");
   1.173 +    }
   1.174 +
   1.175 +#ifdef MOZ_ENABLE_PROFILER_SPS
   1.176 +    ShutdownPluginProfiling();
   1.177 +#endif
   1.178 +
   1.179 +    if (!mShutdown) {
   1.180 +        NS_WARNING("Plugin host deleted the module without shutting down.");
   1.181 +        NPError err;
   1.182 +        NP_Shutdown(&err);
   1.183 +    }
   1.184 +
   1.185 +    NS_ASSERTION(mShutdown, "NP_Shutdown didn't");
   1.186 +
   1.187 +    if (mSubprocess) {
   1.188 +        mSubprocess->Delete();
   1.189 +        mSubprocess = nullptr;
   1.190 +    }
   1.191 +
   1.192 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.193 +    if (mFlashProcess1)
   1.194 +        UnregisterInjectorCallback(mFlashProcess1);
   1.195 +    if (mFlashProcess2)
   1.196 +        UnregisterInjectorCallback(mFlashProcess2);
   1.197 +#endif
   1.198 +
   1.199 +    Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
   1.200 +    Preferences::UnregisterCallback(TimeoutChanged, kParentTimeoutPref, this);
   1.201 +#ifdef XP_WIN
   1.202 +    Preferences::UnregisterCallback(TimeoutChanged, kHangUITimeoutPref, this);
   1.203 +    Preferences::UnregisterCallback(TimeoutChanged, kHangUIMinDisplayPref, this);
   1.204 +
   1.205 +    if (mHangUIParent) {
   1.206 +        delete mHangUIParent;
   1.207 +        mHangUIParent = nullptr;
   1.208 +    }
   1.209 +#endif
   1.210 +}
   1.211 +
   1.212 +#ifdef MOZ_CRASHREPORTER
   1.213 +void
   1.214 +PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
   1.215 +{
   1.216 +#ifdef XP_WIN
   1.217 +    // mCrashReporterMutex is already held by the caller
   1.218 +    mCrashReporterMutex.AssertCurrentThreadOwns();
   1.219 +#endif
   1.220 +    typedef nsDependentCString CS;
   1.221 +
   1.222 +    // Get the plugin filename, try to get just the file leafname
   1.223 +    const std::string& pluginFile = mSubprocess->GetPluginFilePath();
   1.224 +    size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR);
   1.225 +    if (filePos == std::string::npos)
   1.226 +        filePos = 0;
   1.227 +    else
   1.228 +        filePos++;
   1.229 +    notes.Put(NS_LITERAL_CSTRING("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
   1.230 +
   1.231 +    nsCString pluginName;
   1.232 +    nsCString pluginVersion;
   1.233 +
   1.234 +    nsRefPtr<nsPluginHost> ph = nsPluginHost::GetInst();
   1.235 +    if (ph) {
   1.236 +        nsPluginTag* tag = ph->TagForPlugin(mPlugin);
   1.237 +        if (tag) {
   1.238 +            pluginName = tag->mName;
   1.239 +            pluginVersion = tag->mVersion;
   1.240 +        }
   1.241 +    }
   1.242 +
   1.243 +    notes.Put(NS_LITERAL_CSTRING("PluginName"), pluginName);
   1.244 +    notes.Put(NS_LITERAL_CSTRING("PluginVersion"), pluginVersion);
   1.245 +
   1.246 +    CrashReporterParent* crashReporter = CrashReporter();
   1.247 +    if (crashReporter) {
   1.248 +#ifdef XP_WIN
   1.249 +        if (mPluginCpuUsageOnHang.Length() > 0) {
   1.250 +            notes.Put(NS_LITERAL_CSTRING("NumberOfProcessors"),
   1.251 +                      nsPrintfCString("%d", PR_GetNumberOfProcessors()));
   1.252 +
   1.253 +            nsCString cpuUsageStr;
   1.254 +            cpuUsageStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[0] * 100) / 100);
   1.255 +            notes.Put(NS_LITERAL_CSTRING("PluginCpuUsage"), cpuUsageStr);
   1.256 +
   1.257 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.258 +            for (uint32_t i=1; i<mPluginCpuUsageOnHang.Length(); ++i) {
   1.259 +                nsCString tempStr;
   1.260 +                tempStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[i] * 100) / 100);
   1.261 +                notes.Put(nsPrintfCString("CpuUsageFlashProcess%d", i), tempStr);
   1.262 +            }
   1.263 +#endif
   1.264 +        }
   1.265 +#endif
   1.266 +    }
   1.267 +}
   1.268 +#endif  // MOZ_CRASHREPORTER
   1.269 +
   1.270 +void
   1.271 +PluginModuleParent::SetChildTimeout(const int32_t aChildTimeout)
   1.272 +{
   1.273 +    int32_t timeoutMs = (aChildTimeout > 0) ? (1000 * aChildTimeout) :
   1.274 +                      MessageChannel::kNoTimeout;
   1.275 +    SetReplyTimeoutMs(timeoutMs);
   1.276 +}
   1.277 +
   1.278 +void
   1.279 +PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
   1.280 +{
   1.281 +    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   1.282 +#ifndef XP_WIN
   1.283 +    if (!strcmp(aPref, kChildTimeoutPref)) {
   1.284 +      // The timeout value used by the parent for children
   1.285 +      int32_t timeoutSecs = Preferences::GetInt(kChildTimeoutPref, 0);
   1.286 +      static_cast<PluginModuleParent*>(aModule)->SetChildTimeout(timeoutSecs);
   1.287 +#else
   1.288 +    if (!strcmp(aPref, kChildTimeoutPref) ||
   1.289 +        !strcmp(aPref, kHangUIMinDisplayPref) ||
   1.290 +        !strcmp(aPref, kHangUITimeoutPref)) {
   1.291 +      static_cast<PluginModuleParent*>(aModule)->EvaluateHangUIState(true);
   1.292 +#endif // XP_WIN
   1.293 +    } else if (!strcmp(aPref, kParentTimeoutPref)) {
   1.294 +      // The timeout value used by the child for its parent
   1.295 +      int32_t timeoutSecs = Preferences::GetInt(kParentTimeoutPref, 0);
   1.296 +      unused << static_cast<PluginModuleParent*>(aModule)->SendSetParentHangTimeout(timeoutSecs);
   1.297 +    }
   1.298 +}
   1.299 +
   1.300 +void
   1.301 +PluginModuleParent::CleanupFromTimeout(const bool aFromHangUI)
   1.302 +{
   1.303 +    if (mShutdown) {
   1.304 +      return;
   1.305 +    }
   1.306 +
   1.307 +    if (!OkToCleanup()) {
   1.308 +        // there's still plugin code on the C++ stack, try again
   1.309 +        MessageLoop::current()->PostDelayedTask(
   1.310 +            FROM_HERE,
   1.311 +            mTaskFactory.NewRunnableMethod(
   1.312 +                &PluginModuleParent::CleanupFromTimeout, aFromHangUI), 10);
   1.313 +        return;
   1.314 +    }
   1.315 +
   1.316 +    /* If the plugin container was terminated by the Plugin Hang UI, 
   1.317 +       then either the I/O thread detects a channel error, or the 
   1.318 +       main thread must set the error (whomever gets there first).
   1.319 +       OTOH, if we terminate and return false from 
   1.320 +       ShouldContinueFromReplyTimeout, then the channel state has 
   1.321 +       already been set to ChannelTimeout and we should call the 
   1.322 +       regular Close function. */
   1.323 +    if (aFromHangUI) {
   1.324 +        GetIPCChannel()->CloseWithError();
   1.325 +    } else {
   1.326 +        Close();
   1.327 +    }
   1.328 +}
   1.329 +
   1.330 +#ifdef XP_WIN
   1.331 +namespace {
   1.332 +
   1.333 +uint64_t
   1.334 +FileTimeToUTC(const FILETIME& ftime) 
   1.335 +{
   1.336 +  ULARGE_INTEGER li;
   1.337 +  li.LowPart = ftime.dwLowDateTime;
   1.338 +  li.HighPart = ftime.dwHighDateTime;
   1.339 +  return li.QuadPart;
   1.340 +}
   1.341 +
   1.342 +struct CpuUsageSamples
   1.343 +{
   1.344 +  uint64_t sampleTimes[2];
   1.345 +  uint64_t cpuTimes[2];
   1.346 +};
   1.347 +
   1.348 +bool 
   1.349 +GetProcessCpuUsage(const InfallibleTArray<base::ProcessHandle>& processHandles, InfallibleTArray<float>& cpuUsage)
   1.350 +{
   1.351 +  InfallibleTArray<CpuUsageSamples> samples(processHandles.Length());
   1.352 +  FILETIME creationTime, exitTime, kernelTime, userTime, currentTime;
   1.353 +  BOOL res;
   1.354 +
   1.355 +  for (uint32_t i = 0; i < processHandles.Length(); ++i) {
   1.356 +    ::GetSystemTimeAsFileTime(&currentTime);
   1.357 +    res = ::GetProcessTimes(processHandles[i], &creationTime, &exitTime, &kernelTime, &userTime);
   1.358 +    if (!res) {
   1.359 +      NS_WARNING("failed to get process times");
   1.360 +      return false;
   1.361 +    }
   1.362 +  
   1.363 +    CpuUsageSamples s;
   1.364 +    s.sampleTimes[0] = FileTimeToUTC(currentTime);
   1.365 +    s.cpuTimes[0]    = FileTimeToUTC(kernelTime) + FileTimeToUTC(userTime);
   1.366 +    samples.AppendElement(s);
   1.367 +  }
   1.368 +
   1.369 +  // we already hung for a while, a little bit longer won't matter
   1.370 +  ::Sleep(50);
   1.371 +
   1.372 +  const int32_t numberOfProcessors = PR_GetNumberOfProcessors();
   1.373 +
   1.374 +  for (uint32_t i = 0; i < processHandles.Length(); ++i) {
   1.375 +    ::GetSystemTimeAsFileTime(&currentTime);
   1.376 +    res = ::GetProcessTimes(processHandles[i], &creationTime, &exitTime, &kernelTime, &userTime);
   1.377 +    if (!res) {
   1.378 +      NS_WARNING("failed to get process times");
   1.379 +      return false;
   1.380 +    }
   1.381 +
   1.382 +    samples[i].sampleTimes[1] = FileTimeToUTC(currentTime);
   1.383 +    samples[i].cpuTimes[1]    = FileTimeToUTC(kernelTime) + FileTimeToUTC(userTime);    
   1.384 +
   1.385 +    const uint64_t deltaSampleTime = samples[i].sampleTimes[1] - samples[i].sampleTimes[0];
   1.386 +    const uint64_t deltaCpuTime    = samples[i].cpuTimes[1]    - samples[i].cpuTimes[0];
   1.387 +    const float usage = 100.f * (float(deltaCpuTime) / deltaSampleTime) / numberOfProcessors;
   1.388 +    cpuUsage.AppendElement(usage);
   1.389 +  }
   1.390 +
   1.391 +  return true;
   1.392 +}
   1.393 +
   1.394 +} // anonymous namespace
   1.395 +
   1.396 +void
   1.397 +PluginModuleParent::ExitedCxxStack()
   1.398 +{
   1.399 +    FinishHangUI();
   1.400 +}
   1.401 +
   1.402 +#endif // #ifdef XP_WIN
   1.403 +
   1.404 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.405 +static bool
   1.406 +CreateFlashMinidump(DWORD processId, ThreadId childThread,
   1.407 +                    nsIFile* parentMinidump, const nsACString& name)
   1.408 +{
   1.409 +  if (processId == 0) {
   1.410 +    return false;
   1.411 +  }
   1.412 +
   1.413 +  base::ProcessHandle handle;
   1.414 +  if (!base::OpenPrivilegedProcessHandle(processId, &handle)) {
   1.415 +    return false;
   1.416 +  }
   1.417 +
   1.418 +  bool res = CreateAdditionalChildMinidump(handle, 0, parentMinidump, name);
   1.419 +  base::CloseProcessHandle(handle);
   1.420 +
   1.421 +  return res;
   1.422 +}
   1.423 +#endif
   1.424 +
   1.425 +bool
   1.426 +PluginModuleParent::ShouldContinueFromReplyTimeout()
   1.427 +{
   1.428 +#ifdef XP_WIN
   1.429 +    if (LaunchHangUI()) {
   1.430 +        return true;
   1.431 +    }
   1.432 +    // If LaunchHangUI returned false then we should proceed with the 
   1.433 +    // original plugin hang behaviour and kill the plugin container.
   1.434 +    FinishHangUI();
   1.435 +#endif // XP_WIN
   1.436 +    TerminateChildProcess(MessageLoop::current());
   1.437 +    return false;
   1.438 +}
   1.439 +
   1.440 +void
   1.441 +PluginModuleParent::TerminateChildProcess(MessageLoop* aMsgLoop)
   1.442 +{
   1.443 +#ifdef MOZ_CRASHREPORTER
   1.444 +#ifdef XP_WIN
   1.445 +    mozilla::MutexAutoLock lock(mCrashReporterMutex);
   1.446 +    CrashReporterParent* crashReporter = mCrashReporter;
   1.447 +    if (!crashReporter) {
   1.448 +        // If mCrashReporter is null then the hang has ended, the plugin module
   1.449 +        // is shutting down. There's nothing to do here.
   1.450 +        return;
   1.451 +    }
   1.452 +#else
   1.453 +    CrashReporterParent* crashReporter = CrashReporter();
   1.454 +#endif
   1.455 +    crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
   1.456 +                                       NS_LITERAL_CSTRING("1"));
   1.457 +#ifdef XP_WIN
   1.458 +    if (mHangUIParent) {
   1.459 +        unsigned int hangUIDuration = mHangUIParent->LastShowDurationMs();
   1.460 +        if (hangUIDuration) {
   1.461 +            nsPrintfCString strHangUIDuration("%u", hangUIDuration);
   1.462 +            crashReporter->AnnotateCrashReport(
   1.463 +                    NS_LITERAL_CSTRING("PluginHangUIDuration"),
   1.464 +                    strHangUIDuration);
   1.465 +        }
   1.466 +    }
   1.467 +#endif // XP_WIN
   1.468 +    if (crashReporter->GeneratePairedMinidump(this)) {
   1.469 +        mPluginDumpID = crashReporter->ChildDumpID();
   1.470 +        PLUGIN_LOG_DEBUG(
   1.471 +                ("generated paired browser/plugin minidumps: %s)",
   1.472 +                 NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
   1.473 +
   1.474 +        nsAutoCString additionalDumps("browser");
   1.475 +
   1.476 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.477 +        nsCOMPtr<nsIFile> pluginDumpFile;
   1.478 +
   1.479 +        if (GetMinidumpForID(mPluginDumpID, getter_AddRefs(pluginDumpFile)) &&
   1.480 +            pluginDumpFile) {
   1.481 +          nsCOMPtr<nsIFile> childDumpFile;
   1.482 +
   1.483 +          if (CreateFlashMinidump(mFlashProcess1, 0, pluginDumpFile,
   1.484 +                                  NS_LITERAL_CSTRING("flash1"))) {
   1.485 +            additionalDumps.Append(",flash1");
   1.486 +          }
   1.487 +          if (CreateFlashMinidump(mFlashProcess2, 0, pluginDumpFile,
   1.488 +                                  NS_LITERAL_CSTRING("flash2"))) {
   1.489 +            additionalDumps.Append(",flash2");
   1.490 +          }
   1.491 +        }
   1.492 +#endif
   1.493 +
   1.494 +        crashReporter->AnnotateCrashReport(
   1.495 +            NS_LITERAL_CSTRING("additional_minidumps"),
   1.496 +            additionalDumps);
   1.497 +    } else {
   1.498 +        NS_WARNING("failed to capture paired minidumps from hang");
   1.499 +    }
   1.500 +#endif
   1.501 +
   1.502 +#ifdef XP_WIN
   1.503 +    // collect cpu usage for plugin processes
   1.504 +
   1.505 +    InfallibleTArray<base::ProcessHandle> processHandles;
   1.506 +
   1.507 +    processHandles.AppendElement(OtherProcess());
   1.508 +
   1.509 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.510 +    {
   1.511 +      base::ProcessHandle handle;
   1.512 +      if (mFlashProcess1 && base::OpenProcessHandle(mFlashProcess1, &handle)) {
   1.513 +        processHandles.AppendElement(handle);
   1.514 +      }
   1.515 +      if (mFlashProcess2 && base::OpenProcessHandle(mFlashProcess2, &handle)) {
   1.516 +        processHandles.AppendElement(handle);
   1.517 +      }
   1.518 +    }
   1.519 +#endif
   1.520 +
   1.521 +    if (!GetProcessCpuUsage(processHandles, mPluginCpuUsageOnHang)) {
   1.522 +      mPluginCpuUsageOnHang.Clear();
   1.523 +    }
   1.524 +#endif
   1.525 +
   1.526 +    // this must run before the error notification from the channel,
   1.527 +    // or not at all
   1.528 +    bool isFromHangUI = aMsgLoop != MessageLoop::current();
   1.529 +    aMsgLoop->PostTask(
   1.530 +        FROM_HERE,
   1.531 +        mTaskFactory.NewRunnableMethod(
   1.532 +            &PluginModuleParent::CleanupFromTimeout, isFromHangUI));
   1.533 +
   1.534 +    if (!KillProcess(OtherProcess(), 1, false))
   1.535 +        NS_WARNING("failed to kill subprocess!");
   1.536 +}
   1.537 +
   1.538 +#ifdef XP_WIN
   1.539 +void
   1.540 +PluginModuleParent::EvaluateHangUIState(const bool aReset)
   1.541 +{
   1.542 +    int32_t minDispSecs = Preferences::GetInt(kHangUIMinDisplayPref, 10);
   1.543 +    int32_t autoStopSecs = Preferences::GetInt(kChildTimeoutPref, 0);
   1.544 +    int32_t timeoutSecs = 0;
   1.545 +    if (autoStopSecs > 0 && autoStopSecs < minDispSecs) {
   1.546 +        /* If we're going to automatically terminate the plugin within a 
   1.547 +           time frame shorter than minDispSecs, there's no point in 
   1.548 +           showing the hang UI; it would just flash briefly on the screen. */
   1.549 +        mHangUIEnabled = false;
   1.550 +    } else {
   1.551 +        timeoutSecs = Preferences::GetInt(kHangUITimeoutPref, 0);
   1.552 +        mHangUIEnabled = timeoutSecs > 0;
   1.553 +    }
   1.554 +    if (mHangUIEnabled) {
   1.555 +        if (aReset) {
   1.556 +            mIsTimerReset = true;
   1.557 +            SetChildTimeout(timeoutSecs);
   1.558 +            return;
   1.559 +        } else if (mIsTimerReset) {
   1.560 +            /* The Hang UI is being shown, so now we're setting the 
   1.561 +               timeout to kChildTimeoutPref while we wait for a user 
   1.562 +               response. ShouldContinueFromReplyTimeout will fire 
   1.563 +               after (reply timeout / 2) seconds, which is not what 
   1.564 +               we want. Doubling the timeout value here so that we get 
   1.565 +               the right result. */
   1.566 +            autoStopSecs *= 2;
   1.567 +        }
   1.568 +    }
   1.569 +    mIsTimerReset = false;
   1.570 +    SetChildTimeout(autoStopSecs);
   1.571 +}
   1.572 +
   1.573 +bool
   1.574 +PluginModuleParent::GetPluginName(nsAString& aPluginName)
   1.575 +{
   1.576 +    nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
   1.577 +    if (!host) {
   1.578 +        return false;
   1.579 +    }
   1.580 +    nsPluginTag* pluginTag = host->TagForPlugin(mPlugin);
   1.581 +    if (!pluginTag) {
   1.582 +        return false;
   1.583 +    }
   1.584 +    CopyUTF8toUTF16(pluginTag->mName, aPluginName);
   1.585 +    return true;
   1.586 +}
   1.587 +
   1.588 +bool
   1.589 +PluginModuleParent::LaunchHangUI()
   1.590 +{
   1.591 +    if (!mHangUIEnabled) {
   1.592 +        return false;
   1.593 +    }
   1.594 +    if (mHangUIParent) {
   1.595 +        if (mHangUIParent->IsShowing()) {
   1.596 +            // We've already shown the UI but the timeout has expired again.
   1.597 +            return false;
   1.598 +        }
   1.599 +        if (mHangUIParent->DontShowAgain()) {
   1.600 +            return !mHangUIParent->WasLastHangStopped();
   1.601 +        }
   1.602 +        delete mHangUIParent;
   1.603 +        mHangUIParent = nullptr;
   1.604 +    }
   1.605 +    mHangUIParent = new PluginHangUIParent(this, 
   1.606 +            Preferences::GetInt(kHangUITimeoutPref, 0),
   1.607 +            Preferences::GetInt(kChildTimeoutPref, 0));
   1.608 +    nsAutoString pluginName;
   1.609 +    if (!GetPluginName(pluginName)) {
   1.610 +        return false;
   1.611 +    }
   1.612 +    bool retval = mHangUIParent->Init(pluginName);
   1.613 +    if (retval) {
   1.614 +        /* Once the UI is shown we switch the timeout over to use 
   1.615 +           kChildTimeoutPref, allowing us to terminate a hung plugin 
   1.616 +           after kChildTimeoutPref seconds if the user doesn't respond to 
   1.617 +           the hang UI. */
   1.618 +        EvaluateHangUIState(false);
   1.619 +    }
   1.620 +    return retval;
   1.621 +}
   1.622 +
   1.623 +void
   1.624 +PluginModuleParent::FinishHangUI()
   1.625 +{
   1.626 +    if (mHangUIEnabled && mHangUIParent) {
   1.627 +        bool needsCancel = mHangUIParent->IsShowing();
   1.628 +        // If we're still showing, send a Cancel notification
   1.629 +        if (needsCancel) {
   1.630 +            mHangUIParent->Cancel();
   1.631 +        }
   1.632 +        /* If we cancelled the UI or if the user issued a response,
   1.633 +           we need to reset the child process timeout. */
   1.634 +        if (needsCancel ||
   1.635 +            !mIsTimerReset && mHangUIParent->WasShown()) {
   1.636 +            /* We changed the timeout to kChildTimeoutPref when the plugin hang
   1.637 +               UI was displayed. Now that we're finishing the UI, we need to 
   1.638 +               switch it back to kHangUITimeoutPref. */
   1.639 +            EvaluateHangUIState(true);
   1.640 +        }
   1.641 +    }
   1.642 +}
   1.643 +#endif // XP_WIN
   1.644 +
   1.645 +#ifdef MOZ_CRASHREPORTER
   1.646 +CrashReporterParent*
   1.647 +PluginModuleParent::CrashReporter()
   1.648 +{
   1.649 +    return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
   1.650 +}
   1.651 +
   1.652 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.653 +static void
   1.654 +RemoveMinidump(nsIFile* minidump)
   1.655 +{
   1.656 +    if (!minidump)
   1.657 +        return;
   1.658 +
   1.659 +    minidump->Remove(false);
   1.660 +    nsCOMPtr<nsIFile> extraFile;
   1.661 +    if (GetExtraFileForMinidump(minidump,
   1.662 +                                getter_AddRefs(extraFile))) {
   1.663 +        extraFile->Remove(true);
   1.664 +    }
   1.665 +}
   1.666 +#endif // MOZ_CRASHREPORTER_INJECTOR
   1.667 +
   1.668 +void
   1.669 +PluginModuleParent::ProcessFirstMinidump()
   1.670 +{
   1.671 +#ifdef XP_WIN
   1.672 +    mozilla::MutexAutoLock lock(mCrashReporterMutex);
   1.673 +#endif
   1.674 +    CrashReporterParent* crashReporter = CrashReporter();
   1.675 +    if (!crashReporter)
   1.676 +        return;
   1.677 +
   1.678 +    AnnotationTable notes(4);
   1.679 +    WriteExtraDataForMinidump(notes);
   1.680 +
   1.681 +    if (!mPluginDumpID.IsEmpty()) {
   1.682 +        crashReporter->GenerateChildData(&notes);
   1.683 +        return;
   1.684 +    }
   1.685 +
   1.686 +    uint32_t sequence = UINT32_MAX;
   1.687 +    nsCOMPtr<nsIFile> dumpFile;
   1.688 +    nsAutoCString flashProcessType;
   1.689 +    TakeMinidump(getter_AddRefs(dumpFile), &sequence);
   1.690 +
   1.691 +#ifdef MOZ_CRASHREPORTER_INJECTOR
   1.692 +    nsCOMPtr<nsIFile> childDumpFile;
   1.693 +    uint32_t childSequence;
   1.694 +
   1.695 +    if (mFlashProcess1 &&
   1.696 +        TakeMinidumpForChild(mFlashProcess1,
   1.697 +                             getter_AddRefs(childDumpFile),
   1.698 +                             &childSequence)) {
   1.699 +        if (childSequence < sequence) {
   1.700 +            RemoveMinidump(dumpFile);
   1.701 +            dumpFile = childDumpFile;
   1.702 +            sequence = childSequence;
   1.703 +            flashProcessType.AssignLiteral("Broker");
   1.704 +        }
   1.705 +        else {
   1.706 +            RemoveMinidump(childDumpFile);
   1.707 +        }
   1.708 +    }
   1.709 +    if (mFlashProcess2 &&
   1.710 +        TakeMinidumpForChild(mFlashProcess2,
   1.711 +                             getter_AddRefs(childDumpFile),
   1.712 +                             &childSequence)) {
   1.713 +        if (childSequence < sequence) {
   1.714 +            RemoveMinidump(dumpFile);
   1.715 +            dumpFile = childDumpFile;
   1.716 +            sequence = childSequence;
   1.717 +            flashProcessType.AssignLiteral("Sandbox");
   1.718 +        }
   1.719 +        else {
   1.720 +            RemoveMinidump(childDumpFile);
   1.721 +        }
   1.722 +    }
   1.723 +#endif
   1.724 +
   1.725 +    if (!dumpFile) {
   1.726 +        NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
   1.727 +        return;
   1.728 +    }
   1.729 +
   1.730 +    PLUGIN_LOG_DEBUG(("got child minidump: %s",
   1.731 +                      NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
   1.732 +
   1.733 +    GetIDFromMinidump(dumpFile, mPluginDumpID);
   1.734 +    if (!flashProcessType.IsEmpty()) {
   1.735 +        notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"), flashProcessType);
   1.736 +    }
   1.737 +    crashReporter->GenerateCrashReportForMinidump(dumpFile, &notes);
   1.738 +}
   1.739 +#endif
   1.740 +
   1.741 +void
   1.742 +PluginModuleParent::ActorDestroy(ActorDestroyReason why)
   1.743 +{
   1.744 +    switch (why) {
   1.745 +    case AbnormalShutdown: {
   1.746 +#ifdef MOZ_CRASHREPORTER
   1.747 +        ProcessFirstMinidump();
   1.748 +#endif
   1.749 +
   1.750 +        mShutdown = true;
   1.751 +        // Defer the PluginCrashed method so that we don't re-enter
   1.752 +        // and potentially modify the actor child list while enumerating it.
   1.753 +        if (mPlugin)
   1.754 +            MessageLoop::current()->PostTask(
   1.755 +                FROM_HERE,
   1.756 +                mTaskFactory.NewRunnableMethod(
   1.757 +                    &PluginModuleParent::NotifyPluginCrashed));
   1.758 +        break;
   1.759 +    }
   1.760 +    case NormalShutdown:
   1.761 +        mShutdown = true;
   1.762 +        break;
   1.763 +
   1.764 +    default:
   1.765 +        NS_RUNTIMEABORT("Unexpected shutdown reason for toplevel actor.");
   1.766 +    }
   1.767 +}
   1.768 +
   1.769 +void
   1.770 +PluginModuleParent::NotifyPluginCrashed()
   1.771 +{
   1.772 +    if (!OkToCleanup()) {
   1.773 +        // there's still plugin code on the C++ stack.  try again
   1.774 +        MessageLoop::current()->PostDelayedTask(
   1.775 +            FROM_HERE,
   1.776 +            mTaskFactory.NewRunnableMethod(
   1.777 +                &PluginModuleParent::NotifyPluginCrashed), 10);
   1.778 +        return;
   1.779 +    }
   1.780 +
   1.781 +    if (mPlugin)
   1.782 +        mPlugin->PluginCrashed(mPluginDumpID, mBrowserDumpID);
   1.783 +}
   1.784 +
   1.785 +PPluginIdentifierParent*
   1.786 +PluginModuleParent::AllocPPluginIdentifierParent(const nsCString& aString,
   1.787 +                                                 const int32_t& aInt,
   1.788 +                                                 const bool& aTemporary)
   1.789 +{
   1.790 +    if (aTemporary) {
   1.791 +        NS_ERROR("Plugins don't create temporary identifiers.");
   1.792 +        return nullptr; // should abort the plugin
   1.793 +    }
   1.794 +
   1.795 +    NPIdentifier npident = aString.IsVoid() ?
   1.796 +        mozilla::plugins::parent::_getintidentifier(aInt) :
   1.797 +        mozilla::plugins::parent::_getstringidentifier(aString.get());
   1.798 +
   1.799 +    if (!npident) {
   1.800 +        NS_WARNING("Failed to get identifier!");
   1.801 +        return nullptr;
   1.802 +    }
   1.803 +
   1.804 +    PluginIdentifierParent* ident = new PluginIdentifierParent(npident, false);
   1.805 +    mIdentifiers.Put(npident, ident);
   1.806 +    return ident;
   1.807 +}
   1.808 +
   1.809 +bool
   1.810 +PluginModuleParent::DeallocPPluginIdentifierParent(PPluginIdentifierParent* aActor)
   1.811 +{
   1.812 +    delete aActor;
   1.813 +    return true;
   1.814 +}
   1.815 +
   1.816 +PPluginInstanceParent*
   1.817 +PluginModuleParent::AllocPPluginInstanceParent(const nsCString& aMimeType,
   1.818 +                                               const uint16_t& aMode,
   1.819 +                                               const InfallibleTArray<nsCString>& aNames,
   1.820 +                                               const InfallibleTArray<nsCString>& aValues,
   1.821 +                                               NPError* rv)
   1.822 +{
   1.823 +    NS_ERROR("Not reachable!");
   1.824 +    return nullptr;
   1.825 +}
   1.826 +
   1.827 +bool
   1.828 +PluginModuleParent::DeallocPPluginInstanceParent(PPluginInstanceParent* aActor)
   1.829 +{
   1.830 +    PLUGIN_LOG_DEBUG_METHOD;
   1.831 +    delete aActor;
   1.832 +    return true;
   1.833 +}
   1.834 +
   1.835 +void
   1.836 +PluginModuleParent::SetPluginFuncs(NPPluginFuncs* aFuncs)
   1.837 +{
   1.838 +    aFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
   1.839 +    aFuncs->javaClass = nullptr;
   1.840 +
   1.841 +    // Gecko should always call these functions through a PluginLibrary object.
   1.842 +    aFuncs->newp = nullptr;
   1.843 +    aFuncs->clearsitedata = nullptr;
   1.844 +    aFuncs->getsiteswithdata = nullptr;
   1.845 +
   1.846 +    aFuncs->destroy = NPP_Destroy;
   1.847 +    aFuncs->setwindow = NPP_SetWindow;
   1.848 +    aFuncs->newstream = NPP_NewStream;
   1.849 +    aFuncs->destroystream = NPP_DestroyStream;
   1.850 +    aFuncs->asfile = NPP_StreamAsFile;
   1.851 +    aFuncs->writeready = NPP_WriteReady;
   1.852 +    aFuncs->write = NPP_Write;
   1.853 +    aFuncs->print = NPP_Print;
   1.854 +    aFuncs->event = NPP_HandleEvent;
   1.855 +    aFuncs->urlnotify = NPP_URLNotify;
   1.856 +    aFuncs->getvalue = NPP_GetValue;
   1.857 +    aFuncs->setvalue = NPP_SetValue;
   1.858 +    aFuncs->gotfocus = nullptr;
   1.859 +    aFuncs->lostfocus = nullptr;
   1.860 +    aFuncs->urlredirectnotify = nullptr;
   1.861 +
   1.862 +    // Provide 'NPP_URLRedirectNotify', 'NPP_ClearSiteData', and
   1.863 +    // 'NPP_GetSitesWithData' functionality if it is supported by the plugin.
   1.864 +    bool urlRedirectSupported = false;
   1.865 +    unused << CallOptionalFunctionsSupported(&urlRedirectSupported,
   1.866 +                                             &mClearSiteDataSupported,
   1.867 +                                             &mGetSitesWithDataSupported);
   1.868 +    if (urlRedirectSupported) {
   1.869 +      aFuncs->urlredirectnotify = NPP_URLRedirectNotify;
   1.870 +    }
   1.871 +}
   1.872 +
   1.873 +NPError
   1.874 +PluginModuleParent::NPP_Destroy(NPP instance,
   1.875 +                                NPSavedData** /*saved*/)
   1.876 +{
   1.877 +    // FIXME/cjones:
   1.878 +    //  (1) send a "destroy" message to the child
   1.879 +    //  (2) the child shuts down its instance
   1.880 +    //  (3) remove both parent and child IDs from map
   1.881 +    //  (4) free parent
   1.882 +    PLUGIN_LOG_DEBUG_FUNCTION;
   1.883 +
   1.884 +    PluginInstanceParent* parentInstance =
   1.885 +        static_cast<PluginInstanceParent*>(instance->pdata);
   1.886 +
   1.887 +    if (!parentInstance)
   1.888 +        return NPERR_NO_ERROR;
   1.889 +
   1.890 +    NPError retval = parentInstance->Destroy();
   1.891 +    instance->pdata = nullptr;
   1.892 +
   1.893 +    unused << PluginInstanceParent::Call__delete__(parentInstance);
   1.894 +    return retval;
   1.895 +}
   1.896 +
   1.897 +NPError
   1.898 +PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type,
   1.899 +                                  NPStream* stream, NPBool seekable,
   1.900 +                                  uint16_t* stype)
   1.901 +{
   1.902 +    PROFILER_LABEL("PluginModuleParent", "NPP_NewStream");
   1.903 +    PluginInstanceParent* i = InstCast(instance);
   1.904 +    if (!i)
   1.905 +        return NPERR_GENERIC_ERROR;
   1.906 +
   1.907 +    return i->NPP_NewStream(type, stream, seekable,
   1.908 +                            stype);
   1.909 +}
   1.910 +
   1.911 +NPError
   1.912 +PluginModuleParent::NPP_SetWindow(NPP instance, NPWindow* window)
   1.913 +{
   1.914 +    PluginInstanceParent* i = InstCast(instance);
   1.915 +    if (!i)
   1.916 +        return NPERR_GENERIC_ERROR;
   1.917 +
   1.918 +    return i->NPP_SetWindow(window);
   1.919 +}
   1.920 +
   1.921 +NPError
   1.922 +PluginModuleParent::NPP_DestroyStream(NPP instance,
   1.923 +                                      NPStream* stream,
   1.924 +                                      NPReason reason)
   1.925 +{
   1.926 +    PluginInstanceParent* i = InstCast(instance);
   1.927 +    if (!i)
   1.928 +        return NPERR_GENERIC_ERROR;
   1.929 +
   1.930 +    return i->NPP_DestroyStream(stream, reason);
   1.931 +}
   1.932 +
   1.933 +int32_t
   1.934 +PluginModuleParent::NPP_WriteReady(NPP instance,
   1.935 +                                   NPStream* stream)
   1.936 +{
   1.937 +    BrowserStreamParent* s = StreamCast(instance, stream);
   1.938 +    if (!s)
   1.939 +        return -1;
   1.940 +
   1.941 +    return s->WriteReady();
   1.942 +}
   1.943 +
   1.944 +int32_t
   1.945 +PluginModuleParent::NPP_Write(NPP instance,
   1.946 +                              NPStream* stream,
   1.947 +                              int32_t offset,
   1.948 +                              int32_t len,
   1.949 +                              void* buffer)
   1.950 +{
   1.951 +    BrowserStreamParent* s = StreamCast(instance, stream);
   1.952 +    if (!s)
   1.953 +        return -1;
   1.954 +
   1.955 +    return s->Write(offset, len, buffer);
   1.956 +}
   1.957 +
   1.958 +void
   1.959 +PluginModuleParent::NPP_StreamAsFile(NPP instance,
   1.960 +                                     NPStream* stream,
   1.961 +                                     const char* fname)
   1.962 +{
   1.963 +    BrowserStreamParent* s = StreamCast(instance, stream);
   1.964 +    if (!s)
   1.965 +        return;
   1.966 +
   1.967 +    s->StreamAsFile(fname);
   1.968 +}
   1.969 +
   1.970 +void
   1.971 +PluginModuleParent::NPP_Print(NPP instance, NPPrint* platformPrint)
   1.972 +{
   1.973 +    PluginInstanceParent* i = InstCast(instance);
   1.974 +    if (i)
   1.975 +        i->NPP_Print(platformPrint);
   1.976 +}
   1.977 +
   1.978 +int16_t
   1.979 +PluginModuleParent::NPP_HandleEvent(NPP instance, void* event)
   1.980 +{
   1.981 +    PluginInstanceParent* i = InstCast(instance);
   1.982 +    if (!i)
   1.983 +        return false;
   1.984 +
   1.985 +    return i->NPP_HandleEvent(event);
   1.986 +}
   1.987 +
   1.988 +void
   1.989 +PluginModuleParent::NPP_URLNotify(NPP instance, const char* url,
   1.990 +                                  NPReason reason, void* notifyData)
   1.991 +{
   1.992 +    PluginInstanceParent* i = InstCast(instance);
   1.993 +    if (!i)
   1.994 +        return;
   1.995 +
   1.996 +    i->NPP_URLNotify(url, reason, notifyData);
   1.997 +}
   1.998 +
   1.999 +NPError
  1.1000 +PluginModuleParent::NPP_GetValue(NPP instance,
  1.1001 +                                 NPPVariable variable, void *ret_value)
  1.1002 +{
  1.1003 +    PluginInstanceParent* i = InstCast(instance);
  1.1004 +    if (!i)
  1.1005 +        return NPERR_GENERIC_ERROR;
  1.1006 +
  1.1007 +    return i->NPP_GetValue(variable, ret_value);
  1.1008 +}
  1.1009 +
  1.1010 +NPError
  1.1011 +PluginModuleParent::NPP_SetValue(NPP instance, NPNVariable variable,
  1.1012 +                                 void *value)
  1.1013 +{
  1.1014 +    PluginInstanceParent* i = InstCast(instance);
  1.1015 +    if (!i)
  1.1016 +        return NPERR_GENERIC_ERROR;
  1.1017 +
  1.1018 +    return i->NPP_SetValue(variable, value);
  1.1019 +}
  1.1020 +
  1.1021 +bool
  1.1022 +PluginModuleParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
  1.1023 +{
  1.1024 +#ifndef MOZ_X11
  1.1025 +    NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
  1.1026 +#else
  1.1027 +    NS_ABORT_IF_FALSE(0 > mPluginXSocketFdDup.get(),
  1.1028 +                      "Already backed up X resources??");
  1.1029 +    mPluginXSocketFdDup.forget();
  1.1030 +    if (aXSocketFd.IsValid()) {
  1.1031 +      mPluginXSocketFdDup.reset(aXSocketFd.PlatformHandle());
  1.1032 +    }
  1.1033 +#endif
  1.1034 +    return true;
  1.1035 +}
  1.1036 +
  1.1037 +void
  1.1038 +PluginModuleParent::NPP_URLRedirectNotify(NPP instance, const char* url,
  1.1039 +                                          int32_t status, void* notifyData)
  1.1040 +{
  1.1041 +  PluginInstanceParent* i = InstCast(instance);
  1.1042 +  if (!i)
  1.1043 +    return;
  1.1044 +
  1.1045 +  i->NPP_URLRedirectNotify(url, status, notifyData);
  1.1046 +}
  1.1047 +
  1.1048 +bool
  1.1049 +PluginModuleParent::AnswerNPN_UserAgent(nsCString* userAgent)
  1.1050 +{
  1.1051 +    *userAgent = NullableString(mNPNIface->uagent(nullptr));
  1.1052 +    return true;
  1.1053 +}
  1.1054 +
  1.1055 +PluginIdentifierParent*
  1.1056 +PluginModuleParent::GetIdentifierForNPIdentifier(NPP npp, NPIdentifier aIdentifier)
  1.1057 +{
  1.1058 +    PluginIdentifierParent* ident;
  1.1059 +    if (mIdentifiers.Get(aIdentifier, &ident)) {
  1.1060 +        if (ident->IsTemporary()) {
  1.1061 +            ident->AddTemporaryRef();
  1.1062 +        }
  1.1063 +        return ident;
  1.1064 +    }
  1.1065 +
  1.1066 +    nsCString string;
  1.1067 +    int32_t intval = -1;
  1.1068 +    bool temporary = false;
  1.1069 +    if (mozilla::plugins::parent::_identifierisstring(aIdentifier)) {
  1.1070 +        NPUTF8* chars =
  1.1071 +            mozilla::plugins::parent::_utf8fromidentifier(aIdentifier);
  1.1072 +        if (!chars) {
  1.1073 +            return nullptr;
  1.1074 +        }
  1.1075 +        string.Adopt(chars);
  1.1076 +        temporary = !NPStringIdentifierIsPermanent(npp, aIdentifier);
  1.1077 +    }
  1.1078 +    else {
  1.1079 +        intval = mozilla::plugins::parent::_intfromidentifier(aIdentifier);
  1.1080 +        string.SetIsVoid(true);
  1.1081 +    }
  1.1082 +
  1.1083 +    ident = new PluginIdentifierParent(aIdentifier, temporary);
  1.1084 +    if (!SendPPluginIdentifierConstructor(ident, string, intval, temporary))
  1.1085 +        return nullptr;
  1.1086 +
  1.1087 +    if (!temporary) {
  1.1088 +        mIdentifiers.Put(aIdentifier, ident);
  1.1089 +    }
  1.1090 +    return ident;
  1.1091 +}
  1.1092 +
  1.1093 +PluginInstanceParent*
  1.1094 +PluginModuleParent::InstCast(NPP instance)
  1.1095 +{
  1.1096 +    PluginInstanceParent* ip =
  1.1097 +        static_cast<PluginInstanceParent*>(instance->pdata);
  1.1098 +
  1.1099 +    // If the plugin crashed and the PluginInstanceParent was deleted,
  1.1100 +    // instance->pdata will be nullptr.
  1.1101 +    if (!ip)
  1.1102 +        return nullptr;
  1.1103 +
  1.1104 +    if (instance != ip->mNPP) {
  1.1105 +        NS_RUNTIMEABORT("Corrupted plugin data.");
  1.1106 +    }
  1.1107 +    return ip;
  1.1108 +}
  1.1109 +
  1.1110 +BrowserStreamParent*
  1.1111 +PluginModuleParent::StreamCast(NPP instance,
  1.1112 +                               NPStream* s)
  1.1113 +{
  1.1114 +    PluginInstanceParent* ip = InstCast(instance);
  1.1115 +    if (!ip)
  1.1116 +        return nullptr;
  1.1117 +
  1.1118 +    BrowserStreamParent* sp =
  1.1119 +        static_cast<BrowserStreamParent*>(static_cast<AStream*>(s->pdata));
  1.1120 +    if (sp->mNPP != ip || s != sp->mStream) {
  1.1121 +        NS_RUNTIMEABORT("Corrupted plugin stream data.");
  1.1122 +    }
  1.1123 +    return sp;
  1.1124 +}
  1.1125 +
  1.1126 +bool
  1.1127 +PluginModuleParent::HasRequiredFunctions()
  1.1128 +{
  1.1129 +    return true;
  1.1130 +}
  1.1131 +
  1.1132 +nsresult
  1.1133 +PluginModuleParent::AsyncSetWindow(NPP instance, NPWindow* window)
  1.1134 +{
  1.1135 +    PluginInstanceParent* i = InstCast(instance);
  1.1136 +    if (!i)
  1.1137 +        return NS_ERROR_FAILURE;
  1.1138 +
  1.1139 +    return i->AsyncSetWindow(window);
  1.1140 +}
  1.1141 +
  1.1142 +nsresult
  1.1143 +PluginModuleParent::GetImageContainer(NPP instance,
  1.1144 +                             mozilla::layers::ImageContainer** aContainer)
  1.1145 +{
  1.1146 +    PluginInstanceParent* i = InstCast(instance);
  1.1147 +    return !i ? NS_ERROR_FAILURE : i->GetImageContainer(aContainer);
  1.1148 +}
  1.1149 +
  1.1150 +nsresult
  1.1151 +PluginModuleParent::GetImageSize(NPP instance,
  1.1152 +                                 nsIntSize* aSize)
  1.1153 +{
  1.1154 +    PluginInstanceParent* i = InstCast(instance);
  1.1155 +    return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize);
  1.1156 +}
  1.1157 +
  1.1158 +nsresult
  1.1159 +PluginModuleParent::SetBackgroundUnknown(NPP instance)
  1.1160 +{
  1.1161 +    PluginInstanceParent* i = InstCast(instance);
  1.1162 +    if (!i)
  1.1163 +        return NS_ERROR_FAILURE;
  1.1164 +
  1.1165 +    return i->SetBackgroundUnknown();
  1.1166 +}
  1.1167 +
  1.1168 +nsresult
  1.1169 +PluginModuleParent::BeginUpdateBackground(NPP instance,
  1.1170 +                                          const nsIntRect& aRect,
  1.1171 +                                          gfxContext** aCtx)
  1.1172 +{
  1.1173 +    PluginInstanceParent* i = InstCast(instance);
  1.1174 +    if (!i)
  1.1175 +        return NS_ERROR_FAILURE;
  1.1176 +
  1.1177 +    return i->BeginUpdateBackground(aRect, aCtx);
  1.1178 +}
  1.1179 +
  1.1180 +nsresult
  1.1181 +PluginModuleParent::EndUpdateBackground(NPP instance,
  1.1182 +                                        gfxContext* aCtx,
  1.1183 +                                        const nsIntRect& aRect)
  1.1184 +{
  1.1185 +    PluginInstanceParent* i = InstCast(instance);
  1.1186 +    if (!i)
  1.1187 +        return NS_ERROR_FAILURE;
  1.1188 +
  1.1189 +    return i->EndUpdateBackground(aCtx, aRect);
  1.1190 +}
  1.1191 +
  1.1192 +#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
  1.1193 +nsresult
  1.1194 +PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
  1.1195 +{
  1.1196 +    PLUGIN_LOG_DEBUG_METHOD;
  1.1197 +
  1.1198 +    mNPNIface = bFuncs;
  1.1199 +
  1.1200 +    if (mShutdown) {
  1.1201 +        *error = NPERR_GENERIC_ERROR;
  1.1202 +        return NS_ERROR_FAILURE;
  1.1203 +    }
  1.1204 +
  1.1205 +    uint32_t flags = 0;
  1.1206 +
  1.1207 +    if (!CallNP_Initialize(flags, error)) {
  1.1208 +        Close();
  1.1209 +        return NS_ERROR_FAILURE;
  1.1210 +    }
  1.1211 +    else if (*error != NPERR_NO_ERROR) {
  1.1212 +        Close();
  1.1213 +        return NS_OK;
  1.1214 +    }
  1.1215 +
  1.1216 +    SetPluginFuncs(pFuncs);
  1.1217 +
  1.1218 +    return NS_OK;
  1.1219 +}
  1.1220 +#else
  1.1221 +nsresult
  1.1222 +PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
  1.1223 +{
  1.1224 +    PLUGIN_LOG_DEBUG_METHOD;
  1.1225 +
  1.1226 +    mNPNIface = bFuncs;
  1.1227 +
  1.1228 +    if (mShutdown) {
  1.1229 +        *error = NPERR_GENERIC_ERROR;
  1.1230 +        return NS_ERROR_FAILURE;
  1.1231 +    }
  1.1232 +
  1.1233 +    uint32_t flags = 0;
  1.1234 +#ifdef XP_WIN
  1.1235 +    flags |= kAllowAsyncDrawing;
  1.1236 +#endif
  1.1237 +
  1.1238 +    if (!CallNP_Initialize(flags, error)) {
  1.1239 +        Close();
  1.1240 +        return NS_ERROR_FAILURE;
  1.1241 +    }
  1.1242 +    if (*error != NPERR_NO_ERROR) {
  1.1243 +        Close();
  1.1244 +        return NS_OK;
  1.1245 +    }
  1.1246 +
  1.1247 +#if defined XP_WIN
  1.1248 +    // Send the info needed to join the chrome process's audio session to the
  1.1249 +    // plugin process
  1.1250 +    nsID id;
  1.1251 +    nsString sessionName;
  1.1252 +    nsString iconPath;
  1.1253 +
  1.1254 +    if (NS_SUCCEEDED(mozilla::widget::GetAudioSessionData(id, sessionName,
  1.1255 +                                                          iconPath)))
  1.1256 +        unused << SendSetAudioSessionData(id, sessionName, iconPath);
  1.1257 +#endif
  1.1258 +
  1.1259 +#ifdef MOZ_CRASHREPORTER_INJECTOR
  1.1260 +    InitializeInjector();
  1.1261 +#endif
  1.1262 +
  1.1263 +    return NS_OK;
  1.1264 +}
  1.1265 +#endif
  1.1266 +
  1.1267 +nsresult
  1.1268 +PluginModuleParent::NP_Shutdown(NPError* error)
  1.1269 +{
  1.1270 +    PLUGIN_LOG_DEBUG_METHOD;
  1.1271 +
  1.1272 +    if (mShutdown) {
  1.1273 +        *error = NPERR_GENERIC_ERROR;
  1.1274 +        return NS_ERROR_FAILURE;
  1.1275 +    }
  1.1276 +
  1.1277 +    bool ok = CallNP_Shutdown(error);
  1.1278 +
  1.1279 +    // if NP_Shutdown() is nested within another interrupt call, this will
  1.1280 +    // break things.  but lord help us if we're doing that anyway; the
  1.1281 +    // plugin dso will have been unloaded on the other side by the
  1.1282 +    // CallNP_Shutdown() message
  1.1283 +    Close();
  1.1284 +
  1.1285 +    return ok ? NS_OK : NS_ERROR_FAILURE;
  1.1286 +}
  1.1287 +
  1.1288 +nsresult
  1.1289 +PluginModuleParent::NP_GetMIMEDescription(const char** mimeDesc)
  1.1290 +{
  1.1291 +    PLUGIN_LOG_DEBUG_METHOD;
  1.1292 +
  1.1293 +    *mimeDesc = "application/x-foobar";
  1.1294 +    return NS_OK;
  1.1295 +}
  1.1296 +
  1.1297 +nsresult
  1.1298 +PluginModuleParent::NP_GetValue(void *future, NPPVariable aVariable,
  1.1299 +                                   void *aValue, NPError* error)
  1.1300 +{
  1.1301 +    PR_LOG(GetPluginLog(), PR_LOG_WARNING, ("%s Not implemented, requested variable %i", __FUNCTION__,
  1.1302 +                                        (int) aVariable));
  1.1303 +
  1.1304 +    //TODO: implement this correctly
  1.1305 +    *error = NPERR_GENERIC_ERROR;
  1.1306 +    return NS_OK;
  1.1307 +}
  1.1308 +
  1.1309 +#if defined(XP_WIN) || defined(XP_MACOSX)
  1.1310 +nsresult
  1.1311 +PluginModuleParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
  1.1312 +{
  1.1313 +    NS_ASSERTION(pFuncs, "Null pointer!");
  1.1314 +
  1.1315 +    // We need to have the child process update its function table
  1.1316 +    // here by actually calling NP_GetEntryPoints since the parent's
  1.1317 +    // function table can reflect nullptr entries in the child's table.
  1.1318 +    if (!CallNP_GetEntryPoints(error)) {
  1.1319 +        return NS_ERROR_FAILURE;
  1.1320 +    }
  1.1321 +    else if (*error != NPERR_NO_ERROR) {
  1.1322 +        return NS_OK;
  1.1323 +    }
  1.1324 +
  1.1325 +    SetPluginFuncs(pFuncs);
  1.1326 +
  1.1327 +    return NS_OK;
  1.1328 +}
  1.1329 +#endif
  1.1330 +
  1.1331 +nsresult
  1.1332 +PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
  1.1333 +                            uint16_t mode, int16_t argc, char* argn[],
  1.1334 +                            char* argv[], NPSavedData* saved,
  1.1335 +                            NPError* error)
  1.1336 +{
  1.1337 +    PLUGIN_LOG_DEBUG_METHOD;
  1.1338 +
  1.1339 +    if (mShutdown) {
  1.1340 +        *error = NPERR_GENERIC_ERROR;
  1.1341 +        return NS_ERROR_FAILURE;
  1.1342 +    }
  1.1343 +
  1.1344 +    // create the instance on the other side
  1.1345 +    InfallibleTArray<nsCString> names;
  1.1346 +    InfallibleTArray<nsCString> values;
  1.1347 +
  1.1348 +    for (int i = 0; i < argc; ++i) {
  1.1349 +        names.AppendElement(NullableString(argn[i]));
  1.1350 +        values.AppendElement(NullableString(argv[i]));
  1.1351 +    }
  1.1352 +
  1.1353 +    PluginInstanceParent* parentInstance =
  1.1354 +        new PluginInstanceParent(this, instance,
  1.1355 +                                 nsDependentCString(pluginType), mNPNIface);
  1.1356 +
  1.1357 +    if (!parentInstance->Init()) {
  1.1358 +        delete parentInstance;
  1.1359 +        return NS_ERROR_FAILURE;
  1.1360 +    }
  1.1361 +
  1.1362 +    instance->pdata = parentInstance;
  1.1363 +
  1.1364 +    if (!CallPPluginInstanceConstructor(parentInstance,
  1.1365 +                                        nsDependentCString(pluginType), mode,
  1.1366 +                                        names, values, error)) {
  1.1367 +        // |parentInstance| is automatically deleted.
  1.1368 +        instance->pdata = nullptr;
  1.1369 +        // if IPC is down, we'll get an immediate "failed" return, but
  1.1370 +        // without *error being set.  So make sure that the error
  1.1371 +        // condition is signaled to nsNPAPIPluginInstance
  1.1372 +        if (NPERR_NO_ERROR == *error)
  1.1373 +            *error = NPERR_GENERIC_ERROR;
  1.1374 +        return NS_ERROR_FAILURE;
  1.1375 +    }
  1.1376 +
  1.1377 +    if (*error != NPERR_NO_ERROR) {
  1.1378 +        NPP_Destroy(instance, 0);
  1.1379 +        return NS_ERROR_FAILURE;
  1.1380 +    }
  1.1381 +
  1.1382 +    TimeoutChanged(kParentTimeoutPref, this);
  1.1383 +    
  1.1384 +    return NS_OK;
  1.1385 +}
  1.1386 +
  1.1387 +nsresult
  1.1388 +PluginModuleParent::NPP_ClearSiteData(const char* site, uint64_t flags,
  1.1389 +                                      uint64_t maxAge)
  1.1390 +{
  1.1391 +    if (!mClearSiteDataSupported)
  1.1392 +        return NS_ERROR_NOT_AVAILABLE;
  1.1393 +
  1.1394 +    NPError result;
  1.1395 +    if (!CallNPP_ClearSiteData(NullableString(site), flags, maxAge, &result))
  1.1396 +        return NS_ERROR_FAILURE;
  1.1397 +
  1.1398 +    switch (result) {
  1.1399 +    case NPERR_NO_ERROR:
  1.1400 +        return NS_OK;
  1.1401 +    case NPERR_TIME_RANGE_NOT_SUPPORTED:
  1.1402 +        return NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED;
  1.1403 +    case NPERR_MALFORMED_SITE:
  1.1404 +        return NS_ERROR_INVALID_ARG;
  1.1405 +    default:
  1.1406 +        return NS_ERROR_FAILURE;
  1.1407 +    }
  1.1408 +}
  1.1409 +
  1.1410 +nsresult
  1.1411 +PluginModuleParent::NPP_GetSitesWithData(InfallibleTArray<nsCString>& result)
  1.1412 +{
  1.1413 +    if (!mGetSitesWithDataSupported)
  1.1414 +        return NS_ERROR_NOT_AVAILABLE;
  1.1415 +
  1.1416 +    if (!CallNPP_GetSitesWithData(&result))
  1.1417 +        return NS_ERROR_FAILURE;
  1.1418 +
  1.1419 +    return NS_OK;
  1.1420 +}
  1.1421 +
  1.1422 +#if defined(XP_MACOSX)
  1.1423 +nsresult
  1.1424 +PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
  1.1425 +{
  1.1426 +    PluginInstanceParent* i = InstCast(instance);
  1.1427 +    if (!i)
  1.1428 +        return NS_ERROR_FAILURE;
  1.1429 +
  1.1430 +    return i->IsRemoteDrawingCoreAnimation(aDrawing);
  1.1431 +}
  1.1432 +
  1.1433 +nsresult
  1.1434 +PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
  1.1435 +{
  1.1436 +    PluginInstanceParent* i = InstCast(instance);
  1.1437 +    if (!i)
  1.1438 +        return NS_ERROR_FAILURE;
  1.1439 +
  1.1440 +    return i->ContentsScaleFactorChanged(aContentsScaleFactor);
  1.1441 +}
  1.1442 +#endif // #if defined(XP_MACOSX)
  1.1443 +
  1.1444 +bool
  1.1445 +PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
  1.1446 +                                                      NPError* aError,
  1.1447 +                                                      bool* aBoolVal)
  1.1448 +{
  1.1449 +    NPBool boolVal = false;
  1.1450 +    *aError = mozilla::plugins::parent::_getvalue(nullptr, aVariable, &boolVal);
  1.1451 +    *aBoolVal = boolVal ? true : false;
  1.1452 +    return true;
  1.1453 +}
  1.1454 +
  1.1455 +#if defined(MOZ_WIDGET_QT)
  1.1456 +static const int kMaxtimeToProcessEvents = 30;
  1.1457 +bool
  1.1458 +PluginModuleParent::AnswerProcessSomeEvents()
  1.1459 +{
  1.1460 +    PLUGIN_LOG_DEBUG(("Spinning mini nested loop ..."));
  1.1461 +    QCoreApplication::processEvents(QEventLoop::AllEvents, kMaxtimeToProcessEvents);
  1.1462 +
  1.1463 +    PLUGIN_LOG_DEBUG(("... quitting mini nested loop"));
  1.1464 +
  1.1465 +    return true;
  1.1466 +}
  1.1467 +
  1.1468 +#elif defined(XP_MACOSX)
  1.1469 +bool
  1.1470 +PluginModuleParent::AnswerProcessSomeEvents()
  1.1471 +{
  1.1472 +    mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop();
  1.1473 +    return true;
  1.1474 +}
  1.1475 +
  1.1476 +#elif !defined(MOZ_WIDGET_GTK)
  1.1477 +bool
  1.1478 +PluginModuleParent::AnswerProcessSomeEvents()
  1.1479 +{
  1.1480 +    NS_RUNTIMEABORT("unreached");
  1.1481 +    return false;
  1.1482 +}
  1.1483 +
  1.1484 +#else
  1.1485 +static const int kMaxChancesToProcessEvents = 20;
  1.1486 +
  1.1487 +bool
  1.1488 +PluginModuleParent::AnswerProcessSomeEvents()
  1.1489 +{
  1.1490 +    PLUGIN_LOG_DEBUG(("Spinning mini nested loop ..."));
  1.1491 +
  1.1492 +    int i = 0;
  1.1493 +    for (; i < kMaxChancesToProcessEvents; ++i)
  1.1494 +        if (!g_main_context_iteration(nullptr, FALSE))
  1.1495 +            break;
  1.1496 +
  1.1497 +    PLUGIN_LOG_DEBUG(("... quitting mini nested loop; processed %i tasks", i));
  1.1498 +
  1.1499 +    return true;
  1.1500 +}
  1.1501 +#endif
  1.1502 +
  1.1503 +bool
  1.1504 +PluginModuleParent::RecvProcessNativeEventsInInterruptCall()
  1.1505 +{
  1.1506 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1507 +#if defined(OS_WIN)
  1.1508 +    ProcessNativeEventsInInterruptCall();
  1.1509 +    return true;
  1.1510 +#else
  1.1511 +    NS_NOTREACHED(
  1.1512 +        "PluginModuleParent::RecvProcessNativeEventsInInterruptCall not implemented!");
  1.1513 +    return false;
  1.1514 +#endif
  1.1515 +}
  1.1516 +
  1.1517 +void
  1.1518 +PluginModuleParent::ProcessRemoteNativeEventsInInterruptCall()
  1.1519 +{
  1.1520 +#if defined(OS_WIN)
  1.1521 +    unused << SendProcessNativeEventsInInterruptCall();
  1.1522 +    return;
  1.1523 +#endif
  1.1524 +    NS_NOTREACHED(
  1.1525 +        "PluginModuleParent::ProcessRemoteNativeEventsInInterruptCall not implemented!");
  1.1526 +}
  1.1527 +
  1.1528 +bool
  1.1529 +PluginModuleParent::RecvPluginShowWindow(const uint32_t& aWindowId, const bool& aModal,
  1.1530 +                                         const int32_t& aX, const int32_t& aY,
  1.1531 +                                         const size_t& aWidth, const size_t& aHeight)
  1.1532 +{
  1.1533 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1534 +#if defined(XP_MACOSX)
  1.1535 +    CGRect windowBound = ::CGRectMake(aX, aY, aWidth, aHeight);
  1.1536 +    mac_plugin_interposing::parent::OnPluginShowWindow(aWindowId, windowBound, aModal);
  1.1537 +    return true;
  1.1538 +#else
  1.1539 +    NS_NOTREACHED(
  1.1540 +        "PluginInstanceParent::RecvPluginShowWindow not implemented!");
  1.1541 +    return false;
  1.1542 +#endif
  1.1543 +}
  1.1544 +
  1.1545 +bool
  1.1546 +PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId)
  1.1547 +{
  1.1548 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1549 +#if defined(XP_MACOSX)
  1.1550 +    mac_plugin_interposing::parent::OnPluginHideWindow(aWindowId, OtherSidePID());
  1.1551 +    return true;
  1.1552 +#else
  1.1553 +    NS_NOTREACHED(
  1.1554 +        "PluginInstanceParent::RecvPluginHideWindow not implemented!");
  1.1555 +    return false;
  1.1556 +#endif
  1.1557 +}
  1.1558 +
  1.1559 +PCrashReporterParent*
  1.1560 +PluginModuleParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
  1.1561 +                                              uint32_t* processType)
  1.1562 +{
  1.1563 +#ifdef MOZ_CRASHREPORTER
  1.1564 +    return new CrashReporterParent();
  1.1565 +#else
  1.1566 +    return nullptr;
  1.1567 +#endif
  1.1568 +}
  1.1569 +
  1.1570 +bool
  1.1571 +PluginModuleParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
  1.1572 +{
  1.1573 +#ifdef MOZ_CRASHREPORTER
  1.1574 +#ifdef XP_WIN
  1.1575 +    mozilla::MutexAutoLock lock(mCrashReporterMutex);
  1.1576 +    if (actor == static_cast<PCrashReporterParent*>(mCrashReporter)) {
  1.1577 +        mCrashReporter = nullptr;
  1.1578 +    }
  1.1579 +#endif
  1.1580 +#endif
  1.1581 +    delete actor;
  1.1582 +    return true;
  1.1583 +}
  1.1584 +
  1.1585 +bool
  1.1586 +PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo)
  1.1587 +{
  1.1588 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1589 +#if defined(XP_MACOSX)
  1.1590 +    mac_plugin_interposing::parent::OnSetCursor(aCursorInfo);
  1.1591 +    return true;
  1.1592 +#else
  1.1593 +    NS_NOTREACHED(
  1.1594 +        "PluginInstanceParent::RecvSetCursor not implemented!");
  1.1595 +    return false;
  1.1596 +#endif
  1.1597 +}
  1.1598 +
  1.1599 +bool
  1.1600 +PluginModuleParent::RecvShowCursor(const bool& aShow)
  1.1601 +{
  1.1602 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1603 +#if defined(XP_MACOSX)
  1.1604 +    mac_plugin_interposing::parent::OnShowCursor(aShow);
  1.1605 +    return true;
  1.1606 +#else
  1.1607 +    NS_NOTREACHED(
  1.1608 +        "PluginInstanceParent::RecvShowCursor not implemented!");
  1.1609 +    return false;
  1.1610 +#endif
  1.1611 +}
  1.1612 +
  1.1613 +bool
  1.1614 +PluginModuleParent::RecvPushCursor(const NSCursorInfo& aCursorInfo)
  1.1615 +{
  1.1616 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1617 +#if defined(XP_MACOSX)
  1.1618 +    mac_plugin_interposing::parent::OnPushCursor(aCursorInfo);
  1.1619 +    return true;
  1.1620 +#else
  1.1621 +    NS_NOTREACHED(
  1.1622 +        "PluginInstanceParent::RecvPushCursor not implemented!");
  1.1623 +    return false;
  1.1624 +#endif
  1.1625 +}
  1.1626 +
  1.1627 +bool
  1.1628 +PluginModuleParent::RecvPopCursor()
  1.1629 +{
  1.1630 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1631 +#if defined(XP_MACOSX)
  1.1632 +    mac_plugin_interposing::parent::OnPopCursor();
  1.1633 +    return true;
  1.1634 +#else
  1.1635 +    NS_NOTREACHED(
  1.1636 +        "PluginInstanceParent::RecvPopCursor not implemented!");
  1.1637 +    return false;
  1.1638 +#endif
  1.1639 +}
  1.1640 +
  1.1641 +bool
  1.1642 +PluginModuleParent::RecvGetNativeCursorsSupported(bool* supported)
  1.1643 +{
  1.1644 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1645 +#if defined(XP_MACOSX)
  1.1646 +    *supported =
  1.1647 +      Preferences::GetBool("dom.ipc.plugins.nativeCursorSupport", false);
  1.1648 +    return true;
  1.1649 +#else
  1.1650 +    NS_NOTREACHED(
  1.1651 +        "PluginInstanceParent::RecvGetNativeCursorSupportLevel not implemented!");
  1.1652 +    return false;
  1.1653 +#endif
  1.1654 +}
  1.1655 +
  1.1656 +bool
  1.1657 +PluginModuleParent::RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
  1.1658 +                                         const nsCString& aMessage)
  1.1659 +{
  1.1660 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1661 +
  1.1662 +    NPObject* aNPObj = nullptr;
  1.1663 +    if (aActor) {
  1.1664 +        aNPObj = static_cast<PluginScriptableObjectParent*>(aActor)->GetObject(true);
  1.1665 +        if (!aNPObj) {
  1.1666 +            NS_ERROR("Failed to get object!");
  1.1667 +            return false;
  1.1668 +        }
  1.1669 +    }
  1.1670 +    mozilla::plugins::parent::_setexception(aNPObj, NullableStringGet(aMessage));
  1.1671 +    return true;
  1.1672 +}
  1.1673 +
  1.1674 +bool
  1.1675 +PluginModuleParent::RecvNPN_ReloadPlugins(const bool& aReloadPages)
  1.1676 +{
  1.1677 +    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
  1.1678 +
  1.1679 +    mozilla::plugins::parent::_reloadplugins(aReloadPages);
  1.1680 +    return true;
  1.1681 +}
  1.1682 +
  1.1683 +#ifdef MOZ_CRASHREPORTER_INJECTOR
  1.1684 +
  1.1685 +// We only add the crash reporter to subprocess which have the filename
  1.1686 +// FlashPlayerPlugin*
  1.1687 +#define FLASH_PROCESS_PREFIX "FLASHPLAYERPLUGIN"
  1.1688 +
  1.1689 +static DWORD
  1.1690 +GetFlashChildOfPID(DWORD pid, HANDLE snapshot)
  1.1691 +{
  1.1692 +    PROCESSENTRY32 entry = {
  1.1693 +        sizeof(entry)
  1.1694 +    };
  1.1695 +    for (BOOL ok = Process32First(snapshot, &entry);
  1.1696 +         ok;
  1.1697 +         ok = Process32Next(snapshot, &entry)) {
  1.1698 +        if (entry.th32ParentProcessID == pid) {
  1.1699 +            nsString name(entry.szExeFile);
  1.1700 +            ToUpperCase(name);
  1.1701 +            if (StringBeginsWith(name, NS_LITERAL_STRING(FLASH_PROCESS_PREFIX))) {
  1.1702 +                return entry.th32ProcessID;
  1.1703 +            }
  1.1704 +        }
  1.1705 +    }
  1.1706 +    return 0;
  1.1707 +}
  1.1708 +
  1.1709 +// We only look for child processes of the Flash plugin, NPSWF*
  1.1710 +#define FLASH_PLUGIN_PREFIX "NPSWF"
  1.1711 +
  1.1712 +void
  1.1713 +PluginModuleParent::InitializeInjector()
  1.1714 +{
  1.1715 +    if (!Preferences::GetBool("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false))
  1.1716 +        return;
  1.1717 +
  1.1718 +    nsCString path(Process()->GetPluginFilePath().c_str());
  1.1719 +    ToUpperCase(path);
  1.1720 +    int32_t lastSlash = path.RFindCharInSet("\\/");
  1.1721 +    if (kNotFound == lastSlash)
  1.1722 +        return;
  1.1723 +
  1.1724 +    if (!StringBeginsWith(Substring(path, lastSlash + 1),
  1.1725 +                          NS_LITERAL_CSTRING(FLASH_PLUGIN_PREFIX)))
  1.1726 +        return;
  1.1727 +
  1.1728 +    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1.1729 +    if (INVALID_HANDLE_VALUE == snapshot)
  1.1730 +        return;
  1.1731 +
  1.1732 +    DWORD pluginProcessPID = GetProcessId(Process()->GetChildProcessHandle());
  1.1733 +    mFlashProcess1 = GetFlashChildOfPID(pluginProcessPID, snapshot);
  1.1734 +    if (mFlashProcess1) {
  1.1735 +        InjectCrashReporterIntoProcess(mFlashProcess1, this);
  1.1736 +
  1.1737 +        mFlashProcess2 = GetFlashChildOfPID(mFlashProcess1, snapshot);
  1.1738 +        if (mFlashProcess2) {
  1.1739 +            InjectCrashReporterIntoProcess(mFlashProcess2, this);
  1.1740 +        }
  1.1741 +    }
  1.1742 +}
  1.1743 +
  1.1744 +void
  1.1745 +PluginModuleParent::OnCrash(DWORD processID)
  1.1746 +{
  1.1747 +    if (!mShutdown) {
  1.1748 +        GetIPCChannel()->CloseWithError();
  1.1749 +        KillProcess(OtherProcess(), 1, false);
  1.1750 +    }
  1.1751 +}
  1.1752 +
  1.1753 +#endif // MOZ_CRASHREPORTER_INJECTOR
  1.1754 +
  1.1755 +#ifdef MOZ_ENABLE_PROFILER_SPS
  1.1756 +class PluginProfilerObserver MOZ_FINAL : public nsIObserver,
  1.1757 +                                         public nsSupportsWeakReference
  1.1758 +{
  1.1759 +public:
  1.1760 +    NS_DECL_ISUPPORTS
  1.1761 +    NS_DECL_NSIOBSERVER
  1.1762 +
  1.1763 +    explicit PluginProfilerObserver(PluginModuleParent* pmp)
  1.1764 +      : mPmp(pmp)
  1.1765 +    {}
  1.1766 +
  1.1767 +private:
  1.1768 +    PluginModuleParent* mPmp;
  1.1769 +};
  1.1770 +
  1.1771 +NS_IMPL_ISUPPORTS(PluginProfilerObserver, nsIObserver, nsISupportsWeakReference)
  1.1772 +
  1.1773 +NS_IMETHODIMP
  1.1774 +PluginProfilerObserver::Observe(nsISupports *aSubject,
  1.1775 +                                const char *aTopic,
  1.1776 +                                const char16_t *aData)
  1.1777 +{
  1.1778 +    nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
  1.1779 +    if (pse) {
  1.1780 +      nsCString result;
  1.1781 +      bool success = mPmp->CallGeckoGetProfile(&result);
  1.1782 +      if (success && !result.IsEmpty()) {
  1.1783 +          pse->AddSubProfile(result.get());
  1.1784 +      }
  1.1785 +    }
  1.1786 +    return NS_OK;
  1.1787 +}
  1.1788 +
  1.1789 +void
  1.1790 +PluginModuleParent::InitPluginProfiling()
  1.1791 +{
  1.1792 +    nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
  1.1793 +    if (observerService) {
  1.1794 +        mProfilerObserver = new PluginProfilerObserver(this);
  1.1795 +        observerService->AddObserver(mProfilerObserver, "profiler-subprocess", false);
  1.1796 +    }
  1.1797 +}
  1.1798 +
  1.1799 +void
  1.1800 +PluginModuleParent::ShutdownPluginProfiling()
  1.1801 +{
  1.1802 +    nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
  1.1803 +    if (observerService) {
  1.1804 +        observerService->RemoveObserver(mProfilerObserver, "profiler-subprocess");
  1.1805 +    }
  1.1806 +}
  1.1807 +#endif

mercurial