Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/ipc/RemoteContentController.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/layers/RemoteContentController.h"
8
9
#include "base/message_loop.h"
10
#include "base/task.h"
11
#include "MainThreadUtils.h"
12
#include "mozilla/dom/ContentParent.h"
13
#include "mozilla/dom/TabParent.h"
14
#include "mozilla/layers/APZCCallbackHelper.h"
15
#include "mozilla/layers/APZCTreeManagerParent.h"  // for APZCTreeManagerParent
16
#include "mozilla/layers/APZThreadUtils.h"
17
#include "mozilla/layout/RenderFrameParent.h"
18
#include "mozilla/gfx/GPUProcessManager.h"
19
#include "mozilla/Unused.h"
20
#include "Units.h"
21
22
namespace mozilla {
23
namespace layers {
24
25
using namespace mozilla::gfx;
26
27
RemoteContentController::RemoteContentController()
28
  : mCompositorThread(MessageLoop::current())
29
  , mCanSend(true)
30
0
{
31
0
}
32
33
RemoteContentController::~RemoteContentController()
34
0
{
35
0
}
36
37
void
38
RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
39
0
{
40
0
  MOZ_ASSERT(IsRepaintThread());
41
0
42
0
  if (mCanSend) {
43
0
    Unused << SendRequestContentRepaint(aFrameMetrics);
44
0
  }
45
0
}
46
47
void
48
RemoteContentController::HandleTapOnMainThread(TapType aTapType,
49
                                               LayoutDevicePoint aPoint,
50
                                               Modifiers aModifiers,
51
                                               ScrollableLayerGuid aGuid,
52
                                               uint64_t aInputBlockId)
53
0
{
54
0
  MOZ_ASSERT(NS_IsMainThread());
55
0
56
0
  dom::TabParent* tab = dom::TabParent::GetTabParentFromLayersId(aGuid.mLayersId);
57
0
  if (tab) {
58
0
    tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
59
0
  }
60
0
}
61
62
void
63
RemoteContentController::HandleTapOnCompositorThread(TapType aTapType,
64
                                                     LayoutDevicePoint aPoint,
65
                                                     Modifiers aModifiers,
66
                                                     ScrollableLayerGuid aGuid,
67
                                                     uint64_t aInputBlockId)
68
0
{
69
0
  MOZ_ASSERT(XRE_IsGPUProcess());
70
0
  MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
71
0
72
0
  // The raw pointer to APZCTreeManagerParent is ok here because we are on the
73
0
  // compositor thread.
74
0
  APZCTreeManagerParent* apzctmp =
75
0
      CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
76
0
  if (apzctmp) {
77
0
    Unused << apzctmp->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
78
0
  }
79
0
}
80
81
void
82
RemoteContentController::HandleTap(TapType aTapType,
83
                                   const LayoutDevicePoint& aPoint,
84
                                   Modifiers aModifiers,
85
                                   const ScrollableLayerGuid& aGuid,
86
                                   uint64_t aInputBlockId)
87
0
{
88
0
  APZThreadUtils::AssertOnControllerThread();
89
0
90
0
  if (XRE_GetProcessType() == GeckoProcessType_GPU) {
91
0
    if (MessageLoop::current() == mCompositorThread) {
92
0
      HandleTapOnCompositorThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
93
0
    } else {
94
0
      // We have to send messages from the compositor thread
95
0
      mCompositorThread->PostTask(NewRunnableMethod<TapType,
96
0
                                                    LayoutDevicePoint,
97
0
                                                    Modifiers,
98
0
                                                    ScrollableLayerGuid,
99
0
                                                    uint64_t>(
100
0
        "layers::RemoteContentController::HandleTapOnCompositorThread",
101
0
        this,
102
0
        &RemoteContentController::HandleTapOnCompositorThread,
103
0
        aTapType,
104
0
        aPoint,
105
0
        aModifiers,
106
0
        aGuid,
107
0
        aInputBlockId));
108
0
    }
109
0
    return;
110
0
  }
111
0
112
0
  MOZ_ASSERT(XRE_IsParentProcess());
113
0
114
0
  if (NS_IsMainThread()) {
115
0
    HandleTapOnMainThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
116
0
  } else {
117
0
    // We don't want to get the TabParent or call TabParent::SendHandleTap() from a non-main thread (this might happen
118
0
    // on Android, where this is called from the Java UI thread)
119
0
    NS_DispatchToMainThread(NewRunnableMethod<TapType,
120
0
                                              LayoutDevicePoint,
121
0
                                              Modifiers,
122
0
                                              ScrollableLayerGuid,
123
0
                                              uint64_t>(
124
0
      "layers::RemoteContentController::HandleTapOnMainThread",
125
0
      this,
126
0
      &RemoteContentController::HandleTapOnMainThread,
127
0
      aTapType,
128
0
      aPoint,
129
0
      aModifiers,
130
0
      aGuid,
131
0
      aInputBlockId));
132
0
  }
133
0
}
134
135
void
136
RemoteContentController::NotifyPinchGestureOnCompositorThread(
137
    PinchGestureInput::PinchGestureType aType,
138
    const ScrollableLayerGuid& aGuid,
139
    LayoutDeviceCoord aSpanChange,
140
    Modifiers aModifiers)
141
0
{
142
0
  MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
143
0
144
0
  // The raw pointer to APZCTreeManagerParent is ok here because we are on the
145
0
  // compositor thread.
146
0
  APZCTreeManagerParent* apzctmp =
147
0
      CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
148
0
  if (apzctmp) {
149
0
    Unused << apzctmp->SendNotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
150
0
  }
151
0
}
152
153
void
154
RemoteContentController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
155
                                            const ScrollableLayerGuid& aGuid,
156
                                            LayoutDeviceCoord aSpanChange,
157
                                            Modifiers aModifiers)
158
0
{
159
0
  APZThreadUtils::AssertOnControllerThread();
160
0
161
0
  // For now we only ever want to handle this NotifyPinchGesture message in
162
0
  // the parent process, even if the APZ is sending it to a content process.
163
0
164
0
  // If we're in the GPU process, try to find a handle to the parent process
165
0
  // and send it there.
166
0
  if (XRE_IsGPUProcess()) {
167
0
    if (MessageLoop::current() == mCompositorThread) {
168
0
      NotifyPinchGestureOnCompositorThread(aType, aGuid, aSpanChange, aModifiers);
169
0
    } else {
170
0
      mCompositorThread->PostTask(NewRunnableMethod<PinchGestureInput::PinchGestureType,
171
0
                                                    ScrollableLayerGuid,
172
0
                                                    LayoutDeviceCoord,
173
0
                                                    Modifiers>(
174
0
        "layers::RemoteContentController::NotifyPinchGestureOnCompositorThread",
175
0
        this,
176
0
        &RemoteContentController::NotifyPinchGestureOnCompositorThread,
177
0
        aType,
178
0
        aGuid,
179
0
        aSpanChange,
180
0
        aModifiers));
181
0
    }
182
0
    return;
183
0
  }
184
0
185
0
  // If we're in the parent process, handle it directly. We don't have a handle
186
0
  // to the widget though, so we fish out the ChromeProcessController and
187
0
  // delegate to that instead.
188
0
  if (XRE_IsParentProcess()) {
189
0
    MOZ_ASSERT(NS_IsMainThread());
190
0
    RefPtr<GeckoContentController> rootController =
191
0
        CompositorBridgeParent::GetGeckoContentControllerForRoot(aGuid.mLayersId);
192
0
    if (rootController) {
193
0
      rootController->NotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
194
0
    }
195
0
  }
196
0
}
197
198
void
199
RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
200
0
{
201
0
  (MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
202
0
    PostDelayedTask(std::move(aTask), aDelayMs);
203
0
}
204
205
bool
206
RemoteContentController::IsRepaintThread()
207
0
{
208
0
  return MessageLoop::current() == mCompositorThread;
209
0
}
210
211
void
212
RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
213
0
{
214
0
  mCompositorThread->PostTask(std::move(aTask));
215
0
}
216
217
void
218
RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
219
                                              APZStateChange aChange,
220
                                              int aArg)
221
0
{
222
0
  if (MessageLoop::current() != mCompositorThread) {
223
0
    // We have to send messages from the compositor thread
224
0
    mCompositorThread->PostTask(
225
0
      NewRunnableMethod<ScrollableLayerGuid, APZStateChange, int>(
226
0
        "layers::RemoteContentController::NotifyAPZStateChange",
227
0
        this,
228
0
        &RemoteContentController::NotifyAPZStateChange,
229
0
        aGuid,
230
0
        aChange,
231
0
        aArg));
232
0
    return;
233
0
  }
234
0
235
0
  if (mCanSend) {
236
0
    Unused << SendNotifyAPZStateChange(aGuid, aChange, aArg);
237
0
  }
238
0
}
239
240
void
241
RemoteContentController::UpdateOverscrollVelocity(float aX, float aY, bool aIsRootContent)
242
0
{
243
0
  if (MessageLoop::current() != mCompositorThread) {
244
0
    mCompositorThread->PostTask(NewRunnableMethod<float, float, bool>(
245
0
      "layers::RemoteContentController::UpdateOverscrollVelocity",
246
0
      this,
247
0
      &RemoteContentController::UpdateOverscrollVelocity,
248
0
      aX,
249
0
      aY,
250
0
      aIsRootContent));
251
0
    return;
252
0
  }
253
0
  if (mCanSend) {
254
0
    Unused << SendUpdateOverscrollVelocity(aX, aY, aIsRootContent);
255
0
  }
256
0
}
257
258
void
259
RemoteContentController::UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent)
260
0
{
261
0
  if (MessageLoop::current() != mCompositorThread) {
262
0
    mCompositorThread->PostTask(NewRunnableMethod<float, float, bool>(
263
0
      "layers::RemoteContentController::UpdateOverscrollOffset",
264
0
      this,
265
0
      &RemoteContentController::UpdateOverscrollOffset,
266
0
      aX,
267
0
      aY,
268
0
      aIsRootContent));
269
0
    return;
270
0
  }
271
0
  if (mCanSend) {
272
0
    Unused << SendUpdateOverscrollOffset(aX, aY, aIsRootContent);
273
0
  }
274
0
}
275
276
void
277
RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
278
                                                   const nsString& aEvent)
279
0
{
280
0
  if (MessageLoop::current() != mCompositorThread) {
281
0
    // We have to send messages from the compositor thread
282
0
    mCompositorThread->PostTask(
283
0
      NewRunnableMethod<FrameMetrics::ViewID, nsString>(
284
0
        "layers::RemoteContentController::NotifyMozMouseScrollEvent",
285
0
        this,
286
0
        &RemoteContentController::NotifyMozMouseScrollEvent,
287
0
        aScrollId,
288
0
        aEvent));
289
0
    return;
290
0
  }
291
0
292
0
  if (mCanSend) {
293
0
    Unused << SendNotifyMozMouseScrollEvent(aScrollId, aEvent);
294
0
  }
295
0
}
296
297
void
298
RemoteContentController::NotifyFlushComplete()
299
0
{
300
0
  MOZ_ASSERT(IsRepaintThread());
301
0
302
0
  if (mCanSend) {
303
0
    Unused << SendNotifyFlushComplete();
304
0
  }
305
0
}
306
307
void
308
RemoteContentController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
309
0
{
310
0
  if (MessageLoop::current() != mCompositorThread) {
311
0
    // We have to send messages from the compositor thread
312
0
    mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
313
0
      "layers::RemoteContentController::NotifyAsyncScrollbarDragRejected",
314
0
      this,
315
0
      &RemoteContentController::NotifyAsyncScrollbarDragRejected,
316
0
      aScrollId));
317
0
    return;
318
0
  }
319
0
320
0
  if (mCanSend) {
321
0
    Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
322
0
  }
323
0
}
324
325
void
326
RemoteContentController::NotifyAsyncAutoscrollRejected(const FrameMetrics::ViewID& aScrollId)
327
0
{
328
0
  if (MessageLoop::current() != mCompositorThread) {
329
0
    // We have to send messages from the compositor thread
330
0
    mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
331
0
      "layers::RemoteContentController::NotifyAsyncAutoscrollRejected",
332
0
      this,
333
0
      &RemoteContentController::NotifyAsyncAutoscrollRejected,
334
0
      aScrollId));
335
0
    return;
336
0
  }
337
0
338
0
  if (mCanSend) {
339
0
    Unused << SendNotifyAsyncAutoscrollRejected(aScrollId);
340
0
  }
341
0
}
342
343
void
344
RemoteContentController::CancelAutoscroll(const ScrollableLayerGuid& aGuid)
345
0
{
346
0
  if (XRE_GetProcessType() == GeckoProcessType_GPU) {
347
0
    CancelAutoscrollCrossProcess(aGuid);
348
0
  } else {
349
0
    CancelAutoscrollInProcess(aGuid);
350
0
  }
351
0
}
352
353
void
354
RemoteContentController::CancelAutoscrollInProcess(const ScrollableLayerGuid& aGuid)
355
0
{
356
0
  MOZ_ASSERT(XRE_IsParentProcess());
357
0
358
0
  if (!NS_IsMainThread()) {
359
0
    NS_DispatchToMainThread(NewRunnableMethod<ScrollableLayerGuid>(
360
0
        "layers::RemoteContentController::CancelAutoscrollInProcess",
361
0
        this,
362
0
        &RemoteContentController::CancelAutoscrollInProcess,
363
0
        aGuid));
364
0
    return;
365
0
  }
366
0
367
0
  APZCCallbackHelper::CancelAutoscroll(aGuid.mScrollId);
368
0
}
369
370
void
371
RemoteContentController::CancelAutoscrollCrossProcess(const ScrollableLayerGuid& aGuid)
372
0
{
373
0
  MOZ_ASSERT(XRE_IsGPUProcess());
374
0
375
0
  if (MessageLoop::current() != mCompositorThread) {
376
0
    mCompositorThread->PostTask(NewRunnableMethod<ScrollableLayerGuid>(
377
0
        "layers::RemoteContentController::CancelAutoscrollCrossProcess",
378
0
        this,
379
0
        &RemoteContentController::CancelAutoscrollCrossProcess,
380
0
        aGuid));
381
0
    return;
382
0
  }
383
0
384
0
  // The raw pointer to APZCTreeManagerParent is ok here because we are on the
385
0
  // compositor thread.
386
0
  if (APZCTreeManagerParent* parent =
387
0
      CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId)) {
388
0
    Unused << parent->SendCancelAutoscroll(aGuid.mScrollId);
389
0
  }
390
0
}
391
392
void
393
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
394
0
{
395
0
  // This controller could possibly be kept alive longer after this
396
0
  // by a RefPtr, but it is no longer valid to send messages.
397
0
  mCanSend = false;
398
0
}
399
400
void
401
RemoteContentController::Destroy()
402
0
{
403
0
  if (mCanSend) {
404
0
    mCanSend = false;
405
0
    Unused << SendDestroy();
406
0
  }
407
0
}
408
409
} // namespace layers
410
} // namespace mozilla