Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/plugins/ipc/PluginProcessParent.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * vim: sw=4 ts=4 et :
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/plugins/PluginProcessParent.h"
8
9
#include "base/string_util.h"
10
#include "base/process_util.h"
11
12
#include "mozilla/ipc/BrowserProcessSubThread.h"
13
#include "mozilla/plugins/PluginMessageUtils.h"
14
#include "mozilla/Telemetry.h"
15
#include "nsThreadUtils.h"
16
17
using std::vector;
18
using std::string;
19
20
using mozilla::ipc::BrowserProcessSubThread;
21
using mozilla::ipc::GeckoChildProcessHost;
22
using mozilla::plugins::LaunchCompleteTask;
23
using mozilla::plugins::PluginProcessParent;
24
25
#ifdef XP_WIN
26
PluginProcessParent::PidSet* PluginProcessParent::sPidSet = nullptr;
27
#endif
28
29
PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) :
30
      GeckoChildProcessHost(GeckoProcessType_Plugin)
31
    , mPluginFilePath(aPluginFilePath)
32
    , mTaskFactory(this)
33
    , mMainMsgLoop(MessageLoop::current())
34
#ifdef XP_WIN
35
    , mChildPid(0)
36
#endif
37
0
{
38
0
}
39
40
PluginProcessParent::~PluginProcessParent()
41
0
{
42
#ifdef XP_WIN
43
    if (sPidSet && mChildPid) {
44
        sPidSet->RemoveEntry(mChildPid);
45
        if (sPidSet->IsEmpty()) {
46
            delete sPidSet;
47
            sPidSet = nullptr;
48
        }
49
    }
50
#endif
51
}
52
53
bool
54
PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
55
                            int32_t aSandboxLevel,
56
                            bool aIsSandboxLoggingEnabled)
57
0
{
58
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
59
    // At present, the Mac Flash plugin sandbox does not support different
60
    // levels and is enabled via a boolean pref or environment variable.
61
    // On Mac, when |aSandboxLevel| is positive, we enable the sandbox.
62
#if defined(XP_WIN)
63
    mSandboxLevel = aSandboxLevel;
64
65
    // The sandbox process sometimes needs read access to the plugin file.
66
    if (aSandboxLevel >= 3) {
67
        std::wstring pluginFile(NS_ConvertUTF8toUTF16(mPluginFilePath.c_str()).get());
68
        mAllowedFilesRead.push_back(pluginFile);
69
    }
70
#endif // XP_WIN
71
#else
72
0
    if (aSandboxLevel != 0) {
73
0
        MOZ_ASSERT(false,
74
0
                   "Can't enable an NPAPI process sandbox for platform/build.");
75
0
    }
76
0
#endif
77
0
78
0
    mLaunchCompleteTask = std::move(aLaunchCompleteTask);
79
0
80
0
    vector<string> args;
81
0
    args.push_back(MungePluginDsoPath(mPluginFilePath));
82
0
83
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
84
    if (aSandboxLevel > 0) {
85
        args.push_back("-flashSandboxLevel");
86
        args.push_back(std::to_string(aSandboxLevel));
87
        if (aIsSandboxLoggingEnabled) {
88
            args.push_back("-flashSandboxLogging");
89
        }
90
    }
91
#endif
92
93
0
    bool result = AsyncLaunch(args);
94
0
    if (!result) {
95
0
        mLaunchCompleteTask = nullptr;
96
0
    }
97
0
    return result;
98
0
}
99
100
void
101
PluginProcessParent::Delete()
102
0
{
103
0
  MessageLoop* currentLoop = MessageLoop::current();
104
0
  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
105
0
106
0
  if (currentLoop == ioLoop) {
107
0
      delete this;
108
0
      return;
109
0
  }
110
0
111
0
  ioLoop->PostTask(
112
0
    NewNonOwningRunnableMethod("plugins::PluginProcessParent::Delete",
113
0
                               this,
114
0
                               &PluginProcessParent::Delete));
115
0
}
116
117
/**
118
 * This function exists so that we may provide an additional level of
119
 * indirection between the task being posted to main event loop (a
120
 * RunnableMethod) and the launch complete task itself. This is needed
121
 * for cases when both WaitUntilConnected or OnChannel* race to invoke the
122
 * task.
123
 */
124
void
125
PluginProcessParent::RunLaunchCompleteTask()
126
0
{
127
0
    if (mLaunchCompleteTask) {
128
0
        mLaunchCompleteTask->Run();
129
0
        mLaunchCompleteTask = nullptr;
130
0
    }
131
0
}
132
133
bool
134
PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
135
0
{
136
0
    bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
137
0
    if (mLaunchCompleteTask) {
138
0
        if (result) {
139
0
            mLaunchCompleteTask->SetLaunchSucceeded();
140
0
        }
141
0
        RunLaunchCompleteTask();
142
0
    }
143
0
    return result;
144
0
}
145
146
void
147
PluginProcessParent::OnChannelConnected(int32_t peer_pid)
148
0
{
149
#ifdef XP_WIN
150
    mChildPid = static_cast<uint32_t>(peer_pid);
151
    if (!sPidSet) {
152
        sPidSet = new PluginProcessParent::PidSet();
153
    }
154
    sPidSet->PutEntry(mChildPid);
155
#endif
156
157
0
    GeckoChildProcessHost::OnChannelConnected(peer_pid);
158
0
}
159
160
void
161
PluginProcessParent::OnChannelError()
162
0
{
163
0
    GeckoChildProcessHost::OnChannelError();
164
0
}
165
166
bool
167
PluginProcessParent::IsConnected()
168
0
{
169
0
    mozilla::MonitorAutoLock lock(mMonitor);
170
0
    return mProcessState == PROCESS_CONNECTED;
171
0
}
172
173
bool
174
0
PluginProcessParent::IsPluginProcessId(base::ProcessId procId) {
175
#ifdef XP_WIN
176
    MOZ_ASSERT(XRE_IsParentProcess());
177
    return sPidSet && sPidSet->Contains(static_cast<uint32_t>(procId));
178
#else
179
0
    NS_ERROR("IsPluginProcessId not available on this platform.");
180
0
    return false;
181
0
#endif
182
0
}