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