tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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, &currentScale](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(&current), 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