RemoteContentController.cpp (21225B)
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 "CompositorThread.h" 10 #include "MainThreadUtils.h" 11 #include "ipc/RemoteContentController.h" 12 #include "mozilla/dom/BrowserParent.h" 13 #include "mozilla/layers/APZCCallbackHelper.h" 14 #include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent 15 #include "mozilla/layers/APZThreadUtils.h" 16 #include "mozilla/layers/DoubleTapToZoom.h" 17 #include "mozilla/layers/CompositorBridgeParent.h" 18 #include "mozilla/layers/MatrixMessage.h" 19 #include "mozilla/gfx/GPUProcessManager.h" 20 #include "Units.h" 21 #ifdef MOZ_WIDGET_ANDROID 22 # include "mozilla/jni/Utils.h" 23 #endif 24 25 static mozilla::LazyLogModule sApzRemoteLog("apz.cc.remote"); 26 27 namespace mozilla { 28 namespace layers { 29 30 using namespace mozilla::gfx; 31 32 RemoteContentController::RemoteContentController() 33 : mCompositorThread(NS_GetCurrentThread()), mCanSend(true) { 34 MOZ_ASSERT(CompositorThread()->IsOnCurrentThread()); 35 } 36 37 RemoteContentController::~RemoteContentController() = default; 38 39 void RemoteContentController::NotifyLayerTransforms( 40 nsTArray<MatrixMessage>&& aTransforms) { 41 if (!mCompositorThread->IsOnCurrentThread()) { 42 // We have to send messages from the compositor thread 43 mCompositorThread->Dispatch( 44 NewRunnableMethod<StoreCopyPassByRRef<nsTArray<MatrixMessage>>>( 45 "layers::RemoteContentController::NotifyLayerTransforms", this, 46 &RemoteContentController::NotifyLayerTransforms, 47 std::move(aTransforms))); 48 return; 49 } 50 51 if (mCanSend) { 52 (void)SendLayerTransforms(aTransforms); 53 } 54 } 55 56 void RemoteContentController::RequestContentRepaint( 57 const RepaintRequest& aRequest) { 58 MOZ_ASSERT(IsRepaintThread()); 59 60 if (mCanSend) { 61 (void)SendRequestContentRepaint(aRequest); 62 } 63 } 64 65 void RemoteContentController::HandleTapOnParentProcessMainThread( 66 TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, 67 ScrollableLayerGuid aGuid, uint64_t aInputBlockId, 68 const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { 69 MOZ_LOG(sApzRemoteLog, LogLevel::Debug, 70 ("HandleTapOnMainThread(%d)", (int)aTapType)); 71 MOZ_ASSERT(NS_IsMainThread()); 72 73 dom::BrowserParent* tab = 74 dom::BrowserParent::GetBrowserParentFromLayersId(aGuid.mLayersId); 75 if (tab) { 76 tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId, 77 aDoubleTapToZoomMetrics); 78 } 79 } 80 81 void RemoteContentController::HandleTapOnGPUProcessMainThread( 82 TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, 83 ScrollableLayerGuid aGuid, uint64_t aInputBlockId, 84 const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { 85 MOZ_ASSERT(XRE_IsGPUProcess()); 86 MOZ_ASSERT(NS_IsMainThread()); 87 88 // Send a message to the controller thread to handle the single-tap gesture. 89 APZInputBridgeParent* apzib = 90 CompositorBridgeParent::GetApzInputBridgeParentForRoot(aGuid.mLayersId); 91 if (apzib) { 92 (void)apzib->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, 93 aInputBlockId, aDoubleTapToZoomMetrics); 94 } 95 } 96 97 void RemoteContentController::HandleTap( 98 TapType aTapType, const LayoutDevicePoint& aPoint, Modifiers aModifiers, 99 const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, 100 const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { 101 MOZ_LOG(sApzRemoteLog, LogLevel::Debug, ("HandleTap(%d)", (int)aTapType)); 102 APZThreadUtils::AssertOnControllerThread(); 103 104 if (XRE_GetProcessType() == GeckoProcessType_GPU) { 105 if (NS_IsMainThread()) { 106 HandleTapOnGPUProcessMainThread(aTapType, aPoint, aModifiers, aGuid, 107 aInputBlockId, aDoubleTapToZoomMetrics); 108 } else { 109 NS_DispatchToMainThread(NewRunnableMethod<TapType, LayoutDevicePoint, 110 Modifiers, ScrollableLayerGuid, 111 uint64_t, 112 Maybe<DoubleTapToZoomMetrics>>( 113 "layers::RemoteContentController::HandleTapOnGPUProcessMainThread", 114 this, &RemoteContentController::HandleTapOnGPUProcessMainThread, 115 aTapType, aPoint, aModifiers, aGuid, aInputBlockId, 116 aDoubleTapToZoomMetrics)); 117 } 118 return; 119 } 120 121 MOZ_ASSERT(XRE_IsParentProcess()); 122 123 if (NS_IsMainThread()) { 124 HandleTapOnParentProcessMainThread(aTapType, aPoint, aModifiers, aGuid, 125 aInputBlockId, aDoubleTapToZoomMetrics); 126 } else { 127 // We must be on Android, running on the Java UI thread 128 #ifndef MOZ_WIDGET_ANDROID 129 MOZ_ASSERT(false); 130 #else 131 // We don't want to get the BrowserParent or call 132 // BrowserParent::SendHandleTap() from a non-main thread, so we need to 133 // redispatch to the main thread. However, we should use the same 134 // mechanism that the Android widget uses when dispatching input events 135 // to Gecko, which is nsAppShell::PostEvent. Note in particular that 136 // using NS_DispatchToMainThread would post to a different message loop, 137 // and introduces the possibility of this tap event getting processed 138 // out of order with respect to the touch events that synthesized it. 139 mozilla::jni::DispatchToGeckoPriorityQueue(NewRunnableMethod< 140 TapType, LayoutDevicePoint, 141 Modifiers, ScrollableLayerGuid, 142 uint64_t, 143 Maybe<DoubleTapToZoomMetrics>>( 144 "layers::RemoteContentController::HandleTapOnParentProcessMainThread", 145 this, &RemoteContentController::HandleTapOnParentProcessMainThread, 146 aTapType, aPoint, aModifiers, aGuid, aInputBlockId, 147 aDoubleTapToZoomMetrics)); 148 #endif 149 } 150 } 151 152 void RemoteContentController::NotifyPinchGestureOnCompositorThread( 153 PinchGestureInput::PinchGestureType aType, const ScrollableLayerGuid& aGuid, 154 const LayoutDevicePoint& aFocusPoint, LayoutDeviceCoord aSpanChange, 155 Modifiers aModifiers) { 156 MOZ_ASSERT(mCompositorThread->IsOnCurrentThread()); 157 158 // The raw pointer to APZCTreeManagerParent is ok here because we are on 159 // the compositor thread. 160 APZCTreeManagerParent* apzctmp = 161 CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId); 162 if (apzctmp) { 163 (void)apzctmp->SendNotifyPinchGesture(aType, aGuid, aFocusPoint, 164 aSpanChange, aModifiers); 165 } 166 } 167 168 void RemoteContentController::NotifyPinchGesture( 169 PinchGestureInput::PinchGestureType aType, const ScrollableLayerGuid& aGuid, 170 const LayoutDevicePoint& aFocusPoint, LayoutDeviceCoord aSpanChange, 171 Modifiers aModifiers) { 172 APZThreadUtils::AssertOnControllerThread(); 173 174 // For now we only ever want to handle this NotifyPinchGesture message in 175 // the parent process, even if the APZ is sending it to a content process. 176 177 // If we're in the GPU process, try to find a handle to the parent process 178 // and send it there. 179 if (XRE_IsGPUProcess()) { 180 if (mCompositorThread->IsOnCurrentThread()) { 181 NotifyPinchGestureOnCompositorThread(aType, aGuid, aFocusPoint, 182 aSpanChange, aModifiers); 183 } else { 184 mCompositorThread->Dispatch( 185 NewRunnableMethod<PinchGestureInput::PinchGestureType, 186 ScrollableLayerGuid, LayoutDevicePoint, 187 LayoutDeviceCoord, Modifiers>( 188 "layers::RemoteContentController::" 189 "NotifyPinchGestureOnCompositorThread", 190 this, 191 &RemoteContentController::NotifyPinchGestureOnCompositorThread, 192 aType, aGuid, aFocusPoint, aSpanChange, aModifiers)); 193 } 194 return; 195 } 196 197 // If we're in the parent process, handle it directly. We don't have a 198 // handle to the widget though, so we fish out the ChromeProcessController 199 // and delegate to that instead. 200 if (XRE_IsParentProcess()) { 201 MOZ_ASSERT(NS_IsMainThread()); 202 RefPtr<GeckoContentController> rootController = 203 CompositorBridgeParent::GetGeckoContentControllerForRoot( 204 aGuid.mLayersId); 205 if (rootController) { 206 rootController->NotifyPinchGesture(aType, aGuid, aFocusPoint, aSpanChange, 207 aModifiers); 208 } 209 } 210 } 211 212 bool RemoteContentController::IsRepaintThread() { 213 return mCompositorThread->IsOnCurrentThread(); 214 } 215 216 void RemoteContentController::DispatchToRepaintThread( 217 already_AddRefed<Runnable> aTask) { 218 mCompositorThread->Dispatch(std::move(aTask)); 219 } 220 221 void RemoteContentController::NotifyAPZStateChange( 222 const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg, 223 Maybe<uint64_t> aInputBlockId) { 224 if (!mCompositorThread->IsOnCurrentThread()) { 225 // We have to send messages from the compositor thread 226 mCompositorThread->Dispatch( 227 NewRunnableMethod<ScrollableLayerGuid, APZStateChange, int, 228 Maybe<uint64_t>>( 229 "layers::RemoteContentController::NotifyAPZStateChange", this, 230 &RemoteContentController::NotifyAPZStateChange, aGuid, aChange, 231 aArg, aInputBlockId)); 232 return; 233 } 234 235 if (mCanSend) { 236 (void)SendNotifyAPZStateChange(aGuid, aChange, aArg, aInputBlockId); 237 } 238 } 239 240 void RemoteContentController::UpdateOverscrollVelocity( 241 const ScrollableLayerGuid& aGuid, float aX, float aY, bool aIsRootContent) { 242 if (XRE_IsParentProcess()) { 243 #ifdef MOZ_WIDGET_ANDROID 244 // We always want these to go to the parent process on Android 245 if (!NS_IsMainThread()) { 246 mozilla::jni::DispatchToGeckoPriorityQueue( 247 NewRunnableMethod<ScrollableLayerGuid, float, float, bool>( 248 "layers::RemoteContentController::UpdateOverscrollVelocity", this, 249 &RemoteContentController::UpdateOverscrollVelocity, aGuid, aX, aY, 250 aIsRootContent)); 251 return; 252 } 253 #endif 254 255 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 256 RefPtr<GeckoContentController> rootController = 257 CompositorBridgeParent::GetGeckoContentControllerForRoot( 258 aGuid.mLayersId); 259 if (rootController) { 260 rootController->UpdateOverscrollVelocity(aGuid, aX, aY, aIsRootContent); 261 } 262 } else if (XRE_IsGPUProcess()) { 263 if (!mCompositorThread->IsOnCurrentThread()) { 264 mCompositorThread->Dispatch( 265 NewRunnableMethod<ScrollableLayerGuid, float, float, bool>( 266 "layers::RemoteContentController::UpdateOverscrollVelocity", this, 267 &RemoteContentController::UpdateOverscrollVelocity, aGuid, aX, aY, 268 aIsRootContent)); 269 return; 270 } 271 272 MOZ_RELEASE_ASSERT(mCompositorThread->IsOnCurrentThread()); 273 GeckoContentController* rootController = 274 CompositorBridgeParent::GetGeckoContentControllerForRoot( 275 aGuid.mLayersId); 276 if (rootController) { 277 MOZ_RELEASE_ASSERT(rootController->IsRemote()); 278 (void)static_cast<RemoteContentController*>(rootController) 279 ->SendUpdateOverscrollVelocity(aGuid, aX, aY, aIsRootContent); 280 } 281 } 282 } 283 284 void RemoteContentController::UpdateOverscrollOffset( 285 const ScrollableLayerGuid& aGuid, float aX, float aY, bool aIsRootContent) { 286 if (XRE_IsParentProcess()) { 287 #ifdef MOZ_WIDGET_ANDROID 288 // We always want these to go to the parent process on Android 289 if (!NS_IsMainThread()) { 290 mozilla::jni::DispatchToGeckoPriorityQueue( 291 NewRunnableMethod<ScrollableLayerGuid, float, float, bool>( 292 "layers::RemoteContentController::UpdateOverscrollOffset", this, 293 &RemoteContentController::UpdateOverscrollOffset, aGuid, aX, aY, 294 aIsRootContent)); 295 return; 296 } 297 #endif 298 299 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 300 RefPtr<GeckoContentController> rootController = 301 CompositorBridgeParent::GetGeckoContentControllerForRoot( 302 aGuid.mLayersId); 303 if (rootController) { 304 rootController->UpdateOverscrollOffset(aGuid, aX, aY, aIsRootContent); 305 } 306 } else if (XRE_IsGPUProcess()) { 307 if (!mCompositorThread->IsOnCurrentThread()) { 308 mCompositorThread->Dispatch( 309 NewRunnableMethod<ScrollableLayerGuid, float, float, bool>( 310 "layers::RemoteContentController::UpdateOverscrollOffset", this, 311 &RemoteContentController::UpdateOverscrollOffset, aGuid, aX, aY, 312 aIsRootContent)); 313 return; 314 } 315 316 MOZ_RELEASE_ASSERT(mCompositorThread->IsOnCurrentThread()); 317 GeckoContentController* rootController = 318 CompositorBridgeParent::GetGeckoContentControllerForRoot( 319 aGuid.mLayersId); 320 if (rootController) { 321 MOZ_RELEASE_ASSERT(rootController->IsRemote()); 322 (void)static_cast<RemoteContentController*>(rootController) 323 ->SendUpdateOverscrollOffset(aGuid, aX, aY, aIsRootContent); 324 } 325 } 326 } 327 328 void RemoteContentController::HideDynamicToolbar( 329 const ScrollableLayerGuid& aGuid) { 330 // We always want these to go to the parent process 331 if (XRE_IsParentProcess()) { 332 #ifdef MOZ_WIDGET_ANDROID 333 if (!NS_IsMainThread()) { 334 mozilla::jni::DispatchToGeckoPriorityQueue( 335 NewRunnableMethod<ScrollableLayerGuid>( 336 "layers::RemoteContentController::HideDynamicToolbar", this, 337 &RemoteContentController::HideDynamicToolbar, aGuid)); 338 return; 339 } 340 #endif 341 342 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 343 RefPtr<GeckoContentController> rootController = 344 CompositorBridgeParent::GetGeckoContentControllerForRoot( 345 aGuid.mLayersId); 346 if (rootController) { 347 rootController->HideDynamicToolbar(aGuid); 348 } 349 } else if (XRE_IsGPUProcess()) { 350 if (!mCompositorThread->IsOnCurrentThread()) { 351 mCompositorThread->Dispatch(NewRunnableMethod<ScrollableLayerGuid>( 352 "layers::RemoteContentController::HideDynamicToolbar", this, 353 &RemoteContentController::HideDynamicToolbar, aGuid)); 354 return; 355 } 356 357 MOZ_RELEASE_ASSERT(mCompositorThread->IsOnCurrentThread()); 358 GeckoContentController* rootController = 359 CompositorBridgeParent::GetGeckoContentControllerForRoot( 360 aGuid.mLayersId); 361 if (rootController) { 362 MOZ_RELEASE_ASSERT(rootController->IsRemote()); 363 (void)static_cast<RemoteContentController*>(rootController) 364 ->SendHideDynamicToolbar(); 365 } 366 } 367 } 368 369 void RemoteContentController::NotifyMozMouseScrollEvent( 370 const ScrollableLayerGuid::ViewID& aScrollId, const nsString& aEvent) { 371 if (!mCompositorThread->IsOnCurrentThread()) { 372 // We have to send messages from the compositor thread 373 mCompositorThread->Dispatch( 374 NewRunnableMethod<ScrollableLayerGuid::ViewID, nsString>( 375 "layers::RemoteContentController::NotifyMozMouseScrollEvent", this, 376 &RemoteContentController::NotifyMozMouseScrollEvent, aScrollId, 377 aEvent)); 378 return; 379 } 380 381 if (mCanSend) { 382 (void)SendNotifyMozMouseScrollEvent(aScrollId, aEvent); 383 } 384 } 385 386 void RemoteContentController::NotifyFlushComplete() { 387 MOZ_ASSERT(IsRepaintThread()); 388 389 if (mCanSend) { 390 (void)SendNotifyFlushComplete(); 391 } 392 } 393 394 void RemoteContentController::NotifyAsyncScrollbarDragInitiated( 395 uint64_t aDragBlockId, const ScrollableLayerGuid::ViewID& aScrollId, 396 ScrollDirection aDirection) { 397 if (!mCompositorThread->IsOnCurrentThread()) { 398 // We have to send messages from the compositor thread 399 mCompositorThread->Dispatch( 400 NewRunnableMethod<uint64_t, ScrollableLayerGuid::ViewID, 401 ScrollDirection>( 402 "layers::RemoteContentController::" 403 "NotifyAsyncScrollbarDragInitiated", 404 this, &RemoteContentController::NotifyAsyncScrollbarDragInitiated, 405 aDragBlockId, aScrollId, aDirection)); 406 return; 407 } 408 409 if (mCanSend) { 410 (void)SendNotifyAsyncScrollbarDragInitiated(aDragBlockId, aScrollId, 411 aDirection); 412 } 413 } 414 415 void RemoteContentController::NotifyAsyncScrollbarDragRejected( 416 const ScrollableLayerGuid::ViewID& aScrollId) { 417 if (!mCompositorThread->IsOnCurrentThread()) { 418 // We have to send messages from the compositor thread 419 mCompositorThread->Dispatch(NewRunnableMethod<ScrollableLayerGuid::ViewID>( 420 "layers::RemoteContentController::NotifyAsyncScrollbarDragRejected", 421 this, &RemoteContentController::NotifyAsyncScrollbarDragRejected, 422 aScrollId)); 423 return; 424 } 425 426 if (mCanSend) { 427 (void)SendNotifyAsyncScrollbarDragRejected(aScrollId); 428 } 429 } 430 431 void RemoteContentController::NotifyAsyncAutoscrollRejected( 432 const ScrollableLayerGuid::ViewID& aScrollId) { 433 if (!mCompositorThread->IsOnCurrentThread()) { 434 // We have to send messages from the compositor thread 435 mCompositorThread->Dispatch(NewRunnableMethod<ScrollableLayerGuid::ViewID>( 436 "layers::RemoteContentController::NotifyAsyncAutoscrollRejected", this, 437 &RemoteContentController::NotifyAsyncAutoscrollRejected, aScrollId)); 438 return; 439 } 440 441 if (mCanSend) { 442 (void)SendNotifyAsyncAutoscrollRejected(aScrollId); 443 } 444 } 445 446 void RemoteContentController::CancelAutoscroll( 447 const ScrollableLayerGuid& aGuid) { 448 if (XRE_GetProcessType() == GeckoProcessType_GPU) { 449 CancelAutoscrollCrossProcess(aGuid); 450 } else { 451 CancelAutoscrollInProcess(aGuid); 452 } 453 } 454 455 void RemoteContentController::CancelAutoscrollInProcess( 456 const ScrollableLayerGuid& aGuid) { 457 MOZ_ASSERT(XRE_IsParentProcess()); 458 NS_DispatchToMainThread(NewRunnableFunction( 459 "layers::CancelAutoScroll", &APZCCallbackHelper::CancelAutoscroll, 460 aGuid.mScrollId)); 461 } 462 463 void RemoteContentController::CancelAutoscrollCrossProcess( 464 const ScrollableLayerGuid& aGuid) { 465 MOZ_ASSERT(XRE_IsGPUProcess()); 466 467 if (!mCompositorThread->IsOnCurrentThread()) { 468 mCompositorThread->Dispatch(NewRunnableMethod<ScrollableLayerGuid>( 469 "layers::RemoteContentController::CancelAutoscrollCrossProcess", this, 470 &RemoteContentController::CancelAutoscrollCrossProcess, aGuid)); 471 return; 472 } 473 474 // The raw pointer to APZCTreeManagerParent is ok here because we are on 475 // the compositor thread. 476 if (APZCTreeManagerParent* parent = 477 CompositorBridgeParent::GetApzcTreeManagerParentForRoot( 478 aGuid.mLayersId)) { 479 (void)parent->SendCancelAutoscroll(aGuid.mScrollId); 480 } 481 } 482 483 void RemoteContentController::NotifyScaleGestureComplete( 484 const ScrollableLayerGuid& aGuid, float aScale) { 485 if (XRE_GetProcessType() == GeckoProcessType_GPU) { 486 NotifyScaleGestureCompleteCrossProcess(aGuid, aScale); 487 } else { 488 NotifyScaleGestureCompleteInProcess(aGuid, aScale); 489 } 490 } 491 492 void RemoteContentController::NotifyScaleGestureCompleteInProcess( 493 const ScrollableLayerGuid& aGuid, float aScale) { 494 MOZ_ASSERT(XRE_IsParentProcess()); 495 496 if (!NS_IsMainThread()) { 497 NS_DispatchToMainThread(NewRunnableMethod<ScrollableLayerGuid, float>( 498 "layers::RemoteContentController::" 499 "NotifyScaleGestureCompleteInProcess", 500 this, &RemoteContentController::NotifyScaleGestureCompleteInProcess, 501 aGuid, aScale)); 502 return; 503 } 504 505 RefPtr<GeckoContentController> rootController = 506 CompositorBridgeParent::GetGeckoContentControllerForRoot(aGuid.mLayersId); 507 if (rootController) { 508 MOZ_ASSERT(rootController != this); 509 if (rootController != this) { 510 rootController->NotifyScaleGestureComplete(aGuid, aScale); 511 } 512 } 513 } 514 515 void RemoteContentController::NotifyScaleGestureCompleteCrossProcess( 516 const ScrollableLayerGuid& aGuid, float aScale) { 517 MOZ_ASSERT(XRE_IsGPUProcess()); 518 519 if (!mCompositorThread->IsOnCurrentThread()) { 520 mCompositorThread->Dispatch(NewRunnableMethod<ScrollableLayerGuid, float>( 521 "layers::RemoteContentController::" 522 "NotifyScaleGestureCompleteCrossProcess", 523 this, &RemoteContentController::NotifyScaleGestureCompleteCrossProcess, 524 aGuid, aScale)); 525 return; 526 } 527 528 // The raw pointer to APZCTreeManagerParent is ok here because we are on 529 // the compositor thread. 530 if (APZCTreeManagerParent* parent = 531 CompositorBridgeParent::GetApzcTreeManagerParentForRoot( 532 aGuid.mLayersId)) { 533 (void)parent->SendNotifyScaleGestureComplete(aGuid.mScrollId, aScale); 534 } 535 } 536 537 void RemoteContentController::ActorDestroy(ActorDestroyReason aWhy) { 538 // This controller could possibly be kept alive longer after this 539 // by a RefPtr, but it is no longer valid to send messages. 540 mCanSend = false; 541 } 542 543 void RemoteContentController::Destroy() { 544 if (mCanSend) { 545 mCanSend = false; 546 (void)SendDestroy(); 547 } 548 } 549 550 mozilla::ipc::IPCResult RemoteContentController::RecvDestroy() { 551 // The actor on the other side is about to get destroyed, so let's not 552 // send it any more messages. 553 mCanSend = false; 554 return IPC_OK(); 555 } 556 557 bool RemoteContentController::IsRemote() { return true; } 558 559 } // namespace layers 560 } // namespace mozilla