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