DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (6863f516ba38)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: sw=2 ts=4 et :
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/ipc/IOThreadChild.h"
#include "mozilla/plugins/PluginProcessChild.h"

#include "prlink.h"

#include "base/command_line.h"
#include "base/string_util.h"
#include "nsDebugImpl.h"
#include "nsThreadManager.h"
#include "ClearOnShutdown.h"

#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
#  include "mozilla/SandboxSettings.h"
#endif

#if defined(XP_MACOSX)
#  include "nsCocoaFeatures.h"
// An undocumented CoreGraphics framework method, present in the same form
// since at least OS X 10.5.
extern "C" CGError CGSSetDebugOptions(int options);
#endif

#ifdef XP_WIN
#  if defined(MOZ_SANDBOX)
#    include "mozilla/sandboxTarget.h"
#    include "ProcessUtils.h"
#    include "nsDirectoryService.h"
#  endif
#endif

using mozilla::ipc::IOThreadChild;

#ifdef OS_WIN
#  include <algorithm>
#endif

namespace mozilla {
namespace plugins {

#if defined(XP_WIN) && defined(MOZ_SANDBOX)
static void SetSandboxTempPath(const std::wstring& aFullTmpPath) {
  // Save the TMP environment variable so that is is picked up by GetTempPath().
  // Note that we specifically write to the TMP variable, as that is the first
  // variable that is checked by GetTempPath() to determine its output.
  Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", aFullTmpPath.c_str()));

  // We also set TEMP in case there is naughty third-party code that is
  // referencing the environment variable directly.
  Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", aFullTmpPath.c_str()));
}
#endif

bool PluginProcessChild::Init(int aArgc, char* aArgv[]) {
  nsDebugImpl::SetMultiprocessMode("NPAPI");

#if defined(XP_MACOSX)
  // Remove the trigger for "dyld interposing" that we added in
  // GeckoChildProcessHost::PerformAsyncLaunch(), in the host
  // process just before we were launched.  Dyld interposing will still
  // happen in our process (the plugin child process).  But we don't want
  // it to happen in any processes that the plugin might launch from our
  // process.
  nsCString interpose(PR_GetEnv("DYLD_INSERT_LIBRARIES"));
  if (!interpose.IsEmpty()) {
    // If we added the path to libplugin_child_interpose.dylib to an
    // existing DYLD_INSERT_LIBRARIES, we appended it to the end, after a
    // ":" path seperator.
    int32_t lastSeparatorPos = interpose.RFind(":");
    int32_t lastTriggerPos = interpose.RFind("libplugin_child_interpose.dylib");
    bool needsReset = false;
    if (lastTriggerPos != -1) {
      if (lastSeparatorPos == -1) {
        interpose.Truncate();
        needsReset = true;
      } else if (lastTriggerPos > lastSeparatorPos) {
        interpose.SetLength(lastSeparatorPos);
        needsReset = true;
      }
    }
    if (needsReset) {
      nsCString setInterpose("DYLD_INSERT_LIBRARIES=");
      if (!interpose.IsEmpty()) {
        setInterpose.Append(interpose);
      }
      // Values passed to PR_SetEnv() must be seperately allocated.
      char* setInterposePtr = strdup(setInterpose.get());
      PR_SetEnv(setInterposePtr);
    }
  }
#endif

  // Certain plugins, such as flash, steal the unhandled exception filter
  // thus we never get crash reports when they fault. This call fixes it.
  message_loop()->set_exception_restoration(true);

  std::string pluginFilename;

#if defined(OS_POSIX)
  // NB: need to be very careful in ensuring that the first arg
  // (after the binary name) here is indeed the plugin module path.
  // Keep in sync with dom/plugins/PluginModuleParent.
  std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
  MOZ_ASSERT(values.size() >= 2, "not enough args");

  pluginFilename = UnmungePluginDsoPath(values[1]);

#  if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
  int level;
  if (values.size() >= 4 && values[2] == "-flashSandboxLevel" &&
      (level = std::stoi(values[3], nullptr)) > 0) {
    level = ClampFlashSandboxLevel(level);
    MOZ_ASSERT(level > 0);

    bool enableLogging = false;
    if (values.size() >= 5 && values[4] == "-flashSandboxLogging") {
      enableLogging = true;
    }

    mPlugin.EnableFlashSandbox(level, enableLogging);
  }
#  endif

#elif defined(OS_WIN)
  std::vector<std::wstring> values =
      CommandLine::ForCurrentProcess()->GetLooseValues();
  MOZ_ASSERT(values.size() >= 1, "not enough loose args");

  // parameters are:
  // values[0] is path to plugin DLL
  // values[1] is path to folder that should be used for temp files
  // values[2] is path to the Flash Player roaming folder
  //   (this is always that Flash folder, regardless of what plugin is being
  //   run)
  pluginFilename = WideToUTF8(values[0]);

  // We don't initialize XPCOM but we need the thread manager and the
  // logging framework for the FunctionBroker.
  NS_SetMainThread();
  mozilla::TimeStamp::Startup();
  NS_LogInit();
  mozilla::LogModule::Init(aArgc, aArgv);
  nsThreadManager::get().Init();

#  if defined(MOZ_SANDBOX)
  MOZ_ASSERT(values.size() >= 3,
             "not enough loose args for sandboxed plugin process");

  // The sandbox closes off the default location temp file location so we set
  // a new one here (regardless of whether or not we are sandboxing).
  SetSandboxTempPath(values[1]);
  PluginModuleChild::SetFlashRoamingPath(values[2]);

  // This is probably the earliest we would want to start the sandbox.
  // As we attempt to tighten the sandbox, we may need to consider moving this
  // to later in the plugin initialization.
  mozilla::SandboxTarget::Instance()->StartSandbox();
#  endif
#else
#  error Sorry
#endif

  bool retval = mPlugin.InitForChrome(pluginFilename, ParentPid(),
                                      IOThreadChild::message_loop(),
                                      IOThreadChild::channel());
#if defined(XP_MACOSX)
  if (nsCocoaFeatures::OnYosemiteOrLater()) {
    // Explicitly turn off CGEvent logging.  This works around bug 1092855.
    // If there are already CGEvents in the log, turning off logging also
    // causes those events to be written to disk.  But at this point no
    // CGEvents have yet been processed.  CGEvents are events (usually
    // input events) pulled from the WindowServer.  An option of 0x80000008
    // turns on CGEvent logging.
    CGSSetDebugOptions(0x80000007);
  }
#endif
  return retval;
}

void PluginProcessChild::CleanUp() {
#if defined(OS_WIN)
  MOZ_ASSERT(NS_IsMainThread());

  // Shutdown components we started in Init.  Note that KillClearOnShutdown
  // is an event that is regularly part of XPCOM shutdown.  We do not
  // call XPCOM's shutdown but we need this event to be sent to avoid
  // leaking objects labeled as ClearOnShutdown.
  nsThreadManager::get().Shutdown();
  NS_LogTerm();
#endif

  mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownFinal);
}

}  // namespace plugins
}  // namespace mozilla