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 "base/basictypes.h"
8 
9 #include "BrowserParent.h"
10 
11 #ifdef ACCESSIBILITY
12 #  include "mozilla/a11y/DocAccessibleParent.h"
13 #  include "mozilla/a11y/Platform.h"
14 #  include "mozilla/a11y/ProxyAccessibleBase.h"
15 #  include "nsAccessibilityService.h"
16 #endif
17 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
18 #include "mozilla/dom/ChromeMessageSender.h"
19 #include "mozilla/dom/ContentParent.h"
20 #include "mozilla/dom/DataTransfer.h"
21 #include "mozilla/dom/DataTransferItemList.h"
22 #include "mozilla/dom/Event.h"
23 #include "mozilla/dom/indexedDB/ActorsParent.h"
24 #include "mozilla/dom/PaymentRequestParent.h"
25 #include "mozilla/dom/BrowserBridgeParent.h"
26 #include "mozilla/dom/RemoteDragStartData.h"
27 #include "mozilla/dom/RemoteWebProgress.h"
28 #include "mozilla/dom/RemoteWebProgressRequest.h"
29 #include "mozilla/dom/SessionHistoryEntry.h"
30 #include "mozilla/dom/SessionStoreUtils.h"
31 #include "mozilla/dom/SessionStoreUtilsBinding.h"
32 #include "mozilla/dom/UserActivation.h"
33 #include "mozilla/EventStateManager.h"
34 #include "mozilla/gfx/2D.h"
35 #include "mozilla/gfx/DataSurfaceHelpers.h"
36 #include "mozilla/gfx/GPUProcessManager.h"
37 #include "mozilla/Hal.h"
38 #include "mozilla/IMEStateManager.h"
39 #include "mozilla/layers/AsyncDragMetrics.h"
40 #include "mozilla/layers/InputAPZContext.h"
41 #include "mozilla/layout/RemoteLayerTreeOwner.h"
42 #include "mozilla/plugins/PPluginWidgetParent.h"
43 #include "mozilla/LookAndFeel.h"
44 #include "mozilla/MouseEvents.h"
45 #include "mozilla/net/NeckoChild.h"
46 #include "mozilla/Preferences.h"
47 #include "mozilla/PresShell.h"
48 #include "mozilla/ProcessHangMonitor.h"
49 #include "mozilla/StaticPrefs_dom.h"
50 #include "mozilla/TextEvents.h"
51 #include "mozilla/TouchEvents.h"
52 #include "mozilla/UniquePtr.h"
53 #include "mozilla/Unused.h"
54 #include "nsCOMPtr.h"
55 #include "nsContentUtils.h"
56 #include "nsDebug.h"
57 #include "nsFocusManager.h"
58 #include "nsFrameLoader.h"
59 #include "nsFrameLoaderOwner.h"
60 #include "nsFrameManager.h"
61 #include "nsIBaseWindow.h"
62 #include "nsIBrowser.h"
63 #include "nsIBrowserController.h"
64 #include "nsIContent.h"
65 #include "nsIDocShell.h"
66 #include "nsIDocShellTreeOwner.h"
67 #include "nsImportModule.h"
68 #include "nsIInterfaceRequestorUtils.h"
69 #include "nsILoadInfo.h"
70 #include "nsIPromptFactory.h"
71 #include "nsIURI.h"
72 #include "nsIWebBrowserChrome.h"
73 #include "nsIWebProtocolHandlerRegistrar.h"
74 #include "nsIXPConnect.h"
75 #include "nsIXULBrowserWindow.h"
76 #include "nsIAppWindow.h"
77 #include "nsSHistory.h"
78 #include "nsViewManager.h"
79 #include "nsVariant.h"
80 #include "nsIWidget.h"
81 #include "nsNetUtil.h"
82 #ifndef XP_WIN
83 #  include "nsJARProtocolHandler.h"
84 #endif
85 #include "nsPIDOMWindow.h"
86 #include "nsPrintfCString.h"
87 #include "nsQueryObject.h"
88 #include "nsServiceManagerUtils.h"
89 #include "nsThreadUtils.h"
90 #include "PermissionMessageUtils.h"
91 #include "StructuredCloneData.h"
92 #include "ColorPickerParent.h"
93 #include "FilePickerParent.h"
94 #include "BrowserChild.h"
95 #include "nsNetCID.h"
96 #include "nsIAuthInformation.h"
97 #include "nsIAuthPromptCallback.h"
98 #include "nsAuthInformationHolder.h"
99 #include "nsICancelable.h"
100 #include "gfxUtils.h"
101 #include "nsILoginManagerAuthPrompter.h"
102 #include "nsPIWindowRoot.h"
103 #include "nsReadableUtils.h"
104 #include "nsIAuthPrompt2.h"
105 #include "gfxDrawable.h"
106 #include "ImageOps.h"
107 #include "UnitTransforms.h"
108 #include <algorithm>
109 #include "mozilla/NullPrincipal.h"
110 #include "mozilla/WebBrowserPersistDocumentParent.h"
111 #include "ProcessPriorityManager.h"
112 #include "nsString.h"
113 #include "IHistory.h"
114 #include "mozilla/dom/WindowGlobalParent.h"
115 #include "mozilla/dom/CanonicalBrowsingContext.h"
116 #include "MMPrinter.h"
117 #include "SessionStoreFunctions.h"
118 #include "mozilla/dom/CrashReport.h"
119 #include "nsISecureBrowserUI.h"
120 
121 #ifdef XP_WIN
122 #  include "mozilla/plugins/PluginWidgetParent.h"
123 #  include "FxRWindowManager.h"
124 #endif
125 
126 #if defined(XP_WIN) && defined(ACCESSIBILITY)
127 #  include "mozilla/a11y/AccessibleWrap.h"
128 #  include "mozilla/a11y/Compatibility.h"
129 #  include "mozilla/a11y/nsWinUtils.h"
130 #endif
131 
132 #ifdef MOZ_ANDROID_HISTORY
133 #  include "GeckoViewHistory.h"
134 #endif
135 
136 using namespace mozilla::dom;
137 using namespace mozilla::ipc;
138 using namespace mozilla::layers;
139 using namespace mozilla::layout;
140 using namespace mozilla::services;
141 using namespace mozilla::widget;
142 using namespace mozilla::gfx;
143 
144 using mozilla::LazyLogModule;
145 using mozilla::StaticAutoPtr;
146 using mozilla::Unused;
147 
148 LazyLogModule gBrowserFocusLog("BrowserFocus");
149 
150 #define LOGBROWSERFOCUS(args) \
151   MOZ_LOG(gBrowserFocusLog, mozilla::LogLevel::Debug, args)
152 
153 /* static */
154 BrowserParent* BrowserParent::sFocus = nullptr;
155 /* static */
156 BrowserParent* BrowserParent::sTopLevelWebFocus = nullptr;
157 /* static */
158 BrowserParent* BrowserParent::sLastMouseRemoteTarget = nullptr;
159 
160 // The flags passed by the webProgress notifications are 16 bits shifted
161 // from the ones registered by webProgressListeners.
162 #define NOTIFY_FLAG_SHIFT 16
163 
164 namespace mozilla {
165 namespace dom {
166 
167 BrowserParent::LayerToBrowserParentTable*
168     BrowserParent::sLayerToBrowserParentTable = nullptr;
169 
170 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserParent)
NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)171   NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
172   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
173   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
174 NS_INTERFACE_MAP_END
175 NS_IMPL_CYCLE_COLLECTION_WEAK(BrowserParent, mFrameLoader, mBrowsingContext)
176 NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserParent)
177 NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserParent)
178 
179 BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId,
180                              const TabContext& aContext,
181                              CanonicalBrowsingContext* aBrowsingContext,
182                              uint32_t aChromeFlags)
183     : TabContext(aContext),
184       mTabId(aTabId),
185       mManager(aManager),
186       mBrowsingContext(aBrowsingContext),
187       mFrameElement(nullptr),
188       mBrowserDOMWindow(nullptr),
189       mFrameLoader(nullptr),
190       mChromeFlags(aChromeFlags),
191       mBrowserBridgeParent(nullptr),
192       mBrowserHost(nullptr),
193       mContentCache(*this),
194       mRemoteLayerTreeOwner{},
195       mLayerTreeEpoch{1},
196       mChildToParentConversionMatrix{},
197       mRect(0, 0, 0, 0),
198       mDimensions(0, 0),
199       mOrientation(0),
200       mDPI(0),
201       mRounding(0),
202       mDefaultScale(0),
203       mUpdatedDimensions(false),
204       mSizeMode(nsSizeMode_Normal),
205       mClientOffset{},
206       mChromeOffset{},
207       mCreatingWindow(false),
208       mDelayedURL{},
209       mDelayedFrameScripts{},
210       mCursor(eCursorInvalid),
211       mCustomCursor{},
212       mCustomCursorHotspotX(0),
213       mCustomCursorHotspotY(0),
214       mVerifyDropLinks{},
215       mDocShellIsActive(false),
216       mMarkedDestroying(false),
217       mIsDestroyed(false),
218       mTabSetsCursor(false),
219       mPreserveLayers(false),
220       mRenderLayers(true),
221       mActiveInPriorityManager(false),
222       mHasLayers(false),
223       mHasPresented(false),
224       mIsReadyToHandleInputEvents(false),
225       mIsMouseEnterIntoWidgetEventSuppressed(false),
226       mSuspendedProgressEvents(false),
227       mSuspendMediaWhenInactive(false) {
228   MOZ_ASSERT(aManager);
229   // When the input event queue is disabled, we don't need to handle the case
230   // that some input events are dispatched before PBrowserConstructor.
231   mIsReadyToHandleInputEvents = !ContentParent::IsInputEventQueueSupported();
232 }
233 
234 BrowserParent::~BrowserParent() = default;
235 
236 /* static */
InitializeStatics()237 void BrowserParent::InitializeStatics() { MOZ_ASSERT(XRE_IsParentProcess()); }
238 
239 /* static */
GetFocused()240 BrowserParent* BrowserParent::GetFocused() { return sFocus; }
241 
242 /* static */
GetLastMouseRemoteTarget()243 BrowserParent* BrowserParent::GetLastMouseRemoteTarget() {
244   return sLastMouseRemoteTarget;
245 }
246 
247 /*static*/
GetFrom(nsFrameLoader * aFrameLoader)248 BrowserParent* BrowserParent::GetFrom(nsFrameLoader* aFrameLoader) {
249   if (!aFrameLoader) {
250     return nullptr;
251   }
252   return aFrameLoader->GetBrowserParent();
253 }
254 
255 /*static*/
GetFrom(PBrowserParent * aBrowserParent)256 BrowserParent* BrowserParent::GetFrom(PBrowserParent* aBrowserParent) {
257   return static_cast<BrowserParent*>(aBrowserParent);
258 }
259 
260 /*static*/
GetFrom(nsIContent * aContent)261 BrowserParent* BrowserParent::GetFrom(nsIContent* aContent) {
262   RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(aContent);
263   if (!loaderOwner) {
264     return nullptr;
265   }
266   RefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
267   return GetFrom(frameLoader);
268 }
269 
270 /* static */
GetBrowserParentFromLayersId(layers::LayersId aLayersId)271 BrowserParent* BrowserParent::GetBrowserParentFromLayersId(
272     layers::LayersId aLayersId) {
273   if (!sLayerToBrowserParentTable) {
274     return nullptr;
275   }
276   return sLayerToBrowserParentTable->Get(uint64_t(aLayersId));
277 }
278 
279 /*static*/
GetTabIdFrom(nsIDocShell * docShell)280 TabId BrowserParent::GetTabIdFrom(nsIDocShell* docShell) {
281   nsCOMPtr<nsIBrowserChild> browserChild(BrowserChild::GetFrom(docShell));
282   if (browserChild) {
283     return static_cast<BrowserChild*>(browserChild.get())->GetTabId();
284   }
285   return TabId(0);
286 }
287 
AddBrowserParentToTable(layers::LayersId aLayersId,BrowserParent * aBrowserParent)288 void BrowserParent::AddBrowserParentToTable(layers::LayersId aLayersId,
289                                             BrowserParent* aBrowserParent) {
290   if (!sLayerToBrowserParentTable) {
291     sLayerToBrowserParentTable = new LayerToBrowserParentTable();
292   }
293   sLayerToBrowserParentTable->Put(uint64_t(aLayersId), aBrowserParent);
294 }
295 
RemoveBrowserParentFromTable(layers::LayersId aLayersId)296 void BrowserParent::RemoveBrowserParentFromTable(layers::LayersId aLayersId) {
297   if (!sLayerToBrowserParentTable) {
298     return;
299   }
300   sLayerToBrowserParentTable->Remove(uint64_t(aLayersId));
301   if (sLayerToBrowserParentTable->Count() == 0) {
302     delete sLayerToBrowserParentTable;
303     sLayerToBrowserParentTable = nullptr;
304   }
305 }
306 
GetLoadContext()307 already_AddRefed<nsILoadContext> BrowserParent::GetLoadContext() {
308   return do_AddRef(mBrowsingContext);
309 }
310 
311 /**
312  * Will return nullptr if there is no outer window available for the
313  * document hosting the owner element of this BrowserParent. Also will return
314  * nullptr if that outer window is in the process of closing.
315  */
GetParentWindowOuter()316 already_AddRefed<nsPIDOMWindowOuter> BrowserParent::GetParentWindowOuter() {
317   nsCOMPtr<nsIContent> frame = GetOwnerElement();
318   if (!frame) {
319     return nullptr;
320   }
321 
322   nsCOMPtr<nsPIDOMWindowOuter> parent = frame->OwnerDoc()->GetWindow();
323   if (!parent || parent->Closed()) {
324     return nullptr;
325   }
326 
327   return parent.forget();
328 }
329 
GetTopLevelWidget()330 already_AddRefed<nsIWidget> BrowserParent::GetTopLevelWidget() {
331   if (RefPtr<Element> element = mFrameElement) {
332     if (PresShell* presShell = element->OwnerDoc()->GetPresShell()) {
333       nsViewManager* vm = presShell->GetViewManager();
334       nsCOMPtr<nsIWidget> widget;
335       vm->GetRootWidget(getter_AddRefs(widget));
336       return widget.forget();
337     }
338   }
339   return nullptr;
340 }
341 
GetTextInputHandlingWidget() const342 already_AddRefed<nsIWidget> BrowserParent::GetTextInputHandlingWidget() const {
343   if (!mFrameElement) {
344     return nullptr;
345   }
346   PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell();
347   if (!presShell) {
348     return nullptr;
349   }
350   nsPresContext* presContext = presShell->GetPresContext();
351   if (!presContext) {
352     return nullptr;
353   }
354   nsCOMPtr<nsIWidget> widget = presContext->GetTextInputHandlingWidget();
355   return widget.forget();
356 }
357 
GetWidget() const358 already_AddRefed<nsIWidget> BrowserParent::GetWidget() const {
359   if (!mFrameElement) {
360     return nullptr;
361   }
362   nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForContent(mFrameElement);
363   if (!widget) {
364     widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
365   }
366   return widget.forget();
367 }
368 
GetDocWidget() const369 already_AddRefed<nsIWidget> BrowserParent::GetDocWidget() const {
370   if (!mFrameElement) {
371     return nullptr;
372   }
373   return do_AddRef(
374       nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc()));
375 }
376 
GetXULBrowserWindow()377 nsIXULBrowserWindow* BrowserParent::GetXULBrowserWindow() {
378   if (!mFrameElement) {
379     return nullptr;
380   }
381 
382   nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
383   if (!docShell) {
384     return nullptr;
385   }
386 
387   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
388   docShell->GetTreeOwner(getter_AddRefs(treeOwner));
389   if (!treeOwner) {
390     return nullptr;
391   }
392 
393   nsCOMPtr<nsIAppWindow> window = do_GetInterface(treeOwner);
394   if (!window) {
395     return nullptr;
396   }
397 
398   nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
399   window->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow));
400   return xulBrowserWindow;
401 }
402 
GetMaxTouchPoints(Element * aElement)403 uint32_t BrowserParent::GetMaxTouchPoints(Element* aElement) {
404   if (!aElement) {
405     return 0;
406   }
407 
408   if (StaticPrefs::dom_maxtouchpoints_testing_value() >= 0) {
409     return StaticPrefs::dom_maxtouchpoints_testing_value();
410   }
411 
412   nsIWidget* widget = nsContentUtils::WidgetForDocument(aElement->OwnerDoc());
413   return widget ? widget->GetMaxTouchPoints() : 0;
414 }
415 
GetTopLevelDocAccessible() const416 a11y::DocAccessibleParent* BrowserParent::GetTopLevelDocAccessible() const {
417 #ifdef ACCESSIBILITY
418   // XXX Consider managing non top level PDocAccessibles with their parent
419   // document accessible.
420   const ManagedContainer<PDocAccessibleParent>& docs =
421       ManagedPDocAccessibleParent();
422   for (auto iter = docs.ConstIter(); !iter.Done(); iter.Next()) {
423     auto doc = static_cast<a11y::DocAccessibleParent*>(iter.Get()->GetKey());
424     // We want the document for this BrowserParent even if it's for an
425     // embedded out-of-process iframe. Therefore, we use
426     // IsTopLevelInContentProcess. In contrast, using IsToplevel would only
427     // include documents that aren't embedded; e.g. tab documents.
428     if (doc->IsTopLevelInContentProcess()) {
429       return doc;
430     }
431   }
432 
433   MOZ_ASSERT(docs.Count() == 0,
434              "If there isn't a top level accessible doc "
435              "there shouldn't be an accessible doc at all!");
436 #endif
437   return nullptr;
438 }
439 
GetLayersId() const440 LayersId BrowserParent::GetLayersId() const {
441   if (!mRemoteLayerTreeOwner.IsInitialized()) {
442     return LayersId{};
443   }
444   return mRemoteLayerTreeOwner.GetLayersId();
445 }
446 
GetBrowserBridgeParent() const447 BrowserBridgeParent* BrowserParent::GetBrowserBridgeParent() const {
448   return mBrowserBridgeParent;
449 }
450 
GetBrowserHost() const451 BrowserHost* BrowserParent::GetBrowserHost() const { return mBrowserHost; }
452 
GetShowInfo()453 ParentShowInfo BrowserParent::GetShowInfo() {
454   TryCacheDPIAndScale();
455   if (mFrameElement) {
456     nsAutoString name;
457     mFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
458     // FIXME(emilio, bug 1606660): allowfullscreen should probably move to
459     // OwnerShowInfo.
460     bool allowFullscreen =
461         mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
462         mFrameElement->HasAttr(kNameSpaceID_None,
463                                nsGkAtoms::mozallowfullscreen);
464     bool isTransparent =
465         nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()) &&
466         mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
467     return ParentShowInfo(name, allowFullscreen, false, isTransparent, mDPI,
468                           mRounding, mDefaultScale.scale);
469   }
470 
471   return ParentShowInfo(EmptyString(), false, false, false, mDPI, mRounding,
472                         mDefaultScale.scale);
473 }
474 
GetContentPrincipal() const475 already_AddRefed<nsIPrincipal> BrowserParent::GetContentPrincipal() const {
476   nsCOMPtr<nsIBrowser> browser =
477       mFrameElement ? mFrameElement->AsBrowser() : nullptr;
478   NS_ENSURE_TRUE(browser, nullptr);
479 
480   RefPtr<nsIPrincipal> principal;
481 
482   nsresult rv;
483   rv = browser->GetContentPrincipal(getter_AddRefs(principal));
484   NS_ENSURE_SUCCESS(rv, nullptr);
485 
486   return principal.forget();
487 }
488 
SetOwnerElement(Element * aElement)489 void BrowserParent::SetOwnerElement(Element* aElement) {
490   // If we held previous content then unregister for its events.
491   RemoveWindowListeners();
492 
493   // If we change top-level documents then we need to change our
494   // registration with them.
495   RefPtr<nsPIWindowRoot> curTopLevelWin, newTopLevelWin;
496   if (mFrameElement) {
497     curTopLevelWin = nsContentUtils::GetWindowRoot(mFrameElement->OwnerDoc());
498   }
499   if (aElement) {
500     newTopLevelWin = nsContentUtils::GetWindowRoot(aElement->OwnerDoc());
501   }
502   bool isSameTopLevelWin = curTopLevelWin == newTopLevelWin;
503   if (mBrowserHost && curTopLevelWin && !isSameTopLevelWin) {
504     curTopLevelWin->RemoveBrowser(mBrowserHost);
505   }
506 
507   // Update to the new content, and register to listen for events from it.
508   mFrameElement = aElement;
509 
510   if (mBrowserHost && newTopLevelWin && !isSameTopLevelWin) {
511     newTopLevelWin->AddBrowser(mBrowserHost);
512   }
513 
514 #if defined(XP_WIN) && defined(ACCESSIBILITY)
515   if (!mIsDestroyed) {
516     uintptr_t newWindowHandle = 0;
517     if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
518       newWindowHandle =
519           reinterpret_cast<uintptr_t>(widget->GetNativeData(NS_NATIVE_WINDOW));
520     }
521     Unused << SendUpdateNativeWindowHandle(newWindowHandle);
522     a11y::DocAccessibleParent* doc = GetTopLevelDocAccessible();
523     if (doc) {
524       HWND hWnd = reinterpret_cast<HWND>(doc->GetEmulatedWindowHandle());
525       if (hWnd) {
526         HWND parentHwnd = reinterpret_cast<HWND>(newWindowHandle);
527         if (parentHwnd != ::GetParent(hWnd)) {
528           ::SetParent(hWnd, parentHwnd);
529         }
530       }
531     }
532   }
533 #endif
534 
535   AddWindowListeners();
536   TryCacheDPIAndScale();
537 
538   // Try to send down WidgetNativeData, now that this BrowserParent is
539   // associated with a widget.
540   nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
541   if (widget) {
542     WindowsHandle widgetNativeData = reinterpret_cast<WindowsHandle>(
543         widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
544     if (widgetNativeData) {
545       Unused << SendSetWidgetNativeData(widgetNativeData);
546     }
547   }
548 
549   if (mRemoteLayerTreeOwner.IsInitialized()) {
550     mRemoteLayerTreeOwner.OwnerContentChanged();
551   }
552 
553   // Set our BrowsingContext's embedder if we're not embedded within a
554   // BrowserBridgeParent.
555   if (!GetBrowserBridgeParent() && mBrowsingContext && mFrameElement) {
556     mBrowsingContext->SetEmbedderElement(mFrameElement);
557   }
558 
559   VisitChildren([aElement](BrowserBridgeParent* aBrowser) {
560     if (auto* browserParent = aBrowser->GetBrowserParent()) {
561       browserParent->SetOwnerElement(aElement);
562     }
563   });
564 }
565 
CacheFrameLoader(nsFrameLoader * aFrameLoader)566 void BrowserParent::CacheFrameLoader(nsFrameLoader* aFrameLoader) {
567   mFrameLoader = aFrameLoader;
568 }
569 
AddWindowListeners()570 void BrowserParent::AddWindowListeners() {
571   if (mFrameElement) {
572     if (nsCOMPtr<nsPIDOMWindowOuter> window =
573             mFrameElement->OwnerDoc()->GetWindow()) {
574       nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
575       if (eventTarget) {
576         eventTarget->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
577                                       this, false, false);
578         eventTarget->AddEventListener(NS_LITERAL_STRING("fullscreenchange"),
579                                       this, false, false);
580       }
581     }
582   }
583 }
584 
RemoveWindowListeners()585 void BrowserParent::RemoveWindowListeners() {
586   if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
587     nsCOMPtr<nsPIDOMWindowOuter> window =
588         mFrameElement->OwnerDoc()->GetWindow();
589     nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
590     if (eventTarget) {
591       eventTarget->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
592                                        this, false);
593       eventTarget->RemoveEventListener(NS_LITERAL_STRING("fullscreenchange"),
594                                        this, false);
595     }
596   }
597 }
598 
DestroyInternal()599 void BrowserParent::DestroyInternal() {
600   UnsetTopLevelWebFocus(this);
601   UnsetLastMouseRemoteTarget(this);
602 
603   RemoveWindowListeners();
604 
605 #ifdef ACCESSIBILITY
606   if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) {
607     tabDoc->Destroy();
608   }
609 #endif
610 
611   // If this fails, it's most likely due to a content-process crash,
612   // and auto-cleanup will kick in.  Otherwise, the child side will
613   // destroy itself and send back __delete__().
614   Unused << SendDestroy();
615 
616 #ifdef XP_WIN
617   // Let all PluginWidgets know we are tearing down. Prevents
618   // these objects from sending async events after the child side
619   // is shut down.
620   const ManagedContainer<PPluginWidgetParent>& kids =
621       ManagedPPluginWidgetParent();
622   for (auto iter = kids.ConstIter(); !iter.Done(); iter.Next()) {
623     static_cast<mozilla::plugins::PluginWidgetParent*>(iter.Get()->GetKey())
624         ->ParentDestroy();
625   }
626 #endif
627 }
628 
Destroy()629 void BrowserParent::Destroy() {
630   // Aggressively release the window to avoid leaking the world in shutdown
631   // corner cases.
632   mBrowserDOMWindow = nullptr;
633 
634   if (mIsDestroyed) {
635     return;
636   }
637 
638   DestroyInternal();
639 
640   mIsDestroyed = true;
641 
642   Manager()->NotifyTabDestroying();
643 
644   mMarkedDestroying = true;
645 }
646 
RecvEnsureLayersConnected(CompositorOptions * aCompositorOptions)647 mozilla::ipc::IPCResult BrowserParent::RecvEnsureLayersConnected(
648     CompositorOptions* aCompositorOptions) {
649   if (mRemoteLayerTreeOwner.IsInitialized()) {
650     mRemoteLayerTreeOwner.EnsureLayersConnected(aCompositorOptions);
651   }
652   return IPC_OK();
653 }
654 
Recv__delete__()655 mozilla::ipc::IPCResult BrowserParent::Recv__delete__() {
656   MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
657   Manager()->NotifyTabDestroyed(mTabId, mMarkedDestroying);
658   return IPC_OK();
659 }
660 
ActorDestroy(ActorDestroyReason why)661 void BrowserParent::ActorDestroy(ActorDestroyReason why) {
662   ContentProcessManager::GetSingleton()->UnregisterRemoteFrame(mTabId);
663 
664   if (mRemoteLayerTreeOwner.IsInitialized()) {
665     // It's important to unmap layers after the remote browser has been
666     // destroyed, otherwise it may still send messages to the compositor which
667     // will reject them, causing assertions.
668     RemoveBrowserParentFromTable(mRemoteLayerTreeOwner.GetLayersId());
669     mRemoteLayerTreeOwner.Destroy();
670   }
671 
672   // Even though BrowserParent::Destroy calls this, we need to do it here too in
673   // case of a crash.
674   BrowserParent::UnsetTopLevelWebFocus(this);
675   BrowserParent::UnsetLastMouseRemoteTarget(this);
676 
677   if (why == AbnormalShutdown) {
678     // dom_reporting_header must also be enabled for the report to be sent.
679     if (StaticPrefs::dom_reporting_crash_enabled()) {
680       nsCOMPtr<nsIPrincipal> principal = GetContentPrincipal();
681 
682       if (principal) {
683         nsAutoCString crash_reason;
684         CrashReporter::GetAnnotation(OtherPid(),
685                                      CrashReporter::Annotation::MozCrashReason,
686                                      crash_reason);
687         // FIXME(arenevier): Find a less fragile way to identify that a crash
688         // was caused by OOM
689         bool is_oom = false;
690         if (crash_reason == "OOM" || crash_reason == "OOM!" ||
691             StringBeginsWith(crash_reason,
692                              NS_LITERAL_CSTRING("[unhandlable oom]")) ||
693             StringBeginsWith(crash_reason,
694                              NS_LITERAL_CSTRING("Unhandlable OOM"))) {
695           is_oom = true;
696         }
697 
698         CrashReport::Deliver(principal, is_oom);
699       }
700     }
701   }
702 
703   // Prevent executing ContentParent::NotifyTabDestroying in
704   // BrowserParent::Destroy() called by frameLoader->DestroyComplete() below
705   // when tab crashes in contentprocess because ContentParent::ActorDestroy()
706   // in main process will be triggered before this function
707   // and remove the process information that
708   // ContentParent::NotifyTabDestroying need from mContentParentMap.
709 
710   // When tab crashes in content process,
711   // there is no need to call ContentParent::NotifyTabDestroying
712   // because the jobs in ContentParent::NotifyTabDestroying
713   // will be done by ContentParent::ActorDestroy.
714   if (XRE_IsContentProcess() && why == AbnormalShutdown && !mIsDestroyed) {
715     DestroyInternal();
716     mIsDestroyed = true;
717   }
718 
719   // Tell our embedder that the tab is now going away unless we're an
720   // out-of-process iframe.
721   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
722   if (frameLoader) {
723     ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr);
724 
725     if (mBrowsingContext->IsTop()) {
726       // If this is a top-level BrowsingContext, tell the frameloader it's time
727       // to go away. Otherwise, this is a subframe crash, and we can keep the
728       // frameloader around.
729       frameLoader->DestroyComplete();
730     }
731 
732     // If this was a crash, tell our nsFrameLoader to fire crash events.
733     if (why == AbnormalShutdown) {
734       frameLoader->MaybeNotifyCrashed(mBrowsingContext, GetIPCChannel());
735 
736       auto* bridge = GetBrowserBridgeParent();
737       if (bridge && bridge->CanSend() && !mBrowsingContext->IsDiscarded()) {
738         MOZ_ASSERT(!mBrowsingContext->IsTop());
739 
740         // Set the owner process of the root context belonging to a crashed
741         // process to the embedding process, since we'll be showing the crashed
742         // page in that process.
743         mBrowsingContext->SetOwnerProcessId(
744             bridge->Manager()->Manager()->ChildID());
745         mBrowsingContext->SetCurrentInnerWindowId(0);
746 
747         // Tell the browser bridge to show the subframe crashed page.
748         Unused << bridge->SendSubFrameCrashed();
749       }
750     }
751   }
752 
753   mFrameLoader = nullptr;
754 }
755 
RecvMoveFocus(const bool & aForward,const bool & aForDocumentNavigation)756 mozilla::ipc::IPCResult BrowserParent::RecvMoveFocus(
757     const bool& aForward, const bool& aForDocumentNavigation) {
758   LOGBROWSERFOCUS(("RecvMoveFocus %p, aForward: %d, aForDocumentNavigation: %d",
759                    this, aForward, aForDocumentNavigation));
760   BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent();
761   if (bridgeParent) {
762     mozilla::Unused << bridgeParent->SendMoveFocus(aForward,
763                                                    aForDocumentNavigation);
764     return IPC_OK();
765   }
766 
767   nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
768   if (fm) {
769     RefPtr<Element> dummy;
770 
771     uint32_t type =
772         aForward
773             ? (aForDocumentNavigation
774                    ? static_cast<uint32_t>(
775                          nsIFocusManager::MOVEFOCUS_FORWARDDOC)
776                    : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FORWARD))
777             : (aForDocumentNavigation
778                    ? static_cast<uint32_t>(
779                          nsIFocusManager::MOVEFOCUS_BACKWARDDOC)
780                    : static_cast<uint32_t>(
781                          nsIFocusManager::MOVEFOCUS_BACKWARD));
782     fm->MoveFocus(nullptr, mFrameElement, type, nsIFocusManager::FLAG_BYKEY,
783                   getter_AddRefs(dummy));
784   }
785   return IPC_OK();
786 }
787 
RecvSizeShellTo(const uint32_t & aFlags,const int32_t & aWidth,const int32_t & aHeight,const int32_t & aShellItemWidth,const int32_t & aShellItemHeight)788 mozilla::ipc::IPCResult BrowserParent::RecvSizeShellTo(
789     const uint32_t& aFlags, const int32_t& aWidth, const int32_t& aHeight,
790     const int32_t& aShellItemWidth, const int32_t& aShellItemHeight) {
791   NS_ENSURE_TRUE(mFrameElement, IPC_OK());
792 
793   nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
794   NS_ENSURE_TRUE(docShell, IPC_OK());
795 
796   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
797   nsresult rv = docShell->GetTreeOwner(getter_AddRefs(treeOwner));
798   NS_ENSURE_SUCCESS(rv, IPC_OK());
799 
800   int32_t width = aWidth;
801   int32_t height = aHeight;
802 
803   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) {
804     width = mDimensions.width;
805   }
806 
807   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
808     height = mDimensions.height;
809   }
810 
811   nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwner));
812   NS_ENSURE_TRUE(appWin, IPC_OK());
813   appWin->SizeShellToWithLimit(width, height, aShellItemWidth,
814                                aShellItemHeight);
815 
816   return IPC_OK();
817 }
818 
RecvDropLinks(nsTArray<nsString> && aLinks)819 mozilla::ipc::IPCResult BrowserParent::RecvDropLinks(
820     nsTArray<nsString>&& aLinks) {
821   nsCOMPtr<nsIBrowser> browser =
822       mFrameElement ? mFrameElement->AsBrowser() : nullptr;
823   if (browser) {
824     // Verify that links have not been modified by the child. If links have
825     // not been modified then it's safe to load those links using the
826     // SystemPrincipal. If they have been modified by web content, then
827     // we use a NullPrincipal which still allows to load web links.
828     bool loadUsingSystemPrincipal = true;
829     if (aLinks.Length() != mVerifyDropLinks.Length()) {
830       loadUsingSystemPrincipal = false;
831     }
832     for (uint32_t i = 0; i < aLinks.Length(); i++) {
833       if (loadUsingSystemPrincipal) {
834         if (!aLinks[i].Equals(mVerifyDropLinks[i])) {
835           loadUsingSystemPrincipal = false;
836         }
837       }
838     }
839     mVerifyDropLinks.Clear();
840     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
841     if (loadUsingSystemPrincipal) {
842       triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
843     } else {
844       triggeringPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
845     }
846     browser->DropLinks(aLinks, triggeringPrincipal);
847   }
848   return IPC_OK();
849 }
850 
RecvEvent(const RemoteDOMEvent & aEvent)851 mozilla::ipc::IPCResult BrowserParent::RecvEvent(const RemoteDOMEvent& aEvent) {
852   RefPtr<Event> event = aEvent.mEvent;
853   NS_ENSURE_TRUE(event, IPC_OK());
854 
855   RefPtr<EventTarget> target = mFrameElement;
856   NS_ENSURE_TRUE(target, IPC_OK());
857 
858   event->SetOwner(target);
859 
860   target->DispatchEvent(*event);
861   return IPC_OK();
862 }
863 
SendLoadRemoteScript(const nsString & aURL,const bool & aRunInGlobalScope)864 bool BrowserParent::SendLoadRemoteScript(const nsString& aURL,
865                                          const bool& aRunInGlobalScope) {
866   if (mCreatingWindow) {
867     mDelayedFrameScripts.AppendElement(
868         FrameScriptInfo(aURL, aRunInGlobalScope));
869     return true;
870   }
871 
872   MOZ_ASSERT(mDelayedFrameScripts.IsEmpty());
873   return PBrowserParent::SendLoadRemoteScript(aURL, aRunInGlobalScope);
874 }
875 
LoadURL(nsIURI * aURI,nsIPrincipal * aTriggeringPrincipal)876 void BrowserParent::LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) {
877   MOZ_ASSERT(aURI);
878   MOZ_ASSERT(aTriggeringPrincipal);
879 
880   if (mIsDestroyed) {
881     return;
882   }
883 
884   nsCString spec;
885   aURI->GetSpec(spec);
886 
887   if (mCreatingWindow) {
888     // Don't send the message if the child wants to load its own URL.
889     MOZ_ASSERT(mDelayedURL.IsEmpty());
890     mDelayedURL = spec;
891     return;
892   }
893 
894   Unused << SendLoadURL(spec, aTriggeringPrincipal, GetShowInfo());
895 }
896 
ResumeLoad(uint64_t aPendingSwitchID)897 void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID) {
898   MOZ_ASSERT(aPendingSwitchID != 0);
899 
900   if (NS_WARN_IF(mIsDestroyed)) {
901     return;
902   }
903 
904   Unused << SendResumeLoad(aPendingSwitchID, GetShowInfo());
905 }
906 
InitRendering()907 void BrowserParent::InitRendering() {
908   if (mRemoteLayerTreeOwner.IsInitialized()) {
909     return;
910   }
911   mRemoteLayerTreeOwner.Initialize(this);
912 
913   layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId();
914   AddBrowserParentToTable(layersId, this);
915 
916   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
917   if (frameLoader) {
918     nsIFrame* frame = frameLoader->GetPrimaryFrameOfOwningContent();
919     if (frame) {
920       frame->InvalidateFrame();
921     }
922   }
923 
924   TextureFactoryIdentifier textureFactoryIdentifier;
925   mRemoteLayerTreeOwner.GetTextureFactoryIdentifier(&textureFactoryIdentifier);
926   Unused << SendInitRendering(textureFactoryIdentifier, layersId,
927                               mRemoteLayerTreeOwner.GetCompositorOptions(),
928                               mRemoteLayerTreeOwner.IsLayersConnected());
929 
930   RefPtr<nsIWidget> widget = GetTopLevelWidget();
931   if (widget) {
932     ScreenIntMargin safeAreaInsets = widget->GetSafeAreaInsets();
933     Unused << SendSafeAreaInsetsChanged(safeAreaInsets);
934   }
935 
936 #if defined(MOZ_WIDGET_ANDROID)
937   if (XRE_IsParentProcess()) {
938     MOZ_ASSERT(widget);
939 
940     Unused << SendDynamicToolbarMaxHeightChanged(
941         widget->GetDynamicToolbarMaxHeight());
942   }
943 #endif
944 }
945 
AttachLayerManager()946 bool BrowserParent::AttachLayerManager() {
947   return !!mRemoteLayerTreeOwner.AttachLayerManager();
948 }
949 
MaybeShowFrame()950 void BrowserParent::MaybeShowFrame() {
951   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
952   if (!frameLoader) {
953     return;
954   }
955   frameLoader->MaybeShowFrame();
956 }
957 
Show(const OwnerShowInfo & aOwnerInfo)958 bool BrowserParent::Show(const OwnerShowInfo& aOwnerInfo) {
959   mDimensions = aOwnerInfo.size();
960   if (mIsDestroyed) {
961     return false;
962   }
963 
964   MOZ_ASSERT(mRemoteLayerTreeOwner.IsInitialized());
965   if (!mRemoteLayerTreeOwner.AttachLayerManager()) {
966     return false;
967   }
968 
969   mSizeMode = aOwnerInfo.sizeMode();
970   Unused << SendShow(GetShowInfo(), aOwnerInfo);
971   return true;
972 }
973 
RecvSetDimensions(const uint32_t & aFlags,const int32_t & aX,const int32_t & aY,const int32_t & aCx,const int32_t & aCy,const double & aScale)974 mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
975     const uint32_t& aFlags, const int32_t& aX, const int32_t& aY,
976     const int32_t& aCx, const int32_t& aCy, const double& aScale) {
977   MOZ_ASSERT(!(aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER),
978              "We should never see DIM_FLAGS_SIZE_INNER here!");
979 
980   NS_ENSURE_TRUE(mFrameElement, IPC_OK());
981   nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
982   NS_ENSURE_TRUE(docShell, IPC_OK());
983   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
984   docShell->GetTreeOwner(getter_AddRefs(treeOwner));
985   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner);
986   NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK());
987 
988   // We only care about the parameters that actually changed, see more details
989   // in `BrowserChild::SetDimensions()`.
990   // Note that `BrowserChild::SetDimensions()` may be called before receiving
991   // our `SendUIResolutionChanged()` call.  Therefore, if given each cordinate
992   // shouldn't be ignored, we need to recompute it if DPI has been changed.
993   // And also note that don't use `mDefaultScale.scale` here since it may be
994   // different from the result of `GetUnscaledDevicePixelsPerCSSPixel()`.
995   double currentScale;
996   treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&currentScale);
997 
998   int32_t x = aX;
999   int32_t y = aY;
1000   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
1001     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X) {
1002       int32_t unused;
1003       treeOwnerAsWin->GetPosition(&x, &unused);
1004     } else if (aScale != currentScale) {
1005       x = x * currentScale / aScale;
1006     }
1007 
1008     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y) {
1009       int32_t unused;
1010       treeOwnerAsWin->GetPosition(&unused, &y);
1011     } else if (aScale != currentScale) {
1012       y = y * currentScale / aScale;
1013     }
1014   }
1015 
1016   int32_t cx = aCx;
1017   int32_t cy = aCy;
1018   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
1019     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) {
1020       int32_t unused;
1021       treeOwnerAsWin->GetSize(&cx, &unused);
1022     } else if (aScale != currentScale) {
1023       cx = cx * currentScale / aScale;
1024     }
1025 
1026     if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
1027       int32_t unused;
1028       treeOwnerAsWin->GetSize(&unused, &cy);
1029     } else if (aScale != currentScale) {
1030       cy = cy * currentScale / aScale;
1031     }
1032   }
1033 
1034   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
1035       aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
1036     treeOwnerAsWin->SetPositionAndSize(x, y, cx, cy, nsIBaseWindow::eRepaint);
1037     return IPC_OK();
1038   }
1039 
1040   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
1041     treeOwnerAsWin->SetPosition(x, y);
1042     mUpdatedDimensions = false;
1043     UpdatePosition();
1044     return IPC_OK();
1045   }
1046 
1047   if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
1048     treeOwnerAsWin->SetSize(cx, cy, true);
1049     return IPC_OK();
1050   }
1051 
1052   MOZ_ASSERT(false, "Unknown flags!");
1053   return IPC_FAIL_NO_REASON(this);
1054 }
1055 
UpdatePosition()1056 nsresult BrowserParent::UpdatePosition() {
1057   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1058   if (!frameLoader) {
1059     return NS_OK;
1060   }
1061   nsIntRect windowDims;
1062   NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims),
1063                     NS_ERROR_FAILURE);
1064   UpdateDimensions(windowDims, mDimensions);
1065   return NS_OK;
1066 }
1067 
UpdateDimensions(const nsIntRect & rect,const ScreenIntSize & size)1068 void BrowserParent::UpdateDimensions(const nsIntRect& rect,
1069                                      const ScreenIntSize& size) {
1070   if (mIsDestroyed) {
1071     return;
1072   }
1073   nsCOMPtr<nsIWidget> widget = GetWidget();
1074   if (!widget) {
1075     NS_WARNING("No widget found in BrowserParent::UpdateDimensions");
1076     return;
1077   }
1078 
1079   hal::ScreenConfiguration config;
1080   hal::GetCurrentScreenConfiguration(&config);
1081   hal::ScreenOrientation orientation = config.orientation();
1082   LayoutDeviceIntPoint clientOffset = GetClientOffset();
1083   LayoutDeviceIntPoint chromeOffset = -GetChildProcessOffset();
1084 
1085   if (!mUpdatedDimensions || mOrientation != orientation ||
1086       mDimensions != size || !mRect.IsEqualEdges(rect) ||
1087       clientOffset != mClientOffset || chromeOffset != mChromeOffset) {
1088     mUpdatedDimensions = true;
1089     mRect = rect;
1090     mDimensions = size;
1091     mOrientation = orientation;
1092     mClientOffset = clientOffset;
1093     mChromeOffset = chromeOffset;
1094 
1095     Unused << SendUpdateDimensions(GetDimensionInfo());
1096   }
1097 }
1098 
GetDimensionInfo()1099 DimensionInfo BrowserParent::GetDimensionInfo() {
1100   nsCOMPtr<nsIWidget> widget = GetWidget();
1101   MOZ_ASSERT(widget);
1102   CSSToLayoutDeviceScale widgetScale = widget->GetDefaultScale();
1103 
1104   LayoutDeviceIntRect devicePixelRect = ViewAs<LayoutDevicePixel>(
1105       mRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
1106   LayoutDeviceIntSize devicePixelSize = ViewAs<LayoutDevicePixel>(
1107       mDimensions, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
1108 
1109   CSSRect unscaledRect = devicePixelRect / widgetScale;
1110   CSSSize unscaledSize = devicePixelSize / widgetScale;
1111   DimensionInfo di(unscaledRect, unscaledSize, mOrientation, mClientOffset,
1112                    mChromeOffset);
1113   return di;
1114 }
1115 
SizeModeChanged(const nsSizeMode & aSizeMode)1116 void BrowserParent::SizeModeChanged(const nsSizeMode& aSizeMode) {
1117   if (!mIsDestroyed && aSizeMode != mSizeMode) {
1118     mSizeMode = aSizeMode;
1119     Unused << SendSizeModeChanged(aSizeMode);
1120   }
1121 }
1122 
1123 #if defined(MOZ_WIDGET_ANDROID)
DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight)1124 void BrowserParent::DynamicToolbarMaxHeightChanged(ScreenIntCoord aHeight) {
1125   if (!mIsDestroyed) {
1126     Unused << SendDynamicToolbarMaxHeightChanged(aHeight);
1127   }
1128 }
1129 
DynamicToolbarOffsetChanged(ScreenIntCoord aOffset)1130 void BrowserParent::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {
1131   if (!mIsDestroyed) {
1132     Unused << SendDynamicToolbarOffsetChanged(aOffset);
1133   }
1134 }
1135 #endif
1136 
HandleAccessKey(const WidgetKeyboardEvent & aEvent,nsTArray<uint32_t> & aCharCodes)1137 void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent,
1138                                     nsTArray<uint32_t>& aCharCodes) {
1139   if (!mIsDestroyed) {
1140     // Note that we don't need to mark aEvent is posted to a remote process
1141     // because the event may be dispatched to it as normal keyboard event.
1142     // Therefore, we should use local copy to send it.
1143     WidgetKeyboardEvent localEvent(aEvent);
1144     Unused << SendHandleAccessKey(localEvent, aCharCodes);
1145   }
1146 }
1147 
Activate()1148 void BrowserParent::Activate() {
1149   LOGBROWSERFOCUS(("Activate %p", this));
1150   if (!mIsDestroyed) {
1151     SetTopLevelWebFocus(this);  // Intentionally inside "if"
1152     Unused << SendActivate();
1153   }
1154 }
1155 
Deactivate(bool aWindowLowering)1156 void BrowserParent::Deactivate(bool aWindowLowering) {
1157   LOGBROWSERFOCUS(("Deactivate %p", this));
1158   if (!aWindowLowering) {
1159     UnsetTopLevelWebFocus(this);  // Intentionally outside the next "if"
1160   }
1161   if (!mIsDestroyed) {
1162     Unused << SendDeactivate();
1163   }
1164 }
1165 
1166 #ifdef ACCESSIBILITY
AllocPDocAccessibleParent(PDocAccessibleParent * aParent,const uint64_t &,const uint32_t &,const IAccessibleHolder &)1167 a11y::PDocAccessibleParent* BrowserParent::AllocPDocAccessibleParent(
1168     PDocAccessibleParent* aParent, const uint64_t&, const uint32_t&,
1169     const IAccessibleHolder&) {
1170   // Reference freed in DeallocPDocAccessibleParent.
1171   return do_AddRef(new a11y::DocAccessibleParent()).take();
1172 }
1173 
DeallocPDocAccessibleParent(PDocAccessibleParent * aParent)1174 bool BrowserParent::DeallocPDocAccessibleParent(PDocAccessibleParent* aParent) {
1175   // Free reference from AllocPDocAccessibleParent.
1176   static_cast<a11y::DocAccessibleParent*>(aParent)->Release();
1177   return true;
1178 }
1179 
RecvPDocAccessibleConstructor(PDocAccessibleParent * aDoc,PDocAccessibleParent * aParentDoc,const uint64_t & aParentID,const uint32_t & aMsaaID,const IAccessibleHolder & aDocCOMProxy)1180 mozilla::ipc::IPCResult BrowserParent::RecvPDocAccessibleConstructor(
1181     PDocAccessibleParent* aDoc, PDocAccessibleParent* aParentDoc,
1182     const uint64_t& aParentID, const uint32_t& aMsaaID,
1183     const IAccessibleHolder& aDocCOMProxy) {
1184   auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc);
1185 
1186   // If this tab is already shutting down just mark the new actor as shutdown
1187   // and ignore it.  When the tab actor is destroyed it will be too.
1188   if (mIsDestroyed) {
1189     doc->MarkAsShutdown();
1190     return IPC_OK();
1191   }
1192 
1193   if (aParentDoc) {
1194     // A document should never directly be the parent of another document.
1195     // There should always be an outer doc accessible child of the outer
1196     // document containing the child.
1197     MOZ_ASSERT(aParentID);
1198     if (!aParentID) {
1199       return IPC_FAIL_NO_REASON(this);
1200     }
1201 
1202     auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
1203     mozilla::ipc::IPCResult added = parentDoc->AddChildDoc(doc, aParentID);
1204     if (!added) {
1205 #  ifdef DEBUG
1206       return added;
1207 #  else
1208       return IPC_OK();
1209 #  endif
1210     }
1211 
1212 #  ifdef XP_WIN
1213     MOZ_ASSERT(aDocCOMProxy.IsNull());
1214     a11y::WrapperFor(doc)->SetID(aMsaaID);
1215     if (a11y::nsWinUtils::IsWindowEmulationStarted()) {
1216       doc->SetEmulatedWindowHandle(parentDoc->GetEmulatedWindowHandle());
1217     }
1218 #  endif
1219 
1220     return IPC_OK();
1221   }
1222 
1223   if (GetBrowserBridgeParent()) {
1224     // Iframe document rendered in a different process to its embedder.
1225     // In this case, we don't get aParentDoc and aParentID.
1226     MOZ_ASSERT(!aParentDoc && !aParentID);
1227     doc->SetTopLevelInContentProcess();
1228 #  ifdef XP_WIN
1229     MOZ_ASSERT(!aDocCOMProxy.IsNull());
1230     RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
1231     doc->SetCOMInterface(proxy);
1232 #  endif
1233     a11y::ProxyCreated(
1234         doc, a11y::Interfaces::DOCUMENT | a11y::Interfaces::HYPERTEXT);
1235 #  ifdef XP_WIN
1236     // This *must* be called after ProxyCreated because WrapperFor will fail
1237     // before that.
1238     a11y::AccessibleWrap* wrapper = a11y::WrapperFor(doc);
1239     MOZ_ASSERT(wrapper);
1240     wrapper->SetID(aMsaaID);
1241 #  endif
1242     a11y::DocAccessibleParent* embedderDoc;
1243     uint64_t embedderID;
1244     Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
1245     // It's possible the embedder accessible hasn't been set yet; e.g.
1246     // a hidden iframe. In that case, embedderDoc will be null and this will
1247     // be handled when the embedder is set.
1248     if (embedderDoc) {
1249       MOZ_ASSERT(embedderID);
1250       mozilla::ipc::IPCResult added =
1251           embedderDoc->AddChildDoc(doc, embedderID,
1252                                    /* aCreating */ false);
1253       if (!added) {
1254 #  ifdef DEBUG
1255         return added;
1256 #  else
1257         return IPC_OK();
1258 #  endif
1259       }
1260     }
1261     return IPC_OK();
1262   } else {
1263     // null aParentDoc means this document is at the top level in the child
1264     // process.  That means it makes no sense to get an id for an accessible
1265     // that is its parent.
1266     MOZ_ASSERT(!aParentID);
1267     if (aParentID) {
1268       return IPC_FAIL_NO_REASON(this);
1269     }
1270 
1271     doc->SetTopLevel();
1272     a11y::DocManager::RemoteDocAdded(doc);
1273 #  ifdef XP_WIN
1274     a11y::WrapperFor(doc)->SetID(aMsaaID);
1275     MOZ_ASSERT(!aDocCOMProxy.IsNull());
1276 
1277     RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
1278     doc->SetCOMInterface(proxy);
1279     doc->MaybeInitWindowEmulation();
1280     if (a11y::Accessible* outerDoc = doc->OuterDocOfRemoteBrowser()) {
1281       doc->SendParentCOMProxy(outerDoc);
1282     }
1283 #  endif
1284   }
1285   return IPC_OK();
1286 }
1287 #endif
1288 
AllocPFilePickerParent(const nsString & aTitle,const int16_t & aMode)1289 PFilePickerParent* BrowserParent::AllocPFilePickerParent(const nsString& aTitle,
1290                                                          const int16_t& aMode) {
1291   return new FilePickerParent(aTitle, aMode);
1292 }
1293 
DeallocPFilePickerParent(PFilePickerParent * actor)1294 bool BrowserParent::DeallocPFilePickerParent(PFilePickerParent* actor) {
1295   delete actor;
1296   return true;
1297 }
1298 
RecvIndexedDBPermissionRequest(nsIPrincipal * aPrincipal,IndexedDBPermissionRequestResolver && aResolve)1299 IPCResult BrowserParent::RecvIndexedDBPermissionRequest(
1300     nsIPrincipal* aPrincipal, IndexedDBPermissionRequestResolver&& aResolve) {
1301   MOZ_ASSERT(NS_IsMainThread());
1302 
1303   nsCOMPtr<nsIPrincipal> principal(aPrincipal);
1304   if (!principal) {
1305     return IPC_FAIL_NO_REASON(this);
1306   }
1307 
1308   if (NS_WARN_IF(!mFrameElement)) {
1309     return IPC_FAIL_NO_REASON(this);
1310   }
1311 
1312   RefPtr<indexedDB::PermissionRequestHelper> actor =
1313       new indexedDB::PermissionRequestHelper(mFrameElement, principal,
1314                                              aResolve);
1315 
1316   indexedDB::PermissionRequestBase::PermissionValue permission;
1317   nsresult rv = actor->PromptIfNeeded(&permission);
1318   if (NS_FAILED(rv)) {
1319     return IPC_FAIL_NO_REASON(this);
1320   }
1321 
1322   if (permission != indexedDB::PermissionRequestBase::kPermissionPrompt) {
1323     aResolve(permission);
1324   }
1325 
1326   return IPC_OK();
1327 }
1328 
RecvNewWindowGlobal(ManagedEndpoint<PWindowGlobalParent> && aEndpoint,const WindowGlobalInit & aInit)1329 IPCResult BrowserParent::RecvNewWindowGlobal(
1330     ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
1331     const WindowGlobalInit& aInit) {
1332   RefPtr<CanonicalBrowsingContext> browsingContext =
1333       CanonicalBrowsingContext::Get(aInit.context().mBrowsingContextId);
1334   if (!browsingContext) {
1335     return IPC_FAIL(this, "Cannot create for missing BrowsingContext");
1336   }
1337   if (!aInit.principal()) {
1338     return IPC_FAIL(this, "Cannot create without valid principal");
1339   }
1340 
1341   // Construct our new WindowGlobalParent, bind, and initialize it.
1342   RefPtr<WindowGlobalParent> wgp =
1343       WindowGlobalParent::CreateDisconnected(aInit);
1344   BindPWindowGlobalEndpoint(std::move(aEndpoint), wgp);
1345   wgp->Init();
1346   return IPC_OK();
1347 }
1348 
SendMouseEvent(const nsAString & aType,float aX,float aY,int32_t aButton,int32_t aClickCount,int32_t aModifiers)1349 void BrowserParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
1350                                    int32_t aButton, int32_t aClickCount,
1351                                    int32_t aModifiers) {
1352   if (!mIsDestroyed) {
1353     Unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY, aButton,
1354                                              aClickCount, aModifiers);
1355   }
1356 }
1357 
MouseEnterIntoWidget()1358 void BrowserParent::MouseEnterIntoWidget() {
1359   nsCOMPtr<nsIWidget> widget = GetWidget();
1360   if (widget) {
1361     // When we mouseenter the tab, the tab's cursor should
1362     // become the current cursor.  When we mouseexit, we stop.
1363     mTabSetsCursor = true;
1364     if (mCursor != eCursorInvalid) {
1365       widget->SetCursor(mCursor, mCustomCursor, mCustomCursorHotspotX,
1366                         mCustomCursorHotspotY);
1367     }
1368   }
1369 
1370   // Mark that we have missed a mouse enter event, so that
1371   // the next mouse event will create a replacement mouse
1372   // enter event and send it to the child.
1373   mIsMouseEnterIntoWidgetEventSuppressed = true;
1374 }
1375 
SendRealMouseEvent(WidgetMouseEvent & aEvent)1376 void BrowserParent::SendRealMouseEvent(WidgetMouseEvent& aEvent) {
1377   if (mIsDestroyed) {
1378     return;
1379   }
1380 
1381   // XXXedgar, if the synthesized mouse events could deliver to the correct
1382   // process directly (see
1383   // https://bugzilla.mozilla.org/show_bug.cgi?id=1549355), we probably don't
1384   // need to check mReason then.
1385   if (aEvent.mReason == WidgetMouseEvent::eReal) {
1386     if (aEvent.mMessage == eMouseExitFromWidget) {
1387       // Since we are leaving this remote target, so don't need to update
1388       // sLastMouseRemoteTarget, and if we are sLastMouseRemoteTarget, reset it
1389       // to null.
1390       BrowserParent::UnsetLastMouseRemoteTarget(this);
1391     } else {
1392       // Last remote target should not be changed without eMouseExitFromWidget.
1393       MOZ_ASSERT_IF(sLastMouseRemoteTarget, sLastMouseRemoteTarget == this);
1394       sLastMouseRemoteTarget = this;
1395     }
1396   }
1397 
1398   aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint);
1399 
1400   nsCOMPtr<nsIWidget> widget = GetWidget();
1401   if (widget) {
1402     // When we mouseenter the tab, the tab's cursor should
1403     // become the current cursor.  When we mouseexit, we stop.
1404     if (eMouseEnterIntoWidget == aEvent.mMessage) {
1405       mTabSetsCursor = true;
1406       if (mCursor != eCursorInvalid) {
1407         widget->SetCursor(mCursor, mCustomCursor, mCustomCursorHotspotX,
1408                           mCustomCursorHotspotY);
1409       }
1410     } else if (eMouseExitFromWidget == aEvent.mMessage) {
1411       mTabSetsCursor = false;
1412     }
1413   }
1414   if (!mIsReadyToHandleInputEvents) {
1415     if (eMouseEnterIntoWidget == aEvent.mMessage) {
1416       mIsMouseEnterIntoWidgetEventSuppressed = true;
1417     } else if (eMouseExitFromWidget == aEvent.mMessage) {
1418       mIsMouseEnterIntoWidgetEventSuppressed = false;
1419     }
1420     return;
1421   }
1422 
1423   ScrollableLayerGuid guid;
1424   uint64_t blockId;
1425   ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
1426 
1427   bool isInputPriorityEventEnabled = Manager()->IsInputPriorityEventEnabled();
1428 
1429   if (mIsMouseEnterIntoWidgetEventSuppressed) {
1430     // In the case that the BrowserParent suppressed the eMouseEnterWidget event
1431     // due to its corresponding BrowserChild wasn't ready to handle it, we have
1432     // to resend it when the BrowserChild is ready.
1433     mIsMouseEnterIntoWidgetEventSuppressed = false;
1434     WidgetMouseEvent localEvent(aEvent);
1435     localEvent.mMessage = eMouseEnterIntoWidget;
1436     DebugOnly<bool> ret =
1437         isInputPriorityEventEnabled
1438             ? SendRealMouseButtonEvent(localEvent, guid, blockId)
1439             : SendNormalPriorityRealMouseButtonEvent(localEvent, guid, blockId);
1440     NS_WARNING_ASSERTION(
1441         ret, "SendRealMouseButtonEvent(eMouseEnterIntoWidget) failed");
1442     MOZ_ASSERT(!ret || localEvent.HasBeenPostedToRemoteProcess());
1443   }
1444 
1445   if (eMouseMove == aEvent.mMessage) {
1446     if (aEvent.mReason == WidgetMouseEvent::eSynthesized) {
1447       DebugOnly<bool> ret =
1448           isInputPriorityEventEnabled
1449               ? SendSynthMouseMoveEvent(aEvent, guid, blockId)
1450               : SendNormalPrioritySynthMouseMoveEvent(aEvent, guid, blockId);
1451       NS_WARNING_ASSERTION(ret, "SendSynthMouseMoveEvent() failed");
1452       MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1453       return;
1454     }
1455     DebugOnly<bool> ret =
1456         isInputPriorityEventEnabled
1457             ? SendRealMouseMoveEvent(aEvent, guid, blockId)
1458             : SendNormalPriorityRealMouseMoveEvent(aEvent, guid, blockId);
1459     NS_WARNING_ASSERTION(ret, "SendRealMouseMoveEvent() failed");
1460     MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1461     return;
1462   }
1463 
1464   DebugOnly<bool> ret =
1465       isInputPriorityEventEnabled
1466           ? SendRealMouseButtonEvent(aEvent, guid, blockId)
1467           : SendNormalPriorityRealMouseButtonEvent(aEvent, guid, blockId);
1468   NS_WARNING_ASSERTION(ret, "SendRealMouseButtonEvent() failed");
1469   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1470 }
1471 
GetLayoutDeviceToCSSScale()1472 LayoutDeviceToCSSScale BrowserParent::GetLayoutDeviceToCSSScale() {
1473   Document* doc = (mFrameElement ? mFrameElement->OwnerDoc() : nullptr);
1474   nsPresContext* ctx = (doc ? doc->GetPresContext() : nullptr);
1475   return LayoutDeviceToCSSScale(
1476       ctx ? (float)ctx->AppUnitsPerDevPixel() / AppUnitsPerCSSPixel() : 0.0f);
1477 }
1478 
QueryDropLinksForVerification()1479 bool BrowserParent::QueryDropLinksForVerification() {
1480   // Before sending the dragEvent, we query the links being dragged and
1481   // store them on the parent, to make sure the child can not modify links.
1482   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
1483   if (!dragSession) {
1484     NS_WARNING("No dragSession to query links for verification");
1485     return false;
1486   }
1487 
1488   RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
1489   if (!initialDataTransfer) {
1490     NS_WARNING("No initialDataTransfer to query links for verification");
1491     return false;
1492   }
1493 
1494   nsCOMPtr<nsIDroppedLinkHandler> dropHandler =
1495       do_GetService("@mozilla.org/content/dropped-link-handler;1");
1496   if (!dropHandler) {
1497     NS_WARNING("No dropHandler to query links for verification");
1498     return false;
1499   }
1500 
1501   // No more than one drop event can happen simultaneously; reset the link
1502   // verification array and store all links that are being dragged.
1503   mVerifyDropLinks.Clear();
1504 
1505   nsTArray<RefPtr<nsIDroppedLinkItem>> droppedLinkItems;
1506   dropHandler->QueryLinks(initialDataTransfer, droppedLinkItems);
1507 
1508   // Since the entire event is cancelled if one of the links is invalid,
1509   // we can store all links on the parent side without any prior
1510   // validation checks.
1511   nsresult rv = NS_OK;
1512   for (nsIDroppedLinkItem* item : droppedLinkItems) {
1513     nsString tmp;
1514     rv = item->GetUrl(tmp);
1515     if (NS_FAILED(rv)) {
1516       NS_WARNING("Failed to query url for verification");
1517       break;
1518     }
1519     mVerifyDropLinks.AppendElement(tmp);
1520 
1521     rv = item->GetName(tmp);
1522     if (NS_FAILED(rv)) {
1523       NS_WARNING("Failed to query name for verification");
1524       break;
1525     }
1526     mVerifyDropLinks.AppendElement(tmp);
1527 
1528     rv = item->GetType(tmp);
1529     if (NS_FAILED(rv)) {
1530       NS_WARNING("Failed to query type for verification");
1531       break;
1532     }
1533     mVerifyDropLinks.AppendElement(tmp);
1534   }
1535   if (NS_FAILED(rv)) {
1536     mVerifyDropLinks.Clear();
1537     return false;
1538   }
1539   return true;
1540 }
1541 
SendRealDragEvent(WidgetDragEvent & aEvent,uint32_t aDragAction,uint32_t aDropEffect,nsIPrincipal * aPrincipal,nsIContentSecurityPolicy * aCsp)1542 void BrowserParent::SendRealDragEvent(WidgetDragEvent& aEvent,
1543                                       uint32_t aDragAction,
1544                                       uint32_t aDropEffect,
1545                                       nsIPrincipal* aPrincipal,
1546                                       nsIContentSecurityPolicy* aCsp) {
1547   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
1548     return;
1549   }
1550   MOZ_ASSERT(!Manager()->IsInputPriorityEventEnabled());
1551   aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint);
1552   if (aEvent.mMessage == eDrop) {
1553     if (!QueryDropLinksForVerification()) {
1554       return;
1555     }
1556   }
1557   DebugOnly<bool> ret = PBrowserParent::SendRealDragEvent(
1558       aEvent, aDragAction, aDropEffect, aPrincipal, aCsp);
1559   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealDragEvent() failed");
1560   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1561 }
1562 
SendMouseWheelEvent(WidgetWheelEvent & aEvent)1563 void BrowserParent::SendMouseWheelEvent(WidgetWheelEvent& aEvent) {
1564   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
1565     return;
1566   }
1567 
1568   ScrollableLayerGuid guid;
1569   uint64_t blockId;
1570   ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
1571   aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint);
1572   DebugOnly<bool> ret =
1573       Manager()->IsInputPriorityEventEnabled()
1574           ? PBrowserParent::SendMouseWheelEvent(aEvent, guid, blockId)
1575           : PBrowserParent::SendNormalPriorityMouseWheelEvent(aEvent, guid,
1576                                                               blockId);
1577 
1578   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendMouseWheelEvent() failed");
1579   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1580 }
1581 
RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent & aEvent)1582 mozilla::ipc::IPCResult BrowserParent::RecvDispatchWheelEvent(
1583     const mozilla::WidgetWheelEvent& aEvent) {
1584   nsCOMPtr<nsIWidget> widget = GetWidget();
1585   if (!widget) {
1586     return IPC_OK();
1587   }
1588 
1589   WidgetWheelEvent localEvent(aEvent);
1590   localEvent.mWidget = widget;
1591   localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint);
1592 
1593   widget->DispatchInputEvent(&localEvent);
1594   return IPC_OK();
1595 }
1596 
RecvDispatchMouseEvent(const mozilla::WidgetMouseEvent & aEvent)1597 mozilla::ipc::IPCResult BrowserParent::RecvDispatchMouseEvent(
1598     const mozilla::WidgetMouseEvent& aEvent) {
1599   nsCOMPtr<nsIWidget> widget = GetWidget();
1600   if (!widget) {
1601     return IPC_OK();
1602   }
1603 
1604   WidgetMouseEvent localEvent(aEvent);
1605   localEvent.mWidget = widget;
1606   localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint);
1607 
1608   widget->DispatchInputEvent(&localEvent);
1609   return IPC_OK();
1610 }
1611 
RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent & aEvent)1612 mozilla::ipc::IPCResult BrowserParent::RecvDispatchKeyboardEvent(
1613     const mozilla::WidgetKeyboardEvent& aEvent) {
1614   nsCOMPtr<nsIWidget> widget = GetWidget();
1615   if (!widget) {
1616     return IPC_OK();
1617   }
1618 
1619   WidgetKeyboardEvent localEvent(aEvent);
1620   localEvent.mWidget = widget;
1621   localEvent.mRefPoint = TransformChildToParent(localEvent.mRefPoint);
1622 
1623   widget->DispatchInputEvent(&localEvent);
1624   return IPC_OK();
1625 }
1626 
RecvRequestNativeKeyBindings(const uint32_t & aType,const WidgetKeyboardEvent & aEvent,nsTArray<CommandInt> * aCommands)1627 mozilla::ipc::IPCResult BrowserParent::RecvRequestNativeKeyBindings(
1628     const uint32_t& aType, const WidgetKeyboardEvent& aEvent,
1629     nsTArray<CommandInt>* aCommands) {
1630   MOZ_ASSERT(aCommands);
1631   MOZ_ASSERT(aCommands->IsEmpty());
1632 
1633   nsIWidget::NativeKeyBindingsType keyBindingsType =
1634       static_cast<nsIWidget::NativeKeyBindingsType>(aType);
1635   switch (keyBindingsType) {
1636     case nsIWidget::NativeKeyBindingsForSingleLineEditor:
1637     case nsIWidget::NativeKeyBindingsForMultiLineEditor:
1638     case nsIWidget::NativeKeyBindingsForRichTextEditor:
1639       break;
1640     default:
1641       return IPC_FAIL(this, "Invalid aType value");
1642   }
1643 
1644   nsCOMPtr<nsIWidget> widget = GetWidget();
1645   if (!widget) {
1646     return IPC_OK();
1647   }
1648 
1649   WidgetKeyboardEvent localEvent(aEvent);
1650   localEvent.mWidget = widget;
1651 
1652   if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
1653     return IPC_OK();
1654   }
1655 
1656   if (localEvent.InitEditCommandsFor(keyBindingsType)) {
1657     *aCommands = localEvent.EditCommandsConstRef(keyBindingsType).Clone();
1658   }
1659 
1660   return IPC_OK();
1661 }
1662 
1663 class SynthesizedEventObserver : public nsIObserver {
1664   NS_DECL_ISUPPORTS
1665 
1666  public:
SynthesizedEventObserver(BrowserParent * aBrowserParent,const uint64_t & aObserverId)1667   SynthesizedEventObserver(BrowserParent* aBrowserParent,
1668                            const uint64_t& aObserverId)
1669       : mBrowserParent(aBrowserParent), mObserverId(aObserverId) {
1670     MOZ_ASSERT(mBrowserParent);
1671   }
1672 
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)1673   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
1674                      const char16_t* aData) override {
1675     if (!mBrowserParent || !mObserverId) {
1676       // We already sent the notification, or we don't actually need to
1677       // send any notification at all.
1678       return NS_OK;
1679     }
1680 
1681     if (mBrowserParent->IsDestroyed()) {
1682       // If this happens it's probably a bug in the test that's triggering this.
1683       NS_WARNING(
1684           "BrowserParent was unexpectedly destroyed during event "
1685           "synthesization!");
1686     } else if (!mBrowserParent->SendNativeSynthesisResponse(
1687                    mObserverId, nsCString(aTopic))) {
1688       NS_WARNING("Unable to send native event synthesization response!");
1689     }
1690     // Null out browserParent to indicate we already sent the response
1691     mBrowserParent = nullptr;
1692     return NS_OK;
1693   }
1694 
1695  private:
1696   virtual ~SynthesizedEventObserver() = default;
1697 
1698   RefPtr<BrowserParent> mBrowserParent;
1699   uint64_t mObserverId;
1700 };
1701 
1702 NS_IMPL_ISUPPORTS(SynthesizedEventObserver, nsIObserver)
1703 
1704 class MOZ_STACK_CLASS AutoSynthesizedEventResponder {
1705  public:
AutoSynthesizedEventResponder(BrowserParent * aBrowserParent,const uint64_t & aObserverId,const char * aTopic)1706   AutoSynthesizedEventResponder(BrowserParent* aBrowserParent,
1707                                 const uint64_t& aObserverId, const char* aTopic)
1708       : mObserver(new SynthesizedEventObserver(aBrowserParent, aObserverId)),
1709         mTopic(aTopic) {}
1710 
~AutoSynthesizedEventResponder()1711   ~AutoSynthesizedEventResponder() {
1712     // This may be a no-op if the observer already sent a response.
1713     mObserver->Observe(nullptr, mTopic, nullptr);
1714   }
1715 
GetObserver()1716   nsIObserver* GetObserver() { return mObserver; }
1717 
1718  private:
1719   nsCOMPtr<nsIObserver> mObserver;
1720   const char* mTopic;
1721 };
1722 
RecvSynthesizeNativeKeyEvent(const int32_t & aNativeKeyboardLayout,const int32_t & aNativeKeyCode,const uint32_t & aModifierFlags,const nsString & aCharacters,const nsString & aUnmodifiedCharacters,const uint64_t & aObserverId)1723 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeKeyEvent(
1724     const int32_t& aNativeKeyboardLayout, const int32_t& aNativeKeyCode,
1725     const uint32_t& aModifierFlags, const nsString& aCharacters,
1726     const nsString& aUnmodifiedCharacters, const uint64_t& aObserverId) {
1727   AutoSynthesizedEventResponder responder(this, aObserverId, "keyevent");
1728   nsCOMPtr<nsIWidget> widget = GetWidget();
1729   if (widget) {
1730     widget->SynthesizeNativeKeyEvent(
1731         aNativeKeyboardLayout, aNativeKeyCode, aModifierFlags, aCharacters,
1732         aUnmodifiedCharacters, responder.GetObserver());
1733   }
1734   return IPC_OK();
1735 }
1736 
RecvSynthesizeNativeMouseEvent(const LayoutDeviceIntPoint & aPoint,const uint32_t & aNativeMessage,const uint32_t & aModifierFlags,const uint64_t & aObserverId)1737 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseEvent(
1738     const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage,
1739     const uint32_t& aModifierFlags, const uint64_t& aObserverId) {
1740   AutoSynthesizedEventResponder responder(this, aObserverId, "mouseevent");
1741   nsCOMPtr<nsIWidget> widget = GetWidget();
1742   if (widget) {
1743     widget->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, aModifierFlags,
1744                                        responder.GetObserver());
1745   }
1746   return IPC_OK();
1747 }
1748 
RecvSynthesizeNativeMouseMove(const LayoutDeviceIntPoint & aPoint,const uint64_t & aObserverId)1749 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseMove(
1750     const LayoutDeviceIntPoint& aPoint, const uint64_t& aObserverId) {
1751   AutoSynthesizedEventResponder responder(this, aObserverId, "mousemove");
1752   nsCOMPtr<nsIWidget> widget = GetWidget();
1753   if (widget) {
1754     widget->SynthesizeNativeMouseMove(aPoint, responder.GetObserver());
1755   }
1756   return IPC_OK();
1757 }
1758 
RecvSynthesizeNativeMouseScrollEvent(const LayoutDeviceIntPoint & aPoint,const uint32_t & aNativeMessage,const double & aDeltaX,const double & aDeltaY,const double & aDeltaZ,const uint32_t & aModifierFlags,const uint32_t & aAdditionalFlags,const uint64_t & aObserverId)1759 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeMouseScrollEvent(
1760     const LayoutDeviceIntPoint& aPoint, const uint32_t& aNativeMessage,
1761     const double& aDeltaX, const double& aDeltaY, const double& aDeltaZ,
1762     const uint32_t& aModifierFlags, const uint32_t& aAdditionalFlags,
1763     const uint64_t& aObserverId) {
1764   AutoSynthesizedEventResponder responder(this, aObserverId,
1765                                           "mousescrollevent");
1766   nsCOMPtr<nsIWidget> widget = GetWidget();
1767   if (widget) {
1768     widget->SynthesizeNativeMouseScrollEvent(
1769         aPoint, aNativeMessage, aDeltaX, aDeltaY, aDeltaZ, aModifierFlags,
1770         aAdditionalFlags, responder.GetObserver());
1771   }
1772   return IPC_OK();
1773 }
1774 
RecvSynthesizeNativeTouchPoint(const uint32_t & aPointerId,const TouchPointerState & aPointerState,const LayoutDeviceIntPoint & aPoint,const double & aPointerPressure,const uint32_t & aPointerOrientation,const uint64_t & aObserverId)1775 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchPoint(
1776     const uint32_t& aPointerId, const TouchPointerState& aPointerState,
1777     const LayoutDeviceIntPoint& aPoint, const double& aPointerPressure,
1778     const uint32_t& aPointerOrientation, const uint64_t& aObserverId) {
1779   AutoSynthesizedEventResponder responder(this, aObserverId, "touchpoint");
1780   nsCOMPtr<nsIWidget> widget = GetWidget();
1781   if (widget) {
1782     widget->SynthesizeNativeTouchPoint(aPointerId, aPointerState, aPoint,
1783                                        aPointerPressure, aPointerOrientation,
1784                                        responder.GetObserver());
1785   }
1786   return IPC_OK();
1787 }
1788 
RecvSynthesizeNativeTouchTap(const LayoutDeviceIntPoint & aPoint,const bool & aLongTap,const uint64_t & aObserverId)1789 mozilla::ipc::IPCResult BrowserParent::RecvSynthesizeNativeTouchTap(
1790     const LayoutDeviceIntPoint& aPoint, const bool& aLongTap,
1791     const uint64_t& aObserverId) {
1792   AutoSynthesizedEventResponder responder(this, aObserverId, "touchtap");
1793   nsCOMPtr<nsIWidget> widget = GetWidget();
1794   if (widget) {
1795     widget->SynthesizeNativeTouchTap(aPoint, aLongTap, responder.GetObserver());
1796   }
1797   return IPC_OK();
1798 }
1799 
RecvClearNativeTouchSequence(const uint64_t & aObserverId)1800 mozilla::ipc::IPCResult BrowserParent::RecvClearNativeTouchSequence(
1801     const uint64_t& aObserverId) {
1802   AutoSynthesizedEventResponder responder(this, aObserverId, "cleartouch");
1803   nsCOMPtr<nsIWidget> widget = GetWidget();
1804   if (widget) {
1805     widget->ClearNativeTouchSequence(responder.GetObserver());
1806   }
1807   return IPC_OK();
1808 }
1809 
SendRealKeyEvent(WidgetKeyboardEvent & aEvent)1810 void BrowserParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent) {
1811   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
1812     return;
1813   }
1814   aEvent.mRefPoint = TransformParentToChild(aEvent.mRefPoint);
1815 
1816   if (aEvent.mMessage == eKeyPress) {
1817     // XXX Should we do this only when input context indicates an editor having
1818     //     focus and the key event won't cause inputting text?
1819     aEvent.InitAllEditCommands();
1820   } else {
1821     aEvent.PreventNativeKeyBindings();
1822   }
1823   DebugOnly<bool> ret =
1824       Manager()->IsInputPriorityEventEnabled()
1825           ? PBrowserParent::SendRealKeyEvent(aEvent)
1826           : PBrowserParent::SendNormalPriorityRealKeyEvent(aEvent);
1827 
1828   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealKeyEvent() failed");
1829   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1830 }
1831 
SendRealTouchEvent(WidgetTouchEvent & aEvent)1832 void BrowserParent::SendRealTouchEvent(WidgetTouchEvent& aEvent) {
1833   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
1834     return;
1835   }
1836 
1837   // PresShell::HandleEventInternal adds touches on touch end/cancel.  This
1838   // confuses remote content and the panning and zooming logic into thinking
1839   // that the added touches are part of the touchend/cancel, when actually
1840   // they're not.
1841   if (aEvent.mMessage == eTouchEnd || aEvent.mMessage == eTouchCancel) {
1842     for (int i = aEvent.mTouches.Length() - 1; i >= 0; i--) {
1843       if (!aEvent.mTouches[i]->mChanged) {
1844         aEvent.mTouches.RemoveElementAt(i);
1845       }
1846     }
1847   }
1848 
1849   APZData apzData;
1850   ApzAwareEventRoutingToChild(&apzData.guid, &apzData.blockId,
1851                               &apzData.apzResponse);
1852 
1853   if (mIsDestroyed) {
1854     return;
1855   }
1856 
1857   for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) {
1858     aEvent.mTouches[i]->mRefPoint =
1859         TransformParentToChild(aEvent.mTouches[i]->mRefPoint);
1860   }
1861 
1862   static uint32_t sConsecutiveTouchMoveCount = 0;
1863   if (aEvent.mMessage == eTouchMove) {
1864     ++sConsecutiveTouchMoveCount;
1865     SendRealTouchMoveEvent(aEvent, apzData, sConsecutiveTouchMoveCount);
1866     return;
1867   }
1868 
1869   sConsecutiveTouchMoveCount = 0;
1870   DebugOnly<bool> ret =
1871       Manager()->IsInputPriorityEventEnabled()
1872           ? PBrowserParent::SendRealTouchEvent(
1873                 aEvent, apzData.guid, apzData.blockId, apzData.apzResponse)
1874           : PBrowserParent::SendNormalPriorityRealTouchEvent(
1875                 aEvent, apzData.guid, apzData.blockId, apzData.apzResponse);
1876 
1877   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealTouchEvent() failed");
1878   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1879 }
1880 
SendRealTouchMoveEvent(WidgetTouchEvent & aEvent,APZData & aAPZData,uint32_t aConsecutiveTouchMoveCount)1881 void BrowserParent::SendRealTouchMoveEvent(
1882     WidgetTouchEvent& aEvent, APZData& aAPZData,
1883     uint32_t aConsecutiveTouchMoveCount) {
1884   // Touchmove handling is complicated, since IPC compression should be used
1885   // only when there are consecutive touch objects for the same touch on the
1886   // same BrowserParent. IPC compression can be disabled by switching to
1887   // different IPC message.
1888   static bool sIPCMessageType1 = true;
1889   static TabId sLastTargetBrowserParent(0);
1890   static Maybe<APZData> sPreviousAPZData;
1891   // Artificially limit max touch points to 10. That should be in practise
1892   // more than enough.
1893   const uint32_t kMaxTouchMoveIdentifiers = 10;
1894   static Maybe<int32_t> sLastTouchMoveIdentifiers[kMaxTouchMoveIdentifiers];
1895 
1896   // Returns true if aIdentifiers contains all the touches in
1897   // sLastTouchMoveIdentifiers.
1898   auto LastTouchMoveIdentifiersContainedIn =
1899       [&](const nsTArray<int32_t>& aIdentifiers) -> bool {
1900     for (Maybe<int32_t>& entry : sLastTouchMoveIdentifiers) {
1901       if (entry.isSome() && !aIdentifiers.Contains(entry.value())) {
1902         return false;
1903       }
1904     }
1905     return true;
1906   };
1907 
1908   // Cache touch identifiers in sLastTouchMoveIdentifiers array to be used
1909   // when checking whether compression can be done for the next touchmove.
1910   auto SetLastTouchMoveIdentifiers =
1911       [&](const nsTArray<int32_t>& aIdentifiers) {
1912         for (Maybe<int32_t>& entry : sLastTouchMoveIdentifiers) {
1913           entry.reset();
1914         }
1915 
1916         MOZ_ASSERT(aIdentifiers.Length() <= kMaxTouchMoveIdentifiers);
1917         for (uint32_t j = 0; j < aIdentifiers.Length(); ++j) {
1918           sLastTouchMoveIdentifiers[j].emplace(aIdentifiers[j]);
1919         }
1920       };
1921 
1922   AutoTArray<int32_t, kMaxTouchMoveIdentifiers> changedTouches;
1923   bool preventCompression = !StaticPrefs::dom_events_compress_touchmove() ||
1924                             // Ensure the very first touchmove isn't overridden
1925                             // by the second one, so that web pages can get
1926                             // accurate coordinates for the first touchmove.
1927                             aConsecutiveTouchMoveCount < 3 ||
1928                             sPreviousAPZData.isNothing() ||
1929                             sPreviousAPZData.value() != aAPZData ||
1930                             sLastTargetBrowserParent != GetTabId() ||
1931                             aEvent.mTouches.Length() > kMaxTouchMoveIdentifiers;
1932 
1933   if (!preventCompression) {
1934     for (RefPtr<Touch>& touch : aEvent.mTouches) {
1935       if (touch->mChanged) {
1936         changedTouches.AppendElement(touch->mIdentifier);
1937       }
1938     }
1939 
1940     // Prevent compression if the new event has fewer or different touches
1941     // than the old one.
1942     preventCompression = !LastTouchMoveIdentifiersContainedIn(changedTouches);
1943   }
1944 
1945   if (preventCompression) {
1946     sIPCMessageType1 = !sIPCMessageType1;
1947   }
1948 
1949   // Update the last touch move identifiers always, so that when the next
1950   // event comes in, the new identifiers can be compared to the old ones.
1951   // If the pref is disabled, this just does a quick small loop.
1952   SetLastTouchMoveIdentifiers(changedTouches);
1953   sPreviousAPZData.reset();
1954   sPreviousAPZData.emplace(aAPZData);
1955   sLastTargetBrowserParent = GetTabId();
1956 
1957   DebugOnly<bool> ret = true;
1958   if (sIPCMessageType1) {
1959     ret =
1960         Manager()->IsInputPriorityEventEnabled()
1961             ? PBrowserParent::SendRealTouchMoveEvent(
1962                   aEvent, aAPZData.guid, aAPZData.blockId, aAPZData.apzResponse)
1963             : PBrowserParent::SendNormalPriorityRealTouchMoveEvent(
1964                   aEvent, aAPZData.guid, aAPZData.blockId,
1965                   aAPZData.apzResponse);
1966   } else {
1967     ret =
1968         Manager()->IsInputPriorityEventEnabled()
1969             ? PBrowserParent::SendRealTouchMoveEvent2(
1970                   aEvent, aAPZData.guid, aAPZData.blockId, aAPZData.apzResponse)
1971             : PBrowserParent::SendNormalPriorityRealTouchMoveEvent2(
1972                   aEvent, aAPZData.guid, aAPZData.blockId,
1973                   aAPZData.apzResponse);
1974   }
1975 
1976   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealTouchMoveEvent() failed");
1977   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1978 }
1979 
SendPluginEvent(WidgetPluginEvent & aEvent)1980 void BrowserParent::SendPluginEvent(WidgetPluginEvent& aEvent) {
1981   DebugOnly<bool> ret = PBrowserParent::SendPluginEvent(aEvent);
1982   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendPluginEvent() failed");
1983   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
1984 }
1985 
SendHandleTap(TapType aType,const LayoutDevicePoint & aPoint,Modifiers aModifiers,const ScrollableLayerGuid & aGuid,uint64_t aInputBlockId)1986 bool BrowserParent::SendHandleTap(TapType aType,
1987                                   const LayoutDevicePoint& aPoint,
1988                                   Modifiers aModifiers,
1989                                   const ScrollableLayerGuid& aGuid,
1990                                   uint64_t aInputBlockId) {
1991   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
1992     return false;
1993   }
1994   if ((aType == TapType::eSingleTap || aType == TapType::eSecondTap)) {
1995     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
1996     if (fm) {
1997       RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1998       if (frameLoader) {
1999         RefPtr<Element> element = frameLoader->GetOwnerContent();
2000         if (element) {
2001           fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
2002                                     nsIFocusManager::FLAG_BYTOUCH |
2003                                     nsIFocusManager::FLAG_NOSCROLL);
2004         }
2005       }
2006     }
2007   }
2008   return Manager()->IsInputPriorityEventEnabled()
2009              ? PBrowserParent::SendHandleTap(aType,
2010                                              TransformParentToChild(aPoint),
2011                                              aModifiers, aGuid, aInputBlockId)
2012              : PBrowserParent::SendNormalPriorityHandleTap(
2013                    aType, TransformParentToChild(aPoint), aModifiers, aGuid,
2014                    aInputBlockId);
2015 }
2016 
RecvSyncMessage(const nsString & aMessage,const ClonedMessageData & aData,nsTArray<StructuredCloneData> * aRetVal)2017 mozilla::ipc::IPCResult BrowserParent::RecvSyncMessage(
2018     const nsString& aMessage, const ClonedMessageData& aData,
2019     nsTArray<StructuredCloneData>* aRetVal) {
2020   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvSyncMessage",
2021                                              OTHER, aMessage);
2022   MMPrinter::Print("BrowserParent::RecvSyncMessage", aMessage, aData);
2023 
2024   StructuredCloneData data;
2025   ipc::UnpackClonedMessageDataForParent(aData, data);
2026 
2027   if (!ReceiveMessage(aMessage, true, &data, aRetVal)) {
2028     return IPC_FAIL_NO_REASON(this);
2029   }
2030   return IPC_OK();
2031 }
2032 
RecvAsyncMessage(const nsString & aMessage,const ClonedMessageData & aData)2033 mozilla::ipc::IPCResult BrowserParent::RecvAsyncMessage(
2034     const nsString& aMessage, const ClonedMessageData& aData) {
2035   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("BrowserParent::RecvAsyncMessage",
2036                                              OTHER, aMessage);
2037   MMPrinter::Print("BrowserParent::RecvAsyncMessage", aMessage, aData);
2038 
2039   StructuredCloneData data;
2040   ipc::UnpackClonedMessageDataForParent(aData, data);
2041 
2042   if (!ReceiveMessage(aMessage, false, &data, nullptr)) {
2043     return IPC_FAIL_NO_REASON(this);
2044   }
2045   return IPC_OK();
2046 }
2047 
RecvSetCursor(const nsCursor & aCursor,const bool & aHasCustomCursor,const nsCString & aCursorData,const uint32_t & aWidth,const uint32_t & aHeight,const uint32_t & aStride,const gfx::SurfaceFormat & aFormat,const uint32_t & aHotspotX,const uint32_t & aHotspotY,const bool & aForce)2048 mozilla::ipc::IPCResult BrowserParent::RecvSetCursor(
2049     const nsCursor& aCursor, const bool& aHasCustomCursor,
2050     const nsCString& aCursorData, const uint32_t& aWidth,
2051     const uint32_t& aHeight, const uint32_t& aStride,
2052     const gfx::SurfaceFormat& aFormat, const uint32_t& aHotspotX,
2053     const uint32_t& aHotspotY, const bool& aForce) {
2054   nsCOMPtr<nsIWidget> widget = GetWidget();
2055   if (!widget) {
2056     return IPC_OK();
2057   }
2058 
2059   if (aForce) {
2060     widget->ClearCachedCursor();
2061   }
2062 
2063   nsCOMPtr<imgIContainer> cursorImage;
2064   if (aHasCustomCursor) {
2065     if (aHeight * aStride != aCursorData.Length() ||
2066         aStride < aWidth * gfx::BytesPerPixel(aFormat)) {
2067       return IPC_FAIL(this, "Invalid custom cursor data");
2068     }
2069     const gfx::IntSize size(aWidth, aHeight);
2070     RefPtr<gfx::DataSourceSurface> customCursor =
2071         gfx::CreateDataSourceSurfaceFromData(
2072             size, aFormat,
2073             reinterpret_cast<const uint8_t*>(aCursorData.BeginReading()),
2074             aStride);
2075 
2076     RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(customCursor, size);
2077     cursorImage = image::ImageOps::CreateFromDrawable(drawable);
2078   }
2079 
2080   mCursor = aCursor;
2081   mCustomCursor = cursorImage;
2082   mCustomCursorHotspotX = aHotspotX;
2083   mCustomCursorHotspotY = aHotspotY;
2084 
2085   if (!mTabSetsCursor) {
2086     return IPC_OK();
2087   }
2088 
2089   widget->SetCursor(aCursor, cursorImage, aHotspotX, aHotspotY);
2090   return IPC_OK();
2091 }
2092 
RecvSetLinkStatus(const nsString & aStatus)2093 mozilla::ipc::IPCResult BrowserParent::RecvSetLinkStatus(
2094     const nsString& aStatus) {
2095   nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
2096   if (!xulBrowserWindow) {
2097     return IPC_OK();
2098   }
2099 
2100   xulBrowserWindow->SetOverLink(aStatus);
2101 
2102   return IPC_OK();
2103 }
2104 
RecvShowTooltip(const uint32_t & aX,const uint32_t & aY,const nsString & aTooltip,const nsString & aDirection)2105 mozilla::ipc::IPCResult BrowserParent::RecvShowTooltip(
2106     const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip,
2107     const nsString& aDirection) {
2108   nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
2109   if (!xulBrowserWindow) {
2110     return IPC_OK();
2111   }
2112 
2113   // ShowTooltip will end up accessing XULElement properties in JS (specifically
2114   // BoxObject). However, to get it to JS, we need to make sure we're a
2115   // nsFrameLoaderOwner, which implies we're a XULFrameElement. We can then
2116   // safely pass Element into JS.
2117   RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(mFrameElement);
2118   if (!flo) return IPC_OK();
2119 
2120   nsCOMPtr<Element> el = do_QueryInterface(flo);
2121   if (!el) return IPC_OK();
2122 
2123   xulBrowserWindow->ShowTooltip(aX, aY, aTooltip, aDirection, el);
2124   return IPC_OK();
2125 }
2126 
RecvHideTooltip()2127 mozilla::ipc::IPCResult BrowserParent::RecvHideTooltip() {
2128   nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
2129   if (!xulBrowserWindow) {
2130     return IPC_OK();
2131   }
2132 
2133   xulBrowserWindow->HideTooltip();
2134   return IPC_OK();
2135 }
2136 
RecvNotifyIMEFocus(const ContentCache & aContentCache,const IMENotification & aIMENotification,NotifyIMEFocusResolver && aResolve)2137 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEFocus(
2138     const ContentCache& aContentCache, const IMENotification& aIMENotification,
2139     NotifyIMEFocusResolver&& aResolve) {
2140   if (mIsDestroyed) {
2141     return IPC_OK();
2142   }
2143 
2144   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2145   if (!widget) {
2146     aResolve(IMENotificationRequests());
2147     return IPC_OK();
2148   }
2149 
2150   mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
2151   IMEStateManager::NotifyIME(aIMENotification, widget, this);
2152 
2153   IMENotificationRequests requests;
2154   if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
2155     requests = widget->IMENotificationRequestsRef();
2156   }
2157   aResolve(requests);
2158 
2159   return IPC_OK();
2160 }
2161 
RecvNotifyIMETextChange(const ContentCache & aContentCache,const IMENotification & aIMENotification)2162 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMETextChange(
2163     const ContentCache& aContentCache,
2164     const IMENotification& aIMENotification) {
2165   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2166   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2167     return IPC_OK();
2168   }
2169   mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
2170   mContentCache.MaybeNotifyIME(widget, aIMENotification);
2171   return IPC_OK();
2172 }
2173 
RecvNotifyIMECompositionUpdate(const ContentCache & aContentCache,const IMENotification & aIMENotification)2174 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMECompositionUpdate(
2175     const ContentCache& aContentCache,
2176     const IMENotification& aIMENotification) {
2177   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2178   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2179     return IPC_OK();
2180   }
2181   mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
2182   mContentCache.MaybeNotifyIME(widget, aIMENotification);
2183   return IPC_OK();
2184 }
2185 
RecvNotifyIMESelection(const ContentCache & aContentCache,const IMENotification & aIMENotification)2186 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMESelection(
2187     const ContentCache& aContentCache,
2188     const IMENotification& aIMENotification) {
2189   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2190   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2191     return IPC_OK();
2192   }
2193   mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
2194   mContentCache.MaybeNotifyIME(widget, aIMENotification);
2195   return IPC_OK();
2196 }
2197 
RecvUpdateContentCache(const ContentCache & aContentCache)2198 mozilla::ipc::IPCResult BrowserParent::RecvUpdateContentCache(
2199     const ContentCache& aContentCache) {
2200   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2201   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2202     return IPC_OK();
2203   }
2204 
2205   mContentCache.AssignContent(aContentCache, widget);
2206   return IPC_OK();
2207 }
2208 
RecvNotifyIMEMouseButtonEvent(const IMENotification & aIMENotification,bool * aConsumedByIME)2209 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEMouseButtonEvent(
2210     const IMENotification& aIMENotification, bool* aConsumedByIME) {
2211   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2212   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2213     *aConsumedByIME = false;
2214     return IPC_OK();
2215   }
2216   nsresult rv = IMEStateManager::NotifyIME(aIMENotification, widget, this);
2217   *aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
2218   return IPC_OK();
2219 }
2220 
RecvNotifyIMEPositionChange(const ContentCache & aContentCache,const IMENotification & aIMENotification)2221 mozilla::ipc::IPCResult BrowserParent::RecvNotifyIMEPositionChange(
2222     const ContentCache& aContentCache,
2223     const IMENotification& aIMENotification) {
2224   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2225   if (!widget || !IMEStateManager::DoesBrowserParentHaveIMEFocus(this)) {
2226     return IPC_OK();
2227   }
2228   mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
2229   mContentCache.MaybeNotifyIME(widget, aIMENotification);
2230   return IPC_OK();
2231 }
2232 
RecvOnEventNeedingAckHandled(const EventMessage & aMessage)2233 mozilla::ipc::IPCResult BrowserParent::RecvOnEventNeedingAckHandled(
2234     const EventMessage& aMessage) {
2235   // This is called when the child process receives WidgetCompositionEvent or
2236   // WidgetSelectionEvent.
2237   // FYI: Don't check if widget is nullptr here because it's more important to
2238   //      notify mContentCahce of this than handling something in it.
2239   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
2240 
2241   // While calling OnEventNeedingAckHandled(), BrowserParent *might* be
2242   // destroyed since it may send notifications to IME.
2243   RefPtr<BrowserParent> kungFuDeathGrip(this);
2244   mContentCache.OnEventNeedingAckHandled(widget, aMessage);
2245   return IPC_OK();
2246 }
2247 
HandledWindowedPluginKeyEvent(const NativeEventData & aKeyEventData,bool aIsConsumed)2248 void BrowserParent::HandledWindowedPluginKeyEvent(
2249     const NativeEventData& aKeyEventData, bool aIsConsumed) {
2250   DebugOnly<bool> ok =
2251       SendHandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
2252   NS_WARNING_ASSERTION(ok, "SendHandledWindowedPluginKeyEvent failed");
2253 }
2254 
RecvOnWindowedPluginKeyEvent(const NativeEventData & aKeyEventData)2255 mozilla::ipc::IPCResult BrowserParent::RecvOnWindowedPluginKeyEvent(
2256     const NativeEventData& aKeyEventData) {
2257   nsCOMPtr<nsIWidget> widget = GetWidget();
2258   if (NS_WARN_IF(!widget)) {
2259     // Notifies the plugin process of the key event being not consumed by us.
2260     HandledWindowedPluginKeyEvent(aKeyEventData, false);
2261     return IPC_OK();
2262   }
2263   nsresult rv = widget->OnWindowedPluginKeyEvent(aKeyEventData, this);
2264   if (NS_WARN_IF(NS_FAILED(rv))) {
2265     // Notifies the plugin process of the key event being not consumed by us.
2266     HandledWindowedPluginKeyEvent(aKeyEventData, false);
2267     return IPC_OK();
2268   }
2269 
2270   // If the key event is posted to another process, we need to wait a call
2271   // of HandledWindowedPluginKeyEvent().  So, nothing to do here in this case.
2272   if (rv == NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY) {
2273     return IPC_OK();
2274   }
2275 
2276   // Otherwise, the key event is handled synchronously.  Let's notify the
2277   // plugin process of the key event's result.
2278   bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
2279   HandledWindowedPluginKeyEvent(aKeyEventData, consumed);
2280 
2281   return IPC_OK();
2282 }
2283 
RecvRequestFocus(const bool & aCanRaise,const CallerType aCallerType)2284 mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus(
2285     const bool& aCanRaise, const CallerType aCallerType) {
2286   LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise));
2287   if (BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent()) {
2288     mozilla::Unused << bridgeParent->SendRequestFocus(aCanRaise, aCallerType);
2289     return IPC_OK();
2290   }
2291 
2292   if (!mFrameElement) {
2293     return IPC_OK();
2294   }
2295 
2296   nsContentUtils::RequestFrameFocus(*mFrameElement, aCanRaise, aCallerType);
2297   return IPC_OK();
2298 }
2299 
RecvWheelZoomChange(bool aIncrease)2300 mozilla::ipc::IPCResult BrowserParent::RecvWheelZoomChange(bool aIncrease) {
2301   RefPtr<BrowsingContext> bc = GetBrowsingContext();
2302   if (!bc) {
2303     return IPC_OK();
2304   }
2305 
2306   bc->Canonical()->DispatchWheelZoomChange(aIncrease);
2307   return IPC_OK();
2308 }
2309 
RecvEnableDisableCommands(const MaybeDiscarded<BrowsingContext> & aContext,const nsString & aAction,nsTArray<nsCString> && aEnabledCommands,nsTArray<nsCString> && aDisabledCommands)2310 mozilla::ipc::IPCResult BrowserParent::RecvEnableDisableCommands(
2311     const MaybeDiscarded<BrowsingContext>& aContext, const nsString& aAction,
2312     nsTArray<nsCString>&& aEnabledCommands,
2313     nsTArray<nsCString>&& aDisabledCommands) {
2314   if (aContext.IsNullOrDiscarded()) {
2315     return IPC_OK();
2316   }
2317 
2318   nsCOMPtr<nsIBrowserController> browserController =
2319       do_QueryActor("Controllers", aContext.get_canonical());
2320   if (browserController) {
2321     browserController->EnableDisableCommands(aAction, aEnabledCommands,
2322                                              aDisabledCommands);
2323   }
2324 
2325   return IPC_OK();
2326 }
2327 
TransformPoint(const LayoutDeviceIntPoint & aPoint,const LayoutDeviceToLayoutDeviceMatrix4x4 & aMatrix)2328 LayoutDeviceIntPoint BrowserParent::TransformPoint(
2329     const LayoutDeviceIntPoint& aPoint,
2330     const LayoutDeviceToLayoutDeviceMatrix4x4& aMatrix) {
2331   LayoutDevicePoint floatPoint(aPoint);
2332   LayoutDevicePoint floatTransformed = TransformPoint(floatPoint, aMatrix);
2333   // The next line loses precision if an out-of-process iframe
2334   // has been scaled or rotated.
2335   return RoundedToInt(floatTransformed);
2336 }
2337 
TransformPoint(const LayoutDevicePoint & aPoint,const LayoutDeviceToLayoutDeviceMatrix4x4 & aMatrix)2338 LayoutDevicePoint BrowserParent::TransformPoint(
2339     const LayoutDevicePoint& aPoint,
2340     const LayoutDeviceToLayoutDeviceMatrix4x4& aMatrix) {
2341   return aMatrix.TransformPoint(aPoint);
2342 }
2343 
TransformParentToChild(const LayoutDeviceIntPoint & aPoint)2344 LayoutDeviceIntPoint BrowserParent::TransformParentToChild(
2345     const LayoutDeviceIntPoint& aPoint) {
2346   LayoutDeviceToLayoutDeviceMatrix4x4 matrix =
2347       GetChildToParentConversionMatrix();
2348   if (!matrix.Invert()) {
2349     return LayoutDeviceIntPoint(0, 0);
2350   }
2351   return TransformPoint(aPoint, matrix);
2352 }
2353 
TransformParentToChild(const LayoutDevicePoint & aPoint)2354 LayoutDevicePoint BrowserParent::TransformParentToChild(
2355     const LayoutDevicePoint& aPoint) {
2356   LayoutDeviceToLayoutDeviceMatrix4x4 matrix =
2357       GetChildToParentConversionMatrix();
2358   if (!matrix.Invert()) {
2359     return LayoutDevicePoint(0.0, 0.0);
2360   }
2361   return TransformPoint(aPoint, matrix);
2362 }
2363 
TransformChildToParent(const LayoutDeviceIntPoint & aPoint)2364 LayoutDeviceIntPoint BrowserParent::TransformChildToParent(
2365     const LayoutDeviceIntPoint& aPoint) {
2366   return TransformPoint(aPoint, GetChildToParentConversionMatrix());
2367 }
2368 
TransformChildToParent(const LayoutDevicePoint & aPoint)2369 LayoutDevicePoint BrowserParent::TransformChildToParent(
2370     const LayoutDevicePoint& aPoint) {
2371   return TransformPoint(aPoint, GetChildToParentConversionMatrix());
2372 }
2373 
TransformChildToParent(const LayoutDeviceIntRect & aRect)2374 LayoutDeviceIntRect BrowserParent::TransformChildToParent(
2375     const LayoutDeviceIntRect& aRect) {
2376   LayoutDeviceToLayoutDeviceMatrix4x4 matrix =
2377       GetChildToParentConversionMatrix();
2378   LayoutDeviceRect floatRect(aRect);
2379   // The outcome is not ideal if an out-of-process iframe has been rotated
2380   LayoutDeviceRect floatTransformed = matrix.TransformBounds(floatRect);
2381   // The next line loses precision if an out-of-process iframe
2382   // has been scaled or rotated.
2383   return RoundedToInt(floatTransformed);
2384 }
2385 
2386 LayoutDeviceToLayoutDeviceMatrix4x4
GetChildToParentConversionMatrix()2387 BrowserParent::GetChildToParentConversionMatrix() {
2388   if (mChildToParentConversionMatrix) {
2389     return *mChildToParentConversionMatrix;
2390   }
2391   LayoutDevicePoint offset(-GetChildProcessOffset());
2392   return LayoutDeviceToLayoutDeviceMatrix4x4::Translation(offset);
2393 }
2394 
SetChildToParentConversionMatrix(const Maybe<LayoutDeviceToLayoutDeviceMatrix4x4> & aMatrix,const ScreenRect & aRemoteDocumentRect)2395 void BrowserParent::SetChildToParentConversionMatrix(
2396     const Maybe<LayoutDeviceToLayoutDeviceMatrix4x4>& aMatrix,
2397     const ScreenRect& aRemoteDocumentRect) {
2398   mChildToParentConversionMatrix = aMatrix;
2399   if (mIsDestroyed) {
2400     return;
2401   }
2402   mozilla::Unused << SendChildToParentMatrix(ToUnknownMatrix(aMatrix),
2403                                              aRemoteDocumentRect);
2404 }
2405 
GetChildProcessOffset()2406 LayoutDeviceIntPoint BrowserParent::GetChildProcessOffset() {
2407   // The "toplevel widget" in child processes is always at position
2408   // 0,0.  Map the event coordinates to match that.
2409 
2410   LayoutDeviceIntPoint offset(0, 0);
2411   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
2412   if (!frameLoader) {
2413     return offset;
2414   }
2415   nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent();
2416   if (!targetFrame) {
2417     return offset;
2418   }
2419 
2420   nsCOMPtr<nsIWidget> widget = GetWidget();
2421   if (!widget) {
2422     return offset;
2423   }
2424 
2425   nsPresContext* presContext = targetFrame->PresContext();
2426   nsIFrame* rootFrame = presContext->PresShell()->GetRootFrame();
2427   nsView* rootView = rootFrame ? rootFrame->GetView() : nullptr;
2428   if (!rootView) {
2429     return offset;
2430   }
2431 
2432   // Note that we don't want to take into account transforms here:
2433 #if 0
2434   nsPoint pt(0, 0);
2435   nsLayoutUtils::TransformPoint(targetFrame, rootFrame, pt);
2436 #endif
2437   // In practice, when transforms are applied to this frameLoader, we currently
2438   // get the wrong results whether we take transforms into account here or not.
2439   // But applying transforms here gives us the wrong results in all
2440   // circumstances when transforms are applied, unless they're purely
2441   // translational. It also gives us the wrong results whenever CSS transitions
2442   // are used to apply transforms, since the offeets aren't updated as the
2443   // transition is animated.
2444   //
2445   // What we actually need to do is apply the transforms to the coordinates of
2446   // any events we send to the child, and reverse them for any screen
2447   // coordinates that we retrieve from the child.
2448 
2449   // TODO: Once we take into account transforms here, set viewportType
2450   // correctly. For now we use Visual as this means we don't apply
2451   // the layout-to-visual transform in TranslateViewToWidget().
2452   ViewportType viewportType = ViewportType::Visual;
2453 
2454   nsPoint pt = targetFrame->GetOffsetTo(rootFrame);
2455   return -nsLayoutUtils::TranslateViewToWidget(presContext, rootView, pt,
2456                                                viewportType, widget);
2457 }
2458 
GetClientOffset()2459 LayoutDeviceIntPoint BrowserParent::GetClientOffset() {
2460   nsCOMPtr<nsIWidget> widget = GetWidget();
2461   nsCOMPtr<nsIWidget> docWidget = GetDocWidget();
2462 
2463   if (widget == docWidget) {
2464     return widget->GetClientOffset();
2465   }
2466 
2467   return (docWidget->GetClientOffset() +
2468           nsLayoutUtils::WidgetToWidgetOffset(widget, docWidget));
2469 }
2470 
StopIMEStateManagement()2471 void BrowserParent::StopIMEStateManagement() {
2472   if (mIsDestroyed) {
2473     return;
2474   }
2475   Unused << SendStopIMEStateManagement();
2476 }
2477 
RecvReplyKeyEvent(const WidgetKeyboardEvent & aEvent)2478 mozilla::ipc::IPCResult BrowserParent::RecvReplyKeyEvent(
2479     const WidgetKeyboardEvent& aEvent) {
2480   NS_ENSURE_TRUE(mFrameElement, IPC_OK());
2481 
2482   WidgetKeyboardEvent localEvent(aEvent);
2483   localEvent.MarkAsHandledInRemoteProcess();
2484 
2485   // Here we convert the WidgetEvent that we received to an Event
2486   // to be able to dispatch it to the <browser> element as the target element.
2487   Document* doc = mFrameElement->OwnerDoc();
2488   nsPresContext* presContext = doc->GetPresContext();
2489   NS_ENSURE_TRUE(presContext, IPC_OK());
2490 
2491   AutoHandlingUserInputStatePusher userInpStatePusher(localEvent.IsTrusted(),
2492                                                       &localEvent);
2493 
2494   nsEventStatus status = nsEventStatus_eIgnore;
2495 
2496   // Handle access key in this process before dispatching reply event because
2497   // ESM handles it before dispatching the event to the DOM tree.
2498   if (localEvent.mMessage == eKeyPress &&
2499       (localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eChrome) ||
2500        localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eContent))) {
2501     RefPtr<EventStateManager> esm = presContext->EventStateManager();
2502     AutoTArray<uint32_t, 10> accessCharCodes;
2503     localEvent.GetAccessKeyCandidates(accessCharCodes);
2504     if (esm->HandleAccessKey(&localEvent, presContext, accessCharCodes)) {
2505       status = nsEventStatus_eConsumeNoDefault;
2506     }
2507   }
2508 
2509   EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent, nullptr,
2510                             &status);
2511 
2512   if (!localEvent.DefaultPrevented() &&
2513       !localEvent.mFlags.mIsSynthesizedForTests) {
2514     nsCOMPtr<nsIWidget> widget = GetWidget();
2515     if (widget) {
2516       widget->PostHandleKeyEvent(&localEvent);
2517       localEvent.StopPropagation();
2518     }
2519   }
2520 
2521   return IPC_OK();
2522 }
2523 
RecvAccessKeyNotHandled(const WidgetKeyboardEvent & aEvent)2524 mozilla::ipc::IPCResult BrowserParent::RecvAccessKeyNotHandled(
2525     const WidgetKeyboardEvent& aEvent) {
2526   NS_ENSURE_TRUE(mFrameElement, IPC_OK());
2527 
2528   // This is called only when this process had focus and HandleAccessKey
2529   // message was posted to all remote process and each remote process didn't
2530   // execute any content access keys.
2531   // XXX If there were two or more remote processes, this may be called
2532   //     twice or more for a keyboard event, that must be a bug.  But how to
2533   //     detect if received event has already been handled?
2534 
2535   MOZ_ASSERT(aEvent.mMessage == eKeyPress);
2536   WidgetKeyboardEvent localEvent(aEvent);
2537   localEvent.MarkAsHandledInRemoteProcess();
2538   localEvent.mMessage = eAccessKeyNotFound;
2539 
2540   // Here we convert the WidgetEvent that we received to an Event
2541   // to be able to dispatch it to the <browser> element as the target element.
2542   Document* doc = mFrameElement->OwnerDoc();
2543   PresShell* presShell = doc->GetPresShell();
2544   NS_ENSURE_TRUE(presShell, IPC_OK());
2545 
2546   if (presShell->CanDispatchEvent()) {
2547     nsPresContext* presContext = presShell->GetPresContext();
2548     NS_ENSURE_TRUE(presContext, IPC_OK());
2549 
2550     EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent);
2551   }
2552 
2553   return IPC_OK();
2554 }
2555 
RecvRegisterProtocolHandler(const nsString & aScheme,nsIURI * aHandlerURI,const nsString & aTitle,nsIURI * aDocURI)2556 mozilla::ipc::IPCResult BrowserParent::RecvRegisterProtocolHandler(
2557     const nsString& aScheme, nsIURI* aHandlerURI, const nsString& aTitle,
2558     nsIURI* aDocURI) {
2559   nsCOMPtr<nsIWebProtocolHandlerRegistrar> registrar =
2560       do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID);
2561   if (registrar) {
2562     registrar->RegisterProtocolHandler(aScheme, aHandlerURI, aTitle, aDocURI,
2563                                        mFrameElement);
2564   }
2565 
2566   return IPC_OK();
2567 }
2568 
RecvOnStateChange(const Maybe<WebProgressData> & aWebProgressData,const RequestData & aRequestData,const uint32_t aStateFlags,const nsresult aStatus,const Maybe<WebProgressStateChangeData> & aStateChangeData)2569 mozilla::ipc::IPCResult BrowserParent::RecvOnStateChange(
2570     const Maybe<WebProgressData>& aWebProgressData,
2571     const RequestData& aRequestData, const uint32_t aStateFlags,
2572     const nsresult aStatus,
2573     const Maybe<WebProgressStateChangeData>& aStateChangeData) {
2574   if (mSuspendedProgressEvents) {
2575     nsCOMPtr<nsIURI> uri = aRequestData.requestURI();
2576     const uint32_t startDocumentFlags =
2577         nsIWebProgressListener::STATE_START |
2578         nsIWebProgressListener::STATE_IS_DOCUMENT |
2579         nsIWebProgressListener::STATE_IS_REQUEST |
2580         nsIWebProgressListener::STATE_IS_WINDOW |
2581         nsIWebProgressListener::STATE_IS_NETWORK;
2582     // Once we get a load start from something that isn't the initial
2583     // about:blank, we should stop blocking future state changes.
2584     if ((aStateFlags & startDocumentFlags) == startDocumentFlags &&
2585         (aWebProgressData && aWebProgressData->isTopLevel()) &&
2586         (!uri || !NS_IsAboutBlank(uri))) {
2587       mSuspendedProgressEvents = false;
2588     }
2589 
2590     return IPC_OK();
2591   }
2592 
2593   nsCOMPtr<nsIBrowser> browser;
2594   nsCOMPtr<nsIWebProgress> manager;
2595   nsCOMPtr<nsIWebProgressListener> managerAsListener;
2596   if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
2597                               getter_AddRefs(managerAsListener))) {
2598     return IPC_OK();
2599   }
2600 
2601   nsCOMPtr<nsIWebProgress> webProgress;
2602   nsCOMPtr<nsIRequest> request;
2603   ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
2604                                    getter_AddRefs(webProgress),
2605                                    getter_AddRefs(request));
2606 
2607   if (aWebProgressData && aWebProgressData->isTopLevel() &&
2608       aStateChangeData.isSome()) {
2609     Unused << browser->SetIsNavigating(aStateChangeData->isNavigating());
2610     Unused << browser->SetMayEnableCharacterEncodingMenu(
2611         aStateChangeData->mayEnableCharacterEncodingMenu());
2612     Unused << browser->SetCharsetAutodetected(
2613         aStateChangeData->charsetAutodetected());
2614     Unused << browser->UpdateForStateChange(aStateChangeData->charset(),
2615                                             aStateChangeData->documentURI(),
2616                                             aStateChangeData->contentType());
2617   } else if (aStateChangeData.isSome()) {
2618     return IPC_FAIL(
2619         this,
2620         "Unexpected WebProgressStateChangeData for non-top-level WebProgress");
2621   }
2622 
2623   Unused << managerAsListener->OnStateChange(webProgress, request, aStateFlags,
2624                                              aStatus);
2625 
2626   return IPC_OK();
2627 }
2628 
RecvOnProgressChange(const Maybe<WebProgressData> & aWebProgressData,const RequestData & aRequestData,const int32_t aCurSelfProgress,const int32_t aMaxSelfProgress,const int32_t aCurTotalProgress,const int32_t aMaxTotalProgress)2629 mozilla::ipc::IPCResult BrowserParent::RecvOnProgressChange(
2630     const Maybe<WebProgressData>& aWebProgressData,
2631     const RequestData& aRequestData, const int32_t aCurSelfProgress,
2632     const int32_t aMaxSelfProgress, const int32_t aCurTotalProgress,
2633     const int32_t aMaxTotalProgress) {
2634   if (mSuspendedProgressEvents) {
2635     return IPC_OK();
2636   }
2637 
2638   nsCOMPtr<nsIBrowser> browser;
2639   nsCOMPtr<nsIWebProgress> manager;
2640   nsCOMPtr<nsIWebProgressListener> managerAsListener;
2641   if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
2642                               getter_AddRefs(managerAsListener))) {
2643     return IPC_OK();
2644   }
2645 
2646   nsCOMPtr<nsIWebProgress> webProgress;
2647   nsCOMPtr<nsIRequest> request;
2648   ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
2649                                    getter_AddRefs(webProgress),
2650                                    getter_AddRefs(request));
2651 
2652   Unused << managerAsListener->OnProgressChange(
2653       webProgress, request, aCurSelfProgress, aMaxSelfProgress,
2654       aCurTotalProgress, aMaxTotalProgress);
2655 
2656   return IPC_OK();
2657 }
2658 
RecvOnLocationChange(const Maybe<WebProgressData> & aWebProgressData,const RequestData & aRequestData,nsIURI * aLocation,const uint32_t aFlags,const bool aCanGoBack,const bool aCanGoForward,const Maybe<WebProgressLocationChangeData> & aLocationChangeData)2659 mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange(
2660     const Maybe<WebProgressData>& aWebProgressData,
2661     const RequestData& aRequestData, nsIURI* aLocation, const uint32_t aFlags,
2662     const bool aCanGoBack, const bool aCanGoForward,
2663     const Maybe<WebProgressLocationChangeData>& aLocationChangeData) {
2664   if (mSuspendedProgressEvents) {
2665     return IPC_OK();
2666   }
2667 
2668   nsCOMPtr<nsIBrowser> browser;
2669   nsCOMPtr<nsIWebProgress> manager;
2670   nsCOMPtr<nsIWebProgressListener> managerAsListener;
2671   if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
2672                               getter_AddRefs(managerAsListener))) {
2673     return IPC_OK();
2674   }
2675 
2676   nsCOMPtr<nsIWebProgress> webProgress;
2677   nsCOMPtr<nsIRequest> request;
2678   ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
2679                                    getter_AddRefs(webProgress),
2680                                    getter_AddRefs(request));
2681 
2682   Unused << browser->UpdateWebNavigationForLocationChange(aCanGoBack,
2683                                                           aCanGoForward);
2684 
2685   if (aWebProgressData && aWebProgressData->isTopLevel() &&
2686       aLocationChangeData.isSome()) {
2687     nsCOMPtr<nsIPrincipal> contentBlockingAllowListPrincipal;
2688     Unused << browser->SetIsNavigating(aLocationChangeData->isNavigating());
2689     Unused << browser->UpdateForLocationChange(
2690         aLocation, aLocationChangeData->charset(),
2691         aLocationChangeData->mayEnableCharacterEncodingMenu(),
2692         aLocationChangeData->charsetAutodetected(),
2693         aLocationChangeData->documentURI(), aLocationChangeData->title(),
2694         aLocationChangeData->contentPrincipal(),
2695         aLocationChangeData->contentStoragePrincipal(),
2696         aLocationChangeData->csp(), aLocationChangeData->referrerInfo(),
2697         aLocationChangeData->isSyntheticDocument(),
2698         aWebProgressData->innerDOMWindowID(),
2699         aLocationChangeData->requestContextID().isSome(),
2700         aLocationChangeData->requestContextID().valueOr(0),
2701         aLocationChangeData->contentType());
2702   }
2703 
2704   Unused << managerAsListener->OnLocationChange(webProgress, request, aLocation,
2705                                                 aFlags);
2706 
2707   // Since we've now changed Documents, notify the BrowsingContext that we've
2708   // changed. Ideally we'd just let the BrowsingContext do this when it changes
2709   // the current window global, but that happens before this and we have a lot
2710   // of tests that depend on the specific ordering of messages.
2711   if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
2712     GetBrowsingContext()->UpdateSecurityStateForLocationOrMixedContentChange();
2713   }
2714   return IPC_OK();
2715 }
2716 
RecvOnStatusChange(const Maybe<WebProgressData> & aWebProgressData,const RequestData & aRequestData,const nsresult aStatus,const nsString & aMessage)2717 mozilla::ipc::IPCResult BrowserParent::RecvOnStatusChange(
2718     const Maybe<WebProgressData>& aWebProgressData,
2719     const RequestData& aRequestData, const nsresult aStatus,
2720     const nsString& aMessage) {
2721   if (mSuspendedProgressEvents) {
2722     return IPC_OK();
2723   }
2724 
2725   nsCOMPtr<nsIBrowser> browser;
2726   nsCOMPtr<nsIWebProgress> manager;
2727   nsCOMPtr<nsIWebProgressListener> managerAsListener;
2728   if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager),
2729                               getter_AddRefs(managerAsListener))) {
2730     return IPC_OK();
2731   }
2732 
2733   nsCOMPtr<nsIWebProgress> webProgress;
2734   nsCOMPtr<nsIRequest> request;
2735   ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
2736                                    getter_AddRefs(webProgress),
2737                                    getter_AddRefs(request));
2738 
2739   Unused << managerAsListener->OnStatusChange(webProgress, request, aStatus,
2740                                               aMessage.get());
2741 
2742   return IPC_OK();
2743 }
2744 
RecvNavigationFinished()2745 mozilla::ipc::IPCResult BrowserParent::RecvNavigationFinished() {
2746   nsCOMPtr<nsIBrowser> browser =
2747       mFrameElement ? mFrameElement->AsBrowser() : nullptr;
2748 
2749   if (browser) {
2750     browser->SetIsNavigating(false);
2751   }
2752 
2753   return IPC_OK();
2754 }
2755 
RecvNotifyContentBlockingEvent(const uint32_t & aEvent,const RequestData & aRequestData,const bool aBlocked,const nsACString & aTrackingOrigin,nsTArray<nsCString> && aTrackingFullHashes,const Maybe<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason> & aReason)2756 mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
2757     const uint32_t& aEvent, const RequestData& aRequestData,
2758     const bool aBlocked, const nsACString& aTrackingOrigin,
2759     nsTArray<nsCString>&& aTrackingFullHashes,
2760     const Maybe<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason>&
2761         aReason) {
2762   MOZ_ASSERT(aRequestData.elapsedLoadTimeMS().isNothing());
2763 
2764   RefPtr<BrowsingContext> bc = GetBrowsingContext();
2765 
2766   if (!bc || bc->IsDiscarded()) {
2767     return IPC_OK();
2768   }
2769 
2770   // Get the top-level browsing context.
2771   bc = bc->Top();
2772   RefPtr<dom::WindowGlobalParent> wgp =
2773       bc->Canonical()->GetCurrentWindowGlobal();
2774 
2775   // The WindowGlobalParent would be null while running the test
2776   // browser_339445.js. This is unexpected and we will address this in a
2777   // following bug. For now, we first workaround this issue.
2778   if (!wgp) {
2779     return IPC_OK();
2780   }
2781 
2782   nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
2783       aRequestData.requestURI(), aRequestData.originalRequestURI(),
2784       aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
2785 
2786   wgp->NotifyContentBlockingEvent(aEvent, request, aBlocked, aTrackingOrigin,
2787                                   aTrackingFullHashes, aReason);
2788 
2789   return IPC_OK();
2790 }
2791 
2792 mozilla::ipc::IPCResult
RecvReportBlockedEmbedderNodeByClassifier()2793 BrowserParent::RecvReportBlockedEmbedderNodeByClassifier() {
2794   BrowserBridgeParent* bridge = GetBrowserBridgeParent();
2795 
2796   if (!bridge) {
2797     return IPC_OK();
2798   }
2799 
2800   Unused << bridge->SendAddBlockedNodeByClassifier();
2801   return IPC_OK();
2802 }
2803 
GetWebProgressListener(nsIBrowser ** aOutBrowser,nsIWebProgress ** aOutManager,nsIWebProgressListener ** aOutListener)2804 bool BrowserParent::GetWebProgressListener(
2805     nsIBrowser** aOutBrowser, nsIWebProgress** aOutManager,
2806     nsIWebProgressListener** aOutListener) {
2807   MOZ_ASSERT(aOutBrowser);
2808   MOZ_ASSERT(aOutManager);
2809   MOZ_ASSERT(aOutListener);
2810 
2811   nsCOMPtr<nsIBrowser> browser;
2812   RefPtr<Element> currentElement = mFrameElement;
2813 
2814   // In Responsive Design Mode, mFrameElement will be the <iframe mozbrowser>,
2815   // but we want the <xul:browser> that it is embedded in.
2816   while (currentElement) {
2817     browser = currentElement->AsBrowser();
2818     if (browser) {
2819       break;
2820     }
2821 
2822     BrowsingContext* browsingContext =
2823         currentElement->OwnerDoc()->GetBrowsingContext();
2824     currentElement =
2825         browsingContext ? browsingContext->GetEmbedderElement() : nullptr;
2826   }
2827 
2828   if (!browser) {
2829     return false;
2830   }
2831 
2832   nsCOMPtr<nsIWebProgress> manager;
2833   nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
2834   if (NS_FAILED(rv)) {
2835     return false;
2836   }
2837 
2838   nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(manager);
2839   if (!listener) {
2840     // We are no longer remote so we cannot forward this event.
2841     return false;
2842   }
2843 
2844   browser.forget(aOutBrowser);
2845   manager.forget(aOutManager);
2846   listener.forget(aOutListener);
2847 
2848   return true;
2849 }
2850 
ReconstructWebProgressAndRequest(nsIWebProgress * aManager,const Maybe<WebProgressData> & aWebProgressData,const RequestData & aRequestData,nsIWebProgress ** aOutWebProgress,nsIRequest ** aOutRequest)2851 void BrowserParent::ReconstructWebProgressAndRequest(
2852     nsIWebProgress* aManager, const Maybe<WebProgressData>& aWebProgressData,
2853     const RequestData& aRequestData, nsIWebProgress** aOutWebProgress,
2854     nsIRequest** aOutRequest) {
2855   MOZ_DIAGNOSTIC_ASSERT(aOutWebProgress,
2856                         "aOutWebProgress should never be null");
2857   MOZ_DIAGNOSTIC_ASSERT(aOutRequest, "aOutRequest should never be null");
2858 
2859   nsCOMPtr<nsIWebProgress> webProgress;
2860   if (aWebProgressData) {
2861     webProgress = new RemoteWebProgress(
2862         aManager, aWebProgressData->outerDOMWindowID(),
2863         aWebProgressData->innerDOMWindowID(), aWebProgressData->loadType(),
2864         aWebProgressData->isLoadingDocument(), aWebProgressData->isTopLevel());
2865   } else {
2866     webProgress = new RemoteWebProgress(aManager, 0, 0, 0, false, false);
2867   }
2868   webProgress.forget(aOutWebProgress);
2869 
2870   if (aRequestData.requestURI()) {
2871     nsCOMPtr<nsIRequest> request = MakeAndAddRef<RemoteWebProgressRequest>(
2872         aRequestData.requestURI(), aRequestData.originalRequestURI(),
2873         aRequestData.matchedList(), aRequestData.elapsedLoadTimeMS());
2874     request.forget(aOutRequest);
2875   } else {
2876     *aOutRequest = nullptr;
2877   }
2878 }
2879 
RecvSessionStoreUpdate(const Maybe<nsCString> & aDocShellCaps,const Maybe<bool> & aPrivatedMode,nsTArray<nsCString> && aPositions,nsTArray<int32_t> && aPositionDescendants,const nsTArray<InputFormData> & aInputs,const nsTArray<CollectedInputDataValue> & aIdVals,const nsTArray<CollectedInputDataValue> & aXPathVals,nsTArray<nsCString> && aOrigins,nsTArray<nsString> && aKeys,nsTArray<nsString> && aValues,const bool aIsFullStorage,const bool aNeedCollectSHistory,const uint32_t & aFlushId,const bool & aIsFinal,const uint32_t & aEpoch)2880 mozilla::ipc::IPCResult BrowserParent::RecvSessionStoreUpdate(
2881     const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
2882     nsTArray<nsCString>&& aPositions, nsTArray<int32_t>&& aPositionDescendants,
2883     const nsTArray<InputFormData>& aInputs,
2884     const nsTArray<CollectedInputDataValue>& aIdVals,
2885     const nsTArray<CollectedInputDataValue>& aXPathVals,
2886     nsTArray<nsCString>&& aOrigins, nsTArray<nsString>&& aKeys,
2887     nsTArray<nsString>&& aValues, const bool aIsFullStorage,
2888     const bool aNeedCollectSHistory, const uint32_t& aFlushId,
2889     const bool& aIsFinal, const uint32_t& aEpoch) {
2890   UpdateSessionStoreData data;
2891   if (aDocShellCaps.isSome()) {
2892     data.mDocShellCaps.Construct() = aDocShellCaps.value();
2893   }
2894   if (aPrivatedMode.isSome()) {
2895     data.mIsPrivate.Construct() = aPrivatedMode.value();
2896   }
2897   if (aPositions.Length() != 0) {
2898     data.mPositions.Construct(std::move(aPositions));
2899     data.mPositionDescendants.Construct(std::move(aPositionDescendants));
2900   }
2901   if (aIdVals.Length() != 0) {
2902     SessionStoreUtils::ComposeInputData(aIdVals, data.mId.Construct());
2903   }
2904   if (aXPathVals.Length() != 0) {
2905     SessionStoreUtils::ComposeInputData(aXPathVals, data.mXpath.Construct());
2906   }
2907   if (aInputs.Length() != 0) {
2908     nsTArray<int> descendants, numId, numXPath;
2909     nsTArray<nsString> innerHTML;
2910     nsTArray<nsCString> url;
2911     for (const InputFormData& input : aInputs) {
2912       descendants.AppendElement(input.descendants);
2913       numId.AppendElement(input.numId);
2914       numXPath.AppendElement(input.numXPath);
2915       innerHTML.AppendElement(input.innerHTML);
2916       url.AppendElement(input.url);
2917     }
2918 
2919     data.mInputDescendants.Construct(std::move(descendants));
2920     data.mNumId.Construct(std::move(numId));
2921     data.mNumXPath.Construct(std::move(numXPath));
2922     data.mInnerHTML.Construct(std::move(innerHTML));
2923     data.mUrl.Construct(std::move(url));
2924   }
2925   // In normal case, we only update the storage when needed.
2926   // However, we need to reset the session storage(aOrigins.Length() will be 0)
2927   //   if the usage is over the "browser_sessionstore_dom_storage_limit".
2928   // In this case, aIsFullStorage is true.
2929   if (aOrigins.Length() != 0 || aIsFullStorage) {
2930     data.mStorageOrigins.Construct(std::move(aOrigins));
2931     data.mStorageKeys.Construct(std::move(aKeys));
2932     data.mStorageValues.Construct(std::move(aValues));
2933     data.mIsFullStorage.Construct() = aIsFullStorage;
2934   }
2935 
2936   nsCOMPtr<nsISessionStoreFunctions> funcs =
2937       do_ImportModule("resource://gre/modules/SessionStoreFunctions.jsm");
2938   NS_ENSURE_TRUE(funcs, IPC_OK());
2939   nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
2940   AutoJSAPI jsapi;
2941   MOZ_ALWAYS_TRUE(jsapi.Init(wrapped->GetJSObjectGlobal()));
2942   JS::Rooted<JS::Value> dataVal(jsapi.cx());
2943   bool ok = ToJSValue(jsapi.cx(), data, &dataVal);
2944   NS_ENSURE_TRUE(ok, IPC_OK());
2945 
2946   nsresult rv = funcs->UpdateSessionStore(
2947       mFrameElement, aFlushId, aIsFinal, aEpoch, dataVal, aNeedCollectSHistory);
2948   NS_ENSURE_SUCCESS(rv, IPC_OK());
2949 
2950   return IPC_OK();
2951 }
2952 
HandleQueryContentEvent(WidgetQueryContentEvent & aEvent)2953 bool BrowserParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent) {
2954   nsCOMPtr<nsIWidget> textInputHandlingWidget = GetTextInputHandlingWidget();
2955   if (!textInputHandlingWidget) {
2956     return true;
2957   }
2958   if (NS_WARN_IF(!mContentCache.HandleQueryContentEvent(
2959           aEvent, textInputHandlingWidget)) ||
2960       NS_WARN_IF(!aEvent.mSucceeded)) {
2961     return true;
2962   }
2963   switch (aEvent.mMessage) {
2964     case eQueryTextRect:
2965     case eQueryCaretRect:
2966     case eQueryEditorRect: {
2967       nsCOMPtr<nsIWidget> browserWidget = GetWidget();
2968       if (browserWidget != textInputHandlingWidget) {
2969         aEvent.mReply.mRect += nsLayoutUtils::WidgetToWidgetOffset(
2970             browserWidget, textInputHandlingWidget);
2971       }
2972       aEvent.mReply.mRect = TransformChildToParent(aEvent.mReply.mRect);
2973       break;
2974     }
2975     default:
2976       break;
2977   }
2978   return true;
2979 }
2980 
SendCompositionEvent(WidgetCompositionEvent & aEvent)2981 bool BrowserParent::SendCompositionEvent(WidgetCompositionEvent& aEvent) {
2982   if (mIsDestroyed) {
2983     return false;
2984   }
2985 
2986   if (!mContentCache.OnCompositionEvent(aEvent)) {
2987     return true;
2988   }
2989 
2990   bool ret = Manager()->IsInputPriorityEventEnabled()
2991                  ? PBrowserParent::SendCompositionEvent(aEvent)
2992                  : PBrowserParent::SendNormalPriorityCompositionEvent(aEvent);
2993   if (NS_WARN_IF(!ret)) {
2994     return false;
2995   }
2996   MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess());
2997   return true;
2998 }
2999 
SendSelectionEvent(WidgetSelectionEvent & aEvent)3000 bool BrowserParent::SendSelectionEvent(WidgetSelectionEvent& aEvent) {
3001   if (mIsDestroyed) {
3002     return false;
3003   }
3004   nsCOMPtr<nsIWidget> widget = GetWidget();
3005   if (!widget) {
3006     return true;
3007   }
3008   mContentCache.OnSelectionEvent(aEvent);
3009   bool ret = Manager()->IsInputPriorityEventEnabled()
3010                  ? PBrowserParent::SendSelectionEvent(aEvent)
3011                  : PBrowserParent::SendNormalPrioritySelectionEvent(aEvent);
3012   if (NS_WARN_IF(!ret)) {
3013     return false;
3014   }
3015   MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess());
3016   aEvent.mSucceeded = true;
3017   return true;
3018 }
3019 
SendPasteTransferable(const IPCDataTransfer & aDataTransfer,const bool & aIsPrivateData,nsIPrincipal * aRequestingPrincipal,const uint32_t & aContentPolicyType)3020 bool BrowserParent::SendPasteTransferable(const IPCDataTransfer& aDataTransfer,
3021                                           const bool& aIsPrivateData,
3022                                           nsIPrincipal* aRequestingPrincipal,
3023                                           const uint32_t& aContentPolicyType) {
3024   return PBrowserParent::SendPasteTransferable(
3025       aDataTransfer, aIsPrivateData, aRequestingPrincipal, aContentPolicyType);
3026 }
3027 
3028 /* static */
SetTopLevelWebFocus(BrowserParent * aBrowserParent)3029 void BrowserParent::SetTopLevelWebFocus(BrowserParent* aBrowserParent) {
3030   BrowserParent* old = GetFocused();
3031   if (aBrowserParent && !aBrowserParent->GetBrowserBridgeParent()) {
3032     // top-level Web content
3033     sTopLevelWebFocus = aBrowserParent;
3034     BrowserParent* bp = UpdateFocus();
3035     if (old != bp) {
3036       LOGBROWSERFOCUS(
3037           ("SetTopLevelWebFocus updated focus; old: %p, new: %p", old, bp));
3038       IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp);
3039     }
3040   }
3041 }
3042 
3043 /* static */
UnsetTopLevelWebFocus(BrowserParent * aBrowserParent)3044 void BrowserParent::UnsetTopLevelWebFocus(BrowserParent* aBrowserParent) {
3045   BrowserParent* old = GetFocused();
3046   if (sTopLevelWebFocus == aBrowserParent) {
3047     // top-level Web content
3048     sTopLevelWebFocus = nullptr;
3049     sFocus = nullptr;
3050     if (old) {
3051       LOGBROWSERFOCUS(
3052           ("UnsetTopLevelWebFocus moved focus to chrome; old: %p", old));
3053       IMEStateManager::OnFocusMovedBetweenBrowsers(old, nullptr);
3054     }
3055   }
3056 }
3057 
3058 /* static */
UpdateFocusFromBrowsingContext()3059 void BrowserParent::UpdateFocusFromBrowsingContext() {
3060   BrowserParent* old = GetFocused();
3061   BrowserParent* bp = UpdateFocus();
3062   if (old != bp) {
3063     LOGBROWSERFOCUS(
3064         ("UpdateFocusFromBrowsingContext updated focus; old: %p, new: %p", old,
3065          bp));
3066     IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp);
3067   }
3068 }
3069 
3070 /* static */
UpdateFocus()3071 BrowserParent* BrowserParent::UpdateFocus() {
3072   if (!sTopLevelWebFocus) {
3073     sFocus = nullptr;
3074     return nullptr;
3075   }
3076   nsFocusManager* fm = nsFocusManager::GetFocusManager();
3077   if (fm) {
3078     BrowsingContext* bc = fm->GetFocusedBrowsingContextInChrome();
3079     if (bc) {
3080       BrowsingContext* top = bc->Top();
3081       MOZ_ASSERT(top, "Should always have a top BrowsingContext.");
3082       CanonicalBrowsingContext* canonicalTop = top->Canonical();
3083       MOZ_ASSERT(canonicalTop,
3084                  "Casting to canonical should always be possible in the parent "
3085                  "process (top case).");
3086       WindowGlobalParent* globalTop = canonicalTop->GetCurrentWindowGlobal();
3087       if (globalTop) {
3088         RefPtr<BrowserParent> globalTopParent = globalTop->GetBrowserParent();
3089         if (sTopLevelWebFocus == globalTopParent) {
3090           CanonicalBrowsingContext* canonical = bc->Canonical();
3091           MOZ_ASSERT(
3092               canonical,
3093               "Casting to canonical should always be possible in the parent "
3094               "process.");
3095           WindowGlobalParent* global = canonical->GetCurrentWindowGlobal();
3096           if (global) {
3097             RefPtr<BrowserParent> parent = global->GetBrowserParent();
3098             sFocus = parent;
3099             return sFocus;
3100           }
3101           LOGBROWSERFOCUS(
3102               ("Focused BrowsingContext did not have WindowGlobalParent."));
3103         }
3104       } else {
3105         LOGBROWSERFOCUS(
3106             ("Top-level BrowsingContext did not have WindowGlobalParent."));
3107       }
3108     }
3109   }
3110   sFocus = sTopLevelWebFocus;
3111   return sFocus;
3112 }
3113 
3114 /* static */
UnsetTopLevelWebFocusAll()3115 void BrowserParent::UnsetTopLevelWebFocusAll() {
3116   if (sTopLevelWebFocus) {
3117     UnsetTopLevelWebFocus(sTopLevelWebFocus);
3118   }
3119 }
3120 
3121 /* static */
UnsetLastMouseRemoteTarget(BrowserParent * aBrowserParent)3122 void BrowserParent::UnsetLastMouseRemoteTarget(BrowserParent* aBrowserParent) {
3123   if (sLastMouseRemoteTarget == aBrowserParent) {
3124     sLastMouseRemoteTarget = nullptr;
3125   }
3126 }
3127 
RecvRequestIMEToCommitComposition(const bool & aCancel,bool * aIsCommitted,nsString * aCommittedString)3128 mozilla::ipc::IPCResult BrowserParent::RecvRequestIMEToCommitComposition(
3129     const bool& aCancel, bool* aIsCommitted, nsString* aCommittedString) {
3130   nsCOMPtr<nsIWidget> widget = GetTextInputHandlingWidget();
3131   if (!widget) {
3132     *aIsCommitted = false;
3133     return IPC_OK();
3134   }
3135 
3136   *aIsCommitted = mContentCache.RequestIMEToCommitComposition(
3137       widget, aCancel, *aCommittedString);
3138   return IPC_OK();
3139 }
3140 
RecvStartPluginIME(const WidgetKeyboardEvent & aKeyboardEvent,const int32_t & aPanelX,const int32_t & aPanelY,nsString * aCommitted)3141 mozilla::ipc::IPCResult BrowserParent::RecvStartPluginIME(
3142     const WidgetKeyboardEvent& aKeyboardEvent, const int32_t& aPanelX,
3143     const int32_t& aPanelY, nsString* aCommitted) {
3144   nsCOMPtr<nsIWidget> widget = GetWidget();
3145   if (!widget) {
3146     return IPC_OK();
3147   }
3148   Unused << widget->StartPluginIME(aKeyboardEvent, (int32_t&)aPanelX,
3149                                    (int32_t&)aPanelY, *aCommitted);
3150   return IPC_OK();
3151 }
3152 
RecvSetPluginFocused(const bool & aFocused)3153 mozilla::ipc::IPCResult BrowserParent::RecvSetPluginFocused(
3154     const bool& aFocused) {
3155   nsCOMPtr<nsIWidget> widget = GetWidget();
3156   if (!widget) {
3157     return IPC_OK();
3158   }
3159   widget->SetPluginFocused((bool&)aFocused);
3160   return IPC_OK();
3161 }
3162 
RecvSetCandidateWindowForPlugin(const CandidateWindowPosition & aPosition)3163 mozilla::ipc::IPCResult BrowserParent::RecvSetCandidateWindowForPlugin(
3164     const CandidateWindowPosition& aPosition) {
3165   nsCOMPtr<nsIWidget> widget = GetWidget();
3166   if (!widget) {
3167     return IPC_OK();
3168   }
3169 
3170   widget->SetCandidateWindowForPlugin(aPosition);
3171   return IPC_OK();
3172 }
3173 
RecvEnableIMEForPlugin(const bool & aEnable)3174 mozilla::ipc::IPCResult BrowserParent::RecvEnableIMEForPlugin(
3175     const bool& aEnable) {
3176   nsCOMPtr<nsIWidget> widget = GetWidget();
3177   if (!widget) {
3178     return IPC_OK();
3179   }
3180   widget->EnableIMEForPlugin(aEnable);
3181   return IPC_OK();
3182 }
3183 
RecvDefaultProcOfPluginEvent(const WidgetPluginEvent & aEvent)3184 mozilla::ipc::IPCResult BrowserParent::RecvDefaultProcOfPluginEvent(
3185     const WidgetPluginEvent& aEvent) {
3186   nsCOMPtr<nsIWidget> widget = GetWidget();
3187   if (!widget) {
3188     return IPC_OK();
3189   }
3190 
3191   widget->DefaultProcOfPluginEvent(aEvent);
3192   return IPC_OK();
3193 }
3194 
RecvGetInputContext(widget::IMEState * aState)3195 mozilla::ipc::IPCResult BrowserParent::RecvGetInputContext(
3196     widget::IMEState* aState) {
3197   nsCOMPtr<nsIWidget> widget = GetWidget();
3198   if (!widget) {
3199     *aState = widget::IMEState(IMEState::DISABLED,
3200                                IMEState::OPEN_STATE_NOT_SUPPORTED);
3201     return IPC_OK();
3202   }
3203 
3204   *aState = widget->GetInputContext().mIMEState;
3205   return IPC_OK();
3206 }
3207 
RecvSetInputContext(const InputContext & aContext,const InputContextAction & aAction)3208 mozilla::ipc::IPCResult BrowserParent::RecvSetInputContext(
3209     const InputContext& aContext, const InputContextAction& aAction) {
3210   IMEStateManager::SetInputContextForChildProcess(this, aContext, aAction);
3211   return IPC_OK();
3212 }
3213 
RecvSetNativeChildOfShareableWindow(const uintptr_t & aChildWindow)3214 mozilla::ipc::IPCResult BrowserParent::RecvSetNativeChildOfShareableWindow(
3215     const uintptr_t& aChildWindow) {
3216 #if defined(XP_WIN)
3217   nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
3218   if (widget) {
3219     // Note that this call will probably cause a sync native message to the
3220     // process that owns the child window.
3221     widget->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW, aChildWindow);
3222   }
3223   return IPC_OK();
3224 #else
3225   MOZ_ASSERT_UNREACHABLE(
3226       "BrowserParent::RecvSetNativeChildOfShareableWindow not implemented!");
3227   return IPC_FAIL_NO_REASON(this);
3228 #endif
3229 }
3230 
RecvDispatchFocusToTopLevelWindow()3231 mozilla::ipc::IPCResult BrowserParent::RecvDispatchFocusToTopLevelWindow() {
3232   if (nsCOMPtr<nsIWidget> widget = GetTopLevelWidget()) {
3233     widget->SetFocus(nsIWidget::Raise::No, CallerType::System);
3234   }
3235   return IPC_OK();
3236 }
3237 
ReceiveMessage(const nsString & aMessage,bool aSync,StructuredCloneData * aData,nsTArray<StructuredCloneData> * aRetVal)3238 bool BrowserParent::ReceiveMessage(const nsString& aMessage, bool aSync,
3239                                    StructuredCloneData* aData,
3240                                    nsTArray<StructuredCloneData>* aRetVal) {
3241   // If we're for an oop iframe, don't deliver messages to the wrong place.
3242   if (mBrowserBridgeParent) {
3243     return true;
3244   }
3245 
3246   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
3247   if (frameLoader && frameLoader->GetFrameMessageManager()) {
3248     RefPtr<nsFrameMessageManager> manager =
3249         frameLoader->GetFrameMessageManager();
3250 
3251     manager->ReceiveMessage(mFrameElement, frameLoader, aMessage, aSync, aData,
3252                             aRetVal, IgnoreErrors());
3253   }
3254   return true;
3255 }
3256 
3257 // nsIAuthPromptProvider
3258 
3259 // This method is largely copied from nsDocShell::GetAuthPrompt
3260 NS_IMETHODIMP
GetAuthPrompt(uint32_t aPromptReason,const nsIID & iid,void ** aResult)3261 BrowserParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
3262                              void** aResult) {
3263   // we're either allowing auth, or it's a proxy request
3264   nsresult rv;
3265   nsCOMPtr<nsIPromptFactory> wwatch =
3266       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
3267   NS_ENSURE_SUCCESS(rv, rv);
3268 
3269   nsCOMPtr<nsPIDOMWindowOuter> window;
3270   RefPtr<Element> frame = mFrameElement;
3271   if (frame) window = frame->OwnerDoc()->GetWindow();
3272 
3273   // Get an auth prompter for our window so that the parenting
3274   // of the dialogs works as it should when using tabs.
3275   nsCOMPtr<nsISupports> prompt;
3276   rv = wwatch->GetPrompt(window, iid, getter_AddRefs(prompt));
3277   NS_ENSURE_SUCCESS(rv, rv);
3278 
3279   nsCOMPtr<nsILoginManagerAuthPrompter> prompter = do_QueryInterface(prompt);
3280   if (prompter) {
3281     prompter->SetBrowser(mFrameElement);
3282   }
3283 
3284   *aResult = prompt.forget().take();
3285   return NS_OK;
3286 }
3287 
AllocPColorPickerParent(const nsString & aTitle,const nsString & aInitialColor)3288 PColorPickerParent* BrowserParent::AllocPColorPickerParent(
3289     const nsString& aTitle, const nsString& aInitialColor) {
3290   return new ColorPickerParent(aTitle, aInitialColor);
3291 }
3292 
DeallocPColorPickerParent(PColorPickerParent * actor)3293 bool BrowserParent::DeallocPColorPickerParent(PColorPickerParent* actor) {
3294   delete actor;
3295   return true;
3296 }
3297 
GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy) const3298 already_AddRefed<nsFrameLoader> BrowserParent::GetFrameLoader(
3299     bool aUseCachedFrameLoaderAfterDestroy) const {
3300   if (mIsDestroyed && !aUseCachedFrameLoaderAfterDestroy) {
3301     return nullptr;
3302   }
3303 
3304   if (mFrameLoader) {
3305     RefPtr<nsFrameLoader> fl = mFrameLoader;
3306     return fl.forget();
3307   }
3308   RefPtr<Element> frameElement(mFrameElement);
3309   RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(frameElement);
3310   return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr;
3311 }
3312 
TryCacheDPIAndScale()3313 void BrowserParent::TryCacheDPIAndScale() {
3314   if (mDPI > 0) {
3315     return;
3316   }
3317 
3318   nsCOMPtr<nsIWidget> widget = GetWidget();
3319 
3320   if (widget) {
3321     mDPI = widget->GetDPI();
3322     mRounding = widget->RoundsWidgetCoordinatesTo();
3323     mDefaultScale = widget->GetDefaultScale();
3324   }
3325 }
3326 
ApzAwareEventRoutingToChild(ScrollableLayerGuid * aOutTargetGuid,uint64_t * aOutInputBlockId,nsEventStatus * aOutApzResponse)3327 void BrowserParent::ApzAwareEventRoutingToChild(
3328     ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId,
3329     nsEventStatus* aOutApzResponse) {
3330   // Let the widget know that the event will be sent to the child process,
3331   // which will (hopefully) send a confirmation notice back to APZ.
3332   // Do this even if APZ is off since we need it for swipe gesture support on
3333   // OS X without APZ.
3334   InputAPZContext::SetRoutedToChildProcess();
3335 
3336   if (AsyncPanZoomEnabled()) {
3337     if (aOutTargetGuid) {
3338       *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid();
3339 
3340       // There may be cases where the APZ hit-testing code came to a different
3341       // conclusion than the main-thread hit-testing code as to where the event
3342       // is destined. In such cases the layersId of the APZ result may not match
3343       // the layersId of this RemoteLayerTreeOwner. In such cases the
3344       // main-thread hit- testing code "wins" so we need to update the guid to
3345       // reflect this.
3346       if (mRemoteLayerTreeOwner.IsInitialized()) {
3347         if (aOutTargetGuid->mLayersId != mRemoteLayerTreeOwner.GetLayersId()) {
3348           *aOutTargetGuid =
3349               ScrollableLayerGuid(mRemoteLayerTreeOwner.GetLayersId(), 0,
3350                                   ScrollableLayerGuid::NULL_SCROLL_ID);
3351         }
3352       }
3353     }
3354     if (aOutInputBlockId) {
3355       *aOutInputBlockId = InputAPZContext::GetInputBlockId();
3356     }
3357     if (aOutApzResponse) {
3358       *aOutApzResponse = InputAPZContext::GetApzResponse();
3359 
3360       // We can get here without there being an InputAPZContext on the stack
3361       // if a non-native event synthesization function (such as
3362       // nsIDOMWindowUtils.sendTouchEvent()) was used in the parent process to
3363       // synthesize an event that's targeting a content process. Such events do
3364       // not go through APZ. Without an InputAPZContext on the stack we pick up
3365       // the default value "eSentinel" which cannot be sent over IPC, so replace
3366       // it with "eIgnore" instead, which what APZ uses when it ignores an
3367       // event. If a caller needs the ability to synthesize a event with a
3368       // different APZ response, a native event synthesization function (such as
3369       // sendNativeTouchPoint()) can be used.
3370       if (*aOutApzResponse == nsEventStatus_eSentinel) {
3371         *aOutApzResponse = nsEventStatus_eIgnore;
3372       }
3373     }
3374   } else {
3375     if (aOutInputBlockId) {
3376       *aOutInputBlockId = 0;
3377     }
3378     if (aOutApzResponse) {
3379       *aOutApzResponse = nsEventStatus_eIgnore;
3380     }
3381   }
3382 }
3383 
RecvRespondStartSwipeEvent(const uint64_t & aInputBlockId,const bool & aStartSwipe)3384 mozilla::ipc::IPCResult BrowserParent::RecvRespondStartSwipeEvent(
3385     const uint64_t& aInputBlockId, const bool& aStartSwipe) {
3386   if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
3387     widget->ReportSwipeStarted(aInputBlockId, aStartSwipe);
3388   }
3389   return IPC_OK();
3390 }
3391 
GetDocShellIsActive()3392 bool BrowserParent::GetDocShellIsActive() { return mDocShellIsActive; }
3393 
SetDocShellIsActive(bool isActive)3394 void BrowserParent::SetDocShellIsActive(bool isActive) {
3395   mDocShellIsActive = isActive;
3396   SetRenderLayers(isActive);
3397   Unused << SendSetDocShellIsActive(isActive);
3398 
3399   // update active accessible documents on windows
3400 #if defined(XP_WIN) && defined(ACCESSIBILITY)
3401   if (a11y::Compatibility::IsDolphin()) {
3402     if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) {
3403       HWND window = tabDoc->GetEmulatedWindowHandle();
3404       MOZ_ASSERT(window);
3405       if (window) {
3406         if (isActive) {
3407           a11y::nsWinUtils::ShowNativeWindow(window);
3408         } else {
3409           a11y::nsWinUtils::HideNativeWindow(window);
3410         }
3411       }
3412     }
3413   }
3414 #endif
3415 }
3416 
GetSuspendMediaWhenInactive() const3417 bool BrowserParent::GetSuspendMediaWhenInactive() const {
3418   return mSuspendMediaWhenInactive;
3419 }
3420 
SetSuspendMediaWhenInactive(bool aSuspendMediaWhenInactive)3421 void BrowserParent::SetSuspendMediaWhenInactive(
3422     bool aSuspendMediaWhenInactive) {
3423   mSuspendMediaWhenInactive = aSuspendMediaWhenInactive;
3424   Unused << SendSetSuspendMediaWhenInactive(aSuspendMediaWhenInactive);
3425 }
3426 
GetHasPresented()3427 bool BrowserParent::GetHasPresented() { return mHasPresented; }
3428 
GetHasLayers()3429 bool BrowserParent::GetHasLayers() { return mHasLayers; }
3430 
GetRenderLayers()3431 bool BrowserParent::GetRenderLayers() { return mRenderLayers; }
3432 
SetRenderLayers(bool aEnabled)3433 void BrowserParent::SetRenderLayers(bool aEnabled) {
3434   if (mActiveInPriorityManager != aEnabled) {
3435     mActiveInPriorityManager = aEnabled;
3436     // Let's inform the priority manager. This operation can end up with the
3437     // changing of the process priority.
3438     ProcessPriorityManager::TabActivityChanged(this, aEnabled);
3439   }
3440 
3441   if (aEnabled == mRenderLayers) {
3442     if (aEnabled && mHasLayers && mPreserveLayers) {
3443       // RenderLayers might be called when we've been preserving layers,
3444       // and already had layers uploaded. In that case, the MozLayerTreeReady
3445       // event will not naturally arrive, which can confuse the front-end
3446       // layer. So we fire the event here.
3447       RefPtr<BrowserParent> self = this;
3448       LayersObserverEpoch epoch = mLayerTreeEpoch;
3449       NS_DispatchToMainThread(NS_NewRunnableFunction(
3450           "dom::BrowserParent::RenderLayers", [self, epoch]() {
3451             MOZ_ASSERT(NS_IsMainThread());
3452             self->LayerTreeUpdate(epoch, true);
3453           }));
3454     }
3455 
3456     return;
3457   }
3458 
3459   // Preserve layers means that attempts to stop rendering layers
3460   // will be ignored.
3461   if (!aEnabled && mPreserveLayers) {
3462     return;
3463   }
3464 
3465   mRenderLayers = aEnabled;
3466 
3467   SetRenderLayersInternal(aEnabled);
3468 }
3469 
SetRenderLayersInternal(bool aEnabled)3470 void BrowserParent::SetRenderLayersInternal(bool aEnabled) {
3471   // Increment the epoch so that layer tree updates from previous
3472   // RenderLayers requests are ignored.
3473   mLayerTreeEpoch = mLayerTreeEpoch.Next();
3474 
3475   Unused << SendRenderLayers(aEnabled, mLayerTreeEpoch);
3476 
3477   // Ask the child to repaint using the PHangMonitor channel/thread (which may
3478   // be less congested).
3479   if (aEnabled) {
3480     Manager()->PaintTabWhileInterruptingJS(this, mLayerTreeEpoch);
3481   }
3482 }
3483 
PreserveLayers(bool aPreserveLayers)3484 void BrowserParent::PreserveLayers(bool aPreserveLayers) {
3485   mPreserveLayers = aPreserveLayers;
3486 }
3487 
NotifyResolutionChanged()3488 void BrowserParent::NotifyResolutionChanged() {
3489   if (!mIsDestroyed) {
3490     // TryCacheDPIAndScale()'s cache is keyed off of
3491     // mDPI being greater than 0, so this invalidates it.
3492     mDPI = -1;
3493     TryCacheDPIAndScale();
3494     // If mDPI was set to -1 to invalidate it and then TryCacheDPIAndScale
3495     // fails to cache the values, then mDefaultScale.scale might be invalid.
3496     // We don't want to send that value to content. Just send -1 for it too in
3497     // that case.
3498     Unused << SendUIResolutionChanged(mDPI, mRounding,
3499                                       mDPI < 0 ? -1.0 : mDefaultScale.scale);
3500   }
3501 }
3502 
Deprioritize()3503 void BrowserParent::Deprioritize() {
3504   if (mActiveInPriorityManager) {
3505     ProcessPriorityManager::TabActivityChanged(this, false);
3506     mActiveInPriorityManager = false;
3507   }
3508 }
3509 
StartApzAutoscroll(float aAnchorX,float aAnchorY,nsViewID aScrollId,uint32_t aPresShellId)3510 bool BrowserParent::StartApzAutoscroll(float aAnchorX, float aAnchorY,
3511                                        nsViewID aScrollId,
3512                                        uint32_t aPresShellId) {
3513   if (!AsyncPanZoomEnabled()) {
3514     return false;
3515   }
3516 
3517   bool success = false;
3518   if (mRemoteLayerTreeOwner.IsInitialized()) {
3519     layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId();
3520     if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
3521       ScrollableLayerGuid guid(layersId, aPresShellId, aScrollId);
3522 
3523       // The anchor coordinates that are passed in are relative to the origin
3524       // of the screen, but we are sending them to APZ which only knows about
3525       // coordinates relative to the widget, so convert them accordingly.
3526       CSSPoint anchorCss{aAnchorX, aAnchorY};
3527       LayoutDeviceIntPoint anchor =
3528           RoundedToInt(anchorCss * widget->GetDefaultScale());
3529       anchor -= widget->WidgetToScreenOffset();
3530 
3531       success = widget->StartAsyncAutoscroll(
3532           ViewAs<ScreenPixel>(
3533               anchor, PixelCastJustification::LayoutDeviceIsScreenForBounds),
3534           guid);
3535     }
3536   }
3537   return success;
3538 }
3539 
StopApzAutoscroll(nsViewID aScrollId,uint32_t aPresShellId)3540 void BrowserParent::StopApzAutoscroll(nsViewID aScrollId,
3541                                       uint32_t aPresShellId) {
3542   if (!AsyncPanZoomEnabled()) {
3543     return;
3544   }
3545 
3546   if (mRemoteLayerTreeOwner.IsInitialized()) {
3547     layers::LayersId layersId = mRemoteLayerTreeOwner.GetLayersId();
3548     if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
3549       ScrollableLayerGuid guid(layersId, aPresShellId, aScrollId);
3550 
3551       widget->StopAsyncAutoscroll(guid);
3552     }
3553   }
3554 }
3555 
SuppressDisplayport(bool aEnabled)3556 void BrowserParent::SuppressDisplayport(bool aEnabled) {
3557   if (IsDestroyed()) {
3558     return;
3559   }
3560 
3561 #ifdef DEBUG
3562   if (aEnabled) {
3563     mActiveSupressDisplayportCount++;
3564   } else {
3565     mActiveSupressDisplayportCount--;
3566   }
3567   MOZ_ASSERT(mActiveSupressDisplayportCount >= 0);
3568 #endif
3569 
3570   Unused << SendSuppressDisplayport(aEnabled);
3571 }
3572 
NavigateByKey(bool aForward,bool aForDocumentNavigation)3573 void BrowserParent::NavigateByKey(bool aForward, bool aForDocumentNavigation) {
3574   Unused << SendNavigateByKey(aForward, aForDocumentNavigation);
3575 }
3576 
LayerTreeUpdate(const LayersObserverEpoch & aEpoch,bool aActive)3577 void BrowserParent::LayerTreeUpdate(const LayersObserverEpoch& aEpoch,
3578                                     bool aActive) {
3579   // Ignore updates if we're an out-of-process iframe. For oop iframes, our
3580   // |mFrameElement| is that of the top-level document, and so AsyncTabSwitcher
3581   // will treat MozLayerTreeReady / MozLayerTreeCleared events as if they came
3582   // from the top-level tab, which is wrong.
3583   //
3584   // XXX: Should we still be updating |mHasLayers|?
3585   if (GetBrowserBridgeParent()) {
3586     return;
3587   }
3588 
3589   // Ignore updates from old epochs. They might tell us that layers are
3590   // available when we've already sent a message to clear them. We can't trust
3591   // the update in that case since layers could disappear anytime after that.
3592   if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
3593     return;
3594   }
3595 
3596   RefPtr<EventTarget> target = mFrameElement;
3597   if (!target) {
3598     NS_WARNING("Could not locate target for layer tree message.");
3599     return;
3600   }
3601 
3602   mHasLayers = aActive;
3603 
3604   RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
3605   if (aActive) {
3606     mHasPresented = true;
3607     event->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false);
3608   } else {
3609     event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false);
3610   }
3611   event->SetTrusted(true);
3612   event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
3613   mFrameElement->DispatchEvent(*event);
3614 }
3615 
RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch & aEpoch)3616 mozilla::ipc::IPCResult BrowserParent::RecvPaintWhileInterruptingJSNoOp(
3617     const LayersObserverEpoch& aEpoch) {
3618   // We sent a PaintWhileInterruptingJS message when layers were already
3619   // visible. In this case, we should act as if an update occurred even though
3620   // we already have the layers.
3621   LayerTreeUpdate(aEpoch, true);
3622   return IPC_OK();
3623 }
3624 
RecvRemotePaintIsReady()3625 mozilla::ipc::IPCResult BrowserParent::RecvRemotePaintIsReady() {
3626   RefPtr<EventTarget> target = mFrameElement;
3627   if (!target) {
3628     NS_WARNING("Could not locate target for MozAfterRemotePaint message.");
3629     return IPC_OK();
3630   }
3631 
3632   RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
3633   event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false);
3634   event->SetTrusted(true);
3635   event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
3636   mFrameElement->DispatchEvent(*event);
3637   return IPC_OK();
3638 }
3639 
RecvNotifyCompositorTransaction()3640 mozilla::ipc::IPCResult BrowserParent::RecvNotifyCompositorTransaction() {
3641   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
3642 
3643   if (!frameLoader) {
3644     return IPC_OK();
3645   }
3646 
3647   nsIFrame* docFrame = frameLoader->GetPrimaryFrameOfOwningContent();
3648 
3649   if (!docFrame) {
3650     // Bad, but nothing we can do about it (XXX/cjones: or is there?
3651     // maybe bug 589337?).  When the new frame is created, we'll
3652     // probably still be the current render frame and will get to draw
3653     // our content then.  Or, we're shutting down and this update goes
3654     // to /dev/null.
3655     return IPC_OK();
3656   }
3657 
3658   docFrame->InvalidateLayer(DisplayItemType::TYPE_REMOTE);
3659   return IPC_OK();
3660 }
3661 
RecvRemoteIsReadyToHandleInputEvents()3662 mozilla::ipc::IPCResult BrowserParent::RecvRemoteIsReadyToHandleInputEvents() {
3663   // When enabling input event prioritization, input events may preempt other
3664   // normal priority IPC messages. To prevent the input events preempt
3665   // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
3666   // notify the parent that BrowserChild is created and ready to handle input
3667   // events.
3668   SetReadyToHandleInputEvents();
3669   return IPC_OK();
3670 }
3671 
3672 mozilla::plugins::PPluginWidgetParent*
AllocPPluginWidgetParent()3673 BrowserParent::AllocPPluginWidgetParent() {
3674 #ifdef XP_WIN
3675   return new mozilla::plugins::PluginWidgetParent();
3676 #else
3677   MOZ_ASSERT_UNREACHABLE("AllocPPluginWidgetParent only supports Windows");
3678   return nullptr;
3679 #endif
3680 }
3681 
DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent * aActor)3682 bool BrowserParent::DeallocPPluginWidgetParent(
3683     mozilla::plugins::PPluginWidgetParent* aActor) {
3684   delete aActor;
3685   return true;
3686 }
3687 
AllocPPaymentRequestParent()3688 PPaymentRequestParent* BrowserParent::AllocPPaymentRequestParent() {
3689   RefPtr<PaymentRequestParent> actor = new PaymentRequestParent();
3690   return actor.forget().take();
3691 }
3692 
DeallocPPaymentRequestParent(PPaymentRequestParent * aActor)3693 bool BrowserParent::DeallocPPaymentRequestParent(
3694     PPaymentRequestParent* aActor) {
3695   RefPtr<PaymentRequestParent> actor =
3696       dont_AddRef(static_cast<PaymentRequestParent*>(aActor));
3697   return true;
3698 }
3699 
HandleEvent(Event * aEvent)3700 nsresult BrowserParent::HandleEvent(Event* aEvent) {
3701   if (mIsDestroyed) {
3702     return NS_OK;
3703   }
3704 
3705   nsAutoString eventType;
3706   aEvent->GetType(eventType);
3707   if (eventType.EqualsLiteral("MozUpdateWindowPos") ||
3708       eventType.EqualsLiteral("fullscreenchange")) {
3709     // Events that signify the window moving are used to update the position
3710     // and notify the BrowserChild.
3711     return UpdatePosition();
3712   }
3713   return NS_OK;
3714 }
3715 
3716 class FakeChannel final : public nsIChannel,
3717                           public nsIAuthPromptCallback,
3718                           public nsIInterfaceRequestor,
3719                           public nsILoadContext {
3720  public:
FakeChannel(const nsCString & aUri,uint64_t aCallbackId,Element * aElement)3721   FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
3722       : mCallbackId(aCallbackId), mElement(aElement) {
3723     NS_NewURI(getter_AddRefs(mUri), aUri);
3724   }
3725 
3726   NS_DECL_ISUPPORTS
3727 
3728 #define NO_IMPL \
3729   override { return NS_ERROR_NOT_IMPLEMENTED; }
3730   NS_IMETHOD GetName(nsACString&) NO_IMPL;
3731   NS_IMETHOD IsPending(bool*) NO_IMPL;
3732   NS_IMETHOD GetStatus(nsresult*) NO_IMPL;
3733   NS_IMETHOD Cancel(nsresult) NO_IMPL;
3734   NS_IMETHOD GetCanceled(bool* aCanceled) NO_IMPL;
3735   NS_IMETHOD Suspend() NO_IMPL;
3736   NS_IMETHOD Resume() NO_IMPL;
3737   NS_IMETHOD GetLoadGroup(nsILoadGroup**) NO_IMPL;
3738   NS_IMETHOD SetLoadGroup(nsILoadGroup*) NO_IMPL;
3739   NS_IMETHOD SetLoadFlags(nsLoadFlags) NO_IMPL;
3740   NS_IMETHOD GetLoadFlags(nsLoadFlags*) NO_IMPL;
3741   NS_IMETHOD GetTRRMode(nsIRequest::TRRMode* aTRRMode) NO_IMPL;
3742   NS_IMETHOD SetTRRMode(nsIRequest::TRRMode aMode) NO_IMPL;
3743   NS_IMETHOD GetIsDocument(bool*) NO_IMPL;
3744   NS_IMETHOD GetOriginalURI(nsIURI**) NO_IMPL;
3745   NS_IMETHOD SetOriginalURI(nsIURI*) NO_IMPL;
GetURI(nsIURI ** aUri)3746   NS_IMETHOD GetURI(nsIURI** aUri) override {
3747     nsCOMPtr<nsIURI> copy = mUri;
3748     copy.forget(aUri);
3749     return NS_OK;
3750   }
3751   NS_IMETHOD GetOwner(nsISupports**) NO_IMPL;
3752   NS_IMETHOD SetOwner(nsISupports*) NO_IMPL;
GetLoadInfo(nsILoadInfo ** aLoadInfo)3753   NS_IMETHOD GetLoadInfo(nsILoadInfo** aLoadInfo) override {
3754     nsCOMPtr<nsILoadInfo> copy = mLoadInfo;
3755     copy.forget(aLoadInfo);
3756     return NS_OK;
3757   }
SetLoadInfo(nsILoadInfo * aLoadInfo)3758   NS_IMETHOD SetLoadInfo(nsILoadInfo* aLoadInfo) override {
3759     mLoadInfo = aLoadInfo;
3760     return NS_OK;
3761   }
GetNotificationCallbacks(nsIInterfaceRequestor ** aRequestor)3762   NS_IMETHOD GetNotificationCallbacks(
3763       nsIInterfaceRequestor** aRequestor) override {
3764     NS_ADDREF(*aRequestor = this);
3765     return NS_OK;
3766   }
3767   NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor*) NO_IMPL;
3768   NS_IMETHOD GetSecurityInfo(nsISupports**) NO_IMPL;
3769   NS_IMETHOD GetContentType(nsACString&) NO_IMPL;
3770   NS_IMETHOD SetContentType(const nsACString&) NO_IMPL;
3771   NS_IMETHOD GetContentCharset(nsACString&) NO_IMPL;
3772   NS_IMETHOD SetContentCharset(const nsACString&) NO_IMPL;
3773   NS_IMETHOD GetContentLength(int64_t*) NO_IMPL;
3774   NS_IMETHOD SetContentLength(int64_t) NO_IMPL;
3775   NS_IMETHOD Open(nsIInputStream**) NO_IMPL;
3776   NS_IMETHOD AsyncOpen(nsIStreamListener*) NO_IMPL;
3777   NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL;
3778   NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL;
3779   NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL;
3780   NS_IMETHOD SetContentDispositionFilename(const nsAString&) NO_IMPL;
3781   NS_IMETHOD GetContentDispositionHeader(nsACString&) NO_IMPL;
3782   NS_IMETHOD OnAuthAvailable(nsISupports* aContext,
3783                              nsIAuthInformation* aAuthInfo) override;
3784   NS_IMETHOD OnAuthCancelled(nsISupports* aContext, bool userCancel) override;
GetInterface(const nsIID & uuid,void ** result)3785   NS_IMETHOD GetInterface(const nsIID& uuid, void** result) override {
3786     return QueryInterface(uuid, result);
3787   }
3788   NS_IMETHOD GetAssociatedWindow(mozIDOMWindowProxy**) NO_IMPL;
3789   NS_IMETHOD GetTopWindow(mozIDOMWindowProxy**) NO_IMPL;
GetTopFrameElement(Element ** aElement)3790   NS_IMETHOD GetTopFrameElement(Element** aElement) override {
3791     RefPtr<Element> elem = mElement;
3792     elem.forget(aElement);
3793     return NS_OK;
3794   }
3795   NS_IMETHOD GetIsContent(bool*) NO_IMPL;
3796   NS_IMETHOD GetUsePrivateBrowsing(bool*) NO_IMPL;
3797   NS_IMETHOD SetUsePrivateBrowsing(bool) NO_IMPL;
3798   NS_IMETHOD SetPrivateBrowsing(bool) NO_IMPL;
3799   NS_IMETHOD GetScriptableOriginAttributes(JSContext*,
3800                                            JS::MutableHandleValue) NO_IMPL;
3801   NS_IMETHOD_(void)
GetOriginAttributes(mozilla::OriginAttributes & aAttrs)3802   GetOriginAttributes(mozilla::OriginAttributes& aAttrs) override {}
3803   NS_IMETHOD GetUseRemoteTabs(bool*) NO_IMPL;
3804   NS_IMETHOD SetRemoteTabs(bool) NO_IMPL;
3805   NS_IMETHOD GetUseRemoteSubframes(bool*) NO_IMPL;
3806   NS_IMETHOD SetRemoteSubframes(bool) NO_IMPL;
3807   NS_IMETHOD GetUseTrackingProtection(bool*) NO_IMPL;
3808   NS_IMETHOD SetUseTrackingProtection(bool) NO_IMPL;
3809 #undef NO_IMPL
3810 
3811  protected:
3812   ~FakeChannel() = default;
3813 
3814   nsCOMPtr<nsIURI> mUri;
3815   uint64_t mCallbackId;
3816   RefPtr<Element> mElement;
3817   nsCOMPtr<nsILoadInfo> mLoadInfo;
3818 };
3819 
3820 NS_IMPL_ISUPPORTS(FakeChannel, nsIChannel, nsIAuthPromptCallback, nsIRequest,
3821                   nsIInterfaceRequestor, nsILoadContext);
3822 
RecvAsyncAuthPrompt(const nsCString & aUri,const nsString & aRealm,const uint64_t & aCallbackId)3823 mozilla::ipc::IPCResult BrowserParent::RecvAsyncAuthPrompt(
3824     const nsCString& aUri, const nsString& aRealm,
3825     const uint64_t& aCallbackId) {
3826   nsCOMPtr<nsIAuthPrompt2> authPrompt;
3827   GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
3828                 NS_GET_IID(nsIAuthPrompt2), getter_AddRefs(authPrompt));
3829   RefPtr<FakeChannel> channel =
3830       new FakeChannel(aUri, aCallbackId, mFrameElement);
3831   uint32_t promptFlags = nsIAuthInformation::AUTH_HOST;
3832 
3833   RefPtr<nsAuthInformationHolder> holder =
3834       new nsAuthInformationHolder(promptFlags, aRealm, EmptyCString());
3835 
3836   uint32_t level = nsIAuthPrompt2::LEVEL_NONE;
3837   nsCOMPtr<nsICancelable> dummy;
3838   nsresult rv = authPrompt->AsyncPromptAuth(channel, channel, nullptr, level,
3839                                             holder, getter_AddRefs(dummy));
3840 
3841   if (NS_FAILED(rv)) {
3842     return IPC_FAIL_NO_REASON(this);
3843   }
3844   return IPC_OK();
3845 }
3846 
RecvInvokeDragSession(nsTArray<IPCDataTransfer> && aTransfers,const uint32_t & aAction,Maybe<Shmem> && aVisualDnDData,const uint32_t & aStride,const gfx::SurfaceFormat & aFormat,const LayoutDeviceIntRect & aDragRect,nsIPrincipal * aPrincipal,nsIContentSecurityPolicy * aCsp)3847 mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
3848     nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction,
3849     Maybe<Shmem>&& aVisualDnDData, const uint32_t& aStride,
3850     const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect,
3851     nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp) {
3852   PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell();
3853   if (!presShell) {
3854     Unused << Manager()->SendEndDragSession(true, true, LayoutDeviceIntPoint(),
3855                                             0);
3856     // Continue sending input events with input priority when stopping the dnd
3857     // session.
3858     Manager()->SetInputPriorityEventEnabled(true);
3859     return IPC_OK();
3860   }
3861 
3862   RefPtr<RemoteDragStartData> dragStartData = new RemoteDragStartData(
3863       this, std::move(aTransfers), aDragRect, aPrincipal, aCsp);
3864 
3865   if (!aVisualDnDData.isNothing() && aVisualDnDData.ref().IsReadable() &&
3866       aVisualDnDData.ref().Size<char>() >= aDragRect.height * aStride) {
3867     dragStartData->SetVisualization(gfx::CreateDataSourceSurfaceFromData(
3868         gfx::IntSize(aDragRect.width, aDragRect.height), aFormat,
3869         aVisualDnDData.ref().get<uint8_t>(), aStride));
3870   }
3871 
3872   nsCOMPtr<nsIDragService> dragService =
3873       do_GetService("@mozilla.org/widget/dragservice;1");
3874   if (dragService) {
3875     dragService->MaybeAddChildProcess(Manager());
3876   }
3877 
3878   presShell->GetPresContext()
3879       ->EventStateManager()
3880       ->BeginTrackingRemoteDragGesture(mFrameElement, dragStartData);
3881 
3882   if (aVisualDnDData.isSome()) {
3883     Unused << DeallocShmem(aVisualDnDData.ref());
3884   }
3885 
3886   return IPC_OK();
3887 }
3888 
AsyncPanZoomEnabled() const3889 bool BrowserParent::AsyncPanZoomEnabled() const {
3890   nsCOMPtr<nsIWidget> widget = GetWidget();
3891   return widget && widget->AsyncPanZoomEnabled();
3892 }
3893 
StartPersistence(CanonicalBrowsingContext * aContext,nsIWebBrowserPersistDocumentReceiver * aRecv,ErrorResult & aRv)3894 void BrowserParent::StartPersistence(
3895     CanonicalBrowsingContext* aContext,
3896     nsIWebBrowserPersistDocumentReceiver* aRecv, ErrorResult& aRv) {
3897   auto* actor = new WebBrowserPersistDocumentParent();
3898   actor->SetOnReady(aRecv);
3899   bool ok = Manager()->SendPWebBrowserPersistDocumentConstructor(actor, this,
3900                                                                  aContext);
3901   if (!ok) {
3902     aRv.Throw(NS_ERROR_FAILURE);
3903   }
3904   // (The actor will be destroyed on constructor failure.)
3905 }
3906 
RecvLookUpDictionary(const nsString & aText,nsTArray<FontRange> && aFontRangeArray,const bool & aIsVertical,const LayoutDeviceIntPoint & aPoint)3907 mozilla::ipc::IPCResult BrowserParent::RecvLookUpDictionary(
3908     const nsString& aText, nsTArray<FontRange>&& aFontRangeArray,
3909     const bool& aIsVertical, const LayoutDeviceIntPoint& aPoint) {
3910   nsCOMPtr<nsIWidget> widget = GetWidget();
3911   if (!widget) {
3912     return IPC_OK();
3913   }
3914 
3915   widget->LookUpDictionary(aText, aFontRangeArray, aIsVertical,
3916                            TransformChildToParent(aPoint));
3917   return IPC_OK();
3918 }
3919 
RecvShowCanvasPermissionPrompt(const nsCString & aOrigin,const bool & aHideDoorHanger)3920 mozilla::ipc::IPCResult BrowserParent::RecvShowCanvasPermissionPrompt(
3921     const nsCString& aOrigin, const bool& aHideDoorHanger) {
3922   nsCOMPtr<nsIBrowser> browser =
3923       mFrameElement ? mFrameElement->AsBrowser() : nullptr;
3924   if (!browser) {
3925     // If the tab is being closed, the browser may not be available.
3926     // In this case we can ignore the request.
3927     return IPC_OK();
3928   }
3929   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
3930   if (!os) {
3931     return IPC_FAIL_NO_REASON(this);
3932   }
3933   nsresult rv = os->NotifyObservers(
3934       browser,
3935       aHideDoorHanger ? "canvas-permissions-prompt-hide-doorhanger"
3936                       : "canvas-permissions-prompt",
3937       NS_ConvertUTF8toUTF16(aOrigin).get());
3938   if (NS_FAILED(rv)) {
3939     return IPC_FAIL_NO_REASON(this);
3940   }
3941   return IPC_OK();
3942 }
3943 
RecvVisitURI(nsIURI * aURI,nsIURI * aLastVisitedURI,const uint32_t & aFlags)3944 mozilla::ipc::IPCResult BrowserParent::RecvVisitURI(nsIURI* aURI,
3945                                                     nsIURI* aLastVisitedURI,
3946                                                     const uint32_t& aFlags) {
3947   if (!aURI) {
3948     return IPC_FAIL_NO_REASON(this);
3949   }
3950   RefPtr<nsIWidget> widget = GetWidget();
3951   if (NS_WARN_IF(!widget)) {
3952     return IPC_OK();
3953   }
3954   nsCOMPtr<IHistory> history = services::GetHistoryService();
3955   if (history) {
3956     Unused << history->VisitURI(widget, aURI, aLastVisitedURI, aFlags);
3957   }
3958   return IPC_OK();
3959 }
3960 
RecvQueryVisitedState(const nsTArray<RefPtr<nsIURI>> && aURIs)3961 mozilla::ipc::IPCResult BrowserParent::RecvQueryVisitedState(
3962     const nsTArray<RefPtr<nsIURI>>&& aURIs) {
3963 #ifdef MOZ_ANDROID_HISTORY
3964   nsCOMPtr<IHistory> history = services::GetHistoryService();
3965   if (NS_WARN_IF(!history)) {
3966     return IPC_OK();
3967   }
3968   RefPtr<nsIWidget> widget = GetWidget();
3969   if (NS_WARN_IF(!widget)) {
3970     return IPC_OK();
3971   }
3972 
3973   for (size_t i = 0; i < aURIs.Length(); ++i) {
3974     if (!aURIs[i]) {
3975       return IPC_FAIL(this, "Received null URI");
3976     }
3977   }
3978 
3979   GeckoViewHistory* gvHistory = static_cast<GeckoViewHistory*>(history.get());
3980   gvHistory->QueryVisitedState(widget, std::move(aURIs));
3981 
3982   return IPC_OK();
3983 #else
3984   return IPC_FAIL(this, "QueryVisitedState is Android-only");
3985 #endif
3986 }
3987 
LiveResizeStarted()3988 void BrowserParent::LiveResizeStarted() { SuppressDisplayport(true); }
3989 
LiveResizeStopped()3990 void BrowserParent::LiveResizeStopped() { SuppressDisplayport(false); }
3991 
SetBrowserBridgeParent(BrowserBridgeParent * aBrowser)3992 void BrowserParent::SetBrowserBridgeParent(BrowserBridgeParent* aBrowser) {
3993   // We should either be clearing out our reference to a browser bridge, or not
3994   // have either a browser bridge, browser host, or owner content yet.
3995   MOZ_ASSERT(!aBrowser ||
3996              (!mBrowserBridgeParent && !mBrowserHost && !mFrameElement));
3997   mBrowserBridgeParent = aBrowser;
3998 }
3999 
SetBrowserHost(BrowserHost * aBrowser)4000 void BrowserParent::SetBrowserHost(BrowserHost* aBrowser) {
4001   // We should either be clearing out our reference to a browser host, or not
4002   // have either a browser bridge, browser host, or owner content yet.
4003   MOZ_ASSERT(!aBrowser ||
4004              (!mBrowserBridgeParent && !mBrowserHost && !mFrameElement));
4005   mBrowserHost = aBrowser;
4006 }
4007 
RecvSetSystemFont(const nsCString & aFontName)4008 mozilla::ipc::IPCResult BrowserParent::RecvSetSystemFont(
4009     const nsCString& aFontName) {
4010   nsCOMPtr<nsIWidget> widget = GetWidget();
4011   if (widget) {
4012     widget->SetSystemFont(aFontName);
4013   }
4014   return IPC_OK();
4015 }
4016 
RecvGetSystemFont(nsCString * aFontName)4017 mozilla::ipc::IPCResult BrowserParent::RecvGetSystemFont(nsCString* aFontName) {
4018   nsCOMPtr<nsIWidget> widget = GetWidget();
4019   if (widget) {
4020     widget->GetSystemFont(*aFontName);
4021   }
4022   return IPC_OK();
4023 }
4024 
RecvMaybeFireEmbedderLoadEvents(EmbedderElementEventType aFireEventAtEmbeddingElement)4025 mozilla::ipc::IPCResult BrowserParent::RecvMaybeFireEmbedderLoadEvents(
4026     EmbedderElementEventType aFireEventAtEmbeddingElement) {
4027   BrowserBridgeParent* bridge = GetBrowserBridgeParent();
4028   if (!bridge) {
4029     NS_WARNING("Received `load` event on unbridged BrowserParent!");
4030     return IPC_OK();
4031   }
4032 
4033   Unused << bridge->SendMaybeFireEmbedderLoadEvents(
4034       aFireEventAtEmbeddingElement);
4035   return IPC_OK();
4036 }
4037 
RecvScrollRectIntoView(const nsRect & aRect,const ScrollAxis & aVertical,const ScrollAxis & aHorizontal,const ScrollFlags & aScrollFlags,const int32_t & aAppUnitsPerDevPixel)4038 mozilla::ipc::IPCResult BrowserParent::RecvScrollRectIntoView(
4039     const nsRect& aRect, const ScrollAxis& aVertical,
4040     const ScrollAxis& aHorizontal, const ScrollFlags& aScrollFlags,
4041     const int32_t& aAppUnitsPerDevPixel) {
4042   BrowserBridgeParent* bridge = GetBrowserBridgeParent();
4043   if (!bridge || !bridge->CanSend()) {
4044     return IPC_OK();
4045   }
4046 
4047   Unused << bridge->SendScrollRectIntoView(aRect, aVertical, aHorizontal,
4048                                            aScrollFlags, aAppUnitsPerDevPixel);
4049   return IPC_OK();
4050 }
4051 
4052 NS_IMETHODIMP
OnAuthAvailable(nsISupports * aContext,nsIAuthInformation * aAuthInfo)4053 FakeChannel::OnAuthAvailable(nsISupports* aContext,
4054                              nsIAuthInformation* aAuthInfo) {
4055   nsAuthInformationHolder* holder =
4056       static_cast<nsAuthInformationHolder*>(aAuthInfo);
4057 
4058   if (!net::gNeckoChild->SendOnAuthAvailable(
4059           mCallbackId, holder->User(), holder->Password(), holder->Domain())) {
4060     return NS_ERROR_FAILURE;
4061   }
4062   return NS_OK;
4063 }
4064 
4065 NS_IMETHODIMP
OnAuthCancelled(nsISupports * aContext,bool userCancel)4066 FakeChannel::OnAuthCancelled(nsISupports* aContext, bool userCancel) {
4067   if (!net::gNeckoChild->SendOnAuthCancelled(mCallbackId, userCancel)) {
4068     return NS_ERROR_FAILURE;
4069   }
4070   return NS_OK;
4071 }
4072 
RecvIsWindowSupportingProtectedMedia(const uint64_t & aOuterWindowID,IsWindowSupportingProtectedMediaResolver && aResolve)4073 mozilla::ipc::IPCResult BrowserParent::RecvIsWindowSupportingProtectedMedia(
4074     const uint64_t& aOuterWindowID,
4075     IsWindowSupportingProtectedMediaResolver&& aResolve) {
4076 #ifdef XP_WIN
4077   bool isFxrWindow =
4078       FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID);
4079   aResolve(!isFxrWindow);
4080 #else
4081   MOZ_CRASH("Should only be called on Windows");
4082 #endif
4083 
4084   return IPC_OK();
4085 }
4086 
RecvIsWindowSupportingWebVR(const uint64_t & aOuterWindowID,IsWindowSupportingWebVRResolver && aResolve)4087 mozilla::ipc::IPCResult BrowserParent::RecvIsWindowSupportingWebVR(
4088     const uint64_t& aOuterWindowID,
4089     IsWindowSupportingWebVRResolver&& aResolve) {
4090 #ifdef XP_WIN
4091   bool isFxrWindow =
4092       FxRWindowManager::GetInstance()->IsFxRWindow(aOuterWindowID);
4093   aResolve(!isFxrWindow);
4094 #else
4095   aResolve(true);
4096 #endif
4097 
4098   return IPC_OK();
4099 }
4100 
4101 }  // namespace dom
4102 }  // namespace mozilla
4103