BrowserParent.cpp (153110B)
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 "BrowserParent.h" 8 9 #include "base/basictypes.h" 10 #include "mozilla/AlreadyAddRefed.h" 11 #include "mozilla/EventForwards.h" 12 13 #ifdef ACCESSIBILITY 14 # include "mozilla/a11y/DocAccessibleParent.h" 15 # include "mozilla/a11y/Platform.h" 16 # include "nsAccessibilityService.h" 17 #endif 18 #include "mozilla/Components.h" 19 #include "mozilla/EventStateManager.h" 20 #include "mozilla/IMEStateManager.h" 21 #include "mozilla/Logging.h" 22 #include "mozilla/LookAndFeel.h" 23 #include "mozilla/Maybe.h" 24 #include "mozilla/MiscEvents.h" 25 #include "mozilla/MouseEvents.h" 26 #include "mozilla/NativeKeyBindingsType.h" 27 #include "mozilla/Preferences.h" 28 #include "mozilla/PresShell.h" 29 #include "mozilla/ProcessHangMonitor.h" 30 #include "mozilla/RecursiveMutex.h" 31 #include "mozilla/RefPtr.h" 32 #include "mozilla/StaticPrefs_dom.h" 33 #include "mozilla/TextEventDispatcher.h" 34 #include "mozilla/TextEvents.h" 35 #include "mozilla/TouchEvents.h" 36 #include "mozilla/UniquePtr.h" 37 #include "mozilla/dom/BrowserBridgeParent.h" 38 #include "mozilla/dom/BrowserHost.h" 39 #include "mozilla/dom/BrowserSessionStore.h" 40 #include "mozilla/dom/BrowsingContextGroup.h" 41 #include "mozilla/dom/CancelContentJSOptionsBinding.h" 42 #include "mozilla/dom/ChromeMessageSender.h" 43 #include "mozilla/dom/ContentParent.h" 44 #include "mozilla/dom/ContentProcessManager.h" 45 #include "mozilla/dom/DataTransfer.h" 46 #include "mozilla/dom/DataTransferItemList.h" 47 #include "mozilla/dom/DocumentInlines.h" 48 #include "mozilla/dom/Event.h" 49 #include "mozilla/dom/PContentPermissionRequestParent.h" 50 #include "mozilla/dom/PaymentRequestParent.h" 51 #include "mozilla/dom/PointerEventHandler.h" 52 #include "mozilla/dom/RemoteDragStartData.h" 53 #include "mozilla/dom/RemoteWebProgressRequest.h" 54 #include "mozilla/dom/SessionHistoryEntry.h" 55 #include "mozilla/dom/SessionStoreParent.h" 56 #include "mozilla/dom/UserActivation.h" 57 #include "mozilla/dom/indexedDB/ActorsParent.h" 58 #include "mozilla/gfx/2D.h" 59 #include "mozilla/gfx/DataSurfaceHelpers.h" 60 #include "mozilla/gfx/GPUProcessManager.h" 61 #include "mozilla/ipc/Endpoint.h" 62 #include "mozilla/layers/AsyncDragMetrics.h" 63 #include "mozilla/layers/InputAPZContext.h" 64 #include "mozilla/layout/RemoteLayerTreeOwner.h" 65 #include "mozilla/net/CookieJarSettings.h" 66 #include "mozilla/net/NeckoChild.h" 67 #include "nsCOMPtr.h" 68 #include "nsContentPermissionHelper.h" 69 #include "nsContentUtils.h" 70 #include "nsDebug.h" 71 #include "nsFocusManager.h" 72 #include "nsFrameLoader.h" 73 #include "nsFrameLoaderOwner.h" 74 #include "nsFrameManager.h" 75 #include "nsIAppWindow.h" 76 #include "nsIBaseWindow.h" 77 #include "nsIBrowser.h" 78 #include "nsIBrowserController.h" 79 #include "nsIContent.h" 80 #include "nsICookieJarSettings.h" 81 #include "nsIDOMWindowUtils.h" 82 #include "nsIDocShell.h" 83 #include "nsIDocShellTreeOwner.h" 84 #include "nsIInterfaceRequestorUtils.h" 85 #include "nsILoadInfo.h" 86 #include "nsIPromptFactory.h" 87 #include "nsIURI.h" 88 #include "nsIWebBrowserChrome.h" 89 #include "nsIWebProtocolHandlerRegistrar.h" 90 #include "nsIWidget.h" 91 #include "nsIWindowWatcher.h" 92 #include "nsIXPConnect.h" 93 #include "nsIXULBrowserWindow.h" 94 #include "nsImportModule.h" 95 #include "nsLayoutUtils.h" 96 #include "nsNetUtil.h" 97 #include "nsQueryActor.h" 98 #include "nsSHistory.h" 99 #include "nsVariant.h" 100 #ifndef XP_WIN 101 # include "nsJARProtocolHandler.h" 102 #endif 103 #include <algorithm> 104 105 #include "BrowserChild.h" 106 #include "ColorPickerParent.h" 107 #include "FilePickerParent.h" 108 #include "IHistory.h" 109 #include "MMPrinter.h" 110 #include "PermissionMessageUtils.h" 111 #include "ProcessPriorityManager.h" 112 #include "StructuredCloneData.h" 113 #include "UnitTransforms.h" 114 #include "VsyncSource.h" 115 #include "gfxUtils.h" 116 #include "mozilla/NullPrincipal.h" 117 #include "mozilla/ProfilerLabels.h" 118 #include "mozilla/WebBrowserPersistDocumentParent.h" 119 #include "mozilla/dom/CanonicalBrowsingContext.h" 120 #include "mozilla/dom/CrashReport.h" 121 #include "mozilla/dom/WindowGlobalParent.h" 122 #include "nsAuthInformationHolder.h" 123 #include "nsIAuthInformation.h" 124 #include "nsIAuthPrompt2.h" 125 #include "nsIAuthPromptCallback.h" 126 #include "nsICancelable.h" 127 #include "nsILoginManagerAuthPrompter.h" 128 #include "nsISecureBrowserUI.h" 129 #include "nsIXULRuntime.h" 130 #include "nsNetCID.h" 131 #include "nsPIDOMWindow.h" 132 #include "nsPIWindowRoot.h" 133 #include "nsPrintfCString.h" 134 #include "nsQueryObject.h" 135 #include "nsReadableUtils.h" 136 #include "nsServiceManagerUtils.h" 137 #include "nsString.h" 138 #include "nsSubDocumentFrame.h" 139 #include "nsThreadUtils.h" 140 141 #ifdef XP_WIN 142 # include "FxRWindowManager.h" 143 #endif 144 145 #if defined(XP_WIN) && defined(ACCESSIBILITY) 146 # include "mozilla/a11y/AccessibleWrap.h" 147 # include "mozilla/a11y/Compatibility.h" 148 # include "mozilla/a11y/nsWinUtils.h" 149 #endif 150 151 #ifdef MOZ_GECKOVIEW_HISTORY 152 # include "GeckoViewHistory.h" 153 #endif 154 155 #if defined(MOZ_WIDGET_ANDROID) 156 # include "mozilla/widget/nsWindow.h" 157 #endif // defined(MOZ_WIDGET_ANDROID) 158 159 using namespace mozilla::dom; 160 using namespace mozilla::ipc; 161 using namespace mozilla::layers; 162 using namespace mozilla::layout; 163 using namespace mozilla::services; 164 using namespace mozilla::widget; 165 using namespace mozilla::gfx; 166 167 using mozilla::LazyLogModule; 168 169 extern LazyLogModule gBCWebProgressLog; 170 extern LazyLogModule gSHIPBFCacheLog; 171 172 LazyLogModule gBrowserFocusLog("BrowserFocus"); 173 174 #define LOGBROWSERFOCUS(args) \ 175 MOZ_LOG(gBrowserFocusLog, mozilla::LogLevel::Debug, args) 176 177 /* static */ 178 BrowserParent* BrowserParent::sFocus = nullptr; 179 /* static */ 180 BrowserParent* BrowserParent::sTopLevelWebFocus = nullptr; 181 /* static */ 182 BrowserParent* BrowserParent::sLastMouseRemoteTarget = nullptr; 183 184 // The flags passed by the webProgress notifications are 16 bits shifted 185 // from the ones registered by webProgressListeners. 186 #define NOTIFY_FLAG_SHIFT 16 187 188 namespace mozilla { 189 190 /** 191 * Store data of a keypress event which is requesting to handled it in a remote 192 * process or some remote processes. 193 */ 194 class RequestingAccessKeyEventData { 195 public: 196 RequestingAccessKeyEventData() = delete; 197 198 static void OnBrowserParentCreated() { 199 MOZ_ASSERT(sBrowserParentCount <= INT32_MAX); 200 sBrowserParentCount++; 201 } 202 static void OnBrowserParentDestroyed() { 203 MOZ_ASSERT(sBrowserParentCount > 0); 204 sBrowserParentCount--; 205 // To avoid memory leak, we need to reset sData when the last BrowserParent 206 // is destroyed. 207 if (!sBrowserParentCount) { 208 Clear(); 209 } 210 } 211 212 static void Set(const WidgetKeyboardEvent& aKeyPressEvent) { 213 MOZ_ASSERT(aKeyPressEvent.mMessage == eKeyPress); 214 MOZ_ASSERT(sBrowserParentCount > 0); 215 sData = 216 Some(Data{aKeyPressEvent.mAlternativeCharCodes, aKeyPressEvent.mKeyCode, 217 aKeyPressEvent.mCharCode, aKeyPressEvent.mKeyNameIndex, 218 aKeyPressEvent.mCodeNameIndex, aKeyPressEvent.mKeyValue, 219 aKeyPressEvent.mModifiers}); 220 } 221 222 static void Clear() { sData.reset(); } 223 224 [[nodiscard]] static bool Equals(const WidgetKeyboardEvent& aKeyPressEvent) { 225 MOZ_ASSERT(sBrowserParentCount > 0); 226 return sData.isSome() && sData->Equals(aKeyPressEvent); 227 } 228 229 [[nodiscard]] static bool IsSet() { 230 MOZ_ASSERT(sBrowserParentCount > 0); 231 return sData.isSome(); 232 } 233 234 private: 235 struct Data { 236 [[nodiscard]] bool Equals(const WidgetKeyboardEvent& aKeyPressEvent) { 237 return mKeyCode == aKeyPressEvent.mKeyCode && 238 mCharCode == aKeyPressEvent.mCharCode && 239 mKeyNameIndex == aKeyPressEvent.mKeyNameIndex && 240 mCodeNameIndex == aKeyPressEvent.mCodeNameIndex && 241 mKeyValue == aKeyPressEvent.mKeyValue && 242 mModifiers == aKeyPressEvent.mModifiers && 243 mAlternativeCharCodes == aKeyPressEvent.mAlternativeCharCodes; 244 } 245 246 CopyableTArray<AlternativeCharCode> mAlternativeCharCodes; 247 uint32_t mKeyCode; 248 uint32_t mCharCode; 249 KeyNameIndex mKeyNameIndex; 250 CodeNameIndex mCodeNameIndex; 251 nsString mKeyValue; 252 Modifiers mModifiers; 253 }; 254 static Maybe<Data> sData; 255 static int32_t sBrowserParentCount; 256 }; 257 int32_t RequestingAccessKeyEventData::sBrowserParentCount = 0; 258 MOZ_RUNINIT Maybe<RequestingAccessKeyEventData::Data> 259 RequestingAccessKeyEventData::sData; 260 261 namespace dom { 262 263 BrowserParent::LayerToBrowserParentTable* 264 BrowserParent::sLayerToBrowserParentTable = nullptr; 265 266 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserParent) 267 NS_INTERFACE_MAP_ENTRY_CONCRETE(BrowserParent) 268 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider) 269 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 270 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) 271 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener) 272 NS_INTERFACE_MAP_END 273 274 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserParent) 275 276 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserParent) 277 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameLoader) 278 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext) 279 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement) 280 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserDOMWindow) 281 tmp->UnlinkManager(); 282 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE 283 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 284 285 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserParent) 286 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader) 287 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext) 288 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement) 289 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow) 290 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(Manager()) 291 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 292 293 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserParent) 294 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserParent) 295 296 BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId, 297 const TabContext& aContext, 298 CanonicalBrowsingContext* aBrowsingContext, 299 uint32_t aChromeFlags) 300 : TabContext(aContext), 301 mTabId(aTabId), 302 mBrowsingContext(aBrowsingContext), 303 mFrameElement(nullptr), 304 mBrowserDOMWindow(nullptr), 305 mFrameLoader(nullptr), 306 mChromeFlags(aChromeFlags), 307 mBrowserBridgeParent(nullptr), 308 mBrowserHost(nullptr), 309 mContentCache(*this), 310 mRect(0, 0, 0, 0), 311 mDimensions(0, 0), 312 mDPI(0), 313 mRounding(0), 314 mDefaultScale(0), 315 mUpdatedDimensions(false), 316 mSizeMode(nsSizeMode_Normal), 317 mCreatingWindow(false), 318 mMarkedDestroying(false), 319 mIsDestroyed(false), 320 mRemoteTargetSetsCursor(false), 321 mIsPreservingLayers(false), 322 mRenderLayers(true), 323 mPriorityHint(false), 324 mHasLayers(false), 325 mHasPresented(false), 326 mIsReadyToHandleInputEvents(false), 327 mIsMouseEnterIntoWidgetEventSuppressed(false), 328 mLockedNativePointer(false), 329 mShowingTooltip(false) { 330 MOZ_ASSERT(aManager); 331 332 // We access `Manager()` when updating priorities later in this constructor, 333 // so need to initialize it before IPC does. 334 SetManager(aManager); 335 336 // Add a KeepAlive for this BrowserParent upon creation. 337 mContentParentKeepAlive = 338 aManager->TryAddKeepAlive(aBrowsingContext->BrowserId()); 339 340 RequestingAccessKeyEventData::OnBrowserParentCreated(); 341 342 // Make sure to compute our process priority if needed before the block of 343 // code below. This makes sure the block below prioritizes our process if 344 // needed. 345 if (aBrowsingContext->IsTop()) { 346 RecomputeProcessPriority(); 347 } 348 349 // Reflect the BC tree's activeness state on this new BrowserParent. This 350 // ensures that the process will be correctly prioritized based on the 351 // BrowsingContext's current priority after a navigation. 352 // If the BC is not active, we still call `BrowserPriorityChanged` to ensure 353 // the priority is lowered if the BrowsingContext is inactive, but the process 354 // still has FOREGROUND priority from when it was launched. 355 ProcessPriorityManager::BrowserPriorityChanged( 356 this, aBrowsingContext->Top()->IsPriorityActive()); 357 } 358 359 BrowserParent::~BrowserParent() { 360 RequestingAccessKeyEventData::OnBrowserParentDestroyed(); 361 } 362 363 /* static */ 364 BrowserParent* BrowserParent::GetFocused() { return sFocus; } 365 366 /* static */ 367 BrowserParent* BrowserParent::GetLastMouseRemoteTarget() { 368 return sLastMouseRemoteTarget; 369 } 370 371 /*static*/ 372 BrowserParent* BrowserParent::GetFrom(nsFrameLoader* aFrameLoader) { 373 if (!aFrameLoader) { 374 return nullptr; 375 } 376 return aFrameLoader->GetBrowserParent(); 377 } 378 379 /*static*/ 380 BrowserParent* BrowserParent::GetFrom(PBrowserParent* aBrowserParent) { 381 return static_cast<BrowserParent*>(aBrowserParent); 382 } 383 384 /*static*/ 385 BrowserParent* BrowserParent::GetFrom(nsIContent* aContent) { 386 RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(aContent); 387 if (!loaderOwner) { 388 return nullptr; 389 } 390 RefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader(); 391 return GetFrom(frameLoader); 392 } 393 394 /* static */ 395 BrowserParent* BrowserParent::GetBrowserParentFromLayersId( 396 layers::LayersId aLayersId) { 397 if (!sLayerToBrowserParentTable) { 398 return nullptr; 399 } 400 return sLayerToBrowserParentTable->Get(uint64_t(aLayersId)); 401 } 402 403 /*static*/ 404 TabId BrowserParent::GetTabIdFrom(nsIDocShell* docShell) { 405 nsCOMPtr<nsIBrowserChild> browserChild(BrowserChild::GetFrom(docShell)); 406 if (browserChild) { 407 return static_cast<BrowserChild*>(browserChild.get())->GetTabId(); 408 } 409 return TabId(0); 410 } 411 412 ContentParent* BrowserParent::Manager() const { 413 return static_cast<ContentParent*>(PBrowserParent::Manager()); 414 } 415 416 void BrowserParent::AddBrowserParentToTable(layers::LayersId aLayersId, 417 BrowserParent* aBrowserParent) { 418 if (!sLayerToBrowserParentTable) { 419 sLayerToBrowserParentTable = new LayerToBrowserParentTable(); 420 } 421 sLayerToBrowserParentTable->InsertOrUpdate(uint64_t(aLayersId), 422 aBrowserParent); 423 } 424 425 void BrowserParent::RemoveBrowserParentFromTable(layers::LayersId aLayersId) { 426 if (!sLayerToBrowserParentTable) { 427 return; 428 } 429 sLayerToBrowserParentTable->Remove(uint64_t(aLayersId)); 430 if (sLayerToBrowserParentTable->Count() == 0) { 431 delete sLayerToBrowserParentTable; 432 sLayerToBrowserParentTable = nullptr; 433 } 434 } 435 436 already_AddRefed<nsILoadContext> BrowserParent::GetLoadContext() { 437 return do_AddRef(mBrowsingContext); 438 } 439 440 /** 441 * Will return nullptr if there is no outer window available for the 442 * document hosting the owner element of this BrowserParent. Also will return 443 * nullptr if that outer window is in the process of closing. 444 */ 445 already_AddRefed<nsPIDOMWindowOuter> BrowserParent::GetParentWindowOuter() { 446 nsCOMPtr<nsIContent> frame = GetOwnerElement(); 447 if (!frame) { 448 return nullptr; 449 } 450 451 nsCOMPtr<nsPIDOMWindowOuter> parent = frame->OwnerDoc()->GetWindow(); 452 if (!parent || parent->Closed()) { 453 return nullptr; 454 } 455 456 return parent.forget(); 457 } 458 459 already_AddRefed<nsIWidget> BrowserParent::GetTopLevelWidget() { 460 if (RefPtr<Element> element = mFrameElement) { 461 if (PresShell* presShell = element->OwnerDoc()->GetPresShell()) { 462 return do_AddRef(presShell->GetRootWidget()); 463 } 464 } 465 return nullptr; 466 } 467 468 already_AddRefed<nsIWidget> BrowserParent::GetTextInputHandlingWidget() const { 469 if (!mFrameElement) { 470 return nullptr; 471 } 472 PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell(); 473 if (!presShell) { 474 return nullptr; 475 } 476 nsPresContext* presContext = presShell->GetPresContext(); 477 if (!presContext) { 478 return nullptr; 479 } 480 nsCOMPtr<nsIWidget> widget = presContext->GetTextInputHandlingWidget(); 481 return widget.forget(); 482 } 483 484 already_AddRefed<nsIWidget> BrowserParent::GetWidget() const { 485 if (!mFrameElement) { 486 return nullptr; 487 } 488 nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForContent(mFrameElement); 489 if (!widget) { 490 widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc()); 491 } 492 return widget.forget(); 493 } 494 495 already_AddRefed<nsIWidget> BrowserParent::GetDocWidget() const { 496 if (!mFrameElement) { 497 return nullptr; 498 } 499 return do_AddRef( 500 nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc())); 501 } 502 503 nsIXULBrowserWindow* BrowserParent::GetXULBrowserWindow() { 504 if (!mFrameElement) { 505 return nullptr; 506 } 507 508 nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell(); 509 if (!docShell) { 510 return nullptr; 511 } 512 513 nsCOMPtr<nsIDocShellTreeOwner> treeOwner; 514 docShell->GetTreeOwner(getter_AddRefs(treeOwner)); 515 if (!treeOwner) { 516 return nullptr; 517 } 518 519 nsCOMPtr<nsIAppWindow> window = do_GetInterface(treeOwner); 520 if (!window) { 521 return nullptr; 522 } 523 524 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow; 525 window->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); 526 return xulBrowserWindow; 527 } 528 529 uint32_t BrowserParent::GetMaxTouchPoints(Element* aElement) { 530 if (!aElement) { 531 return 0; 532 } 533 534 if (StaticPrefs::dom_maxtouchpoints_testing_value() >= 0) { 535 return StaticPrefs::dom_maxtouchpoints_testing_value(); 536 } 537 538 nsIWidget* widget = nsContentUtils::WidgetForDocument(aElement->OwnerDoc()); 539 return widget ? widget->GetMaxTouchPoints() : 0; 540 } 541 542 a11y::DocAccessibleParent* BrowserParent::GetTopLevelDocAccessible() const { 543 #ifdef ACCESSIBILITY 544 // XXX Consider managing non top level PDocAccessibles with their parent 545 // document accessible. 546 const ManagedContainer<PDocAccessibleParent>& docs = 547 ManagedPDocAccessibleParent(); 548 for (auto* key : docs) { 549 auto* doc = static_cast<a11y::DocAccessibleParent*>(key); 550 // We want the document for this BrowserParent even if it's for an 551 // embedded out-of-process iframe. Therefore, we use 552 // IsTopLevelInContentProcess. In contrast, using IsToplevel would only 553 // include documents that aren't embedded; e.g. tab documents. 554 if (doc->IsTopLevelInContentProcess() && !doc->IsShutdown()) { 555 return doc; 556 } 557 } 558 #endif 559 return nullptr; 560 } 561 562 LayersId BrowserParent::GetLayersId() const { 563 if (!mRemoteLayerTreeOwner.IsInitialized()) { 564 return LayersId{}; 565 } 566 return mRemoteLayerTreeOwner.GetLayersId(); 567 } 568 569 BrowserBridgeParent* BrowserParent::GetBrowserBridgeParent() const { 570 return mBrowserBridgeParent; 571 } 572 573 BrowserHost* BrowserParent::GetBrowserHost() const { return mBrowserHost; } 574 575 bool BrowserParent::IsTransparent() const { 576 return mFrameElement && mFrameElement->HasAttr(nsGkAtoms::transparent) && 577 nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()); 578 } 579 580 ParentShowInfo BrowserParent::GetShowInfo() { 581 TryCacheDPIAndScale(); 582 nsAutoString name; 583 if (mFrameElement) { 584 mFrameElement->GetAttr(nsGkAtoms::name, name); 585 } 586 return ParentShowInfo(name, false, IsTransparent(), mDPI, mRounding, 587 mDefaultScale.scale); 588 } 589 590 already_AddRefed<nsIPrincipal> BrowserParent::GetContentPrincipal() const { 591 nsCOMPtr<nsIBrowser> browser = 592 mFrameElement ? mFrameElement->AsBrowser() : nullptr; 593 NS_ENSURE_TRUE(browser, nullptr); 594 595 RefPtr<nsIPrincipal> principal; 596 597 nsresult rv; 598 rv = browser->GetContentPrincipal(getter_AddRefs(principal)); 599 NS_ENSURE_SUCCESS(rv, nullptr); 600 601 return principal.forget(); 602 } 603 604 void BrowserParent::SetOwnerElement(Element* aElement) { 605 // If we held previous content then unregister for its events. 606 RemoveWindowListeners(); 607 608 // If we change top-level documents then we need to change our 609 // registration with them. 610 RefPtr<nsPIWindowRoot> curTopLevelWin, newTopLevelWin; 611 if (mFrameElement) { 612 curTopLevelWin = nsContentUtils::GetWindowRoot(mFrameElement->OwnerDoc()); 613 } 614 if (aElement) { 615 newTopLevelWin = nsContentUtils::GetWindowRoot(aElement->OwnerDoc()); 616 } 617 bool isSameTopLevelWin = curTopLevelWin == newTopLevelWin; 618 if (mBrowserHost && curTopLevelWin && !isSameTopLevelWin) { 619 curTopLevelWin->RemoveBrowser(mBrowserHost); 620 } 621 622 // Update to the new content, and register to listen for events from it. 623 mFrameElement = aElement; 624 625 if (mBrowserHost && newTopLevelWin && !isSameTopLevelWin) { 626 newTopLevelWin->AddBrowser(mBrowserHost); 627 } 628 629 #if defined(XP_WIN) && defined(ACCESSIBILITY) 630 if (!mIsDestroyed) { 631 uintptr_t newWindowHandle = 0; 632 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 633 newWindowHandle = 634 reinterpret_cast<uintptr_t>(widget->GetNativeData(NS_NATIVE_WINDOW)); 635 } 636 (void)SendUpdateNativeWindowHandle(newWindowHandle); 637 a11y::DocAccessibleParent* doc = GetTopLevelDocAccessible(); 638 if (doc) { 639 HWND hWnd = reinterpret_cast<HWND>(doc->GetEmulatedWindowHandle()); 640 if (hWnd) { 641 HWND parentHwnd = reinterpret_cast<HWND>(newWindowHandle); 642 if (parentHwnd != ::GetParent(hWnd)) { 643 ::SetParent(hWnd, parentHwnd); 644 } 645 } 646 } 647 } 648 #endif 649 650 AddWindowListeners(); 651 652 // The DPI depends on our frame element's widget, so invalidate now in case 653 // we've tried to cache it already. 654 mDPI = -1; 655 TryCacheDPIAndScale(); 656 657 if (mRemoteLayerTreeOwner.IsInitialized()) { 658 mRemoteLayerTreeOwner.OwnerContentChanged(); 659 } 660 661 // Set our BrowsingContext's embedder if we're not embedded within a 662 // BrowserBridgeParent. 663 if (!GetBrowserBridgeParent() && mBrowsingContext && mFrameElement) { 664 mBrowsingContext->SetEmbedderElement(mFrameElement); 665 } 666 667 UpdateVsyncParentVsyncDispatcher(); 668 669 VisitChildren([aElement](BrowserBridgeParent* aBrowser) { 670 if (auto* browserParent = aBrowser->GetBrowserParent()) { 671 browserParent->SetOwnerElement(aElement); 672 } 673 }); 674 } 675 676 void BrowserParent::CacheFrameLoader(nsFrameLoader* aFrameLoader) { 677 mFrameLoader = aFrameLoader; 678 } 679 680 void BrowserParent::AddWindowListeners() { 681 if (mFrameElement) { 682 if (nsCOMPtr<nsPIDOMWindowOuter> window = 683 mFrameElement->OwnerDoc()->GetWindow()) { 684 nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot(); 685 if (eventTarget) { 686 eventTarget->AddEventListener(u"MozUpdateWindowPos"_ns, this, false, 687 false); 688 eventTarget->AddEventListener(u"fullscreenchange"_ns, this, false, 689 false); 690 } 691 } 692 } 693 } 694 695 void BrowserParent::RemoveWindowListeners() { 696 if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) { 697 nsCOMPtr<nsPIDOMWindowOuter> window = 698 mFrameElement->OwnerDoc()->GetWindow(); 699 nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot(); 700 if (eventTarget) { 701 eventTarget->RemoveEventListener(u"MozUpdateWindowPos"_ns, this, false); 702 eventTarget->RemoveEventListener(u"fullscreenchange"_ns, this, false); 703 } 704 } 705 } 706 707 void BrowserParent::Deactivated() { 708 if (mShowingTooltip) { 709 // Reuse the normal tooltip hiding method. 710 (void)RecvHideTooltip(); 711 } 712 UnlockNativePointer(); 713 UnsetTopLevelWebFocus(this); 714 UnsetLastMouseRemoteTarget(this); 715 PointerLockManager::ReleaseLockedRemoteTarget(this); 716 PointerEventHandler::ReleasePointerCaptureRemoteTarget(this); 717 PresShell::ReleaseCapturingRemoteTarget(this); 718 ProcessPriorityManager::BrowserPriorityChanged(this, /* aPriority = */ false); 719 } 720 721 void BrowserParent::Destroy() { 722 // Aggressively release the window to avoid leaking the world in shutdown 723 // corner cases. 724 mBrowserDOMWindow = nullptr; 725 726 if (mIsDestroyed) { 727 return; 728 } 729 730 Deactivated(); 731 732 RemoveWindowListeners(); 733 734 #ifdef ACCESSIBILITY 735 if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) { 736 # if defined(ANDROID) 737 MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor()); 738 # endif 739 tabDoc->Destroy(); 740 } 741 #endif 742 743 // If this fails, it's most likely due to a content-process crash, and 744 // auto-cleanup will kick in. Otherwise, the child side will destroy itself 745 // and send back __delete__(). 746 (void)SendDestroy(); 747 mIsDestroyed = true; 748 749 #if !defined(MOZ_WIDGET_ANDROID) 750 // We're beginning to destroy this BrowserParent. Immediately drop the 751 // keepalive. This can start the shutdown timer, however the ShutDown message 752 // will wait for the BrowserParent to be fully destroyed. 753 // 754 // NOTE: We intentionally skip this step on Android, keeping the KeepAlive 755 // active until the BrowserParent is fully destroyed: 756 // 1. Android has a fixed upper bound on the number of content processes, so 757 // we prefer to re-use them whenever possible (as opposed to letting an 758 // old process wind down while we launch a new one). This restriction will 759 // be relaxed after bug 1565196. 760 // 2. GeckoView always hard-kills content processes (and if it does not, 761 // Android itself will), so we don't concern ourselves with the ForceKill 762 // timer either. 763 mContentParentKeepAlive = nullptr; 764 #endif 765 766 // This `AddKeepAlive` will be cleared if `mMarkedDestroying` is set in 767 // `ActorDestroy`. Out of caution, we don't add the `KeepAlive` if our IPC 768 // actor has somehow already been destroyed, as that would mean `ActorDestroy` 769 // won't be called. 770 if (CanRecv()) { 771 mBrowsingContext->Group()->AddKeepAlive(); 772 } 773 774 mMarkedDestroying = true; 775 } 776 777 mozilla::ipc::IPCResult BrowserParent::RecvDidUnsuppressPainting() { 778 if (!mFrameElement) { 779 return IPC_OK(); 780 } 781 nsSubDocumentFrame* subdocFrame = 782 do_QueryFrame(mFrameElement->GetPrimaryFrame()); 783 if (subdocFrame && subdocFrame->HasRetainedPaintData()) { 784 subdocFrame->ClearRetainedPaintData(); 785 } 786 return IPC_OK(); 787 } 788 789 mozilla::ipc::IPCResult BrowserParent::RecvEnsureLayersConnected( 790 CompositorOptions* aCompositorOptions) { 791 if (mRemoteLayerTreeOwner.IsInitialized()) { 792 mRemoteLayerTreeOwner.EnsureLayersConnected(aCompositorOptions); 793 } 794 return IPC_OK(); 795 } 796 797 void BrowserParent::ActorDestroy(ActorDestroyReason why) { 798 // Need to close undeleted ContentPermissionRequestParents before tab is 799 // closed. 800 // FIXME: Why is PContentPermissionRequest not managed by PBrowser? 801 nsTArray<PContentPermissionRequestParent*> parentArray = 802 nsContentPermissionUtils::GetContentPermissionRequestParentById(mTabId); 803 for (auto& permissionRequestParent : parentArray) { 804 (void)PContentPermissionRequestParent::Send__delete__( 805 permissionRequestParent); 806 } 807 808 // Ensure the ContentParentKeepAlive has been cleared when the actor is 809 // destroyed, and re-check if it's time to send the ShutDown message. 810 mContentParentKeepAlive = nullptr; 811 Manager()->MaybeBeginShutDown(); 812 813 ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); 814 if (cpm) { 815 cpm->UnregisterRemoteFrame(mTabId); 816 } 817 818 if (mRemoteLayerTreeOwner.IsInitialized()) { 819 auto layersId = mRemoteLayerTreeOwner.GetLayersId(); 820 if (mFrameElement) { 821 nsSubDocumentFrame* f = do_QueryFrame(mFrameElement->GetPrimaryFrame()); 822 if (f && f->HasRetainedPaintData() && 823 f->GetRemotePaintData().mLayersId == layersId) { 824 f->ClearRetainedPaintData(); 825 } 826 } 827 828 // It's important to unmap layers after the remote browser has been 829 // destroyed, otherwise it may still send messages to the compositor which 830 // will reject them, causing assertions. 831 RemoveBrowserParentFromTable(layersId); 832 mRemoteLayerTreeOwner.Destroy(); 833 } 834 835 // Even though BrowserParent::Destroy calls this, we need to do it here too in 836 // case of a crash. 837 Deactivated(); 838 839 if (why == AbnormalShutdown) { 840 // dom_reporting_header must also be enabled for the report to be sent. 841 if (StaticPrefs::dom_reporting_crash_enabled()) { 842 nsCOMPtr<nsIPrincipal> principal = GetContentPrincipal(); 843 844 if (principal) { 845 // TODO: Flag out-of-memory crashes appropriately. 846 CrashReport::Deliver(principal, /* aIsOOM */ false); 847 } 848 } 849 } 850 851 // If we were shutting down normally, we held a reference to our 852 // BrowsingContextGroup in `BrowserParent::Destroy`. Clear that reference 853 // here. 854 if (mMarkedDestroying) { 855 mBrowsingContext->Group()->RemoveKeepAlive(); 856 } 857 858 // Tell our embedder that the tab is now going away unless we're an 859 // out-of-process iframe. 860 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true); 861 if (frameLoader) { 862 if (mBrowsingContext->IsTop()) { 863 // If this is a top-level BrowsingContext, tell the frameloader it's time 864 // to go away. Otherwise, this is a subframe crash, and we can keep the 865 // frameloader around. 866 frameLoader->DestroyComplete(); 867 } 868 869 // If this was a crash, tell our nsFrameLoader to fire crash events. 870 if (why == AbnormalShutdown) { 871 frameLoader->MaybeNotifyCrashed(mBrowsingContext, Manager()->ChildID(), 872 GetIPCChannel()); 873 } else if (why == ManagedEndpointDropped) { 874 // If we instead failed due to a constructor error, don't include process 875 // information, as the process did not crash. 876 frameLoader->MaybeNotifyCrashed(mBrowsingContext, ContentParentId{}, 877 nullptr); 878 } 879 } 880 881 mFrameLoader = nullptr; 882 883 // If we were destroyed due to our ManagedEndpoints being dropped, make a 884 // point of showing the subframe crashed UI. We don't fire the full 885 // `MaybeNotifyCrashed` codepath, as the entire process hasn't crashed on us, 886 // and it may confuse the frontend. 887 mBrowsingContext->BrowserParentDestroyed( 888 this, why == AbnormalShutdown || why == ManagedEndpointDropped); 889 } 890 891 mozilla::ipc::IPCResult BrowserParent::RecvMoveFocus( 892 const bool& aForward, const bool& aForDocumentNavigation) { 893 LOGBROWSERFOCUS(("RecvMoveFocus %p, aForward: %d, aForDocumentNavigation: %d", 894 this, aForward, aForDocumentNavigation)); 895 BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent(); 896 if (bridgeParent) { 897 (void)bridgeParent->SendMoveFocus(aForward, aForDocumentNavigation); 898 return IPC_OK(); 899 } 900 901 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager(); 902 if (fm) { 903 RefPtr<Element> dummy; 904 905 uint32_t type = 906 aForward 907 ? (aForDocumentNavigation 908 ? static_cast<uint32_t>( 909 nsIFocusManager::MOVEFOCUS_FORWARDDOC) 910 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARD)) 911 : (aForDocumentNavigation 912 ? static_cast<uint32_t>( 913 nsIFocusManager::MOVEFOCUS_BACKWARDDOC) 914 : static_cast<uint32_t>( 915 nsIFocusManager::MOVEFOCUS_BACKWARD)); 916 fm->MoveFocus(nullptr, mFrameElement, type, nsIFocusManager::FLAG_BYKEY, 917 getter_AddRefs(dummy)); 918 } 919 return IPC_OK(); 920 } 921 922 mozilla::ipc::IPCResult BrowserParent::RecvDropLinks( 923 nsTArray<nsString>&& aLinks) { 924 nsCOMPtr<nsIBrowser> browser = 925 mFrameElement ? mFrameElement->AsBrowser() : nullptr; 926 if (browser) { 927 // Verify that links have not been modified by the child. If links have 928 // not been modified then it's safe to load those links using the 929 // SystemPrincipal. If they have been modified by web content, then 930 // we use a NullPrincipal which still allows to load web links. 931 bool loadUsingSystemPrincipal = true; 932 if (aLinks.Length() != mVerifyDropLinks.Length()) { 933 loadUsingSystemPrincipal = false; 934 } 935 for (uint32_t i = 0; i < aLinks.Length(); i++) { 936 if (loadUsingSystemPrincipal) { 937 if (!aLinks[i].Equals(mVerifyDropLinks[i])) { 938 loadUsingSystemPrincipal = false; 939 } 940 } 941 } 942 mVerifyDropLinks.Clear(); 943 nsCOMPtr<nsIPrincipal> triggeringPrincipal; 944 if (loadUsingSystemPrincipal) { 945 triggeringPrincipal = nsContentUtils::GetSystemPrincipal(); 946 } else { 947 triggeringPrincipal = NullPrincipal::CreateWithoutOriginAttributes(); 948 } 949 browser->DropLinks(aLinks, triggeringPrincipal); 950 } 951 return IPC_OK(); 952 } 953 954 bool BrowserParent::SendLoadRemoteScript(const nsAString& aURL, 955 const bool& aRunInGlobalScope) { 956 if (mCreatingWindow) { 957 mDelayedFrameScripts.AppendElement( 958 FrameScriptInfo(nsString(aURL), aRunInGlobalScope)); 959 return true; 960 } 961 962 MOZ_ASSERT(mDelayedFrameScripts.IsEmpty()); 963 return PBrowserParent::SendLoadRemoteScript(aURL, aRunInGlobalScope); 964 } 965 966 void BrowserParent::LoadURL(nsDocShellLoadState* aLoadState) { 967 MOZ_ASSERT(aLoadState); 968 MOZ_ASSERT(aLoadState->URI()); 969 if (mIsDestroyed) { 970 return; 971 } 972 973 if (mCreatingWindow) { 974 // Don't send the message if the child wants to load its own URL. 975 return; 976 } 977 978 (void)SendLoadURL(WrapNotNull(aLoadState), GetShowInfo()); 979 } 980 981 void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID) { 982 MOZ_ASSERT(aPendingSwitchID != 0); 983 984 if (NS_WARN_IF(mIsDestroyed)) { 985 return; 986 } 987 988 (void)SendResumeLoad(aPendingSwitchID, GetShowInfo()); 989 } 990 991 void BrowserParent::InitRendering() { 992 if (mRemoteLayerTreeOwner.IsInitialized()) { 993 return; 994 } 995 mRemoteLayerTreeOwner.Initialize(this); 996 997 layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId(); 998 AddBrowserParentToTable(layersId, this); 999 1000 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); 1001 if (frameLoader) { 1002 nsIFrame* frame = frameLoader->GetPrimaryFrameOfOwningContent(); 1003 if (frame) { 1004 frame->InvalidateFrame(); 1005 } 1006 } 1007 1008 TextureFactoryIdentifier textureFactoryIdentifier; 1009 mRemoteLayerTreeOwner.GetTextureFactoryIdentifier(&textureFactoryIdentifier); 1010 (void)SendInitRendering(textureFactoryIdentifier, layersId, 1011 mRemoteLayerTreeOwner.GetCompositorOptions(), 1012 mRemoteLayerTreeOwner.IsLayersConnected()); 1013 1014 RefPtr<nsIWidget> widget = GetTopLevelWidget(); 1015 if (widget) { 1016 (void)SendSafeAreaInsetsChanged(widget->GetSafeAreaInsets()); 1017 } 1018 1019 #if defined(MOZ_WIDGET_ANDROID) 1020 MOZ_ASSERT(widget); 1021 1022 if (GetBrowsingContext()->IsTopContent()) { 1023 (void)SendDynamicToolbarMaxHeightChanged( 1024 widget->GetDynamicToolbarMaxHeight()); 1025 } 1026 #endif 1027 } 1028 1029 bool BrowserParent::AttachWindowRenderer() { 1030 return mRemoteLayerTreeOwner.AttachWindowRenderer(); 1031 } 1032 1033 void BrowserParent::MaybeShowFrame() { 1034 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); 1035 if (!frameLoader) { 1036 return; 1037 } 1038 frameLoader->MaybeShowFrame(); 1039 } 1040 1041 bool BrowserParent::Show(const OwnerShowInfo& aOwnerInfo) { 1042 mDimensions = aOwnerInfo.size(); 1043 if (mIsDestroyed) { 1044 return false; 1045 } 1046 1047 MOZ_ASSERT(mRemoteLayerTreeOwner.IsInitialized()); 1048 if (!mRemoteLayerTreeOwner.AttachWindowRenderer()) { 1049 return false; 1050 } 1051 1052 mSizeMode = aOwnerInfo.sizeMode(); 1053 (void)SendShow(GetShowInfo(), aOwnerInfo); 1054 return true; 1055 } 1056 1057 mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions( 1058 mozilla::DimensionRequest aRequest, const double& aScale) { 1059 NS_ENSURE_TRUE(mFrameElement, IPC_OK()); 1060 nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell(); 1061 NS_ENSURE_TRUE(docShell, IPC_OK()); 1062 nsCOMPtr<nsIDocShellTreeOwner> treeOwner; 1063 docShell->GetTreeOwner(getter_AddRefs(treeOwner)); 1064 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner); 1065 NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK()); 1066 1067 // `BrowserChild` only sends the values to actually be changed, see more 1068 // details in `BrowserChild::SetDimensions()`. 1069 // Note that `BrowserChild::SetDimensions()` may be called before receiving 1070 // our `SendUIResolutionChanged()` call. Therefore, if given each coordinate 1071 // shouldn't be ignored, we need to recompute it if DPI has been changed. 1072 // And also note that don't use `mDefaultScale.scale` here since it may be 1073 // different from the result of `GetWidgetCSSToDeviceScale()`. 1074 // NOTE(emilio): We use GetWidgetCSSToDeviceScale() because the old scale is a 1075 // widget scale, and we only use the current scale to scale up/down the 1076 // relevant values. 1077 1078 CSSToLayoutDeviceScale oldScale((float)aScale); 1079 CSSToLayoutDeviceScale currentScale( 1080 (float)treeOwnerAsWin->GetWidgetCSSToDeviceScale()); 1081 1082 if (oldScale != currentScale) { 1083 auto rescaleFunc = [&oldScale, ¤tScale](LayoutDeviceIntCoord& aVal) { 1084 aVal = (LayoutDeviceCoord(aVal) / oldScale * currentScale).Rounded(); 1085 }; 1086 aRequest.mX.apply(rescaleFunc); 1087 aRequest.mY.apply(rescaleFunc); 1088 aRequest.mWidth.apply(rescaleFunc); 1089 aRequest.mHeight.apply(rescaleFunc); 1090 } 1091 1092 // treeOwner is the chrome tree owner, but we wan't the content tree owner. 1093 nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = do_GetInterface(treeOwner); 1094 NS_ENSURE_TRUE(webBrowserChrome, IPC_OK()); 1095 webBrowserChrome->SetDimensions(std::move(aRequest)); 1096 return IPC_OK(); 1097 } 1098 1099 nsresult BrowserParent::UpdatePosition() { 1100 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); 1101 if (!frameLoader) { 1102 return NS_OK; 1103 } 1104 LayoutDeviceIntRect windowDims; 1105 NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims), 1106 NS_ERROR_FAILURE); 1107 // Avoid updating sizes here. 1108 windowDims.SizeTo(mRect.Size()); 1109 UpdateDimensions(windowDims, mDimensions); 1110 return NS_OK; 1111 } 1112 1113 void BrowserParent::UpdateDimensions(const LayoutDeviceIntRect& rect, 1114 const LayoutDeviceIntSize& size) { 1115 if (mIsDestroyed) { 1116 return; 1117 } 1118 nsCOMPtr<nsIWidget> widget = GetWidget(); 1119 if (!widget) { 1120 NS_WARNING("No widget found in BrowserParent::UpdateDimensions"); 1121 return; 1122 } 1123 1124 LayoutDeviceIntPoint clientOffset = GetClientOffset(); 1125 LayoutDeviceIntPoint chromeOffset = !GetBrowserBridgeParent() 1126 ? GetChildProcessOffset() 1127 : LayoutDeviceIntPoint(); 1128 1129 if (!mUpdatedDimensions || mDimensions != size || !mRect.IsEqualEdges(rect) || 1130 clientOffset != mClientOffset || chromeOffset != mChromeOffset) { 1131 mUpdatedDimensions = true; 1132 mRect = rect; 1133 mDimensions = size; 1134 mClientOffset = clientOffset; 1135 mChromeOffset = chromeOffset; 1136 1137 (void)SendUpdateDimensions(GetDimensionInfo()); 1138 UpdateNativePointerLockCenter(widget); 1139 } 1140 } 1141 1142 DimensionInfo BrowserParent::GetDimensionInfo() { 1143 CSSRect unscaledRect = mRect / mDefaultScale; 1144 CSSSize unscaledSize = mDimensions / mDefaultScale; 1145 return DimensionInfo(unscaledRect, unscaledSize, mClientOffset, 1146 mChromeOffset); 1147 } 1148 1149 void BrowserParent::UpdateNativePointerLockCenter(nsIWidget* aWidget) { 1150 if (!mLockedNativePointer) { 1151 return; 1152 } 1153 aWidget->SetNativePointerLockCenter( 1154 LayoutDeviceIntRect(mChromeOffset, mDimensions).Center()); 1155 } 1156 1157 void BrowserParent::SizeModeChanged(const nsSizeMode& aSizeMode) { 1158 if (!mIsDestroyed && aSizeMode != mSizeMode) { 1159 mSizeMode = aSizeMode; 1160 (void)SendSizeModeChanged(aSizeMode); 1161 } 1162 } 1163 1164 void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) { 1165 if (!mIsDestroyed) { 1166 (void)SendDynamicToolbarMaxHeightChanged(aHeight); 1167 } 1168 } 1169 1170 void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) { 1171 if (!mIsDestroyed) { 1172 (void)SendDynamicToolbarOffsetChanged(aOffset); 1173 } 1174 } 1175 1176 #ifdef MOZ_WIDGET_ANDROID 1177 void BrowserParent::KeyboardHeightChanged(ScreenIntCoord aHeight) { 1178 if (!mIsDestroyed) { 1179 (void)SendKeyboardHeightChanged(aHeight); 1180 } 1181 } 1182 1183 void BrowserParent::AndroidPipModeChanged(bool aPipMode) { 1184 if (!mIsDestroyed) { 1185 (void)SendAndroidPipModeChanged(aPipMode); 1186 } 1187 } 1188 #endif 1189 1190 void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent, 1191 nsTArray<uint32_t>& aCharCodes) { 1192 if (!mIsDestroyed) { 1193 // Note that we don't need to mark aEvent is posted to a remote process 1194 // because the event may be dispatched to it as normal keyboard event. 1195 // Therefore, we should use local copy to send it. 1196 WidgetKeyboardEvent localEvent(aEvent); 1197 RequestingAccessKeyEventData::Set(localEvent); 1198 (void)SendHandleAccessKey(localEvent, aCharCodes); 1199 } 1200 } 1201 1202 void BrowserParent::Activate(uint64_t aActionId) { 1203 LOGBROWSERFOCUS(("Activate %p actionid: %" PRIu64, this, aActionId)); 1204 if (!mIsDestroyed) { 1205 SetTopLevelWebFocus(this); // Intentionally inside "if" 1206 (void)SendActivate(aActionId); 1207 } 1208 } 1209 1210 void BrowserParent::Deactivate(bool aWindowLowering, uint64_t aActionId) { 1211 LOGBROWSERFOCUS(("Deactivate %p actionid: %" PRIu64, this, aActionId)); 1212 if (!aWindowLowering) { 1213 UnsetTopLevelWebFocus(this); // Intentionally outside the next "if" 1214 } 1215 if (!mIsDestroyed) { 1216 (void)SendDeactivate(aActionId); 1217 } 1218 } 1219 1220 #ifdef ACCESSIBILITY 1221 a11y::PDocAccessibleParent* BrowserParent::AllocPDocAccessibleParent( 1222 PDocAccessibleParent* aParent, const uint64_t&, 1223 const MaybeDiscardedBrowsingContext&) { 1224 // Reference freed in DeallocPDocAccessibleParent. 1225 return a11y::DocAccessibleParent::New().take(); 1226 } 1227 1228 bool BrowserParent::DeallocPDocAccessibleParent(PDocAccessibleParent* aParent) { 1229 // Free reference from AllocPDocAccessibleParent. 1230 static_cast<a11y::DocAccessibleParent*>(aParent)->Release(); 1231 return true; 1232 } 1233 1234 mozilla::ipc::IPCResult BrowserParent::RecvPDocAccessibleConstructor( 1235 PDocAccessibleParent* aDoc, PDocAccessibleParent* aParentDoc, 1236 const uint64_t& aParentID, 1237 const MaybeDiscardedBrowsingContext& aBrowsingContext) { 1238 # if defined(ANDROID) 1239 MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor()); 1240 # endif 1241 auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc); 1242 1243 // If this tab is already shutting down just mark the new actor as shutdown 1244 // and ignore it. When the tab actor is destroyed it will be too. 1245 if (mIsDestroyed) { 1246 doc->MarkAsShutdown(); 1247 return IPC_OK(); 1248 } 1249 1250 if (aParentDoc) { 1251 // Iframe document rendered in the same process as its embedder. 1252 // A document should never directly be the parent of another document. 1253 // There should always be an outer doc accessible child of the outer 1254 // document containing the child. 1255 MOZ_ASSERT(aParentID); 1256 if (!aParentID) { 1257 return IPC_FAIL_NO_REASON(this); 1258 } 1259 1260 auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc); 1261 if (parentDoc->IsShutdown()) { 1262 // This can happen if parentDoc is an OOP iframe, but its embedder has 1263 // been destroyed. (DocAccessibleParent::Destroy destroys any child 1264 // documents.) The OOP iframe (and anything it embeds) will die soon 1265 // anyway, so mark this document as shutdown and ignore it. 1266 doc->MarkAsShutdown(); 1267 return IPC_OK(); 1268 } 1269 1270 if (aBrowsingContext) { 1271 doc->SetBrowsingContext(aBrowsingContext.get_canonical()); 1272 } 1273 1274 mozilla::ipc::IPCResult added = parentDoc->AddChildDoc(doc, aParentID); 1275 if (!added) { 1276 # ifdef DEBUG 1277 return added; 1278 # else 1279 return IPC_OK(); 1280 # endif 1281 } 1282 1283 # ifdef XP_WIN 1284 if (a11y::nsWinUtils::IsWindowEmulationStarted()) { 1285 doc->SetEmulatedWindowHandle(parentDoc->GetEmulatedWindowHandle()); 1286 } 1287 # endif 1288 1289 return IPC_OK(); 1290 } 1291 1292 if (aBrowsingContext) { 1293 doc->SetBrowsingContext(aBrowsingContext.get_canonical()); 1294 } 1295 1296 if (auto* bridge = GetBrowserBridgeParent()) { 1297 // Iframe document rendered in a different process to its embedder. 1298 // In this case, we don't get aParentDoc and aParentID. 1299 MOZ_ASSERT(!aParentDoc && !aParentID); 1300 doc->SetTopLevelInContentProcess(); 1301 a11y::ProxyCreated(doc); 1302 // It's possible the embedder accessible hasn't been set yet; e.g. 1303 // a hidden iframe. In that case, embedderDoc will be null and this will 1304 // be handled when the embedder is set. 1305 if (a11y::DocAccessibleParent* embedderDoc = 1306 bridge->GetEmbedderAccessibleDoc()) { 1307 mozilla::ipc::IPCResult added = embedderDoc->AddChildDoc(bridge); 1308 if (!added) { 1309 # ifdef DEBUG 1310 return added; 1311 # else 1312 return IPC_OK(); 1313 # endif 1314 } 1315 } 1316 return IPC_OK(); 1317 } else { 1318 // null aParentDoc means this document is at the top level in the child 1319 // process. That means it makes no sense to get an id for an accessible 1320 // that is its parent. 1321 MOZ_ASSERT(!aParentID); 1322 if (aParentID) { 1323 return IPC_FAIL_NO_REASON(this); 1324 } 1325 1326 if (auto* prevTopLevel = GetTopLevelDocAccessible()) { 1327 // Sometimes, we can get a new top level DocAccessibleParent before the 1328 // old one gets destroyed. The old one will die pretty shortly anyway, 1329 // so just destroy it now. If we don't do this, GetTopLevelDocAccessible() 1330 // might return the wrong document for a short while. 1331 prevTopLevel->Destroy(); 1332 } 1333 doc->SetTopLevel(); 1334 a11y::DocManager::RemoteDocAdded(doc); 1335 # ifdef XP_WIN 1336 doc->MaybeInitWindowEmulation(); 1337 # endif 1338 } 1339 return IPC_OK(); 1340 } 1341 #endif 1342 1343 already_AddRefed<PFilePickerParent> BrowserParent::AllocPFilePickerParent( 1344 const nsString& aTitle, const nsIFilePicker::Mode& aMode, 1345 const MaybeDiscarded<BrowsingContext>& aBrowsingContext) { 1346 RefPtr<CanonicalBrowsingContext> browsingContext = 1347 [&]() -> CanonicalBrowsingContext* { 1348 if (aBrowsingContext.IsNullOrDiscarded()) { 1349 return nullptr; 1350 } 1351 if (!aBrowsingContext.get_canonical()->IsOwnedByProcess( 1352 Manager()->ChildID())) { 1353 return nullptr; 1354 } 1355 return aBrowsingContext.get_canonical(); 1356 }(); 1357 return MakeAndAddRef<FilePickerParent>(aTitle, aMode, browsingContext); 1358 } 1359 1360 already_AddRefed<PSessionStoreParent> 1361 BrowserParent::AllocPSessionStoreParent() { 1362 RefPtr<BrowserSessionStore> sessionStore = 1363 BrowserSessionStore::GetOrCreate(mBrowsingContext->Top()); 1364 if (!sessionStore) { 1365 return nullptr; 1366 } 1367 1368 return do_AddRef(new SessionStoreParent(mBrowsingContext, sessionStore)); 1369 } 1370 1371 IPCResult BrowserParent::RecvNewWindowGlobal( 1372 ManagedEndpoint<PWindowGlobalParent>&& aEndpoint, 1373 const WindowGlobalInit& aInit) { 1374 RefPtr<CanonicalBrowsingContext> browsingContext = 1375 CanonicalBrowsingContext::Get(aInit.context().mBrowsingContextId); 1376 if (!browsingContext) { 1377 return IPC_FAIL(this, "Cannot create for missing BrowsingContext"); 1378 } 1379 if (!aInit.principal()) { 1380 return IPC_FAIL(this, "Cannot create without valid principal"); 1381 } 1382 1383 // Ensure we never load a document with a content principal in 1384 // the wrong type of webIsolated process 1385 EnumSet<ValidatePrincipalOptions> validationOptions = {}; 1386 nsCOMPtr<nsIURI> docURI = aInit.documentURI(); 1387 if (docURI->SchemeIs("blob") || docURI->SchemeIs("chrome")) { 1388 // XXXckerschb TODO - Do not use SystemPrincipal for: 1389 // Bug 1699385: Remove allowSystem for blobs 1390 // Bug 1698087: chrome://devtools/content/shared/webextension-fallback.html 1391 // chrome reftests, e.g. 1392 // * chrome://reftest/content/writing-mode/ua-style-sheet-button-1a-ref.html 1393 // * chrome://reftest/content/xul-document-load/test003.xhtml 1394 // * chrome://reftest/content/forms/input/text/centering-1.xhtml 1395 validationOptions = {ValidatePrincipalOptions::AllowSystem}; 1396 } 1397 1398 // Some reftests have frames inside their chrome URIs and those load 1399 // about:blank: 1400 if (xpc::IsInAutomation() && docURI->SchemeIs("about")) { 1401 WindowGlobalParent* wgp = browsingContext->GetParentWindowContext(); 1402 nsAutoCString spec; 1403 NS_ENSURE_SUCCESS(docURI->GetSpec(spec), 1404 IPC_FAIL(this, "Should have spec for about: URI")); 1405 if (spec.Equals("about:blank") && wgp && 1406 wgp->DocumentPrincipal()->IsSystemPrincipal()) { 1407 validationOptions = {ValidatePrincipalOptions::AllowSystem}; 1408 } 1409 } 1410 1411 if (!Manager()->ValidatePrincipal(aInit.principal(), validationOptions)) { 1412 ContentParent::LogAndAssertFailedPrincipalValidationInfo(aInit.principal(), 1413 __func__); 1414 } 1415 1416 // Construct our new WindowGlobalParent, bind, and initialize it. 1417 RefPtr<WindowGlobalParent> wgp = 1418 WindowGlobalParent::CreateDisconnected(aInit); 1419 BindPWindowGlobalEndpoint(std::move(aEndpoint), wgp); 1420 wgp->Init(); 1421 return IPC_OK(); 1422 } 1423 1424 already_AddRefed<PVsyncParent> BrowserParent::AllocPVsyncParent() { 1425 return MakeAndAddRef<VsyncParent>(); 1426 } 1427 1428 IPCResult BrowserParent::RecvPVsyncConstructor(PVsyncParent* aActor) { 1429 UpdateVsyncParentVsyncDispatcher(); 1430 return IPC_OK(); 1431 } 1432 1433 void BrowserParent::UpdateVsyncParentVsyncDispatcher() { 1434 VsyncParent* actor = static_cast<VsyncParent*>( 1435 LoneManagedOrNullAsserts(ManagedPVsyncParent())); 1436 if (!actor) { 1437 return; 1438 } 1439 1440 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1441 RefPtr<VsyncDispatcher> vsyncDispatcher = widget->GetVsyncDispatcher(); 1442 if (!vsyncDispatcher) { 1443 vsyncDispatcher = gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher(); 1444 } 1445 actor->UpdateVsyncDispatcher(vsyncDispatcher); 1446 } 1447 } 1448 1449 void BrowserParent::MouseEnterIntoWidget() { 1450 if (const nsCOMPtr<nsIWidget> widget = GetWidget()) { 1451 // When we mouseenter the remote target, the remote target's cursor should 1452 // become the current cursor. When we mouseexit, we stop. 1453 mRemoteTargetSetsCursor = true; 1454 MOZ_LOG_DEBUG_ONLY( 1455 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Debug, 1456 ("BrowserParent::MouseEnterIntoWidget(): Got the rights to update " 1457 "cursor (%p, widget=%p)", 1458 this, widget.get())); 1459 if (!EventStateManager::CursorSettingManagerHasLockedCursor()) { 1460 widget->SetCursor(mCursor); 1461 EventStateManager::ClearCursorSettingManager(); 1462 MOZ_LOG_DEBUG_ONLY(EventStateManager::MouseCursorUpdateLogRef(), 1463 LogLevel::Info, 1464 ("BrowserParent::MouseEnterIntoWidget(): Updated " 1465 "cursor to the pending one (%p, widget=%p)", 1466 this, widget.get())); 1467 } 1468 } 1469 1470 // Mark that we have missed a mouse enter event, so that 1471 // the next mouse event will create a replacement mouse 1472 // enter event and send it to the child. 1473 mIsMouseEnterIntoWidgetEventSuppressed = true; 1474 } 1475 1476 void BrowserParent::SendRealMouseEvent(WidgetMouseEvent& aEvent) { 1477 if (mIsDestroyed) { 1478 return; 1479 } 1480 1481 // XXXedgar, if the synthesized mouse events could deliver to the correct 1482 // process directly (see 1483 // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably don't 1484 // need to check mReason then. 1485 if (aEvent.mReason == WidgetMouseEvent::eReal) { 1486 if (aEvent.mMessage == eMouseExitFromWidget) { 1487 // Since we are leaving this remote target, so don't need to update 1488 // sLastMouseRemoteTarget, and if we are sLastMouseRemoteTarget, reset it 1489 // to null. 1490 BrowserParent::UnsetLastMouseRemoteTarget(this); 1491 } else { 1492 // Last remote target should not be changed without eMouseExitFromWidget. 1493 MOZ_ASSERT_IF(sLastMouseRemoteTarget, sLastMouseRemoteTarget == this); 1494 sLastMouseRemoteTarget = this; 1495 } 1496 } 1497 1498 aEvent.mRefPoint = TransformParentToChild(aEvent); 1499 1500 if (const nsCOMPtr<nsIWidget> widget = GetWidget()) { 1501 // When we mouseenter the remote target, the remote target's cursor should 1502 // become the current cursor. When we mouseexit, we stop. 1503 // XXX We update cursor even for non-mouse pointer moves in 1504 // EventStateManager. Thus, we might not be able to manage it only with 1505 // eMouseEnterIntoWidget and eMouseExitFromWidget. 1506 if (eMouseEnterIntoWidget == aEvent.mMessage) { 1507 mRemoteTargetSetsCursor = true; 1508 MOZ_LOG_DEBUG_ONLY( 1509 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Debug, 1510 ("BrowserParent::SendRealMouseEvent(aEvent={pointerId=%u, source=%s, " 1511 "message=%s, reason=%s}): Got the rights to update cursor (%p, " 1512 "widget=%p)", 1513 aEvent.pointerId, InputSourceToString(aEvent.mInputSource).get(), 1514 ToChar(aEvent.mMessage), RealOrSynthesized(aEvent.IsReal()), this, 1515 widget.get())); 1516 if (!EventStateManager::CursorSettingManagerHasLockedCursor()) { 1517 widget->SetCursor(mCursor); 1518 EventStateManager::ClearCursorSettingManager(); 1519 MOZ_LOG_DEBUG_ONLY( 1520 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Info, 1521 ("BrowserParent::SendRealMouseEvent(aEvent={pointerId=%u, " 1522 "source=%s, message=%s, reason=%s): Updated cursor to the pending " 1523 "one (%p, widget=%p)", 1524 aEvent.pointerId, InputSourceToString(aEvent.mInputSource).get(), 1525 ToChar(aEvent.mMessage), RealOrSynthesized(aEvent.IsReal()), this, 1526 widget.get())); 1527 } 1528 } else if (eMouseExitFromWidget == aEvent.mMessage) { 1529 mRemoteTargetSetsCursor = false; 1530 MOZ_LOG_DEBUG_ONLY( 1531 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Debug, 1532 ("BrowserParent::SendRealMouseEvent(aEvent={pointerId=%u, source=%s, " 1533 "message=%s, reason=%s}): Lost the rights to update cursor (%p, " 1534 "widget=%p)", 1535 aEvent.pointerId, InputSourceToString(aEvent.mInputSource).get(), 1536 ToChar(aEvent.mMessage), RealOrSynthesized(aEvent.IsReal()), this, 1537 widget.get())); 1538 } 1539 } 1540 if (!mIsReadyToHandleInputEvents) { 1541 if (eMouseEnterIntoWidget == aEvent.mMessage) { 1542 mIsMouseEnterIntoWidgetEventSuppressed = true; 1543 } else if (eMouseExitFromWidget == aEvent.mMessage) { 1544 mIsMouseEnterIntoWidgetEventSuppressed = false; 1545 } 1546 return; 1547 } 1548 1549 ScrollableLayerGuid guid; 1550 uint64_t blockId; 1551 ApzAwareEventRoutingToChild(&guid, &blockId, nullptr); 1552 1553 bool isInputPriorityEventEnabled = Manager()->IsInputPriorityEventEnabled(); 1554 1555 if (mIsMouseEnterIntoWidgetEventSuppressed) { 1556 // In the case that the BrowserParent suppressed the eMouseEnterWidget event 1557 // due to its corresponding BrowserChild wasn't ready to handle it, we have 1558 // to resend it when the BrowserChild is ready. 1559 mIsMouseEnterIntoWidgetEventSuppressed = false; 1560 WidgetMouseEvent localEvent(aEvent); 1561 localEvent.mMessage = eMouseEnterIntoWidget; 1562 DebugOnly<bool> ret = 1563 isInputPriorityEventEnabled 1564 ? SendRealMouseEnterExitWidgetEvent(localEvent, guid, blockId) 1565 : SendNormalPriorityRealMouseEnterExitWidgetEvent(localEvent, guid, 1566 blockId); 1567 NS_WARNING_ASSERTION(ret, "SendRealMouseEnterExitWidgetEvent() failed"); 1568 MOZ_ASSERT(!ret || localEvent.HasBeenPostedToRemoteProcess()); 1569 } 1570 1571 if (eMouseMove == aEvent.mMessage) { 1572 if (aEvent.mReason == WidgetMouseEvent::eSynthesized) { 1573 DebugOnly<bool> ret = 1574 isInputPriorityEventEnabled 1575 ? SendSynthMouseMoveEvent(aEvent, guid, blockId) 1576 : SendNormalPrioritySynthMouseMoveEvent(aEvent, guid, blockId); 1577 NS_WARNING_ASSERTION(ret, "SendSynthMouseMoveEvent() failed"); 1578 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1579 return; 1580 } 1581 1582 if (!aEvent.mFlags.mIsSynthesizedForTests) { 1583 DebugOnly<bool> ret = 1584 isInputPriorityEventEnabled 1585 ? SendRealMouseMoveEvent(aEvent, guid, blockId) 1586 : SendNormalPriorityRealMouseMoveEvent(aEvent, guid, blockId); 1587 NS_WARNING_ASSERTION(ret, "SendRealMouseMoveEvent() failed"); 1588 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1589 return; 1590 } 1591 1592 DebugOnly<bool> ret = 1593 isInputPriorityEventEnabled 1594 ? SendRealMouseMoveEventForTests(aEvent, guid, blockId) 1595 : SendNormalPriorityRealMouseMoveEventForTests(aEvent, guid, 1596 blockId); 1597 NS_WARNING_ASSERTION(ret, "SendRealMouseMoveEventForTests() failed"); 1598 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1599 return; 1600 } 1601 1602 if (eMouseEnterIntoWidget == aEvent.mMessage || 1603 eMouseExitFromWidget == aEvent.mMessage) { 1604 DebugOnly<bool> ret = 1605 isInputPriorityEventEnabled 1606 ? SendRealMouseEnterExitWidgetEvent(aEvent, guid, blockId) 1607 : SendNormalPriorityRealMouseEnterExitWidgetEvent(aEvent, guid, 1608 blockId); 1609 NS_WARNING_ASSERTION(ret, "SendRealMouseEnterExitWidgetEvent() failed"); 1610 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1611 return; 1612 } 1613 1614 DebugOnly<bool> ret = 1615 isInputPriorityEventEnabled 1616 ? aEvent.mClass == ePointerEventClass 1617 ? SendRealPointerButtonEvent(*aEvent.AsPointerEvent(), guid, 1618 blockId) 1619 : SendRealMouseButtonEvent(aEvent, guid, blockId) 1620 : aEvent.mClass == ePointerEventClass 1621 ? SendNormalPriorityRealPointerButtonEvent(*aEvent.AsPointerEvent(), 1622 guid, blockId) 1623 : SendNormalPriorityRealMouseButtonEvent(aEvent, guid, blockId); 1624 NS_WARNING_ASSERTION(ret, "SendRealMouseButtonEvent() failed"); 1625 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1626 } 1627 1628 LayoutDeviceToCSSScale BrowserParent::GetLayoutDeviceToCSSScale() { 1629 Document* doc = (mFrameElement ? mFrameElement->OwnerDoc() : nullptr); 1630 nsPresContext* ctx = (doc ? doc->GetPresContext() : nullptr); 1631 return LayoutDeviceToCSSScale( 1632 ctx ? (float)ctx->AppUnitsPerDevPixel() / AppUnitsPerCSSPixel() : 0.0f); 1633 } 1634 1635 bool BrowserParent::QueryDropLinksForVerification() { 1636 // Before sending the dragEvent, we query the links being dragged and 1637 // store them on the parent, to make sure the child can not modify links. 1638 RefPtr<nsIWidget> widget = GetTopLevelWidget(); 1639 nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession(widget); 1640 if (!dragSession) { 1641 NS_WARNING("No dragSession to query links for verification"); 1642 return false; 1643 } 1644 1645 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer(); 1646 if (!initialDataTransfer) { 1647 NS_WARNING("No initialDataTransfer to query links for verification"); 1648 return false; 1649 } 1650 1651 nsCOMPtr<nsIDroppedLinkHandler> dropHandler = 1652 do_GetService("@mozilla.org/content/dropped-link-handler;1"); 1653 if (!dropHandler) { 1654 NS_WARNING("No dropHandler to query links for verification"); 1655 return false; 1656 } 1657 1658 // No more than one drop event can happen simultaneously; reset the link 1659 // verification array and store all links that are being dragged. 1660 mVerifyDropLinks.Clear(); 1661 1662 nsTArray<RefPtr<nsIDroppedLinkItem>> droppedLinkItems; 1663 dropHandler->QueryLinks(initialDataTransfer, droppedLinkItems); 1664 1665 // Since the entire event is cancelled if one of the links is invalid, 1666 // we can store all links on the parent side without any prior 1667 // validation checks. 1668 nsresult rv = NS_OK; 1669 for (nsIDroppedLinkItem* item : droppedLinkItems) { 1670 nsString tmp; 1671 rv = item->GetUrl(tmp); 1672 if (NS_FAILED(rv)) { 1673 NS_WARNING("Failed to query url for verification"); 1674 break; 1675 } 1676 mVerifyDropLinks.AppendElement(tmp); 1677 1678 rv = item->GetName(tmp); 1679 if (NS_FAILED(rv)) { 1680 NS_WARNING("Failed to query name for verification"); 1681 break; 1682 } 1683 mVerifyDropLinks.AppendElement(tmp); 1684 1685 rv = item->GetType(tmp); 1686 if (NS_FAILED(rv)) { 1687 NS_WARNING("Failed to query type for verification"); 1688 break; 1689 } 1690 mVerifyDropLinks.AppendElement(tmp); 1691 } 1692 if (NS_FAILED(rv)) { 1693 mVerifyDropLinks.Clear(); 1694 return false; 1695 } 1696 return true; 1697 } 1698 1699 void BrowserParent::SendRealDragEvent(WidgetDragEvent& aEvent, 1700 uint32_t aDragAction, 1701 uint32_t aDropEffect, 1702 nsIPrincipal* aPrincipal, 1703 nsIPolicyContainer* aPolicyContainer) { 1704 if (mIsDestroyed || !mIsReadyToHandleInputEvents) { 1705 return; 1706 } 1707 MOZ_ASSERT(!Manager()->IsInputPriorityEventEnabled()); 1708 aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint); 1709 if (aEvent.mMessage == eDrop) { 1710 if (!QueryDropLinksForVerification()) { 1711 return; 1712 } 1713 } 1714 DebugOnly<bool> ret = PBrowserParent::SendRealDragEvent( 1715 aEvent, aDragAction, aDropEffect, aPrincipal, aPolicyContainer); 1716 NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealDragEvent() failed"); 1717 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1718 } 1719 1720 void BrowserParent::SendMouseWheelEvent(WidgetWheelEvent& aEvent) { 1721 if (mIsDestroyed || !mIsReadyToHandleInputEvents) { 1722 return; 1723 } 1724 1725 ScrollableLayerGuid guid; 1726 uint64_t blockId; 1727 ApzAwareEventRoutingToChild(&guid, &blockId, nullptr); 1728 aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint); 1729 DebugOnly<bool> ret = 1730 Manager()->IsInputPriorityEventEnabled() 1731 ? PBrowserParent::SendMouseWheelEvent(aEvent, guid, blockId) 1732 : PBrowserParent::SendNormalPriorityMouseWheelEvent(aEvent, guid, 1733 blockId); 1734 1735 NS_WARNING_ASSERTION(ret, "PBrowserParent::SendMouseWheelEvent() failed"); 1736 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 1737 } 1738 1739 mozilla::ipc::IPCResult BrowserParent::RecvDispatchWheelEvent( 1740 const mozilla::WidgetWheelEvent& aEvent) { 1741 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1742 1743 nsCOMPtr<nsIWidget> widget = GetWidget(); 1744 if (!widget) { 1745 return IPC_OK(); 1746 } 1747 1748 WidgetWheelEvent localEvent(aEvent); 1749 localEvent.mWidget = widget; 1750 localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint); 1751 1752 widget->DispatchInputEvent(&localEvent); 1753 return IPC_OK(); 1754 } 1755 1756 mozilla::ipc::IPCResult BrowserParent::RecvDispatchMouseEvent( 1757 const mozilla::WidgetMouseEvent& aEvent) { 1758 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1759 1760 nsCOMPtr<nsIWidget> widget = GetWidget(); 1761 if (!widget) { 1762 return IPC_OK(); 1763 } 1764 1765 WidgetMouseEvent localEvent(aEvent); 1766 localEvent.mWidget = widget; 1767 localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint); 1768 1769 widget->DispatchInputEvent(&localEvent); 1770 return IPC_OK(); 1771 } 1772 1773 mozilla::ipc::IPCResult BrowserParent::RecvDispatchKeyboardEvent( 1774 const mozilla::WidgetKeyboardEvent& aEvent) { 1775 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1776 1777 nsCOMPtr<nsIWidget> widget = GetWidget(); 1778 if (!widget) { 1779 return IPC_OK(); 1780 } 1781 1782 WidgetKeyboardEvent localEvent(aEvent); 1783 localEvent.mWidget = widget; 1784 localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint); 1785 1786 widget->DispatchInputEvent(&localEvent); 1787 return IPC_OK(); 1788 } 1789 1790 mozilla::ipc::IPCResult BrowserParent::RecvDispatchTouchEvent( 1791 const mozilla::WidgetTouchEvent& aEvent) { 1792 // This is used by DevTools to emulate touch events from mouse events in the 1793 // responsive design mode. Therefore, we should accept the IPC messages even 1794 // if it's not in the automation mode but the browsing context is in RDM pane. 1795 // And the IPC message could be just delayed after closing the responsive 1796 // design mode. Therefore, we shouldn't return IPC_FAIL since doing it makes 1797 // the tab crash. 1798 if (!xpc::IsInAutomation()) { 1799 NS_ENSURE_TRUE(mBrowsingContext, IPC_OK()); 1800 NS_ENSURE_TRUE(mBrowsingContext->Top()->GetInRDMPane(), IPC_OK()); 1801 } 1802 1803 nsCOMPtr<nsIWidget> widget = GetWidget(); 1804 if (!widget) { 1805 return IPC_OK(); 1806 } 1807 1808 WidgetTouchEvent localEvent(aEvent); 1809 localEvent.mWidget = widget; 1810 1811 for (uint32_t i = 0; i < localEvent.mTouches.Length(); i++) { 1812 localEvent.mTouches[i]->mRefPoint = 1813 TransformChildToParent(localEvent.mTouches[i]->mRefPoint); 1814 } 1815 1816 widget->DispatchInputEvent(&localEvent); 1817 return IPC_OK(); 1818 } 1819 1820 mozilla::ipc::IPCResult BrowserParent::RecvRequestNativeKeyBindings( 1821 const uint32_t& aType, const WidgetKeyboardEvent& aEvent, 1822 nsTArray<CommandInt>* aCommands) { 1823 MOZ_ASSERT(aCommands); 1824 MOZ_ASSERT(aCommands->IsEmpty()); 1825 1826 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1827 1828 NativeKeyBindingsType keyBindingsType = 1829 static_cast<NativeKeyBindingsType>(aType); 1830 switch (keyBindingsType) { 1831 case NativeKeyBindingsType::SingleLineEditor: 1832 case NativeKeyBindingsType::MultiLineEditor: 1833 case NativeKeyBindingsType::RichTextEditor: 1834 break; 1835 default: 1836 return IPC_FAIL(this, "Invalid aType value"); 1837 } 1838 1839 nsCOMPtr<nsIWidget> widget = GetWidget(); 1840 if (!widget) { 1841 return IPC_OK(); 1842 } 1843 1844 WidgetKeyboardEvent localEvent(aEvent); 1845 localEvent.mWidget = widget; 1846 1847 if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) { 1848 return IPC_OK(); 1849 } 1850 1851 Maybe<WritingMode> writingMode; 1852 if (RefPtr<widget::TextEventDispatcher> dispatcher = 1853 widget->GetTextEventDispatcher()) { 1854 writingMode = dispatcher->MaybeQueryWritingModeAtSelection(); 1855 } 1856 if (localEvent.InitEditCommandsFor(keyBindingsType, writingMode)) { 1857 *aCommands = localEvent.EditCommandsConstRef(keyBindingsType).Clone(); 1858 } 1859 1860 return IPC_OK(); 1861 } 1862 1863 class SynthesizedEventCallback final : public nsISynthesizedEventCallback { 1864 NS_DECL_ISUPPORTS 1865 1866 public: 1867 SynthesizedEventCallback(BrowserParent* aBrowserParent, 1868 const uint64_t& aCallbackId) 1869 : mBrowserParent(aBrowserParent), mCallbackId(aCallbackId) { 1870 MOZ_ASSERT(xpc::IsInAutomation()); 1871 MOZ_ASSERT(mBrowserParent); 1872 MOZ_ASSERT(mCallbackId > 0, "Invalid callback ID"); 1873 } 1874 1875 NS_IMETHOD OnCompleteDispatch() override { 1876 MOZ_ASSERT(mCallbackId > 0, "Invalid callback ID"); 1877 1878 if (!mBrowserParent) { 1879 // We already sent the notification, or we don't actually need to 1880 // send any notification at all. 1881 MOZ_ASSERT_UNREACHABLE("OnCompleteDispatch called multiple times"); 1882 return NS_OK; 1883 } 1884 1885 if (mBrowserParent->IsDestroyed()) { 1886 // If this happens it's probably a bug in the test that's triggering this. 1887 NS_WARNING( 1888 "BrowserParent was unexpectedly destroyed during event " 1889 "synthesization!"); 1890 } else if (!mBrowserParent->SendSynthesizedEventResponse(mCallbackId)) { 1891 NS_WARNING("Unable to send native event synthesization response!"); 1892 } 1893 1894 // Null out browserParent to indicate we already sent the response 1895 mBrowserParent = nullptr; 1896 return NS_OK; 1897 } 1898 1899 static already_AddRefed<SynthesizedEventCallback> MaybeCreate( 1900 BrowserParent* aBrowserParent, const Maybe<uint64_t>& aCallbackId) { 1901 if (aCallbackId.isNothing()) { 1902 // No callback ID means we don't need to send a response. 1903 return nullptr; 1904 } 1905 return MakeAndAddRef<SynthesizedEventCallback>(aBrowserParent, 1906 aCallbackId.value()); 1907 } 1908 1909 private: 1910 virtual ~SynthesizedEventCallback() { 1911 if (mBrowserParent) { 1912 NS_WARNING( 1913 "SynthesizedEventCallback destroyed without calling " 1914 "OnCompleteDispatch!"); 1915 } 1916 }; 1917 1918 RefPtr<BrowserParent> mBrowserParent; 1919 uint64_t mCallbackId; 1920 }; 1921 1922 NS_IMPL_ISUPPORTS(SynthesizedEventCallback, nsISynthesizedEventCallback) 1923 1924 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeKeyEvent( 1925 const int32_t& aNativeKeyboardLayout, const int32_t& aNativeKeyCode, 1926 const uint32_t& aModifierFlags, const nsString& aCharacters, 1927 const nsString& aUnmodifiedCharacters, const Maybe<uint64_t>& aCallbackId) { 1928 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1929 1930 nsCOMPtr<nsISynthesizedEventCallback> callback = 1931 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 1932 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1933 widget->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode, 1934 aModifierFlags, aCharacters, 1935 aUnmodifiedCharacters, callback); 1936 } 1937 return IPC_OK(); 1938 } 1939 1940 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseEvent( 1941 const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage, 1942 const int16_t& aButton, const uint32_t& aModifierFlags, 1943 const Maybe<uint64_t>& aCallbackId) { 1944 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1945 1946 const uint32_t last = 1947 static_cast<uint32_t>(nsIWidget::NativeMouseMessage::LeaveWindow); 1948 NS_ENSURE_TRUE(aNativeMessage <= last, IPC_FAIL(this, "Bogus message")); 1949 1950 nsCOMPtr<nsISynthesizedEventCallback> callback = 1951 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 1952 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1953 widget->SynthesizeNativeMouseEvent( 1954 aPoint, static_cast<nsIWidget::NativeMouseMessage>(aNativeMessage), 1955 static_cast<mozilla::MouseButton>(aButton), 1956 static_cast<nsIWidget::Modifiers>(aModifierFlags), callback); 1957 } 1958 return IPC_OK(); 1959 } 1960 1961 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseMove( 1962 const LayoutDeviceIntPoint& aPoint, const Maybe<uint64_t>& aCallbackId) { 1963 // This is used by pointer lock API. So, even if it's not in the automation 1964 // mode, we need to accept the request. 1965 nsCOMPtr<nsISynthesizedEventCallback> callback = 1966 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 1967 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1968 widget->SynthesizeNativeMouseMove(aPoint, callback); 1969 } 1970 return IPC_OK(); 1971 } 1972 1973 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseScrollEvent( 1974 const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage, 1975 const double& aDeltaX, const double& aDeltaY, const double& aDeltaZ, 1976 const uint32_t& aModifierFlags, const uint32_t& aAdditionalFlags, 1977 const Maybe<uint64_t>& aCallbackId) { 1978 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1979 1980 nsCOMPtr<nsISynthesizedEventCallback> callback = 1981 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 1982 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1983 widget->SynthesizeNativeMouseScrollEvent(aPoint, aNativeMessage, aDeltaX, 1984 aDeltaY, aDeltaZ, aModifierFlags, 1985 aAdditionalFlags, callback); 1986 } 1987 return IPC_OK(); 1988 } 1989 1990 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchPoint( 1991 const uint32_t& aPointerId, const TouchPointerState& aPointerState, 1992 const LayoutDeviceIntPoint& aPoint, const double& aPointerPressure, 1993 const uint32_t& aPointerOrientation, const Maybe<uint64_t>& aCallbackId) { 1994 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 1995 1996 nsCOMPtr<nsISynthesizedEventCallback> callback = 1997 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 1998 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 1999 widget->SynthesizeNativeTouchPoint(aPointerId, aPointerState, aPoint, 2000 aPointerPressure, aPointerOrientation, 2001 callback); 2002 } 2003 return IPC_OK(); 2004 } 2005 2006 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchPadPinch( 2007 const TouchpadGesturePhase& aEventPhase, const float& aScale, 2008 const LayoutDeviceIntPoint& aPoint, const int32_t& aModifierFlags) { 2009 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 2010 2011 nsCOMPtr<nsIWidget> widget = GetWidget(); 2012 if (widget) { 2013 widget->SynthesizeNativeTouchPadPinch(aEventPhase, aScale, aPoint, 2014 aModifierFlags); 2015 } 2016 return IPC_OK(); 2017 } 2018 2019 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchTap( 2020 const LayoutDeviceIntPoint& aPoint, const bool& aLongTap, 2021 const Maybe<uint64_t>& aCallbackId) { 2022 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 2023 2024 nsCOMPtr<nsISynthesizedEventCallback> callback = 2025 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 2026 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 2027 widget->SynthesizeNativeTouchTap(aPoint, aLongTap, callback); 2028 } 2029 return IPC_OK(); 2030 } 2031 2032 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativePenInput( 2033 const uint32_t& aPointerId, const TouchPointerState& aPointerState, 2034 const LayoutDeviceIntPoint& aPoint, const double& aPressure, 2035 const uint32_t& aRotation, const int32_t& aTiltX, const int32_t& aTiltY, 2036 const int32_t& aButton, const Maybe<uint64_t>& aCallbackId) { 2037 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 2038 2039 nsCOMPtr<nsISynthesizedEventCallback> callback = 2040 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 2041 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 2042 widget->SynthesizeNativePenInput(aPointerId, aPointerState, aPoint, 2043 aPressure, aRotation, aTiltX, aTiltY, 2044 aButton, callback); 2045 } 2046 return IPC_OK(); 2047 } 2048 2049 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchpadDoubleTap( 2050 const LayoutDeviceIntPoint& aPoint, const uint32_t& aModifierFlags) { 2051 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 2052 2053 nsCOMPtr<nsIWidget> widget = GetWidget(); 2054 if (widget) { 2055 widget->SynthesizeNativeTouchpadDoubleTap(aPoint, aModifierFlags); 2056 } 2057 return IPC_OK(); 2058 } 2059 2060 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchpadPan( 2061 const TouchpadGesturePhase& aEventPhase, const LayoutDeviceIntPoint& aPoint, 2062 const double& aDeltaX, const double& aDeltaY, const int32_t& aModifierFlags, 2063 const Maybe<uint64_t>& aCallbackId) { 2064 NS_ENSURE_TRUE(xpc::IsInAutomation(), IPC_FAIL(this, "Unexpected event")); 2065 2066 nsCOMPtr<nsISynthesizedEventCallback> callback = 2067 SynthesizedEventCallback::MaybeCreate(this, aCallbackId); 2068 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 2069 widget->SynthesizeNativeTouchpadPan(aEventPhase, aPoint, aDeltaX, aDeltaY, 2070 aModifierFlags, callback); 2071 } 2072 return IPC_OK(); 2073 } 2074 2075 mozilla::ipc::IPCResult BrowserParent::RecvLockNativePointer() { 2076 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 2077 mLockedNativePointer = true; // do before updating the center 2078 UpdateNativePointerLockCenter(widget); 2079 widget->LockNativePointer(); 2080 } 2081 return IPC_OK(); 2082 } 2083 2084 void BrowserParent::UnlockNativePointer() { 2085 if (!mLockedNativePointer) { 2086 return; 2087 } 2088 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 2089 widget->UnlockNativePointer(); 2090 mLockedNativePointer = false; 2091 } 2092 } 2093 2094 mozilla::ipc::IPCResult BrowserParent::RecvUnlockNativePointer() { 2095 UnlockNativePointer(); 2096 return IPC_OK(); 2097 } 2098 2099 void BrowserParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent) { 2100 if (mIsDestroyed || !mIsReadyToHandleInputEvents) { 2101 return; 2102 } 2103 aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint); 2104 2105 // NOTE: If you call `InitAllEditCommands()` for the other messages too, 2106 // you also need to update 2107 // TextEventDispatcher::DispatchKeyboardEventInternal(). 2108 if (aEvent.mMessage == eKeyPress) { 2109 // If current input context is editable, the edit commands are initialized 2110 // by TextEventDispatcher::DispatchKeyboardEventInternal(). Otherwise, 2111 // we need to do it here (they are not necessary for the parent process, 2112 // therefore, we need to do it here for saving the runtime cost). 2113 if (!aEvent.AreAllEditCommandsInitialized()) { 2114 // XXX Is it good thing that the keypress event will be handled in an 2115 // editor even though the user pressed the key combination before the 2116 // focus change has not been completed in the parent process yet or 2117 // focus change will happen? If no, we can stop doing this. 2118 Maybe<WritingMode> writingMode; 2119 if (aEvent.mWidget) { 2120 if (RefPtr<widget::TextEventDispatcher> dispatcher = 2121 aEvent.mWidget->GetTextEventDispatcher()) { 2122 writingMode = dispatcher->MaybeQueryWritingModeAtSelection(); 2123 } 2124 } 2125 aEvent.InitAllEditCommands(writingMode); 2126 } 2127 } else { 2128 aEvent.PreventNativeKeyBindings(); 2129 } 2130 SentKeyEventData sendKeyEventData{ 2131 aEvent.mKeyCode, aEvent.mCharCode, aEvent.mPseudoCharCode, 2132 aEvent.mKeyNameIndex, aEvent.mCodeNameIndex, aEvent.mModifiers, 2133 nsID::GenerateUUID()}; 2134 const bool ok = 2135 Manager()->IsInputPriorityEventEnabled() 2136 ? PBrowserParent::SendRealKeyEvent(aEvent, sendKeyEventData.mUUID) 2137 : PBrowserParent::SendNormalPriorityRealKeyEvent( 2138 aEvent, sendKeyEventData.mUUID); 2139 2140 NS_WARNING_ASSERTION(ok, "PBrowserParent::SendRealKeyEvent() failed"); 2141 MOZ_ASSERT(!ok || aEvent.HasBeenPostedToRemoteProcess()); 2142 if (ok && aEvent.IsWaitingReplyFromRemoteProcess()) { 2143 mWaitingReplyKeyboardEvents.AppendElement(sendKeyEventData); 2144 } 2145 } 2146 2147 void BrowserParent::SendRealTouchEvent(WidgetTouchEvent& aEvent) { 2148 if (mIsDestroyed || !mIsReadyToHandleInputEvents) { 2149 return; 2150 } 2151 2152 // PresShell::HandleEventInternal adds touches on touch end/cancel. This 2153 // confuses remote content and the panning and zooming logic into thinking 2154 // that the added touches are part of the touchend/cancel, when actually 2155 // they're not. 2156 if (aEvent.mMessage == eTouchEnd || aEvent.mMessage == eTouchCancel) { 2157 aEvent.mTouches.RemoveElementsBy( 2158 [](const auto& touch) { return !touch->mChanged; }); 2159 } 2160 2161 APZData apzData; 2162 ApzAwareEventRoutingToChild(&apzData.guid, &apzData.blockId, 2163 &apzData.apzResponse); 2164 2165 if (mIsDestroyed) { 2166 return; 2167 } 2168 2169 for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) { 2170 aEvent.mTouches[i]->mRefPoint = 2171 TransformParentToChild(aEvent.mTouches[i]->mRefPoint); 2172 } 2173 2174 static uint32_t sConsecutiveTouchMoveCount = 0; 2175 if (aEvent.mMessage == eTouchMove) { 2176 ++sConsecutiveTouchMoveCount; 2177 SendRealTouchMoveEvent(aEvent, apzData, sConsecutiveTouchMoveCount); 2178 return; 2179 } 2180 2181 sConsecutiveTouchMoveCount = 0; 2182 DebugOnly<bool> ret = 2183 Manager()->IsInputPriorityEventEnabled() 2184 ? PBrowserParent::SendRealTouchEvent( 2185 aEvent, apzData.guid, apzData.blockId, apzData.apzResponse) 2186 : PBrowserParent::SendNormalPriorityRealTouchEvent( 2187 aEvent, apzData.guid, apzData.blockId, apzData.apzResponse); 2188 2189 NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealTouchEvent() failed"); 2190 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 2191 } 2192 2193 void BrowserParent::SendRealTouchMoveEvent( 2194 WidgetTouchEvent& aEvent, APZData& aAPZData, 2195 uint32_t aConsecutiveTouchMoveCount) { 2196 // Touchmove handling is complicated, since IPC compression should be used 2197 // only when there are consecutive touch objects for the same touch on the 2198 // same BrowserParent. IPC compression can be disabled by switching to 2199 // different IPC message. 2200 static bool sIPCMessageType1 = true; 2201 static TabId sLastTargetBrowserParent(0); 2202 static Maybe<APZData> sPreviousAPZData; 2203 // Artificially limit max touch points to 10. That should be in practise 2204 // more than enough. 2205 const uint32_t kMaxTouchMoveIdentifiers = 10; 2206 static Maybe<int32_t> sLastTouchMoveIdentifiers[kMaxTouchMoveIdentifiers]; 2207 2208 // Returns true if aIdentifiers contains all the touches in 2209 // sLastTouchMoveIdentifiers. 2210 auto LastTouchMoveIdentifiersContainedIn = 2211 [&](const nsTArray<int32_t>& aIdentifiers) -> bool { 2212 for (Maybe<int32_t>& entry : sLastTouchMoveIdentifiers) { 2213 if (entry.isSome() && !aIdentifiers.Contains(entry.value())) { 2214 return false; 2215 } 2216 } 2217 return true; 2218 }; 2219 2220 // Cache touch identifiers in sLastTouchMoveIdentifiers array to be used 2221 // when checking whether compression can be done for the next touchmove. 2222 auto SetLastTouchMoveIdentifiers = 2223 [&](const nsTArray<int32_t>& aIdentifiers) { 2224 for (Maybe<int32_t>& entry : sLastTouchMoveIdentifiers) { 2225 entry.reset(); 2226 } 2227 2228 MOZ_ASSERT(aIdentifiers.Length() <= kMaxTouchMoveIdentifiers); 2229 for (uint32_t j = 0; j < aIdentifiers.Length(); ++j) { 2230 sLastTouchMoveIdentifiers[j].emplace(aIdentifiers[j]); 2231 } 2232 }; 2233 2234 AutoTArray<int32_t, kMaxTouchMoveIdentifiers> changedTouches; 2235 bool preventCompression = !StaticPrefs::dom_events_compress_touchmove() || 2236 // Ensure the very first touchmove isn't overridden 2237 // by the second one, so that web pages can get 2238 // accurate coordinates for the first touchmove. 2239 aConsecutiveTouchMoveCount < 3 || 2240 sPreviousAPZData.isNothing() || 2241 sPreviousAPZData.value() != aAPZData || 2242 sLastTargetBrowserParent != GetTabId() || 2243 aEvent.mTouches.Length() > kMaxTouchMoveIdentifiers; 2244 2245 if (!preventCompression) { 2246 for (RefPtr<Touch>& touch : aEvent.mTouches) { 2247 if (touch->mChanged) { 2248 changedTouches.AppendElement(touch->mIdentifier); 2249 } 2250 } 2251 2252 // Prevent compression if the new event has fewer or different touches 2253 // than the old one. 2254 preventCompression = !LastTouchMoveIdentifiersContainedIn(changedTouches); 2255 } 2256 2257 if (preventCompression) { 2258 sIPCMessageType1 = !sIPCMessageType1; 2259 } 2260 2261 // Update the last touch move identifiers always, so that when the next 2262 // event comes in, the new identifiers can be compared to the old ones. 2263 // If the pref is disabled, this just does a quick small loop. 2264 SetLastTouchMoveIdentifiers(changedTouches); 2265 sPreviousAPZData.reset(); 2266 sPreviousAPZData.emplace(aAPZData); 2267 sLastTargetBrowserParent = GetTabId(); 2268 2269 DebugOnly<bool> ret = true; 2270 if (sIPCMessageType1) { 2271 ret = 2272 Manager()->IsInputPriorityEventEnabled() 2273 ? PBrowserParent::SendRealTouchMoveEvent( 2274 aEvent, aAPZData.guid, aAPZData.blockId, aAPZData.apzResponse) 2275 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent( 2276 aEvent, aAPZData.guid, aAPZData.blockId, 2277 aAPZData.apzResponse); 2278 } else { 2279 ret = 2280 Manager()->IsInputPriorityEventEnabled() 2281 ? PBrowserParent::SendRealTouchMoveEvent2( 2282 aEvent, aAPZData.guid, aAPZData.blockId, aAPZData.apzResponse) 2283 : PBrowserParent::SendNormalPriorityRealTouchMoveEvent2( 2284 aEvent, aAPZData.guid, aAPZData.blockId, 2285 aAPZData.apzResponse); 2286 } 2287 2288 NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealTouchMoveEvent() failed"); 2289 MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess()); 2290 } 2291 2292 bool BrowserParent::SendHandleTap( 2293 TapType aType, const LayoutDevicePoint& aPoint, Modifiers aModifiers, 2294 const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, 2295 const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { 2296 if (mIsDestroyed || !mIsReadyToHandleInputEvents) { 2297 return false; 2298 } 2299 if ((aType == TapType::eSingleTap || aType == TapType::eSecondTap)) { 2300 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { 2301 if (RefPtr<nsFrameLoader> frameLoader = GetFrameLoader()) { 2302 if (RefPtr<Element> element = frameLoader->GetOwnerContent()) { 2303 fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE | 2304 nsIFocusManager::FLAG_BYTOUCH | 2305 nsIFocusManager::FLAG_NOSCROLL); 2306 } 2307 } 2308 } 2309 } 2310 return Manager()->IsInputPriorityEventEnabled() 2311 ? PBrowserParent::SendHandleTap( 2312 aType, TransformParentToChild(aPoint), aModifiers, aGuid, 2313 aInputBlockId, aDoubleTapToZoomMetrics) 2314 : PBrowserParent::SendNormalPriorityHandleTap( 2315 aType, TransformParentToChild(aPoint), aModifiers, aGuid, 2316 aInputBlockId, aDoubleTapToZoomMetrics); 2317 } 2318 2319 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizedEventResponse( 2320 const uint64_t& aCallbackId) { 2321 AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(aCallbackId); 2322 return IPC_OK(); 2323 } 2324 2325 mozilla::ipc::IPCResult BrowserParent::RecvSyncMessage( 2326 const nsString& aMessage, const ClonedMessageData& aData, 2327 nsTArray<UniquePtr<ipc::StructuredCloneData>>* aRetVal) { 2328 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvSyncMessage", 2329 OTHER, aMessage); 2330 MMPrinter::Print("BrowserParent::RecvSyncMessage", aMessage, aData); 2331 2332 ipc::StructuredCloneData data; 2333 ipc::UnpackClonedMessageData(aData, data); 2334 2335 if (!ReceiveMessage(aMessage, true, &data, aRetVal)) { 2336 return IPC_FAIL_NO_REASON(this); 2337 } 2338 return IPC_OK(); 2339 } 2340 2341 mozilla::ipc::IPCResult BrowserParent::RecvAsyncMessage( 2342 const nsString& aMessage, const ClonedMessageData& aData) { 2343 AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvAsyncMessage", 2344 OTHER, aMessage); 2345 MMPrinter::Print("BrowserParent::RecvAsyncMessage", aMessage, aData); 2346 2347 StructuredCloneData data; 2348 ipc::UnpackClonedMessageData(aData, data); 2349 2350 if (!ReceiveMessage(aMessage, false, &data, nullptr)) { 2351 return IPC_FAIL_NO_REASON(this); 2352 } 2353 return IPC_OK(); 2354 } 2355 2356 mozilla::ipc::IPCResult BrowserParent::RecvSetCursor( 2357 const nsCursor& aCursor, Maybe<IPCImage>&& aCustomCursor, 2358 const float& aResolutionX, const float& aResolutionY, 2359 const uint32_t& aHotspotX, const uint32_t& aHotspotY, const bool& aForce) { 2360 const nsCOMPtr<nsIWidget> widget = GetWidget(); 2361 if (!widget) { 2362 return IPC_OK(); 2363 } 2364 2365 if (aForce) { 2366 widget->ClearCachedCursor(); 2367 } 2368 2369 nsCOMPtr<imgIContainer> customCursorImage; 2370 if (aCustomCursor) { 2371 customCursorImage = nsContentUtils::IPCImageToImage(*aCustomCursor); 2372 if (!customCursorImage) { 2373 return IPC_FAIL(this, "Invalid custom cursor data"); 2374 } 2375 } 2376 2377 mCursor = nsIWidget::Cursor{aCursor, 2378 std::move(customCursorImage), 2379 aHotspotX, 2380 aHotspotY, 2381 {aResolutionX, aResolutionY}}; 2382 if (!mRemoteTargetSetsCursor) { 2383 MOZ_LOG_DEBUG_ONLY( 2384 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Debug, 2385 ("BrowserParent::RecvSetCursor(): Stopped updating the cursor " 2386 "due to no rights (%p, widget=%p)", 2387 this, widget.get())); 2388 return IPC_OK(); 2389 } 2390 2391 if (EventStateManager::CursorSettingManagerHasLockedCursor()) { 2392 MOZ_LOG_DEBUG_ONLY( 2393 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Debug, 2394 ("BrowserParent::RecvSetCursor(): Stopped updating the cursor " 2395 "due to during a lock (%p, widget=%p)", 2396 this, widget.get())); 2397 return IPC_OK(); 2398 } 2399 2400 widget->SetCursor(mCursor); 2401 MOZ_LOG_DEBUG_ONLY( 2402 EventStateManager::MouseCursorUpdateLogRef(), LogLevel::Info, 2403 ("BrowserParent::RecvSetCursor(): Updated the cursor (%p, widget=%p)", 2404 this, widget.get())); 2405 return IPC_OK(); 2406 } 2407 2408 mozilla::ipc::IPCResult BrowserParent::RecvSetLinkStatus( 2409 const nsString& aStatus) { 2410 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); 2411 if (!xulBrowserWindow) { 2412 return IPC_OK(); 2413 } 2414 2415 xulBrowserWindow->SetOverLink(aStatus); 2416 2417 return IPC_OK(); 2418 } 2419 2420 mozilla::ipc::IPCResult BrowserParent::RecvShowTooltip( 2421 const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip, 2422 const nsString& aDirection) { 2423 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); 2424 if (!xulBrowserWindow) { 2425 return IPC_OK(); 2426 } 2427 2428 // ShowTooltip will end up accessing XULElement properties in JS (specifically 2429 // BoxObject). However, to get it to JS, we need to make sure we're a 2430 // nsFrameLoaderOwner, which implies we're a XULFrameElement. We can then 2431 // safely pass Element into JS. 2432 RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(mFrameElement); 2433 if (!flo) return IPC_OK(); 2434 2435 nsCOMPtr<Element> el = do_QueryInterface(flo); 2436 if (!el) return IPC_OK(); 2437 2438 if (NS_SUCCEEDED( 2439 xulBrowserWindow->ShowTooltip(aX, aY, aTooltip, aDirection, el))) { 2440 mShowingTooltip = true; 2441 } 2442 return IPC_OK(); 2443 } 2444 2445 mozilla::ipc::IPCResult BrowserParent::RecvHideTooltip() { 2446 mShowingTooltip = false; 2447 2448 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow(); 2449 if (!xulBrowserWindow) { 2450 return IPC_OK(); 2451 } 2452 2453 xulBrowserWindow->HideTooltip(); 2454 return IPC_OK(); 2455 } 2456 2457 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEFocus( 2458 const ContentCache& aContentCache, const IMENotification& aIMENotification, 2459 NotifyIMEFocusResolver&& aResolve) { 2460 if (mIsDestroyed) { 2461 return IPC_OK(); 2462 } 2463 2464 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2465 if (!widget) { 2466 aResolve(IMENotificationRequests()); 2467 return IPC_OK(); 2468 } 2469 if (NS_WARN_IF(!aContentCache.IsValid())) { 2470 return IPC_FAIL(this, "Invalid content cache data"); 2471 } 2472 mContentCache.AssignContent(aContentCache, widget, &aIMENotification); 2473 IMEStateManager::NotifyIME(aIMENotification, widget, this); 2474 2475 IMENotificationRequests requests; 2476 if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) { 2477 requests = widget->IMENotificationRequestsRef(); 2478 } 2479 aResolve(requests); 2480 2481 return IPC_OK(); 2482 } 2483 2484 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMETextChange( 2485 const ContentCache& aContentCache, 2486 const IMENotification& aIMENotification) { 2487 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2488 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2489 return IPC_OK(); 2490 } 2491 if (NS_WARN_IF(!aContentCache.IsValid())) { 2492 return IPC_FAIL(this, "Invalid content cache data"); 2493 } 2494 mContentCache.AssignContent(aContentCache, widget, &aIMENotification); 2495 mContentCache.MaybeNotifyIME(widget, aIMENotification); 2496 return IPC_OK(); 2497 } 2498 2499 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMECompositionUpdate( 2500 const ContentCache& aContentCache, 2501 const IMENotification& aIMENotification) { 2502 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2503 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2504 return IPC_OK(); 2505 } 2506 if (NS_WARN_IF(!aContentCache.IsValid())) { 2507 return IPC_FAIL(this, "Invalid content cache data"); 2508 } 2509 mContentCache.AssignContent(aContentCache, widget, &aIMENotification); 2510 mContentCache.MaybeNotifyIME(widget, aIMENotification); 2511 return IPC_OK(); 2512 } 2513 2514 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMESelection( 2515 const ContentCache& aContentCache, 2516 const IMENotification& aIMENotification) { 2517 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2518 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2519 return IPC_OK(); 2520 } 2521 if (NS_WARN_IF(!aContentCache.IsValid())) { 2522 return IPC_FAIL(this, "Invalid content cache data"); 2523 } 2524 mContentCache.AssignContent(aContentCache, widget, &aIMENotification); 2525 mContentCache.MaybeNotifyIME(widget, aIMENotification); 2526 return IPC_OK(); 2527 } 2528 2529 mozilla::ipc::IPCResult BrowserParent::RecvUpdateContentCache( 2530 const ContentCache& aContentCache) { 2531 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2532 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2533 return IPC_OK(); 2534 } 2535 if (NS_WARN_IF(!aContentCache.IsValid())) { 2536 return IPC_FAIL(this, "Invalid content cache data"); 2537 } 2538 mContentCache.AssignContent(aContentCache, widget); 2539 return IPC_OK(); 2540 } 2541 2542 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEMouseButtonEvent( 2543 const IMENotification& aIMENotification, bool* aConsumedByIME) { 2544 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2545 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2546 *aConsumedByIME = false; 2547 return IPC_OK(); 2548 } 2549 nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, this); 2550 *aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED; 2551 return IPC_OK(); 2552 } 2553 2554 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEPositionChange( 2555 const ContentCache& aContentCache, 2556 const IMENotification& aIMENotification) { 2557 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2558 if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) { 2559 return IPC_OK(); 2560 } 2561 if (NS_WARN_IF(!aContentCache.IsValid())) { 2562 return IPC_FAIL(this, "Invalid content cache data"); 2563 } 2564 mContentCache.AssignContent(aContentCache, widget, &aIMENotification); 2565 mContentCache.MaybeNotifyIME(widget, aIMENotification); 2566 return IPC_OK(); 2567 } 2568 2569 mozilla::ipc::IPCResult BrowserParent::RecvOnEventNeedingAckHandled( 2570 const EventMessage& aMessage, const uint32_t& aCompositionId) { 2571 // This is called when the child process receives WidgetCompositionEvent or 2572 // WidgetSelectionEvent. 2573 // FYI: Don't check if widget is nullptr here because it's more important to 2574 // notify mContentCahce of this than handling something in it. 2575 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 2576 2577 // While calling OnEventNeedingAckHandled(), BrowserParent *might* be 2578 // destroyed since it may send notifications to IME. 2579 RefPtr<BrowserParent> kungFuDeathGrip(this); 2580 mContentCache.OnEventNeedingAckHandled(widget, aMessage, aCompositionId); 2581 return IPC_OK(); 2582 } 2583 2584 mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus( 2585 const bool& aCanRaise, const CallerType aCallerType) { 2586 LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise)); 2587 if (BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent()) { 2588 (void)bridgeParent->SendRequestFocus(aCanRaise, aCallerType); 2589 return IPC_OK(); 2590 } 2591 2592 if (!mFrameElement) { 2593 return IPC_OK(); 2594 } 2595 2596 nsContentUtils::RequestFrameFocus(*mFrameElement, aCanRaise, aCallerType); 2597 return IPC_OK(); 2598 } 2599 2600 mozilla::ipc::IPCResult BrowserParent::RecvWheelZoomChange(bool aIncrease) { 2601 RefPtr<BrowsingContext> bc = GetBrowsingContext(); 2602 if (!bc) { 2603 return IPC_OK(); 2604 } 2605 2606 bc->Canonical()->DispatchWheelZoomChange(aIncrease); 2607 return IPC_OK(); 2608 } 2609 2610 mozilla::ipc::IPCResult BrowserParent::RecvEnableDisableCommands( 2611 const MaybeDiscarded<BrowsingContext>& aContext, const nsString& aAction, 2612 nsTArray<nsCString>&& aEnabledCommands, 2613 nsTArray<nsCString>&& aDisabledCommands) { 2614 if (aContext.IsNullOrDiscarded()) { 2615 return IPC_OK(); 2616 } 2617 2618 nsCOMPtr<nsIBrowserController> browserController = do_QueryActor( 2619 "Controllers", aContext.get_canonical()->GetCurrentWindowGlobal()); 2620 if (browserController) { 2621 browserController->EnableDisableCommands(aAction, aEnabledCommands, 2622 aDisabledCommands); 2623 } 2624 2625 return IPC_OK(); 2626 } 2627 2628 LayoutDeviceIntPoint BrowserParent::TransformPoint( 2629 const LayoutDeviceIntPoint& aPoint, 2630 const LayoutDeviceToLayoutDeviceMatrix4x4& aMatrix) { 2631 LayoutDevicePoint floatPoint(aPoint); 2632 LayoutDevicePoint floatTransformed = TransformPoint(floatPoint, aMatrix); 2633 // The next line loses precision if an out-of-process iframe 2634 // has been scaled or rotated. 2635 return RoundedToInt(floatTransformed); 2636 } 2637 2638 LayoutDevicePoint BrowserParent::TransformPoint( 2639 const LayoutDevicePoint& aPoint, 2640 const LayoutDeviceToLayoutDeviceMatrix4x4& aMatrix) { 2641 return aMatrix.TransformPoint(aPoint); 2642 } 2643 2644 LayoutDeviceIntPoint BrowserParent::TransformParentToChild( 2645 const WidgetMouseEvent& aEvent) { 2646 MOZ_ASSERT(aEvent.mWidget); 2647 2648 nsCOMPtr<nsIWidget> widget = GetWidget(); 2649 if (widget && widget != aEvent.mWidget) { 2650 return TransformParentToChild( 2651 aEvent.mRefPoint + 2652 nsLayoutUtils::WidgetToWidgetOffset(aEvent.mWidget, widget)); 2653 } 2654 return TransformParentToChild(aEvent.mRefPoint); 2655 } 2656 2657 LayoutDeviceIntPoint BrowserParent::TransformParentToChild( 2658 const LayoutDeviceIntPoint& aPoint) { 2659 LayoutDeviceToLayoutDeviceMatrix4x4 matrix = 2660 GetChildToParentConversionMatrix(); 2661 if (!matrix.Invert()) { 2662 return LayoutDeviceIntPoint(); 2663 } 2664 auto transformed = UntransformBy(matrix, aPoint); 2665 if (!transformed) { 2666 return LayoutDeviceIntPoint(); 2667 } 2668 return transformed.ref(); 2669 } 2670 2671 LayoutDevicePoint BrowserParent::TransformParentToChild( 2672 const LayoutDevicePoint& aPoint) { 2673 LayoutDeviceToLayoutDeviceMatrix4x4 matrix = 2674 GetChildToParentConversionMatrix(); 2675 if (!matrix.Invert()) { 2676 return LayoutDevicePoint(); 2677 } 2678 auto transformed = UntransformBy(matrix, aPoint); 2679 if (!transformed) { 2680 return LayoutDeviceIntPoint(); 2681 } 2682 return transformed.ref(); 2683 } 2684 2685 LayoutDeviceIntPoint BrowserParent::TransformChildToParent( 2686 const LayoutDeviceIntPoint& aPoint) { 2687 return TransformPoint(aPoint, GetChildToParentConversionMatrix()); 2688 } 2689 2690 LayoutDevicePoint BrowserParent::TransformChildToParent( 2691 const LayoutDevicePoint& aPoint) { 2692 return TransformPoint(aPoint, GetChildToParentConversionMatrix()); 2693 } 2694 2695 LayoutDeviceIntRect BrowserParent::TransformChildToParent( 2696 const LayoutDeviceIntRect& aRect) { 2697 LayoutDeviceToLayoutDeviceMatrix4x4 matrix = 2698 GetChildToParentConversionMatrix(); 2699 LayoutDeviceRect floatRect(aRect); 2700 // The outcome is not ideal if an out-of-process iframe has been rotated 2701 LayoutDeviceRect floatTransformed = matrix.TransformBounds(floatRect); 2702 // The next line loses precision if an out-of-process iframe 2703 // has been scaled or rotated. 2704 return RoundedToInt(floatTransformed); 2705 } 2706 2707 LayoutDeviceToLayoutDeviceMatrix4x4 2708 BrowserParent::GetChildToParentConversionMatrix() { 2709 if (mChildToParentConversionMatrix) { 2710 return *mChildToParentConversionMatrix; 2711 } 2712 LayoutDevicePoint offset(GetChildProcessOffset()); 2713 return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset); 2714 } 2715 2716 void BrowserParent::SetChildToParentConversionMatrix( 2717 const Maybe<LayoutDeviceToLayoutDeviceMatrix4x4>& aMatrix, 2718 const ScreenRect& aRemoteDocumentRect) { 2719 if (mChildToParentConversionMatrix == aMatrix && 2720 mRemoteDocumentRect.isSome() && 2721 mRemoteDocumentRect.value() == aRemoteDocumentRect) { 2722 return; 2723 } 2724 2725 mChildToParentConversionMatrix = aMatrix; 2726 mRemoteDocumentRect = Some(aRemoteDocumentRect); 2727 if (mIsDestroyed) { 2728 return; 2729 } 2730 (void)SendChildToParentMatrix(ToUnknownMatrix(aMatrix), aRemoteDocumentRect); 2731 } 2732 2733 LayoutDeviceIntPoint BrowserParent::GetChildProcessOffset() { 2734 // The "toplevel widget" in child processes is always at position 2735 // 0,0. Map the event coordinates to match that. 2736 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); 2737 if (!frameLoader) { 2738 return {}; 2739 } 2740 nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent(); 2741 if (!targetFrame) { 2742 return {}; 2743 } 2744 2745 nsCOMPtr<nsIWidget> widget = GetWidget(); 2746 if (!widget) { 2747 return {}; 2748 } 2749 2750 // In practice, when transforms are applied to this frameLoader, we currently 2751 // get the wrong results whether we take transforms into account here or not. 2752 // But applying transforms here gives us the wrong results in all 2753 // circumstances when transforms are applied, unless they're purely 2754 // translational. It also gives us the wrong results whenever CSS transitions 2755 // are used to apply transforms, since the offeets aren't updated as the 2756 // transition is animated. 2757 // 2758 // What we actually need to do is apply the transforms to the coordinates of 2759 // any events we send to the child, and reverse them for any screen 2760 // coordinates that we retrieve from the child. 2761 auto point = nsLayoutUtils::FrameToWidgetOffset(targetFrame, widget); 2762 if (!point) { 2763 return {}; 2764 } 2765 nsPresContext* pc = targetFrame->PresContext(); 2766 return LayoutDeviceIntPoint::FromAppUnitsRounded(*point, 2767 pc->AppUnitsPerDevPixel()); 2768 } 2769 2770 LayoutDeviceIntPoint BrowserParent::GetClientOffset() { 2771 nsCOMPtr<nsIWidget> widget = GetWidget(); 2772 nsCOMPtr<nsIWidget> docWidget = GetDocWidget(); 2773 2774 if (widget == docWidget) { 2775 return widget->GetClientOffset(); 2776 } 2777 2778 return (docWidget->GetClientOffset() + 2779 nsLayoutUtils::WidgetToWidgetOffset(widget, docWidget)); 2780 } 2781 2782 void BrowserParent::StopIMEStateManagement() { 2783 if (mIsDestroyed) { 2784 return; 2785 } 2786 (void)SendStopIMEStateManagement(); 2787 } 2788 2789 mozilla::ipc::IPCResult BrowserParent::RecvReplyKeyEvent( 2790 const WidgetKeyboardEvent& aEvent, const nsID& aUUID) { 2791 NS_ENSURE_TRUE(mFrameElement, IPC_OK()); 2792 2793 // First, verify aEvent is what we've sent to a remote process. 2794 Maybe<size_t> index = [&]() -> Maybe<size_t> { 2795 for (const size_t i : IntegerRange(mWaitingReplyKeyboardEvents.Length())) { 2796 const SentKeyEventData& data = mWaitingReplyKeyboardEvents[i]; 2797 if (data.mUUID.Equals(aUUID)) { 2798 if (NS_WARN_IF(data.mKeyCode != aEvent.mKeyCode) || 2799 NS_WARN_IF(data.mCharCode != aEvent.mCharCode) || 2800 NS_WARN_IF(data.mPseudoCharCode != aEvent.mPseudoCharCode) || 2801 NS_WARN_IF(data.mKeyNameIndex != aEvent.mKeyNameIndex) || 2802 NS_WARN_IF(data.mCodeNameIndex != aEvent.mCodeNameIndex) || 2803 NS_WARN_IF(data.mModifiers != aEvent.mModifiers)) { 2804 // Got different event data from what we stored before dispatching an 2805 // event with the ID. 2806 return Nothing(); 2807 } 2808 return Some(i); 2809 } 2810 } 2811 // No entry found. 2812 return Nothing(); 2813 }(); 2814 if (MOZ_UNLIKELY(index.isNothing())) { 2815 return IPC_FAIL(this, "Bogus reply keyboard event"); 2816 } 2817 // Don't discard the older keyboard events because the order may be changed if 2818 // the remote process has a event listener which takes too long time and while 2819 // the freezing, user may switch the tab, or if the remote process sends 2820 // synchronous XMLHttpRequest. 2821 mWaitingReplyKeyboardEvents.RemoveElementAt(*index); 2822 2823 // If the event propagation was stopped by the child, it means that the event 2824 // was ignored in the child. In the case, we should ignore it too because the 2825 // focused web app didn't have a chance to prevent its default. 2826 if (aEvent.PropagationStopped()) { 2827 return IPC_OK(); 2828 } 2829 2830 WidgetKeyboardEvent localEvent(aEvent); 2831 localEvent.MarkAsHandledInRemoteProcess(); 2832 2833 // Here we convert the WidgetEvent that we received to an Event 2834 // to be able to dispatch it to the <browser> element as the target element. 2835 RefPtr<nsPresContext> presContext = 2836 mFrameElement->OwnerDoc()->GetPresContext(); 2837 NS_ENSURE_TRUE(presContext, IPC_OK()); 2838 2839 AutoHandlingUserInputStatePusher userInpStatePusher(localEvent.IsTrusted(), 2840 &localEvent); 2841 2842 nsEventStatus status = nsEventStatus_eIgnore; 2843 2844 // Handle access key in this process before dispatching reply event because 2845 // ESM handles it before dispatching the event to the DOM tree. 2846 if (localEvent.mMessage == eKeyPress && 2847 (localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eChrome) || 2848 localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eContent))) { 2849 RefPtr<EventStateManager> esm = presContext->EventStateManager(); 2850 AutoTArray<uint32_t, 10> accessCharCodes; 2851 localEvent.GetAccessKeyCandidates(accessCharCodes); 2852 if (esm->HandleAccessKey(&localEvent, presContext, accessCharCodes)) { 2853 status = nsEventStatus_eConsumeNoDefault; 2854 } 2855 } 2856 2857 RefPtr<Element> frameElement = mFrameElement; 2858 EventDispatcher::Dispatch(frameElement, presContext, &localEvent, nullptr, 2859 &status); 2860 2861 if (!localEvent.DefaultPrevented() && 2862 !localEvent.mFlags.mIsSynthesizedForTests) { 2863 nsCOMPtr<nsIWidget> widget = GetWidget(); 2864 if (widget) { 2865 widget->PostHandleKeyEvent(&localEvent); 2866 localEvent.StopPropagation(); 2867 } 2868 } 2869 2870 return IPC_OK(); 2871 } 2872 2873 mozilla::ipc::IPCResult BrowserParent::RecvAccessKeyNotHandled( 2874 const WidgetKeyboardEvent& aEvent) { 2875 NS_ENSURE_TRUE(mFrameElement, IPC_OK()); 2876 2877 // This is called only when this process had focus and HandleAccessKey 2878 // message was posted to all remote process and each remote process didn't 2879 // execute any content access keys. 2880 2881 if (MOZ_UNLIKELY(aEvent.mMessage != eKeyPress || !aEvent.IsTrusted())) { 2882 return IPC_FAIL(this, "Called with unexpected event"); 2883 } 2884 2885 // If there is no requesting event, the event may have already been handled 2886 // when it's returned from another remote process. 2887 if (MOZ_UNLIKELY(!RequestingAccessKeyEventData::IsSet())) { 2888 return IPC_OK(); 2889 } 2890 2891 // If the event does not match with the one which we requested a remote 2892 // process to handle access key of (that means that we has already requested 2893 // for another key press), we should ignore this call because user focuses 2894 // to the last key press. 2895 if (MOZ_UNLIKELY(!RequestingAccessKeyEventData::Equals(aEvent))) { 2896 return IPC_OK(); 2897 } 2898 2899 RequestingAccessKeyEventData::Clear(); 2900 2901 WidgetKeyboardEvent localEvent(aEvent); 2902 localEvent.MarkAsHandledInRemoteProcess(); 2903 localEvent.mMessage = eAccessKeyNotFound; 2904 2905 // Here we convert the WidgetEvent that we received to an Event 2906 // to be able to dispatch it to the <browser> element as the target element. 2907 Document* doc = mFrameElement->OwnerDoc(); 2908 PresShell* presShell = doc->GetPresShell(); 2909 NS_ENSURE_TRUE(presShell, IPC_OK()); 2910 2911 if (presShell->CanDispatchEvent()) { 2912 RefPtr<nsPresContext> presContext = presShell->GetPresContext(); 2913 NS_ENSURE_TRUE(presContext, IPC_OK()); 2914 2915 RefPtr<Element> frameElement = mFrameElement; 2916 EventDispatcher::Dispatch(frameElement, presContext, &localEvent); 2917 } 2918 2919 return IPC_OK(); 2920 } 2921 2922 mozilla::ipc::IPCResult BrowserParent::RecvRegisterProtocolHandler( 2923 const nsString& aScheme, nsIURI* aHandlerURI, const nsString& aTitle, 2924 nsIURI* aDocURI) { 2925 nsCOMPtr<nsIWebProtocolHandlerRegistrar> registrar = 2926 do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID); 2927 if (registrar) { 2928 registrar->RegisterProtocolHandler(aScheme, aHandlerURI, aTitle, aDocURI, 2929 mFrameElement); 2930 } 2931 2932 return IPC_OK(); 2933 } 2934 2935 mozilla::ipc::IPCResult BrowserParent::RecvOnStateChange( 2936 const WebProgressData& aWebProgressData, const RequestData& aRequestData, 2937 const uint32_t aStateFlags, const nsresult aStatus, 2938 const Maybe<WebProgressStateChangeData>& aStateChangeData) { 2939 RefPtr<CanonicalBrowsingContext> browsingContext; 2940 nsCOMPtr<nsIRequest> request; 2941 if (!ReceiveProgressListenerData(aWebProgressData, aRequestData, 2942 getter_AddRefs(browsingContext), 2943 getter_AddRefs(request))) { 2944 return IPC_OK(); 2945 } 2946 2947 if (aStateChangeData.isSome()) { 2948 if (!browsingContext->IsTopContent()) { 2949 return IPC_FAIL( 2950 this, 2951 "Unexpected WebProgressStateChangeData for non toplevel webProgress"); 2952 } 2953 2954 if (nsCOMPtr<nsIBrowser> browser = GetBrowser()) { 2955 (void)browser->SetIsNavigating(aStateChangeData->isNavigating()); 2956 (void)browser->SetMayEnableCharacterEncodingMenu( 2957 aStateChangeData->mayEnableCharacterEncodingMenu()); 2958 (void)browser->UpdateForStateChange(aStateChangeData->charset(), 2959 aStateChangeData->documentURI(), 2960 aStateChangeData->contentType()); 2961 } 2962 } 2963 2964 if (auto* listener = browsingContext->GetWebProgress()) { 2965 listener->OnStateChange(listener, request, aStateFlags, aStatus); 2966 } 2967 2968 return IPC_OK(); 2969 } 2970 2971 mozilla::ipc::IPCResult BrowserParent::RecvOnProgressChange( 2972 const int32_t aCurTotalProgress, const int32_t aMaxTotalProgress) { 2973 // We only collect progress change notifications for the toplevel 2974 // BrowserParent. 2975 // FIXME: In the future, consider merging in progress change information from 2976 // oop subframes. 2977 if (!GetBrowsingContext()->IsTopContent() || 2978 !GetBrowsingContext()->GetWebProgress()) { 2979 return IPC_OK(); 2980 } 2981 2982 // NOTE: We always capture progress change notifications only in the top 2983 // content in nsDocShell (totalProgress reflects this). 2984 // NOTE: This notification was filtered by nsBrowserStatusFilter in the 2985 // content process, so other arguments are unavailable. See comments in 2986 // PBrowser.ipdl for more information. 2987 GetBrowsingContext()->GetWebProgress()->OnProgressChange( 2988 nullptr, nullptr, 0, 0, aCurTotalProgress, aMaxTotalProgress); 2989 2990 return IPC_OK(); 2991 } 2992 2993 mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange( 2994 const WebProgressData& aWebProgressData, const RequestData& aRequestData, 2995 nsIURI* aLocation, const uint32_t aFlags, const bool aCanGoBack, 2996 const bool aCanGoBackIgnoringUserInteraction, const bool aCanGoForward, 2997 const Maybe<WebProgressLocationChangeData>& aLocationChangeData) { 2998 RefPtr<CanonicalBrowsingContext> browsingContext; 2999 nsCOMPtr<nsIRequest> request; 3000 if (!ReceiveProgressListenerData(aWebProgressData, aRequestData, 3001 getter_AddRefs(browsingContext), 3002 getter_AddRefs(request))) { 3003 return IPC_OK(); 3004 } 3005 3006 browsingContext->SetCurrentRemoteURI(aLocation); 3007 3008 nsCOMPtr<nsIBrowser> browser = GetBrowser(); 3009 if (!mozilla::SessionHistoryInParent() && browser) { 3010 (void)browser->UpdateWebNavigationForLocationChange( 3011 aCanGoBack, aCanGoBackIgnoringUserInteraction, aCanGoForward); 3012 } 3013 3014 if (aLocationChangeData.isSome()) { 3015 if (!browsingContext->IsTopContent()) { 3016 return IPC_FAIL(this, 3017 "Unexpected WebProgressLocationChangeData for non " 3018 "toplevel webProgress"); 3019 } 3020 3021 if (browser) { 3022 (void)browser->SetIsNavigating(aLocationChangeData->isNavigating()); 3023 (void)browser->UpdateForLocationChange( 3024 aLocation, aLocationChangeData->charset(), 3025 aLocationChangeData->mayEnableCharacterEncodingMenu(), 3026 aLocationChangeData->documentURI(), aLocationChangeData->title(), 3027 aLocationChangeData->contentPrincipal(), 3028 aLocationChangeData->contentPartitionedPrincipal(), 3029 aLocationChangeData->policyContainer(), 3030 aLocationChangeData->referrerInfo(), 3031 aLocationChangeData->isSyntheticDocument(), 3032 aLocationChangeData->requestContextID().isSome(), 3033 aLocationChangeData->requestContextID().valueOr(0), 3034 aLocationChangeData->contentType()); 3035 } 3036 } 3037 3038 if (auto* listener = browsingContext->GetWebProgress()) { 3039 listener->OnLocationChange(listener, request, aLocation, aFlags); 3040 } 3041 3042 // Since we've now changed Documents, notify the BrowsingContext that we've 3043 // changed. Ideally we'd just let the BrowsingContext do this when it changes 3044 // the current window global, but that happens before this and we have a lot 3045 // of tests that depend on the specific ordering of messages. 3046 if (browsingContext->IsTopContent() && 3047 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) { 3048 browsingContext->UpdateSecurityState(); 3049 } 3050 return IPC_OK(); 3051 } 3052 3053 mozilla::ipc::IPCResult BrowserParent::RecvOnStatusChange( 3054 const nsString& aMessage) { 3055 // NOTE: As nsBrowserStatusFilter discarded which BrowsingContext the status 3056 // change was delivered to, we always deliver to the root BrowsingContext. 3057 if (auto* listener = GetBrowsingContext()->Top()->GetWebProgress()) { 3058 // NOTE: This notification was filtered by nsBrowserStatusFilter in the 3059 // content process, so other arguments are unavailable. See comments in 3060 // PBrowser.ipdl for more information. 3061 listener->OnStatusChange(nullptr, nullptr, NS_OK, aMessage.get()); 3062 } 3063 3064 return IPC_OK(); 3065 } 3066 3067 mozilla::ipc::IPCResult BrowserParent::RecvNavigationFinished() { 3068 nsCOMPtr<nsIBrowser> browser = 3069 mFrameElement ? mFrameElement->AsBrowser() : nullptr; 3070 3071 if (browser) { 3072 browser->SetIsNavigating(false); 3073 } 3074 3075 return IPC_OK(); 3076 } 3077 3078 mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent( 3079 const uint32_t& aEvent, const RequestData& aRequestData, 3080 const bool aBlocked, const nsACString& aTrackingOrigin, 3081 nsTArray<nsCString>&& aTrackingFullHashes, 3082 const Maybe< 3083 mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason>& 3084 aReason, 3085 const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) { 3086 RefPtr<BrowsingContext> bc = GetBrowsingContext(); 3087 3088 if (!bc || bc->IsDiscarded()) { 3089 return IPC_OK(); 3090 } 3091 3092 // Get the top-level browsing context. 3093 bc = bc->Top(); 3094 RefPtr<dom::WindowGlobalParent> wgp = 3095 bc->Canonical()->GetCurrentWindowGlobal(); 3096 3097 // The WindowGlobalParent would be null while running the test 3098 // browser_339445.js. This is unexpected and we will address this in a 3099 // following bug. For now, we first workaround this issue. 3100 if (!wgp) { 3101 return IPC_OK(); 3102 } 3103 3104 nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>( 3105 aRequestData.requestURI(), aRequestData.originalRequestURI(), 3106 aRequestData.matchedList()); 3107 request->SetCanceledReason(aRequestData.canceledReason()); 3108 3109 wgp->NotifyContentBlockingEvent(aEvent, request, aBlocked, aTrackingOrigin, 3110 aTrackingFullHashes, aReason, 3111 aCanvasFingerprintingEvent); 3112 3113 return IPC_OK(); 3114 } 3115 3116 already_AddRefed<nsIBrowser> BrowserParent::GetBrowser() { 3117 nsCOMPtr<nsIBrowser> browser; 3118 RefPtr<Element> currentElement = mFrameElement; 3119 3120 // In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>, 3121 // but we want the <xul:browser> that it is embedded in. 3122 while (currentElement) { 3123 browser = currentElement->AsBrowser(); 3124 if (browser) { 3125 break; 3126 } 3127 3128 BrowsingContext* browsingContext = 3129 currentElement->OwnerDoc()->GetBrowsingContext(); 3130 currentElement = 3131 browsingContext ? browsingContext->GetEmbedderElement() : nullptr; 3132 } 3133 3134 return browser.forget(); 3135 } 3136 3137 bool BrowserParent::ReceiveProgressListenerData( 3138 const WebProgressData& aWebProgressData, const RequestData& aRequestData, 3139 CanonicalBrowsingContext** aBrowsingContext, nsIRequest** aRequest) { 3140 *aBrowsingContext = nullptr; 3141 *aRequest = nullptr; 3142 3143 // Look up the BrowsingContext which this notification was fired for. 3144 if (aWebProgressData.browsingContext().IsNullOrDiscarded()) { 3145 MOZ_LOG(gBCWebProgressLog, LogLevel::Warning, 3146 ("WebProgress Ignored: BrowsingContext is null or discarded")); 3147 return false; 3148 } 3149 RefPtr<CanonicalBrowsingContext> browsingContext = 3150 aWebProgressData.browsingContext().get_canonical(); 3151 3152 // Double-check that we actually manage this BrowsingContext, and are not 3153 // receiving a malformed or out-of-date request. browsingContext should either 3154 // be the toplevel one managed by this BrowserParent, or embedded within a 3155 // WindowGlobalParent managed by this BrowserParent. 3156 if (browsingContext != mBrowsingContext) { 3157 WindowGlobalParent* embedder = browsingContext->GetParentWindowContext(); 3158 if (!embedder || embedder->GetBrowserParent() != this) { 3159 MOZ_LOG(gBCWebProgressLog, LogLevel::Warning, 3160 ("WebProgress Ignored: wrong embedder process")); 3161 return false; 3162 } 3163 } 3164 3165 // The current process for this BrowsingContext may have changed since the 3166 // notification was fired. Don't fire events for it anymore, as ownership of 3167 // the BrowsingContext has been moved elsewhere. 3168 if (RefPtr<WindowGlobalParent> current = 3169 browsingContext->GetCurrentWindowGlobal(); 3170 current && current->GetBrowserParent() != this) { 3171 MOZ_LOG(gBCWebProgressLog, LogLevel::Warning, 3172 ("WebProgress Ignored: no longer current window global")); 3173 return false; 3174 } 3175 3176 if (RefPtr<BrowsingContextWebProgress> progress = 3177 browsingContext->GetWebProgress()) { 3178 progress->SetLoadType(aWebProgressData.loadType()); 3179 } 3180 3181 nsCOMPtr<nsIRequest> request; 3182 if (aRequestData.requestURI()) { 3183 request = MakeAndAddRef<RemoteWebProgressRequest>( 3184 aRequestData.requestURI(), aRequestData.originalRequestURI(), 3185 aRequestData.matchedList()); 3186 request->SetCanceledReason(aRequestData.canceledReason()); 3187 } 3188 3189 browsingContext.forget(aBrowsingContext); 3190 request.forget(aRequest); 3191 return true; 3192 } 3193 3194 mozilla::ipc::IPCResult BrowserParent::RecvIntrinsicSizeOrRatioChanged( 3195 const Maybe<IntrinsicSize>& aIntrinsicSize, 3196 const Maybe<AspectRatio>& aIntrinsicRatio) { 3197 BrowserBridgeParent* bridge = GetBrowserBridgeParent(); 3198 if (!bridge || !bridge->CanSend()) { 3199 return IPC_OK(); 3200 } 3201 3202 (void)bridge->SendIntrinsicSizeOrRatioChanged(aIntrinsicSize, 3203 aIntrinsicRatio); 3204 3205 return IPC_OK(); 3206 } 3207 3208 mozilla::ipc::IPCResult BrowserParent::RecvImageLoadComplete( 3209 const nsresult& aResult) { 3210 BrowserBridgeParent* bridge = GetBrowserBridgeParent(); 3211 if (!bridge || !bridge->CanSend()) { 3212 return IPC_OK(); 3213 } 3214 3215 (void)bridge->SendImageLoadComplete(aResult); 3216 3217 return IPC_OK(); 3218 } 3219 3220 bool BrowserParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent) { 3221 nsCOMPtr<nsIWidget> textInputHandlingWidget = GetTextInputHandlingWidget(); 3222 if (!textInputHandlingWidget) { 3223 return true; 3224 } 3225 if (!mContentCache.HandleQueryContentEvent(aEvent, textInputHandlingWidget) || 3226 NS_WARN_IF(aEvent.Failed())) { 3227 return true; 3228 } 3229 switch (aEvent.mMessage) { 3230 case eQueryTextRect: 3231 case eQueryCaretRect: 3232 case eQueryEditorRect: { 3233 nsCOMPtr<nsIWidget> browserWidget = GetWidget(); 3234 if (browserWidget != textInputHandlingWidget) { 3235 aEvent.mReply->mRect += nsLayoutUtils::WidgetToWidgetOffset( 3236 browserWidget, textInputHandlingWidget); 3237 } 3238 aEvent.mReply->mRect = TransformChildToParent(aEvent.mReply->mRect); 3239 break; 3240 } 3241 default: 3242 break; 3243 } 3244 return true; 3245 } 3246 3247 bool BrowserParent::SendCompositionEvent(WidgetCompositionEvent& aEvent, 3248 uint32_t aCompositionId) { 3249 if (mIsDestroyed) { 3250 return false; 3251 } 3252 3253 // When the composition is handled in a remote process, we need to handle 3254 // commit/cancel result for composition with the composition ID to avoid 3255 // to abort newer composition. Therefore, we need to let the remote process 3256 // know the composition ID. 3257 MOZ_ASSERT(aCompositionId != 0); 3258 aEvent.mCompositionId = aCompositionId; 3259 3260 if (!mContentCache.OnCompositionEvent(aEvent)) { 3261 return true; 3262 } 3263 3264 bool ret = Manager()->IsInputPriorityEventEnabled() 3265 ? PBrowserParent::SendCompositionEvent(aEvent) 3266 : PBrowserParent::SendNormalPriorityCompositionEvent(aEvent); 3267 if (NS_WARN_IF(!ret)) { 3268 return false; 3269 } 3270 MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess()); 3271 return true; 3272 } 3273 3274 bool BrowserParent::SendSelectionEvent(WidgetSelectionEvent& aEvent) { 3275 if (mIsDestroyed) { 3276 return false; 3277 } 3278 nsCOMPtr<nsIWidget> widget = GetWidget(); 3279 if (!widget) { 3280 return true; 3281 } 3282 mContentCache.OnSelectionEvent(aEvent); 3283 bool ret = Manager()->IsInputPriorityEventEnabled() 3284 ? PBrowserParent::SendSelectionEvent(aEvent) 3285 : PBrowserParent::SendNormalPrioritySelectionEvent(aEvent); 3286 if (NS_WARN_IF(!ret)) { 3287 return false; 3288 } 3289 MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess()); 3290 aEvent.mSucceeded = true; 3291 return true; 3292 } 3293 3294 bool BrowserParent::SendSimpleContentCommandEvent( 3295 const mozilla::WidgetContentCommandEvent& aEvent) { 3296 MOZ_ASSERT(aEvent.mMessage != eContentCommandInsertText); 3297 MOZ_ASSERT(aEvent.mMessage != eContentCommandReplaceText); 3298 MOZ_ASSERT(aEvent.mMessage != eContentCommandPasteTransferable); 3299 MOZ_ASSERT(aEvent.mMessage != eContentCommandLookUpDictionary); 3300 MOZ_ASSERT(aEvent.mMessage != eContentCommandScroll); 3301 3302 if (mIsDestroyed) { 3303 return false; 3304 } 3305 mContentCache.OnContentCommandEvent(aEvent); 3306 return Manager()->IsInputPriorityEventEnabled() 3307 ? PBrowserParent::SendSimpleContentCommandEvent(aEvent.mMessage) 3308 : PBrowserParent::SendNormalPrioritySimpleContentCommandEvent( 3309 aEvent.mMessage); 3310 } 3311 3312 bool BrowserParent::SendInsertText(const WidgetContentCommandEvent& aEvent) { 3313 if (mIsDestroyed) { 3314 return false; 3315 } 3316 mContentCache.OnContentCommandEvent(aEvent); 3317 return Manager()->IsInputPriorityEventEnabled() 3318 ? PBrowserParent::SendInsertText(aEvent.mString.ref()) 3319 : PBrowserParent::SendNormalPriorityInsertText( 3320 aEvent.mString.ref()); 3321 } 3322 3323 bool BrowserParent::SendReplaceText(const WidgetContentCommandEvent& aEvent) { 3324 if (mIsDestroyed) { 3325 return false; 3326 } 3327 mContentCache.OnContentCommandEvent(aEvent); 3328 return Manager()->IsInputPriorityEventEnabled() 3329 ? PBrowserParent::SendReplaceText( 3330 aEvent.mSelection.mReplaceSrcString, aEvent.mString.ref(), 3331 aEvent.mSelection.mOffset, 3332 aEvent.mSelection.mPreventSetSelection) 3333 : PBrowserParent::SendNormalPriorityReplaceText( 3334 aEvent.mSelection.mReplaceSrcString, aEvent.mString.ref(), 3335 aEvent.mSelection.mOffset, 3336 aEvent.mSelection.mPreventSetSelection); 3337 } 3338 3339 bool BrowserParent::SendPasteTransferable(IPCTransferable&& aTransferable) { 3340 return PBrowserParent::SendPasteTransferable(std::move(aTransferable)); 3341 } 3342 3343 /* static */ 3344 void BrowserParent::SetTopLevelWebFocus(BrowserParent* aBrowserParent) { 3345 BrowserParent* old = GetFocused(); 3346 if (aBrowserParent && !aBrowserParent->GetBrowserBridgeParent()) { 3347 // top-level Web content 3348 sTopLevelWebFocus = aBrowserParent; 3349 BrowserParent* bp = UpdateFocus(); 3350 if (old != bp) { 3351 LOGBROWSERFOCUS( 3352 ("SetTopLevelWebFocus updated focus; old: %p, new: %p", old, bp)); 3353 IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp); 3354 } 3355 } 3356 } 3357 3358 /* static */ 3359 void BrowserParent::UnsetTopLevelWebFocus(BrowserParent* aBrowserParent) { 3360 BrowserParent* old = GetFocused(); 3361 if (sTopLevelWebFocus == aBrowserParent) { 3362 // top-level Web content 3363 sTopLevelWebFocus = nullptr; 3364 sFocus = nullptr; 3365 if (old) { 3366 LOGBROWSERFOCUS( 3367 ("UnsetTopLevelWebFocus moved focus to chrome; old: %p", old)); 3368 IMEStateManager::OnFocusMovedBetweenBrowsers(old, nullptr); 3369 } 3370 } 3371 } 3372 3373 /* static */ 3374 void BrowserParent::UpdateFocusFromBrowsingContext() { 3375 BrowserParent* old = GetFocused(); 3376 BrowserParent* bp = UpdateFocus(); 3377 if (old != bp) { 3378 LOGBROWSERFOCUS( 3379 ("UpdateFocusFromBrowsingContext updated focus; old: %p, new: %p", old, 3380 bp)); 3381 IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp); 3382 } 3383 } 3384 3385 /* static */ 3386 BrowserParent* BrowserParent::UpdateFocus() { 3387 if (!sTopLevelWebFocus) { 3388 sFocus = nullptr; 3389 return nullptr; 3390 } 3391 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 3392 if (fm) { 3393 BrowsingContext* bc = fm->GetFocusedBrowsingContextInChrome(); 3394 if (bc) { 3395 BrowsingContext* top = bc->Top(); 3396 MOZ_ASSERT(top, "Should always have a top BrowsingContext."); 3397 CanonicalBrowsingContext* canonicalTop = top->Canonical(); 3398 MOZ_ASSERT(canonicalTop, 3399 "Casting to canonical should always be possible in the parent " 3400 "process (top case)."); 3401 WindowGlobalParent* globalTop = canonicalTop->GetCurrentWindowGlobal(); 3402 if (globalTop) { 3403 RefPtr<BrowserParent> globalTopParent = globalTop->GetBrowserParent(); 3404 if (sTopLevelWebFocus == globalTopParent) { 3405 CanonicalBrowsingContext* canonical = bc->Canonical(); 3406 MOZ_ASSERT( 3407 canonical, 3408 "Casting to canonical should always be possible in the parent " 3409 "process."); 3410 WindowGlobalParent* global = canonical->GetCurrentWindowGlobal(); 3411 if (global) { 3412 RefPtr<BrowserParent> parent = global->GetBrowserParent(); 3413 sFocus = parent; 3414 return sFocus; 3415 } 3416 LOGBROWSERFOCUS( 3417 ("Focused BrowsingContext did not have WindowGlobalParent.")); 3418 } 3419 } else { 3420 LOGBROWSERFOCUS( 3421 ("Top-level BrowsingContext did not have WindowGlobalParent.")); 3422 } 3423 } 3424 } 3425 sFocus = sTopLevelWebFocus; 3426 return sFocus; 3427 } 3428 3429 /* static */ 3430 void BrowserParent::UnsetTopLevelWebFocusAll() { 3431 if (sTopLevelWebFocus) { 3432 UnsetTopLevelWebFocus(sTopLevelWebFocus); 3433 } 3434 } 3435 3436 /* static */ 3437 void BrowserParent::UnsetLastMouseRemoteTarget(BrowserParent* aBrowserParent) { 3438 if (sLastMouseRemoteTarget == aBrowserParent) { 3439 sLastMouseRemoteTarget = nullptr; 3440 } 3441 } 3442 3443 mozilla::ipc::IPCResult BrowserParent::RecvRequestIMEToCommitComposition( 3444 const bool& aCancel, const uint32_t& aCompositionId, bool* aIsCommitted, 3445 nsString* aCommittedString) { 3446 nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget(); 3447 if (!widget) { 3448 *aIsCommitted = false; 3449 return IPC_OK(); 3450 } 3451 3452 *aIsCommitted = mContentCache.RequestIMEToCommitComposition( 3453 widget, aCancel, aCompositionId, *aCommittedString); 3454 return IPC_OK(); 3455 } 3456 3457 mozilla::ipc::IPCResult BrowserParent::RecvGetInputContext( 3458 widget::IMEState* aState) { 3459 nsCOMPtr<nsIWidget> widget = GetWidget(); 3460 if (!widget) { 3461 *aState = widget::IMEState(IMEEnabled::Disabled, 3462 IMEState::OPEN_STATE_NOT_SUPPORTED); 3463 return IPC_OK(); 3464 } 3465 3466 *aState = widget->GetInputContext().mIMEState; 3467 return IPC_OK(); 3468 } 3469 3470 mozilla::ipc::IPCResult BrowserParent::RecvSetInputContext( 3471 const InputContext& aContext, const InputContextAction& aAction) { 3472 IMEStateManager::SetInputContextForChildProcess(this, aContext, aAction); 3473 return IPC_OK(); 3474 } 3475 3476 bool BrowserParent::ReceiveMessage( 3477 const nsString& aMessage, bool aSync, ipc::StructuredCloneData* aData, 3478 nsTArray<UniquePtr<ipc::StructuredCloneData>>* aRetVal) { 3479 // If we're for an oop iframe, don't deliver messages to the wrong place. 3480 if (mBrowserBridgeParent) { 3481 return true; 3482 } 3483 3484 RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true); 3485 if (frameLoader && frameLoader->GetFrameMessageManager()) { 3486 RefPtr<nsFrameMessageManager> manager = 3487 frameLoader->GetFrameMessageManager(); 3488 3489 manager->ReceiveMessage(mFrameElement, frameLoader, aMessage, aSync, aData, 3490 aRetVal, IgnoreErrors()); 3491 } 3492 return true; 3493 } 3494 3495 // nsIAuthPromptProvider 3496 3497 // This method is largely copied from nsDocShell::GetAuthPrompt 3498 NS_IMETHODIMP 3499 BrowserParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid, 3500 void** aResult) { 3501 // we're either allowing auth, or it's a proxy request 3502 nsresult rv; 3503 nsCOMPtr<nsIPromptFactory> wwatch = 3504 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); 3505 NS_ENSURE_SUCCESS(rv, rv); 3506 3507 nsCOMPtr<nsPIDOMWindowOuter> window; 3508 RefPtr<Element> frame = mFrameElement; 3509 if (frame) window = frame->OwnerDoc()->GetWindow(); 3510 3511 // Get an auth prompter for our window so that the parenting 3512 // of the dialogs works as it should when using tabs. 3513 nsCOMPtr<nsISupports> prompt; 3514 rv = wwatch->GetPrompt(window, iid, getter_AddRefs(prompt)); 3515 NS_ENSURE_SUCCESS(rv, rv); 3516 3517 nsCOMPtr<nsILoginManagerAuthPrompter> prompter = do_QueryInterface(prompt); 3518 if (prompter) { 3519 prompter->SetBrowser(mFrameElement); 3520 } 3521 3522 *aResult = prompt.forget().take(); 3523 return NS_OK; 3524 } 3525 3526 already_AddRefed<PColorPickerParent> BrowserParent::AllocPColorPickerParent( 3527 const MaybeDiscarded<BrowsingContext>& aBrowsingContext, 3528 const nsString& aTitle, const nsString& aInitialColor, 3529 const nsTArray<nsString>& aDefaultColors) { 3530 RefPtr<CanonicalBrowsingContext> browsingContext = 3531 [&]() -> CanonicalBrowsingContext* { 3532 if (aBrowsingContext.IsNullOrDiscarded()) { 3533 return nullptr; 3534 } 3535 if (!aBrowsingContext.get_canonical()->IsOwnedByProcess( 3536 Manager()->ChildID())) { 3537 return nullptr; 3538 } 3539 return aBrowsingContext.get_canonical(); 3540 }(); 3541 return MakeAndAddRef<ColorPickerParent>(browsingContext, aTitle, 3542 aInitialColor, aDefaultColors); 3543 } 3544 3545 already_AddRefed<nsFrameLoader> BrowserParent::GetFrameLoader( 3546 bool aUseCachedFrameLoaderAfterDestroy) const { 3547 if (mIsDestroyed && !aUseCachedFrameLoaderAfterDestroy) { 3548 return nullptr; 3549 } 3550 3551 if (mFrameLoader) { 3552 RefPtr<nsFrameLoader> fl = mFrameLoader; 3553 return fl.forget(); 3554 } 3555 RefPtr<Element> frameElement(mFrameElement); 3556 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(frameElement); 3557 return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr; 3558 } 3559 3560 void BrowserParent::TryCacheDPIAndScale() { 3561 if (mDPI > 0) { 3562 return; 3563 } 3564 3565 const auto oldDefaultScale = mDefaultScale; 3566 nsCOMPtr<nsIWidget> widget = GetWidget(); 3567 mDPI = widget ? widget->GetDPI() : nsIWidget::GetFallbackDPI(); 3568 mRounding = widget ? widget->RoundsWidgetCoordinatesTo() : 1; 3569 mDefaultScale = 3570 widget ? widget->GetDefaultScale() : nsIWidget::GetFallbackDefaultScale(); 3571 3572 if (mDefaultScale != oldDefaultScale) { 3573 // The change of the default scale factor will affect the child dimensions 3574 // so we need to invalidate it. 3575 mUpdatedDimensions = false; 3576 } 3577 } 3578 3579 void BrowserParent::ApzAwareEventRoutingToChild( 3580 ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId, 3581 nsEventStatus* aOutApzResponse) { 3582 // Let the widget know that the event will be sent to the child process, 3583 // which will (hopefully) send a confirmation notice back to APZ. 3584 // Do this even if APZ is off since we need it for swipe gesture support on 3585 // OS X without APZ. 3586 InputAPZContext::SetRoutedToChildProcess(); 3587 3588 if (AsyncPanZoomEnabled()) { 3589 if (aOutTargetGuid) { 3590 *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid(); 3591 3592 // There may be cases where the APZ hit-testing code came to a different 3593 // conclusion than the main-thread hit-testing code as to where the event 3594 // is destined. In such cases the layersId of the APZ result may not match 3595 // the layersId of this RemoteLayerTreeOwner. In such cases the 3596 // main-thread hit- testing code "wins" so we need to update the guid to 3597 // reflect this. 3598 if (mRemoteLayerTreeOwner.IsInitialized()) { 3599 if (aOutTargetGuid->mLayersId != mRemoteLayerTreeOwner.GetLayersId()) { 3600 *aOutTargetGuid = 3601 ScrollableLayerGuid(mRemoteLayerTreeOwner.GetLayersId(), 0, 3602 ScrollableLayerGuid::NULL_SCROLL_ID); 3603 } 3604 } 3605 } 3606 if (aOutInputBlockId) { 3607 *aOutInputBlockId = InputAPZContext::GetInputBlockId(); 3608 } 3609 if (aOutApzResponse) { 3610 *aOutApzResponse = InputAPZContext::GetApzResponse(); 3611 3612 // We can get here without there being an InputAPZContext on the stack 3613 // if a non-native event synthesization function (such as 3614 // nsIDOMWindowUtils.sendTouchEvent()) was used in the parent process to 3615 // synthesize an event that's targeting a content process. Such events do 3616 // not go through APZ. Without an InputAPZContext on the stack we pick up 3617 // the default value "eSentinel" which cannot be sent over IPC, so replace 3618 // it with "eIgnore" instead, which what APZ uses when it ignores an 3619 // event. If a caller needs the ability to synthesize a event with a 3620 // different APZ response, a native event synthesization function (such as 3621 // sendNativeTouchPoint()) can be used. 3622 if (*aOutApzResponse == nsEventStatus_eSentinel) { 3623 *aOutApzResponse = nsEventStatus_eIgnore; 3624 } 3625 } 3626 } else { 3627 if (aOutInputBlockId) { 3628 *aOutInputBlockId = 0; 3629 } 3630 if (aOutApzResponse) { 3631 *aOutApzResponse = nsEventStatus_eIgnore; 3632 } 3633 } 3634 } 3635 3636 mozilla::ipc::IPCResult BrowserParent::RecvRespondStartSwipeEvent( 3637 const uint64_t& aInputBlockId, const bool& aStartSwipe) { 3638 if (nsCOMPtr<nsIWidget> widget = GetWidget()) { 3639 widget->ReportSwipeStarted(aInputBlockId, aStartSwipe); 3640 } 3641 return IPC_OK(); 3642 } 3643 3644 bool BrowserParent::GetDocShellIsActive() const { 3645 return mBrowsingContext && mBrowsingContext->IsActive(); 3646 } 3647 3648 bool BrowserParent::GetHasPresented() { return mHasPresented; } 3649 3650 bool BrowserParent::GetHasLayers() { return mHasLayers; } 3651 3652 bool BrowserParent::GetRenderLayers() { return mRenderLayers; } 3653 3654 void BrowserParent::SetRenderLayers(bool aEnabled) { 3655 if (aEnabled == mRenderLayers) { 3656 return; 3657 } 3658 3659 // Preserve layers means that attempts to stop rendering layers 3660 // will be ignored. 3661 if (!aEnabled && mIsPreservingLayers) { 3662 return; 3663 } 3664 3665 mRenderLayers = aEnabled; 3666 3667 SetRenderLayersInternal(aEnabled); 3668 } 3669 3670 void BrowserParent::SetRenderLayersInternal(bool aEnabled) { 3671 (void)SendRenderLayers(aEnabled); 3672 3673 // Ask the child to repaint/unload layers using the PHangMonitor 3674 // channel/thread (which may be less congested). 3675 if (aEnabled) { 3676 Manager()->PaintTabWhileInterruptingJS(this); 3677 } else { 3678 Manager()->UnloadLayersWhileInterruptingJS(this); 3679 } 3680 } 3681 3682 bool BrowserParent::GetPriorityHint() { return mPriorityHint; } 3683 3684 void BrowserParent::SetPriorityHint(bool aPriorityHint) { 3685 mPriorityHint = aPriorityHint; 3686 RecomputeProcessPriority(); 3687 } 3688 3689 void BrowserParent::RecomputeProcessPriority() { 3690 auto* bc = GetBrowsingContext(); 3691 ProcessPriorityManager::BrowserPriorityChanged( 3692 bc, bc->IsActive() || mPriorityHint); 3693 } 3694 3695 void BrowserParent::PreserveLayers(bool aPreserveLayers) { 3696 if (mIsPreservingLayers == aPreserveLayers) { 3697 return; 3698 } 3699 mIsPreservingLayers = aPreserveLayers; 3700 (void)SendPreserveLayers(aPreserveLayers); 3701 } 3702 3703 void BrowserParent::NotifyResolutionChanged() { 3704 if (mIsDestroyed) { 3705 return; 3706 } 3707 // TryCacheDPIAndScale()'s cache is keyed off of 3708 // mDPI being greater than 0, so this invalidates it. 3709 mDPI = -1; 3710 TryCacheDPIAndScale(); 3711 // If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale 3712 // fails to cache the values, then mDefaultScale.scale might be invalid. 3713 // We don't want to send that value to content. Just send -1 for it too in 3714 // that case. 3715 (void)SendUIResolutionChanged(mDPI, mRounding, 3716 mDPI < 0 ? -1.0 : mDefaultScale.scale); 3717 } 3718 3719 void BrowserParent::NotifyTransparencyChanged() { 3720 if (!mIsDestroyed) { 3721 (void)SendTransparencyChanged(IsTransparent()); 3722 } 3723 } 3724 3725 bool BrowserParent::CanCancelContentJS( 3726 nsIRemoteTab::NavigationType aNavigationType, int32_t aNavigationIndex, 3727 nsIURI* aNavigationURI) const { 3728 // Pre-checking if we can cancel content js in the parent is only 3729 // supported when session history in the parent is enabled. 3730 if (!mozilla::SessionHistoryInParent()) { 3731 // If session history in the parent isn't enabled, this check will 3732 // be fully done in BrowserChild::CanCancelContentJS 3733 return true; 3734 } 3735 3736 nsCOMPtr<nsISHistory> history = mBrowsingContext->GetSessionHistory(); 3737 3738 if (!history) { 3739 // If there is no history we can't possibly know if it's ok to 3740 // cancel content js. 3741 return false; 3742 } 3743 3744 int32_t current; 3745 NS_ENSURE_SUCCESS(history->GetIndex(¤t), false); 3746 3747 if (current == -1) { 3748 // This tab has no history! Just return. 3749 return false; 3750 } 3751 3752 nsCOMPtr<nsISHEntry> entry; 3753 NS_ENSURE_SUCCESS(history->GetEntryAtIndex(current, getter_AddRefs(entry)), 3754 false); 3755 3756 nsCOMPtr<nsIURI> currentURI = entry->GetURI(); 3757 if (!net::SchemeIsHttpOrHttps(currentURI) && !currentURI->SchemeIs("file")) { 3758 // Only cancel content JS for http(s) and file URIs. Other URIs are probably 3759 // internal and we should just let them run to completion. 3760 return false; 3761 } 3762 3763 if (aNavigationType == nsIRemoteTab::NAVIGATE_BACK) { 3764 aNavigationIndex = current - 1; 3765 } else if (aNavigationType == nsIRemoteTab::NAVIGATE_FORWARD) { 3766 aNavigationIndex = current + 1; 3767 } else if (aNavigationType == nsIRemoteTab::NAVIGATE_URL) { 3768 if (!aNavigationURI) { 3769 return false; 3770 } 3771 3772 if (aNavigationURI->SchemeIs("javascript")) { 3773 // "javascript:" URIs don't (necessarily) trigger navigation to a 3774 // different page, so don't allow the current page's JS to terminate. 3775 return false; 3776 } 3777 3778 // If navigating directly to a URL (e.g. via hitting Enter in the location 3779 // bar), then we can cancel anytime the next URL is different from the 3780 // current, *excluding* the ref ("#"). 3781 bool equals; 3782 NS_ENSURE_SUCCESS(currentURI->EqualsExceptRef(aNavigationURI, &equals), 3783 false); 3784 return !equals; 3785 } 3786 // Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't 3787 // need to do anything special. 3788 3789 int32_t delta = aNavigationIndex > current ? 1 : -1; 3790 for (int32_t i = current + delta; i != aNavigationIndex + delta; i += delta) { 3791 nsCOMPtr<nsISHEntry> nextEntry; 3792 // If `i` happens to be negative, this call will fail (which is what we 3793 // would want to happen). 3794 NS_ENSURE_SUCCESS(history->GetEntryAtIndex(i, getter_AddRefs(nextEntry)), 3795 false); 3796 3797 nsCOMPtr<nsISHEntry> laterEntry = delta == 1 ? nextEntry : entry; 3798 nsCOMPtr<nsIURI> thisURI = entry->GetURI(); 3799 nsCOMPtr<nsIURI> nextURI = nextEntry->GetURI(); 3800 3801 // If we changed origin and the load wasn't in a subframe, we know it was 3802 // a full document load, so we can cancel the content JS safely. 3803 if (!laterEntry->GetIsSubFrame()) { 3804 nsAutoCString thisHost; 3805 NS_ENSURE_SUCCESS(thisURI->GetPrePath(thisHost), false); 3806 3807 nsAutoCString nextHost; 3808 NS_ENSURE_SUCCESS(nextURI->GetPrePath(nextHost), false); 3809 3810 if (!thisHost.Equals(nextHost)) { 3811 return true; 3812 } 3813 } 3814 3815 entry = nextEntry; 3816 } 3817 3818 return false; 3819 } 3820 3821 void BrowserParent::SuppressDisplayport(bool aEnabled) { 3822 if (IsDestroyed()) { 3823 return; 3824 } 3825 3826 #ifdef DEBUG 3827 if (aEnabled) { 3828 mActiveSupressDisplayportCount++; 3829 } else { 3830 mActiveSupressDisplayportCount--; 3831 } 3832 MOZ_ASSERT(mActiveSupressDisplayportCount >= 0); 3833 #endif 3834 3835 (void)SendSuppressDisplayport(aEnabled); 3836 } 3837 3838 void BrowserParent::NavigateByKey(bool aForward, bool aForDocumentNavigation) { 3839 (void)SendNavigateByKey(aForward, aForDocumentNavigation); 3840 } 3841 3842 void BrowserParent::LayerTreeUpdate(bool aActive) { 3843 if (NS_WARN_IF(mHasLayers == aActive)) { 3844 return; 3845 } 3846 mHasPresented |= aActive; 3847 mHasLayers = aActive; 3848 if (GetBrowserBridgeParent()) { 3849 // Ignore updates if we're an out-of-process iframe. For oop iframes, our 3850 // |mFrameElement| is that of the top-level document, and so 3851 // AsyncTabSwitcher will treat MozLayerTreeReady / MozLayerTreeCleared 3852 // events as if they came from the top-level tab, which is wrong. 3853 return; 3854 } 3855 3856 if (mIsDestroyed) { 3857 return; 3858 } 3859 3860 RefPtr<Element> frameElement = mFrameElement; 3861 if (NS_WARN_IF(!frameElement)) { 3862 return; 3863 } 3864 3865 RefPtr<Event> event = NS_NewDOMEvent(frameElement, nullptr, nullptr); 3866 if (aActive) { 3867 event->InitEvent(u"MozLayerTreeReady"_ns, true, false); 3868 } else { 3869 event->InitEvent(u"MozLayerTreeCleared"_ns, true, false); 3870 } 3871 event->SetTrusted(true); 3872 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; 3873 frameElement->DispatchEvent(*event); 3874 } 3875 3876 mozilla::ipc::IPCResult BrowserParent::RecvRemoteIsReadyToHandleInputEvents() { 3877 // When enabling input event prioritization, input events may preempt other 3878 // normal priority IPC messages. To prevent the input events preempt 3879 // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to 3880 // notify the parent that BrowserChild is created and ready to handle input 3881 // events. 3882 SetReadyToHandleInputEvents(); 3883 return IPC_OK(); 3884 } 3885 3886 PPaymentRequestParent* BrowserParent::AllocPPaymentRequestParent() { 3887 RefPtr<PaymentRequestParent> actor = new PaymentRequestParent(); 3888 return actor.forget().take(); 3889 } 3890 3891 bool BrowserParent::DeallocPPaymentRequestParent( 3892 PPaymentRequestParent* aActor) { 3893 RefPtr<PaymentRequestParent> actor = 3894 dont_AddRef(static_cast<PaymentRequestParent*>(aActor)); 3895 return true; 3896 } 3897 3898 nsresult BrowserParent::HandleEvent(Event* aEvent) { 3899 if (mIsDestroyed) { 3900 return NS_OK; 3901 } 3902 3903 nsAutoString eventType; 3904 aEvent->GetType(eventType); 3905 if (eventType.EqualsLiteral("MozUpdateWindowPos") || 3906 eventType.EqualsLiteral("fullscreenchange")) { 3907 // Events that signify the window moving are used to update the position 3908 // and notify the BrowserChild. 3909 return UpdatePosition(); 3910 } 3911 return NS_OK; 3912 } 3913 3914 mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession( 3915 nsTArray<IPCTransferableData>&& aTransferables, const uint32_t& aAction, 3916 Maybe<BigBuffer>&& aVisualDnDData, const uint32_t& aStride, 3917 const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect, 3918 nsIPrincipal* aPrincipal, nsIPolicyContainer* aPolicyContainer, 3919 const CookieJarSettingsArgs& aCookieJarSettingsArgs, 3920 const MaybeDiscarded<WindowContext>& aSourceWindowContext, 3921 const MaybeDiscarded<WindowContext>& aSourceTopWindowContext) { 3922 PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell(); 3923 if (!presShell) { 3924 (void)SendEndDragSession(true, true, LayoutDeviceIntPoint(), 0, 3925 nsIDragService::DRAGDROP_ACTION_NONE); 3926 // Continue sending input events with input priority when stopping the dnd 3927 // session. 3928 Manager()->SetInputPriorityEventEnabled(true); 3929 return IPC_OK(); 3930 } 3931 3932 nsCOMPtr<nsICookieJarSettings> cookieJarSettings; 3933 net::CookieJarSettings::Deserialize(aCookieJarSettingsArgs, 3934 getter_AddRefs(cookieJarSettings)); 3935 3936 RefPtr<RemoteDragStartData> dragStartData = new RemoteDragStartData( 3937 this, std::move(aTransferables), aDragRect, aPrincipal, aPolicyContainer, 3938 cookieJarSettings, aSourceWindowContext.GetMaybeDiscarded(), 3939 aSourceTopWindowContext.GetMaybeDiscarded()); 3940 3941 if (aVisualDnDData) { 3942 const auto checkedSize = CheckedInt<size_t>(aDragRect.height) * aStride; 3943 if (checkedSize.isValid() && 3944 aVisualDnDData->Size() >= checkedSize.value()) { 3945 dragStartData->SetVisualization(gfx::CreateDataSourceSurfaceFromData( 3946 gfx::IntSize(aDragRect.width, aDragRect.height), aFormat, 3947 aVisualDnDData->Data(), aStride)); 3948 } 3949 } 3950 3951 nsCOMPtr<nsIDragService> dragService = 3952 do_GetService("@mozilla.org/widget/dragservice;1"); 3953 if (dragService) { 3954 dragService->MaybeAddBrowser(this); 3955 } 3956 3957 presShell->GetPresContext() 3958 ->EventStateManager() 3959 ->BeginTrackingRemoteDragGesture(mFrameElement, dragStartData); 3960 3961 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 3962 os->NotifyObservers(nullptr, "content-invoked-drag", nullptr); 3963 3964 return IPC_OK(); 3965 } 3966 3967 void BrowserParent::GetIPCTransferableData( 3968 nsIDragSession* aSession, 3969 nsTArray<IPCTransferableData>& aIPCTransferables) { 3970 MOZ_ASSERT(aSession); 3971 RefPtr<DataTransfer> transfer = aSession->GetDataTransfer(); 3972 if (!transfer) { 3973 // Pass eDrop to get DataTransfer with external 3974 // drag formats cached. 3975 transfer = new DataTransfer(nullptr, eDrop, true, Nothing()); 3976 aSession->SetDataTransfer(transfer); 3977 } 3978 // Note, even though this fills the DataTransfer object with 3979 // external data, the data is usually transfered over IPC lazily when 3980 // needed. 3981 transfer->FillAllExternalData(); 3982 nsCOMPtr<nsILoadContext> lc = GetLoadContext(); 3983 nsCOMPtr<nsIArray> transferables = transfer->GetTransferables(lc); 3984 nsContentUtils::TransferablesToIPCTransferableDatas( 3985 transferables, aIPCTransferables, false, Manager()); 3986 } 3987 3988 void BrowserParent::MaybeInvokeDragSession(EventMessage aMessage) { 3989 // dnd uses IPCBlob to transfer data to the content process and the IPC 3990 // message is sent as normal priority. When sending input events with input 3991 // priority, the message may be preempted by the later dnd events. To make 3992 // sure the input events and the blob message are processed in time order 3993 // on the content process, we temporarily send the input events with normal 3994 // priority when there is an active dnd session. 3995 Manager()->SetInputPriorityEventEnabled(false); 3996 3997 nsCOMPtr<nsIDragService> dragService = 3998 do_GetService("@mozilla.org/widget/dragservice;1"); 3999 RefPtr<nsIWidget> widget = GetTopLevelWidget(); 4000 if (!dragService || !widget || !GetBrowsingContext()) { 4001 return; 4002 } 4003 4004 RefPtr<nsIDragSession> session = dragService->GetCurrentSession(widget); 4005 if (dragService->MaybeAddBrowser(this)) { 4006 if (session) { 4007 // We need to send transferable data to child process. 4008 nsTArray<IPCTransferableData> ipcTransferables; 4009 GetIPCTransferableData(session, ipcTransferables); 4010 uint32_t action; 4011 session->GetDragAction(&action); 4012 4013 RefPtr<WindowContext> sourceWC; 4014 session->GetSourceWindowContext(getter_AddRefs(sourceWC)); 4015 RefPtr<WindowContext> sourceTopWC; 4016 session->GetSourceTopWindowContext(getter_AddRefs(sourceTopWC)); 4017 RefPtr<nsIPrincipal> principal; 4018 session->GetTriggeringPrincipal(getter_AddRefs(principal)); 4019 (void)SendInvokeChildDragSession(sourceWC, sourceTopWC, principal, 4020 std::move(ipcTransferables), action); 4021 } 4022 return; 4023 } 4024 4025 if (session && session->MustUpdateDataTransfer(aMessage)) { 4026 // We need to send transferable data to child process. 4027 nsTArray<IPCTransferableData> ipcTransferables; 4028 GetIPCTransferableData(session, ipcTransferables); 4029 4030 RefPtr<nsIPrincipal> principal; 4031 session->GetTriggeringPrincipal(getter_AddRefs(principal)); 4032 (void)SendUpdateDragSession(principal, std::move(ipcTransferables), 4033 aMessage); 4034 } 4035 } 4036 4037 mozilla::ipc::IPCResult BrowserParent::RecvUpdateDropEffect( 4038 const uint32_t& aDragAction, const uint32_t& aDropEffect) { 4039 nsCOMPtr<nsIDragService> dragService = 4040 do_GetService("@mozilla.org/widget/dragservice;1"); 4041 if (!dragService) { 4042 return IPC_OK(); 4043 } 4044 4045 RefPtr<nsIWidget> widget = GetTopLevelWidget(); 4046 NS_ENSURE_TRUE(widget, IPC_OK()); 4047 RefPtr<nsIDragSession> dragSession = dragService->GetCurrentSession(widget); 4048 NS_ENSURE_TRUE(dragSession, IPC_OK()); 4049 dragSession->SetDragAction(aDragAction); 4050 RefPtr<DataTransfer> dt = dragSession->GetDataTransfer(); 4051 if (dt) { 4052 dt->SetDropEffectInt(aDropEffect); 4053 } 4054 dragSession->UpdateDragEffect(); 4055 return IPC_OK(); 4056 } 4057 4058 bool BrowserParent::AsyncPanZoomEnabled() const { 4059 nsCOMPtr<nsIWidget> widget = GetWidget(); 4060 return widget && widget->AsyncPanZoomEnabled(); 4061 } 4062 4063 void BrowserParent::StartPersistence( 4064 CanonicalBrowsingContext* aContext, 4065 nsIWebBrowserPersistDocumentReceiver* aRecv, ErrorResult& aRv) { 4066 RefPtr<WebBrowserPersistDocumentParent> actor = 4067 new WebBrowserPersistDocumentParent(); 4068 actor->SetOnReady(aRecv); 4069 bool ok = Manager()->SendPWebBrowserPersistDocumentConstructor(actor, this, 4070 aContext); 4071 if (!ok) { 4072 aRv.Throw(NS_ERROR_FAILURE); 4073 } 4074 // (The actor will be destroyed on constructor failure.) 4075 } 4076 4077 mozilla::ipc::IPCResult BrowserParent::RecvLookUpDictionary( 4078 const nsString& aText, nsTArray<FontRange>&& aFontRangeArray, 4079 const bool& aIsVertical, const LayoutDeviceIntPoint& aPoint) { 4080 nsCOMPtr<nsIWidget> widget = GetWidget(); 4081 if (!widget) { 4082 return IPC_OK(); 4083 } 4084 4085 widget->LookUpDictionary(aText, aFontRangeArray, aIsVertical, 4086 TransformChildToParent(aPoint)); 4087 return IPC_OK(); 4088 } 4089 4090 mozilla::ipc::IPCResult BrowserParent::RecvShowCanvasPermissionPrompt( 4091 const nsCString& aOrigin, const bool& aHideDoorHanger) { 4092 nsCOMPtr<nsIBrowser> browser = 4093 mFrameElement ? mFrameElement->AsBrowser() : nullptr; 4094 if (!browser) { 4095 // If the tab is being closed, the browser may not be available. 4096 // In this case we can ignore the request. 4097 return IPC_OK(); 4098 } 4099 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 4100 if (!os) { 4101 return IPC_FAIL_NO_REASON(this); 4102 } 4103 nsresult rv = os->NotifyObservers( 4104 browser, 4105 aHideDoorHanger ? "canvas-permissions-prompt-hide-doorhanger" 4106 : "canvas-permissions-prompt", 4107 NS_ConvertUTF8toUTF16(aOrigin).get()); 4108 if (NS_FAILED(rv)) { 4109 return IPC_FAIL_NO_REASON(this); 4110 } 4111 return IPC_OK(); 4112 } 4113 4114 mozilla::ipc::IPCResult BrowserParent::RecvShowOnionServicesAuthPrompt( 4115 const nsCString& aOnionName, const nsCString& aTopic) { 4116 nsCOMPtr<nsIBrowser> browser = 4117 mFrameElement ? mFrameElement->AsBrowser() : nullptr; 4118 if (!browser) { 4119 // If the tab is being closed, the browser may not be available. 4120 // In this case we can ignore the request. 4121 return IPC_OK(); 4122 } 4123 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); 4124 if (!os) { 4125 return IPC_FAIL_NO_REASON(this); 4126 } 4127 nsresult rv = os->NotifyObservers(browser, aTopic.get(), 4128 NS_ConvertUTF8toUTF16(aOnionName).get()); 4129 if (NS_FAILED(rv)) { 4130 return IPC_FAIL_NO_REASON(this); 4131 } 4132 return IPC_OK(); 4133 } 4134 4135 mozilla::ipc::IPCResult BrowserParent::RecvVisitURI( 4136 nsIURI* aURI, nsIURI* aLastVisitedURI, const uint32_t& aFlags, 4137 const uint64_t& aBrowserId) { 4138 if (!aURI) { 4139 return IPC_FAIL_NO_REASON(this); 4140 } 4141 RefPtr<nsIWidget> widget = GetWidget(); 4142 if (NS_WARN_IF(!widget)) { 4143 return IPC_OK(); 4144 } 4145 nsCOMPtr<IHistory> history = components::History::Service(); 4146 if (history) { 4147 (void)history->VisitURI(widget, aURI, aLastVisitedURI, aFlags, aBrowserId); 4148 } 4149 return IPC_OK(); 4150 } 4151 4152 mozilla::ipc::IPCResult BrowserParent::RecvQueryVisitedState( 4153 nsTArray<RefPtr<nsIURI>>&& aURIs) { 4154 #ifdef MOZ_GECKOVIEW_HISTORY 4155 nsCOMPtr<IHistory> history = components::History::Service(); 4156 if (NS_WARN_IF(!history)) { 4157 return IPC_OK(); 4158 } 4159 RefPtr<nsIWidget> widget = GetWidget(); 4160 if (NS_WARN_IF(!widget)) { 4161 return IPC_OK(); 4162 } 4163 4164 // FIXME(emilio): Is this check really needed? 4165 for (nsIURI* uri : aURIs) { 4166 if (!uri) { 4167 return IPC_FAIL(this, "Received null URI"); 4168 } 4169 } 4170 4171 auto* gvHistory = static_cast<GeckoViewHistory*>(history.get()); 4172 gvHistory->QueryVisitedState(widget, Manager(), std::move(aURIs)); 4173 return IPC_OK(); 4174 #else 4175 return IPC_FAIL(this, "QueryVisitedState is Android-only"); 4176 #endif 4177 } 4178 4179 void BrowserParent::LiveResizeStarted() { SuppressDisplayport(true); } 4180 4181 void BrowserParent::LiveResizeStopped() { SuppressDisplayport(false); } 4182 4183 void BrowserParent::SetBrowserBridgeParent(BrowserBridgeParent* aBrowser) { 4184 // We should either be clearing out our reference to a browser bridge, or not 4185 // have either a browser bridge, browser host, or owner content yet. 4186 MOZ_ASSERT(!aBrowser || 4187 (!mBrowserBridgeParent && !mBrowserHost && !mFrameElement)); 4188 mBrowserBridgeParent = aBrowser; 4189 } 4190 4191 void BrowserParent::SetBrowserHost(BrowserHost* aBrowser) { 4192 // We should either be clearing out our reference to a browser host, or not 4193 // have either a browser bridge, browser host, or owner content yet. 4194 MOZ_ASSERT(!aBrowser || 4195 (!mBrowserBridgeParent && !mBrowserHost && !mFrameElement)); 4196 mBrowserHost = aBrowser; 4197 } 4198 4199 mozilla::ipc::IPCResult BrowserParent::RecvSetSystemFont( 4200 const nsCString& aFontName) { 4201 nsCOMPtr<nsIWidget> widget = GetWidget(); 4202 if (widget) { 4203 widget->SetSystemFont(aFontName); 4204 } 4205 return IPC_OK(); 4206 } 4207 4208 mozilla::ipc::IPCResult BrowserParent::RecvGetSystemFont(nsCString* aFontName) { 4209 nsCOMPtr<nsIWidget> widget = GetWidget(); 4210 if (widget) { 4211 widget->GetSystemFont(*aFontName); 4212 } 4213 return IPC_OK(); 4214 } 4215 4216 mozilla::ipc::IPCResult BrowserParent::RecvMaybeFireEmbedderLoadEvents( 4217 EmbedderElementEventType aFireEventAtEmbeddingElement) { 4218 BrowserBridgeParent* bridge = GetBrowserBridgeParent(); 4219 if (!bridge) { 4220 NS_WARNING("Received `load` event on unbridged BrowserParent!"); 4221 return IPC_OK(); 4222 } 4223 4224 (void)bridge->SendMaybeFireEmbedderLoadEvents(aFireEventAtEmbeddingElement); 4225 return IPC_OK(); 4226 } 4227 4228 mozilla::ipc::IPCResult BrowserParent::RecvScrollRectIntoView( 4229 const nsRect& aRect, const ScrollAxis& aVertical, 4230 const ScrollAxis& aHorizontal, const ScrollFlags& aScrollFlags, 4231 const int32_t& aAppUnitsPerDevPixel) { 4232 BrowserBridgeParent* bridge = GetBrowserBridgeParent(); 4233 if (!bridge || !bridge->CanSend()) { 4234 return IPC_OK(); 4235 } 4236 4237 (void)bridge->SendScrollRectIntoView(aRect, aVertical, aHorizontal, 4238 aScrollFlags, aAppUnitsPerDevPixel); 4239 return IPC_OK(); 4240 } 4241 4242 mozilla::ipc::IPCResult BrowserParent::RecvIsWindowSupportingProtectedMedia( 4243 const uint64_t& aOuterWindowID, 4244 IsWindowSupportingProtectedMediaResolver&& aResolve) { 4245 #ifdef XP_WIN 4246 bool isFxrWindow = 4247 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID); 4248 aResolve(!isFxrWindow); 4249 #else 4250 # ifdef FUZZING_SNAPSHOT 4251 return IPC_FAIL(this, "Should only be called on Windows"); 4252 # endif 4253 MOZ_CRASH("Should only be called on Windows"); 4254 #endif 4255 4256 return IPC_OK(); 4257 } 4258 4259 mozilla::ipc::IPCResult BrowserParent::RecvIsWindowSupportingWebVR( 4260 const uint64_t& aOuterWindowID, 4261 IsWindowSupportingWebVRResolver&& aResolve) { 4262 #ifdef XP_WIN 4263 bool isFxrWindow = 4264 FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID); 4265 aResolve(!isFxrWindow); 4266 #else 4267 aResolve(true); 4268 #endif 4269 4270 return IPC_OK(); 4271 } 4272 4273 static BrowserParent* GetTopLevelBrowserParent(BrowserParent* aBrowserParent) { 4274 MOZ_ASSERT(aBrowserParent); 4275 BrowserParent* parent = aBrowserParent; 4276 while (BrowserBridgeParent* bridge = parent->GetBrowserBridgeParent()) { 4277 parent = bridge->Manager(); 4278 } 4279 return parent; 4280 } 4281 4282 mozilla::ipc::IPCResult BrowserParent::RecvRequestPointerLock( 4283 RequestPointerLockResolver&& aResolve) { 4284 if (sTopLevelWebFocus != GetTopLevelBrowserParent(this)) { 4285 aResolve("PointerLockDeniedNotFocused"_ns); 4286 return IPC_OK(); 4287 } 4288 4289 nsCString error; 4290 PointerLockManager::SetLockedRemoteTarget(this, error); 4291 aResolve(std::move(error)); 4292 return IPC_OK(); 4293 } 4294 4295 mozilla::ipc::IPCResult BrowserParent::RecvReleasePointerLock() { 4296 MOZ_ASSERT_IF(PointerLockManager::GetLockedRemoteTarget(), 4297 PointerLockManager::GetLockedRemoteTarget() == this); 4298 PointerLockManager::ReleaseLockedRemoteTarget(this); 4299 return IPC_OK(); 4300 } 4301 4302 mozilla::ipc::IPCResult BrowserParent::RecvRequestPointerCapture( 4303 const uint32_t& aPointerId, RequestPointerCaptureResolver&& aResolve) { 4304 aResolve( 4305 PointerEventHandler::SetPointerCaptureRemoteTarget(aPointerId, this)); 4306 return IPC_OK(); 4307 } 4308 4309 mozilla::ipc::IPCResult BrowserParent::RecvReleasePointerCapture( 4310 const uint32_t& aPointerId) { 4311 PointerEventHandler::ReleasePointerCaptureRemoteTarget(aPointerId); 4312 return IPC_OK(); 4313 } 4314 4315 mozilla::ipc::IPCResult BrowserParent::RecvShowDynamicToolbar() { 4316 #if defined(MOZ_WIDGET_ANDROID) 4317 nsCOMPtr<nsIWidget> widget = GetTopLevelWidget(); 4318 if (!widget) { 4319 return IPC_OK(); 4320 } 4321 4322 RefPtr<nsWindow> window = nsWindow::From(widget); 4323 if (!window) { 4324 return IPC_OK(); 4325 } 4326 4327 window->ShowDynamicToolbar(); 4328 #endif // defined(MOZ_WIDGET_ANDROID) 4329 return IPC_OK(); 4330 } 4331 4332 } // namespace dom 4333 } // namespace mozilla