Line data Source code
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 "TabChild.h"
10 :
11 : #include "gfxPrefs.h"
12 : #ifdef ACCESSIBILITY
13 : #include "mozilla/a11y/DocAccessibleChild.h"
14 : #endif
15 : #include "Layers.h"
16 : #include "ContentChild.h"
17 : #include "TabParent.h"
18 : #include "mozilla/Preferences.h"
19 : #include "mozilla/BrowserElementParent.h"
20 : #include "mozilla/ClearOnShutdown.h"
21 : #include "mozilla/EventListenerManager.h"
22 : #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
23 : #include "mozilla/dom/PaymentRequestChild.h"
24 : #include "mozilla/dom/TelemetryScrollProbe.h"
25 : #include "mozilla/IMEStateManager.h"
26 : #include "mozilla/ipc/DocumentRendererChild.h"
27 : #include "mozilla/ipc/URIUtils.h"
28 : #include "mozilla/layers/APZChild.h"
29 : #include "mozilla/layers/APZCCallbackHelper.h"
30 : #include "mozilla/layers/APZCTreeManager.h"
31 : #include "mozilla/layers/APZCTreeManagerChild.h"
32 : #include "mozilla/layers/APZEventState.h"
33 : #include "mozilla/layers/ContentProcessController.h"
34 : #include "mozilla/layers/CompositorBridgeChild.h"
35 : #include "mozilla/layers/DoubleTapToZoom.h"
36 : #include "mozilla/layers/IAPZCTreeManager.h"
37 : #include "mozilla/layers/ImageBridgeChild.h"
38 : #include "mozilla/layers/InputAPZContext.h"
39 : #include "mozilla/layers/PLayerTransactionChild.h"
40 : #include "mozilla/layers/ShadowLayers.h"
41 : #include "mozilla/layers/WebRenderLayerManager.h"
42 : #include "mozilla/layout/RenderFrameChild.h"
43 : #include "mozilla/layout/RenderFrameParent.h"
44 : #include "mozilla/plugins/PPluginWidgetChild.h"
45 : #include "mozilla/LookAndFeel.h"
46 : #include "mozilla/MouseEvents.h"
47 : #include "mozilla/Move.h"
48 : #include "mozilla/PresShell.h"
49 : #include "mozilla/ProcessHangMonitor.h"
50 : #include "mozilla/ScopeExit.h"
51 : #include "mozilla/Services.h"
52 : #include "mozilla/StaticPtr.h"
53 : #include "mozilla/TextEvents.h"
54 : #include "mozilla/TouchEvents.h"
55 : #include "mozilla/Unused.h"
56 : #include "nsContentUtils.h"
57 : #include "nsCSSFrameConstructor.h"
58 : #include "nsDocShell.h"
59 : #include "nsEmbedCID.h"
60 : #include "nsGlobalWindow.h"
61 : #include <algorithm>
62 : #ifdef MOZ_CRASHREPORTER
63 : #include "nsExceptionHandler.h"
64 : #endif
65 : #include "nsFilePickerProxy.h"
66 : #include "mozilla/dom/Element.h"
67 : #include "nsGlobalWindow.h"
68 : #include "nsIBaseWindow.h"
69 : #include "nsIBrowserDOMWindow.h"
70 : #include "nsIDocumentInlines.h"
71 : #include "nsIDocShellTreeOwner.h"
72 : #include "nsIDOMChromeWindow.h"
73 : #include "nsIDOMDocument.h"
74 : #include "nsIDOMEvent.h"
75 : #include "nsIDOMWindow.h"
76 : #include "nsIDOMWindowUtils.h"
77 : #include "nsFocusManager.h"
78 : #include "EventStateManager.h"
79 : #include "nsIDocShell.h"
80 : #include "nsIFrame.h"
81 : #include "nsIURI.h"
82 : #include "nsIURIFixup.h"
83 : #include "nsCDefaultURIFixup.h"
84 : #include "nsIWebBrowser.h"
85 : #include "nsIWebBrowserFocus.h"
86 : #include "nsIWebBrowserSetup.h"
87 : #include "nsIWebProgress.h"
88 : #include "nsIXULRuntime.h"
89 : #include "nsPIDOMWindow.h"
90 : #include "nsPIWindowRoot.h"
91 : #include "nsLayoutUtils.h"
92 : #include "nsPrintfCString.h"
93 : #include "nsThreadUtils.h"
94 : #include "nsViewManager.h"
95 : #include "nsWeakReference.h"
96 : #include "nsWindowWatcher.h"
97 : #include "PermissionMessageUtils.h"
98 : #include "PuppetWidget.h"
99 : #include "StructuredCloneData.h"
100 : #include "nsViewportInfo.h"
101 : #include "nsILoadContext.h"
102 : #include "ipc/nsGUIEventIPC.h"
103 : #include "mozilla/gfx/Matrix.h"
104 : #include "UnitTransforms.h"
105 : #include "ClientLayerManager.h"
106 : #include "LayersLogging.h"
107 : #include "nsDOMClassInfoID.h"
108 : #include "nsColorPickerProxy.h"
109 : #include "nsContentPermissionHelper.h"
110 : #include "nsNetUtil.h"
111 : #include "nsIPermissionManager.h"
112 : #include "nsIURILoader.h"
113 : #include "nsIScriptError.h"
114 : #include "mozilla/EventForwards.h"
115 : #include "nsDeviceContext.h"
116 : #include "nsSandboxFlags.h"
117 : #include "FrameLayerBuilder.h"
118 : #include "VRManagerChild.h"
119 : #include "nsICommandParams.h"
120 : #include "nsISHistory.h"
121 : #include "nsQueryObject.h"
122 : #include "GroupedSHistory.h"
123 : #include "nsIHttpChannel.h"
124 : #include "mozilla/dom/DocGroup.h"
125 : #include "nsString.h"
126 : #include "nsISupportsPrimitives.h"
127 : #include "mozilla/Telemetry.h"
128 :
129 : #ifdef XP_WIN
130 : #include "mozilla/plugins/PluginWidgetChild.h"
131 : #endif
132 :
133 : #ifdef NS_PRINTING
134 : #include "nsIPrintSession.h"
135 : #include "nsIPrintSettings.h"
136 : #include "nsIPrintSettingsService.h"
137 : #include "nsIWebBrowserPrint.h"
138 : #endif
139 :
140 : #define BROWSER_ELEMENT_CHILD_SCRIPT \
141 : NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
142 :
143 : #define TABC_LOG(...)
144 : // #define TABC_LOG(...) printf_stderr("TABC: " __VA_ARGS__)
145 :
146 : using namespace mozilla;
147 : using namespace mozilla::dom;
148 : using namespace mozilla::dom::ipc;
149 : using namespace mozilla::dom::workers;
150 : using namespace mozilla::ipc;
151 : using namespace mozilla::layers;
152 : using namespace mozilla::layout;
153 : using namespace mozilla::docshell;
154 : using namespace mozilla::widget;
155 : using namespace mozilla::jsipc;
156 : using mozilla::layers::GeckoContentController;
157 :
158 0 : NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
159 0 : NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
160 : nsISHistoryListener,
161 : nsIPartialSHistoryListener,
162 : nsISupportsWeakReference)
163 :
164 : static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
165 :
166 : typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
167 : static TabChildMap* sTabChildren;
168 3 : StaticMutex sTabChildrenMutex;
169 :
170 1 : TabChildBase::TabChildBase()
171 1 : : mTabChildGlobal(nullptr)
172 : {
173 1 : mozilla::HoldJSObjects(this);
174 1 : }
175 :
176 0 : TabChildBase::~TabChildBase()
177 : {
178 0 : mAnonymousGlobalScopes.Clear();
179 0 : mozilla::DropJSObjects(this);
180 0 : }
181 :
182 : NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildBase)
183 :
184 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TabChildBase)
185 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChildGlobal)
186 0 : tmp->nsMessageManagerScriptExecutor::Unlink();
187 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebBrowserChrome)
188 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
189 :
190 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TabChildBase)
191 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChildGlobal)
192 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome)
193 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
194 :
195 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TabChildBase)
196 0 : tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
197 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
198 :
199 22 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
200 20 : NS_INTERFACE_MAP_ENTRY(nsISupports)
201 19 : NS_INTERFACE_MAP_END
202 :
203 208 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
204 198 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
205 :
206 : already_AddRefed<nsIDocument>
207 7 : TabChildBase::GetDocument() const
208 : {
209 14 : nsCOMPtr<nsIDOMDocument> domDoc;
210 7 : WebNavigation()->GetDocument(getter_AddRefs(domDoc));
211 14 : nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
212 14 : return doc.forget();
213 : }
214 :
215 : already_AddRefed<nsIPresShell>
216 2 : TabChildBase::GetPresShell() const
217 : {
218 4 : nsCOMPtr<nsIPresShell> result;
219 4 : if (nsCOMPtr<nsIDocument> doc = GetDocument()) {
220 2 : result = doc->GetShell();
221 : }
222 4 : return result.forget();
223 : }
224 :
225 : void
226 0 : TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
227 : const nsAString& aJSONData)
228 : {
229 0 : AutoSafeJSContext cx;
230 0 : JS::Rooted<JS::Value> json(cx, JS::NullValue());
231 0 : dom::ipc::StructuredCloneData data;
232 0 : if (JS_ParseJSON(cx,
233 0 : static_cast<const char16_t*>(aJSONData.BeginReading()),
234 : aJSONData.Length(),
235 : &json)) {
236 0 : ErrorResult rv;
237 0 : data.Write(cx, json, rv);
238 0 : if (NS_WARN_IF(rv.Failed())) {
239 0 : rv.SuppressException();
240 0 : return;
241 : }
242 : }
243 :
244 0 : JS::Rooted<JSObject*> kungFuDeathGrip(cx, GetGlobal());
245 : // Let the BrowserElementScrolling helper (if it exists) for this
246 : // content manipulate the frame state.
247 : RefPtr<nsFrameMessageManager> mm =
248 0 : static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
249 0 : mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
250 0 : aMessageName, false, &data, nullptr, nullptr, nullptr);
251 : }
252 :
253 : bool
254 0 : TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
255 : {
256 0 : MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
257 :
258 0 : if (aFrameMetrics.IsRootContent()) {
259 0 : if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
260 : // Guard against stale updates (updates meant for a pres shell which
261 : // has since been torn down and destroyed).
262 0 : if (aFrameMetrics.GetPresShellId() == shell->GetPresShellId()) {
263 0 : ProcessUpdateFrame(aFrameMetrics);
264 0 : return true;
265 : }
266 : }
267 : } else {
268 : // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
269 : // This requires special handling.
270 0 : FrameMetrics newSubFrameMetrics(aFrameMetrics);
271 0 : APZCCallbackHelper::UpdateSubFrame(newSubFrameMetrics);
272 0 : return true;
273 : }
274 0 : return true;
275 : }
276 :
277 : void
278 0 : TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
279 : {
280 0 : if (!mGlobal || !mTabChildGlobal) {
281 0 : return;
282 : }
283 :
284 0 : FrameMetrics newMetrics = aFrameMetrics;
285 0 : APZCCallbackHelper::UpdateRootFrame(newMetrics);
286 : }
287 :
288 : NS_IMETHODIMP
289 0 : ContentListener::HandleEvent(nsIDOMEvent* aEvent)
290 : {
291 0 : RemoteDOMEvent remoteEvent;
292 0 : remoteEvent.mEvent = do_QueryInterface(aEvent);
293 0 : NS_ENSURE_STATE(remoteEvent.mEvent);
294 0 : mTabChild->SendEvent(remoteEvent);
295 0 : return NS_OK;
296 : }
297 :
298 : class TabChild::DelayedDeleteRunnable final
299 : : public Runnable
300 : {
301 : RefPtr<TabChild> mTabChild;
302 :
303 : public:
304 0 : explicit DelayedDeleteRunnable(TabChild* aTabChild)
305 0 : : Runnable("TabChild::DelayedDeleteRunnable")
306 0 : , mTabChild(aTabChild)
307 : {
308 0 : MOZ_ASSERT(NS_IsMainThread());
309 0 : MOZ_ASSERT(aTabChild);
310 0 : }
311 :
312 : private:
313 0 : ~DelayedDeleteRunnable()
314 0 : {
315 0 : MOZ_ASSERT(NS_IsMainThread());
316 0 : MOZ_ASSERT(!mTabChild);
317 0 : }
318 :
319 : NS_IMETHOD
320 0 : Run() override
321 : {
322 0 : MOZ_ASSERT(NS_IsMainThread());
323 0 : MOZ_ASSERT(mTabChild);
324 :
325 : // Check in case ActorDestroy was called after RecvDestroy message.
326 0 : if (mTabChild->IPCOpen()) {
327 0 : Unused << PBrowserChild::Send__delete__(mTabChild);
328 : }
329 :
330 0 : mTabChild = nullptr;
331 0 : return NS_OK;
332 : }
333 : };
334 :
335 : namespace {
336 : std::map<TabId, RefPtr<TabChild>>&
337 7 : NestedTabChildMap()
338 : {
339 7 : MOZ_ASSERT(NS_IsMainThread());
340 7 : static std::map<TabId, RefPtr<TabChild>> sNestedTabChildMap;
341 7 : return sNestedTabChildMap;
342 : }
343 : } // namespace
344 :
345 : already_AddRefed<TabChild>
346 2 : TabChild::FindTabChild(const TabId& aTabId)
347 : {
348 2 : auto iter = NestedTabChildMap().find(aTabId);
349 2 : if (iter == NestedTabChildMap().end()) {
350 1 : return nullptr;
351 : }
352 2 : RefPtr<TabChild> tabChild = iter->second;
353 1 : return tabChild.forget();
354 : }
355 :
356 : /*static*/ already_AddRefed<TabChild>
357 1 : TabChild::Create(nsIContentChild* aManager,
358 : const TabId& aTabId,
359 : const TabId& aSameTabGroupAs,
360 : const TabContext &aContext,
361 : uint32_t aChromeFlags)
362 : {
363 2 : RefPtr<TabChild> groupChild = FindTabChild(aSameTabGroupAs);
364 1 : dom::TabGroup* group = groupChild ? groupChild->TabGroup() : nullptr;
365 : RefPtr<TabChild> iframe = new TabChild(aManager, aTabId, group,
366 2 : aContext, aChromeFlags);
367 2 : return iframe.forget();
368 : }
369 :
370 1 : TabChild::TabChild(nsIContentChild* aManager,
371 : const TabId& aTabId,
372 : dom::TabGroup* aTabGroup,
373 : const TabContext& aContext,
374 1 : uint32_t aChromeFlags)
375 : : TabContext(aContext)
376 : , mTabGroup(aTabGroup)
377 : , mRemoteFrame(nullptr)
378 : , mManager(aManager)
379 : , mChromeFlags(aChromeFlags)
380 : , mMaxTouchPoints(0)
381 : , mActiveSuppressDisplayport(0)
382 : , mLayersId(0)
383 : , mBeforeUnloadListeners(0)
384 : , mLayersConnected(true)
385 : , mDidFakeShow(false)
386 : , mNotified(false)
387 : , mTriedBrowserInit(false)
388 : , mOrientation(eScreenOrientation_PortraitPrimary)
389 : , mIgnoreKeyPressEvent(false)
390 : , mHasValidInnerSize(false)
391 : , mDestroyed(false)
392 : , mUniqueId(aTabId)
393 : , mDPI(0)
394 : , mRounding(0)
395 : , mDefaultScale(0)
396 : , mIsTransparent(false)
397 : , mIPCOpen(false)
398 : , mParentIsActive(false)
399 : , mDidSetRealShowInfo(false)
400 : , mDidLoadURLInit(false)
401 : , mAwaitingLA(false)
402 : , mSkipKeyPress(false)
403 : , mLayerObserverEpoch(0)
404 : #if defined(XP_WIN) && defined(ACCESSIBILITY)
405 : , mNativeWindowHandle(0)
406 : #endif
407 : #if defined(ACCESSIBILITY)
408 : , mTopLevelDocAccessibleChild(nullptr)
409 : #endif
410 : , mPendingDocShellIsActive(false)
411 : , mPendingDocShellPreserveLayers(false)
412 : , mPendingDocShellReceivedMessage(false)
413 : , mPendingDocShellBlockers(0)
414 1 : , mWidgetNativeData(0)
415 : {
416 2 : nsWeakPtr weakPtrThis(do_GetWeakReference(static_cast<nsITabChild*>(this))); // for capture by the lambda
417 4 : mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId,
418 0 : const nsTArray<TouchBehaviorFlags>& aFlags)
419 : {
420 0 : if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
421 0 : static_cast<TabChild*>(tabChild.get())->SetAllowedTouchBehavior(aInputBlockId, aFlags);
422 : }
423 1 : };
424 :
425 : // preloaded TabChild should not be added to child map
426 1 : if (mUniqueId) {
427 1 : MOZ_ASSERT(NestedTabChildMap().find(mUniqueId) == NestedTabChildMap().end());
428 1 : NestedTabChildMap()[mUniqueId] = this;
429 : }
430 1 : }
431 :
432 : bool
433 17 : TabChild::AsyncPanZoomEnabled() const
434 : {
435 : // This might get called by the TouchEvent::PrefEnabled code before we have
436 : // mCompositorOptions populated (bug 1370089). In that case we just assume
437 : // APZ is enabled because we're in a content process (because TabChild) and
438 : // APZ is probably going to be enabled here since e10s is enabled.
439 17 : return mCompositorOptions ? mCompositorOptions->UseAPZ() : true;
440 : }
441 :
442 : NS_IMETHODIMP
443 1 : TabChild::Observe(nsISupports *aSubject,
444 : const char *aTopic,
445 : const char16_t *aData)
446 : {
447 1 : if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
448 1 : if (AsyncPanZoomEnabled()) {
449 2 : nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
450 2 : nsCOMPtr<nsIDocument> doc(GetDocument());
451 :
452 1 : if (SameCOMIdentity(subject, doc)) {
453 2 : nsCOMPtr<nsIPresShell> shell(doc->GetShell());
454 1 : if (shell) {
455 1 : shell->SetIsFirstPaint(true);
456 : }
457 :
458 1 : APZCCallbackHelper::InitializeRootDisplayport(shell);
459 : }
460 : }
461 : }
462 :
463 1 : return NS_OK;
464 : }
465 :
466 : void
467 0 : TabChild::ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
468 : uint64_t aInputBlockId,
469 : bool aPreventDefault) const
470 : {
471 0 : if (mApzcTreeManager) {
472 0 : mApzcTreeManager->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
473 : }
474 0 : }
475 :
476 : void
477 0 : TabChild::SetTargetAPZC(uint64_t aInputBlockId,
478 : const nsTArray<ScrollableLayerGuid>& aTargets) const
479 : {
480 0 : if (mApzcTreeManager) {
481 0 : mApzcTreeManager->SetTargetAPZC(aInputBlockId, aTargets);
482 : }
483 0 : }
484 :
485 : void
486 0 : TabChild::SetAllowedTouchBehavior(uint64_t aInputBlockId,
487 : const nsTArray<TouchBehaviorFlags>& aTargets) const
488 : {
489 0 : if (mApzcTreeManager) {
490 0 : mApzcTreeManager->SetAllowedTouchBehavior(aInputBlockId, aTargets);
491 : }
492 0 : }
493 :
494 : bool
495 1 : TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
496 : const ViewID& aViewId,
497 : const Maybe<ZoomConstraints>& aConstraints)
498 : {
499 1 : if (!mApzcTreeManager) {
500 0 : return false;
501 : }
502 :
503 2 : ScrollableLayerGuid guid = ScrollableLayerGuid(mLayersId, aPresShellId, aViewId);
504 :
505 1 : mApzcTreeManager->UpdateZoomConstraints(guid, aConstraints);
506 1 : return true;
507 : }
508 :
509 : nsresult
510 1 : TabChild::Init()
511 : {
512 1 : if (!mTabGroup) {
513 1 : mTabGroup = TabGroup::GetFromActor(this);
514 : }
515 :
516 2 : nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
517 1 : if (!webBrowser) {
518 0 : NS_ERROR("Couldn't create a nsWebBrowser?");
519 0 : return NS_ERROR_FAILURE;
520 : }
521 :
522 1 : webBrowser->SetContainerWindow(this);
523 1 : webBrowser->SetOriginAttributes(OriginAttributesRef());
524 1 : mWebNav = do_QueryInterface(webBrowser);
525 1 : NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
526 :
527 2 : nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
528 1 : docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
529 :
530 2 : nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
531 1 : if (!baseWindow) {
532 0 : NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
533 0 : return NS_ERROR_FAILURE;
534 : }
535 :
536 2 : nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(this);
537 1 : mPuppetWidget = static_cast<PuppetWidget*>(widget.get());
538 1 : if (!mPuppetWidget) {
539 0 : NS_ERROR("couldn't create fake widget");
540 0 : return NS_ERROR_FAILURE;
541 : }
542 1 : mPuppetWidget->InfallibleCreate(
543 : nullptr, 0, // no parents
544 2 : LayoutDeviceIntRect(0, 0, 0, 0),
545 : nullptr // HandleWidgetEvent
546 1 : );
547 :
548 1 : baseWindow->InitWindow(0, mPuppetWidget, 0, 0, 0, 0);
549 1 : baseWindow->Create();
550 :
551 : // Set the tab context attributes then pass to docShell
552 1 : NotifyTabContextUpdated(false);
553 :
554 : // IPC uses a WebBrowser object for which DNS prefetching is turned off
555 : // by default. But here we really want it, so enable it explicitly
556 : nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup =
557 2 : do_QueryInterface(baseWindow);
558 1 : if (webBrowserSetup) {
559 1 : webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH,
560 1 : true);
561 : } else {
562 : NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping "
563 0 : "DNS prefetching enable step.");
564 : }
565 :
566 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
567 1 : MOZ_ASSERT(docShell);
568 :
569 2 : docShell->SetAffectPrivateSessionLifetime(
570 2 : mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME);
571 2 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(WebNavigation());
572 1 : MOZ_ASSERT(loadContext);
573 1 : loadContext->SetPrivateBrowsing(OriginAttributesRef().mPrivateBrowsingId > 0);
574 2 : loadContext->SetRemoteTabs(
575 2 : mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
576 :
577 : // Few lines before, baseWindow->Create() will end up creating a new
578 : // window root in nsGlobalWindow::SetDocShell.
579 : // Then this chrome event handler, will be inherited to inner windows.
580 : // We want to also set it to the docshell so that inner windows
581 : // and any code that has access to the docshell
582 : // can all listen to the same chrome event handler.
583 : // XXX: ideally, we would set a chrome event handler earlier,
584 : // and all windows, even the root one, will use the docshell one.
585 2 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
586 1 : NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
587 : nsCOMPtr<EventTarget> chromeHandler =
588 2 : do_QueryInterface(window->GetChromeEventHandler());
589 1 : docShell->SetChromeEventHandler(chromeHandler);
590 :
591 1 : if (window->GetCurrentInnerWindow()) {
592 0 : window->SetKeyboardIndicators(ShowAccelerators(), ShowFocusRings());
593 : } else {
594 : // Skip ShouldShowFocusRing check if no inner window is available
595 1 : window->SetInitialKeyboardIndicators(ShowAccelerators(), ShowFocusRings());
596 : }
597 :
598 : // Set prerender flag if necessary.
599 1 : if (mIsPrerendered) {
600 0 : docShell->SetIsPrerendered();
601 : }
602 :
603 1 : nsContentUtils::SetScrollbarsVisibility(window->GetDocShell(),
604 2 : !!(mChromeFlags & nsIWebBrowserChrome::CHROME_SCROLLBARS));
605 :
606 2 : nsWeakPtr weakPtrThis = do_GetWeakReference(static_cast<nsITabChild*>(this)); // for capture by the lambda
607 : ContentReceivedInputBlockCallback callback(
608 2 : [weakPtrThis](const ScrollableLayerGuid& aGuid,
609 : uint64_t aInputBlockId,
610 0 : bool aPreventDefault)
611 : {
612 0 : if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
613 0 : static_cast<TabChild*>(tabChild.get())->ContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
614 : }
615 2 : });
616 2 : mAPZEventState = new APZEventState(mPuppetWidget, Move(callback));
617 :
618 1 : mIPCOpen = true;
619 :
620 1 : if (GroupedSHistory::GroupedHistoryEnabled()) {
621 : // Set session history listener.
622 0 : nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
623 0 : if (!shistory) {
624 0 : return NS_ERROR_FAILURE;
625 : }
626 0 : mHistoryListener = new TabChildSHistoryListener(this);
627 0 : nsCOMPtr<nsISHistoryListener> listener(do_QueryObject(mHistoryListener));
628 0 : shistory->AddSHistoryListener(listener);
629 0 : nsCOMPtr<nsIPartialSHistoryListener> partialListener(do_QueryObject(mHistoryListener));
630 0 : shistory->SetPartialSHistoryListener(partialListener);
631 : }
632 :
633 1 : return NS_OK;
634 : }
635 :
636 : void
637 1 : TabChild::NotifyTabContextUpdated(bool aIsPreallocated)
638 : {
639 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
640 1 : MOZ_ASSERT(docShell);
641 :
642 1 : if (!docShell) {
643 0 : return;
644 : }
645 :
646 1 : UpdateFrameType();
647 :
648 1 : if (aIsPreallocated) {
649 0 : nsDocShell::Cast(docShell)->SetOriginAttributes(OriginAttributesRef());
650 : }
651 :
652 : // Set SANDBOXED_AUXILIARY_NAVIGATION flag if this is a receiver page.
653 1 : if (!PresentationURL().IsEmpty()) {
654 0 : docShell->SetSandboxFlags(SANDBOXED_AUXILIARY_NAVIGATION);
655 : }
656 : }
657 :
658 : void
659 1 : TabChild::UpdateFrameType()
660 : {
661 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
662 1 : MOZ_ASSERT(docShell);
663 :
664 : // TODO: Bug 1252794 - remove frameType from nsIDocShell.idl
665 2 : docShell->SetFrameType(IsMozBrowserElement() ? nsIDocShell::FRAME_TYPE_BROWSER :
666 2 : nsIDocShell::FRAME_TYPE_REGULAR);
667 1 : }
668 :
669 188 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
670 187 : NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
671 157 : NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
672 157 : NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
673 142 : NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
674 142 : NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
675 76 : NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
676 76 : NS_INTERFACE_MAP_ENTRY(nsITabChild)
677 26 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
678 26 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
679 22 : NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
680 20 : NS_INTERFACE_MAP_END_INHERITING(TabChildBase)
681 :
682 208 : NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
683 198 : NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
684 :
685 : NS_IMETHODIMP
686 2 : TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
687 : {
688 2 : return SetStatusWithContext(aStatusType,
689 6 : aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
690 : : EmptyString(),
691 4 : nullptr);
692 : }
693 :
694 : NS_IMETHODIMP
695 0 : TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
696 : {
697 0 : NS_WARNING("TabChild::GetWebBrowser not supported in TabChild");
698 :
699 0 : return NS_ERROR_NOT_IMPLEMENTED;
700 : }
701 :
702 : NS_IMETHODIMP
703 0 : TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
704 : {
705 0 : NS_WARNING("TabChild::SetWebBrowser not supported in TabChild");
706 :
707 0 : return NS_ERROR_NOT_IMPLEMENTED;
708 : }
709 :
710 : NS_IMETHODIMP
711 1 : TabChild::GetChromeFlags(uint32_t* aChromeFlags)
712 : {
713 1 : *aChromeFlags = mChromeFlags;
714 1 : return NS_OK;
715 : }
716 :
717 : NS_IMETHODIMP
718 0 : TabChild::SetChromeFlags(uint32_t aChromeFlags)
719 : {
720 0 : NS_WARNING("trying to SetChromeFlags from content process?");
721 :
722 0 : return NS_ERROR_NOT_IMPLEMENTED;
723 : }
724 :
725 : NS_IMETHODIMP
726 0 : TabChild::DestroyBrowserWindow()
727 : {
728 0 : NS_WARNING("TabChild::DestroyBrowserWindow not supported in TabChild");
729 :
730 0 : return NS_ERROR_NOT_IMPLEMENTED;
731 : }
732 :
733 : NS_IMETHODIMP
734 0 : TabChild::RemoteSizeShellTo(int32_t aWidth, int32_t aHeight,
735 : int32_t aShellItemWidth, int32_t aShellItemHeight)
736 : {
737 0 : nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
738 0 : nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(ourDocShell));
739 : int32_t width, height;
740 0 : docShellAsWin->GetSize(&width, &height);
741 :
742 0 : uint32_t flags = 0;
743 0 : if (width == aWidth) {
744 0 : flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
745 : }
746 :
747 0 : if (height == aHeight) {
748 0 : flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
749 : }
750 :
751 0 : bool sent = SendSizeShellTo(flags, aWidth, aHeight, aShellItemWidth, aShellItemHeight);
752 :
753 0 : return sent ? NS_OK : NS_ERROR_FAILURE;
754 : }
755 :
756 : NS_IMETHODIMP
757 0 : TabChild::RemoteDropLinks(uint32_t aLinksCount,
758 : nsIDroppedLinkItem** aLinks)
759 : {
760 0 : nsTArray<nsString> linksArray;
761 0 : nsresult rv = NS_OK;
762 0 : for (uint32_t i = 0; i < aLinksCount; i++) {
763 0 : nsString tmp;
764 0 : rv = aLinks[i]->GetUrl(tmp);
765 0 : if (NS_FAILED(rv)) {
766 0 : return rv;
767 : }
768 0 : linksArray.AppendElement(tmp);
769 :
770 0 : rv = aLinks[i]->GetName(tmp);
771 0 : if (NS_FAILED(rv)) {
772 0 : return rv;
773 : }
774 0 : linksArray.AppendElement(tmp);
775 :
776 0 : rv = aLinks[i]->GetType(tmp);
777 0 : if (NS_FAILED(rv)) {
778 0 : return rv;
779 : }
780 0 : linksArray.AppendElement(tmp);
781 : }
782 0 : bool sent = SendDropLinks(linksArray);
783 :
784 0 : return sent ? NS_OK : NS_ERROR_FAILURE;
785 : }
786 :
787 : NS_IMETHODIMP
788 0 : TabChild::SizeBrowserTo(int32_t aWidth, int32_t aHeight)
789 : {
790 0 : NS_WARNING("TabChild::SizeBrowserTo not supported in TabChild");
791 :
792 0 : return NS_ERROR_NOT_IMPLEMENTED;
793 : }
794 :
795 : NS_IMETHODIMP
796 0 : TabChild::ShowAsModal()
797 : {
798 0 : NS_WARNING("TabChild::ShowAsModal not supported in TabChild");
799 :
800 0 : return NS_ERROR_NOT_IMPLEMENTED;
801 : }
802 :
803 : NS_IMETHODIMP
804 0 : TabChild::IsWindowModal(bool* aRetVal)
805 : {
806 0 : *aRetVal = false;
807 0 : return NS_OK;
808 : }
809 :
810 : NS_IMETHODIMP
811 0 : TabChild::ExitModalEventLoop(nsresult aStatus)
812 : {
813 0 : NS_WARNING("TabChild::ExitModalEventLoop not supported in TabChild");
814 :
815 0 : return NS_ERROR_NOT_IMPLEMENTED;
816 : }
817 :
818 : NS_IMETHODIMP
819 2 : TabChild::SetStatusWithContext(uint32_t aStatusType,
820 : const nsAString& aStatusText,
821 : nsISupports* aStatusContext)
822 : {
823 : // We can only send the status after the ipc machinery is set up,
824 : // mRemoteFrame is a good indicator.
825 2 : if (mRemoteFrame)
826 2 : SendSetStatus(aStatusType, nsString(aStatusText));
827 2 : return NS_OK;
828 : }
829 :
830 : NS_IMETHODIMP
831 0 : TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
832 : int32_t aCx, int32_t aCy)
833 : {
834 : // The parent is in charge of the dimension changes. If JS code wants to
835 : // change the dimensions (moveTo, screenX, etc.) we send a message to the
836 : // parent about the new requested dimension, the parent does the resize/move
837 : // then send a message to the child to update itself. For APIs like screenX
838 : // this function is called with the current value for the non-changed values.
839 : // In a series of calls like window.screenX = 10; window.screenY = 10; for
840 : // the second call, since screenX is not yet updated we might accidentally
841 : // reset back screenX to it's old value. To avoid this if a parameter did not
842 : // change we want the parent to ignore its value.
843 : int32_t x, y, cx, cy;
844 0 : GetDimensions(aFlags, &x, &y, &cx, &cy);
845 :
846 0 : if (x == aX) {
847 0 : aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X;
848 : }
849 :
850 0 : if (y == aY) {
851 0 : aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y;
852 : }
853 :
854 0 : if (cx == aCx) {
855 0 : aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
856 : }
857 :
858 0 : if (cy == aCy) {
859 0 : aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
860 : }
861 :
862 0 : Unused << SendSetDimensions(aFlags, aX, aY, aCx, aCy);
863 :
864 0 : return NS_OK;
865 : }
866 :
867 : NS_IMETHODIMP
868 0 : TabChild::GetDimensions(uint32_t aFlags, int32_t* aX,
869 : int32_t* aY, int32_t* aCx, int32_t* aCy)
870 : {
871 0 : ScreenIntRect rect = GetOuterRect();
872 0 : if (aX) {
873 0 : *aX = rect.x;
874 : }
875 0 : if (aY) {
876 0 : *aY = rect.y;
877 : }
878 0 : if (aCx) {
879 0 : *aCx = rect.width;
880 : }
881 0 : if (aCy) {
882 0 : *aCy = rect.height;
883 : }
884 :
885 0 : return NS_OK;
886 : }
887 :
888 : NS_IMETHODIMP
889 0 : TabChild::SetFocus()
890 : {
891 0 : return NS_ERROR_NOT_IMPLEMENTED;
892 : }
893 :
894 : NS_IMETHODIMP
895 4 : TabChild::GetVisibility(bool* aVisibility)
896 : {
897 4 : *aVisibility = true;
898 4 : return NS_OK;
899 : }
900 :
901 : NS_IMETHODIMP
902 0 : TabChild::SetVisibility(bool aVisibility)
903 : {
904 : // should the platform support this? Bug 666365
905 0 : return NS_OK;
906 : }
907 :
908 : NS_IMETHODIMP
909 0 : TabChild::GetTitle(char16_t** aTitle)
910 : {
911 0 : NS_WARNING("TabChild::GetTitle not supported in TabChild");
912 :
913 0 : return NS_ERROR_NOT_IMPLEMENTED;
914 : }
915 :
916 : NS_IMETHODIMP
917 1 : TabChild::SetTitle(const char16_t* aTitle)
918 : {
919 : // JavaScript sends the "DOMTitleChanged" event to the parent
920 : // via the message manager.
921 1 : return NS_OK;
922 : }
923 :
924 : NS_IMETHODIMP
925 0 : TabChild::GetSiteWindow(void** aSiteWindow)
926 : {
927 0 : NS_WARNING("TabChild::GetSiteWindow not supported in TabChild");
928 :
929 0 : return NS_ERROR_NOT_IMPLEMENTED;
930 : }
931 :
932 : NS_IMETHODIMP
933 0 : TabChild::Blur()
934 : {
935 0 : return NS_ERROR_NOT_IMPLEMENTED;
936 : }
937 :
938 : NS_IMETHODIMP
939 0 : TabChild::FocusNextElement(bool aForDocumentNavigation)
940 : {
941 0 : SendMoveFocus(true, aForDocumentNavigation);
942 0 : return NS_OK;
943 : }
944 :
945 : NS_IMETHODIMP
946 0 : TabChild::FocusPrevElement(bool aForDocumentNavigation)
947 : {
948 0 : SendMoveFocus(false, aForDocumentNavigation);
949 0 : return NS_OK;
950 : }
951 :
952 : NS_IMETHODIMP
953 22 : TabChild::GetInterface(const nsIID & aIID, void **aSink)
954 : {
955 22 : if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome3))) {
956 2 : NS_IF_ADDREF(((nsISupports *) (*aSink = mWebBrowserChrome)));
957 2 : return NS_OK;
958 : }
959 :
960 : // XXXbz should we restrict the set of interfaces we hand out here?
961 : // See bug 537429
962 20 : return QueryInterface(aIID, aSink);
963 : }
964 :
965 : NS_IMETHODIMP
966 0 : TabChild::ProvideWindow(mozIDOMWindowProxy* aParent,
967 : uint32_t aChromeFlags,
968 : bool aCalledFromJS,
969 : bool aPositionSpecified, bool aSizeSpecified,
970 : nsIURI* aURI, const nsAString& aName,
971 : const nsACString& aFeatures, bool aForceNoOpener,
972 : bool* aWindowIsNew, mozIDOMWindowProxy** aReturn)
973 : {
974 0 : *aReturn = nullptr;
975 :
976 : // If aParent is inside an <iframe mozbrowser> and this isn't a request to
977 : // open a modal-type window, we're going to create a new <iframe mozbrowser>
978 : // and return its window here.
979 0 : nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
980 0 : bool iframeMoz = (docshell && docshell->GetIsInMozBrowser() &&
981 0 : !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
982 : nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
983 0 : nsIWebBrowserChrome::CHROME_OPENAS_CHROME)));
984 :
985 0 : if (!iframeMoz) {
986 : int32_t openLocation =
987 0 : nsWindowWatcher::GetWindowOpenLocation(nsPIDOMWindowOuter::From(aParent),
988 : aChromeFlags, aCalledFromJS,
989 0 : aPositionSpecified, aSizeSpecified);
990 :
991 : // If it turns out we're opening in the current browser, just hand over the
992 : // current browser's docshell.
993 0 : if (openLocation == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
994 0 : nsCOMPtr<nsIWebBrowser> browser = do_GetInterface(WebNavigation());
995 0 : *aWindowIsNew = false;
996 0 : return browser->GetContentDOMWindow(aReturn);
997 : }
998 : }
999 :
1000 : // Note that ProvideWindowCommon may return NS_ERROR_ABORT if the
1001 : // open window call was canceled. It's important that we pass this error
1002 : // code back to our caller.
1003 0 : ContentChild* cc = ContentChild::GetSingleton();
1004 0 : return cc->ProvideWindowCommon(this,
1005 : aParent,
1006 : iframeMoz,
1007 : aChromeFlags,
1008 : aCalledFromJS,
1009 : aPositionSpecified,
1010 : aSizeSpecified,
1011 : aURI,
1012 : aName,
1013 : aFeatures,
1014 : aForceNoOpener,
1015 : aWindowIsNew,
1016 0 : aReturn);
1017 : }
1018 :
1019 : void
1020 0 : TabChild::DestroyWindow()
1021 : {
1022 0 : nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
1023 0 : if (baseWindow)
1024 0 : baseWindow->Destroy();
1025 :
1026 : // NB: the order of mPuppetWidget->Destroy() and mRemoteFrame->Destroy()
1027 : // is important: we want to kill off remote layers before their
1028 : // frames
1029 0 : if (mPuppetWidget) {
1030 0 : mPuppetWidget->Destroy();
1031 : }
1032 :
1033 0 : if (mRemoteFrame) {
1034 0 : mRemoteFrame->Destroy();
1035 0 : mRemoteFrame = nullptr;
1036 : }
1037 :
1038 :
1039 0 : if (mLayersId != 0) {
1040 0 : StaticMutexAutoLock lock(sTabChildrenMutex);
1041 :
1042 0 : MOZ_ASSERT(sTabChildren);
1043 0 : sTabChildren->Remove(mLayersId);
1044 0 : if (!sTabChildren->Count()) {
1045 0 : delete sTabChildren;
1046 0 : sTabChildren = nullptr;
1047 : }
1048 0 : mLayersId = 0;
1049 : }
1050 0 : }
1051 :
1052 : void
1053 0 : TabChild::ActorDestroy(ActorDestroyReason why)
1054 : {
1055 0 : mIPCOpen = false;
1056 :
1057 0 : DestroyWindow();
1058 :
1059 0 : if (mTabChildGlobal) {
1060 : // We should have a message manager if the global is alive, but it
1061 : // seems sometimes we don't. Assert in aurora/nightly, but don't
1062 : // crash in release builds.
1063 0 : MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
1064 0 : if (mTabChildGlobal->mMessageManager) {
1065 : // The messageManager relays messages via the TabChild which
1066 : // no longer exists.
1067 : static_cast<nsFrameMessageManager*>
1068 0 : (mTabChildGlobal->mMessageManager.get())->Disconnect();
1069 0 : mTabChildGlobal->mMessageManager = nullptr;
1070 : }
1071 : }
1072 :
1073 0 : CompositorBridgeChild* compositorChild = static_cast<CompositorBridgeChild*>(CompositorBridgeChild::Get());
1074 0 : compositorChild->CancelNotifyAfterRemotePaint(this);
1075 :
1076 0 : if (GetTabId() != 0) {
1077 0 : NestedTabChildMap().erase(GetTabId());
1078 : }
1079 0 : }
1080 :
1081 0 : TabChild::~TabChild()
1082 : {
1083 0 : DestroyWindow();
1084 :
1085 0 : nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
1086 0 : if (webBrowser) {
1087 0 : webBrowser->SetContainerWindow(nullptr);
1088 : }
1089 :
1090 0 : if (mHistoryListener) {
1091 0 : mHistoryListener->ClearTabChild();
1092 : }
1093 0 : }
1094 :
1095 : mozilla::ipc::IPCResult
1096 1 : TabChild::RecvLoadURL(const nsCString& aURI,
1097 : const ShowInfo& aInfo)
1098 : {
1099 1 : if (!mDidLoadURLInit) {
1100 1 : mDidLoadURLInit = true;
1101 1 : if (!InitTabChildGlobal()) {
1102 0 : return IPC_FAIL_NO_REASON(this);
1103 : }
1104 :
1105 1 : ApplyShowInfo(aInfo);
1106 : }
1107 :
1108 : nsresult rv =
1109 3 : WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(aURI).get(),
1110 : nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
1111 : nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL,
1112 2 : nullptr, nullptr, nullptr, nsContentUtils::GetSystemPrincipal());
1113 1 : if (NS_FAILED(rv)) {
1114 0 : NS_WARNING("WebNavigation()->LoadURI failed. Eating exception, what else can I do?");
1115 : }
1116 :
1117 : #ifdef MOZ_CRASHREPORTER
1118 1 : CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), aURI);
1119 : #endif
1120 :
1121 1 : return IPC_OK();
1122 : }
1123 :
1124 : void
1125 0 : TabChild::DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
1126 : const uint64_t& aLayersId,
1127 : const CompositorOptions& aCompositorOptions,
1128 : PRenderFrameChild* aRenderFrame, const ShowInfo& aShowInfo)
1129 : {
1130 0 : InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions, aRenderFrame);
1131 0 : RecvShow(ScreenIntSize(0, 0), aShowInfo, mParentIsActive, nsSizeMode_Normal);
1132 0 : mDidFakeShow = true;
1133 0 : }
1134 :
1135 : void
1136 2 : TabChild::ApplyShowInfo(const ShowInfo& aInfo)
1137 : {
1138 2 : if (mDidSetRealShowInfo) {
1139 1 : return;
1140 : }
1141 :
1142 1 : if (!aInfo.fakeShowInfo()) {
1143 : // Once we've got one ShowInfo from parent, no need to update the values
1144 : // anymore.
1145 1 : mDidSetRealShowInfo = true;
1146 : }
1147 :
1148 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
1149 1 : if (docShell) {
1150 2 : nsCOMPtr<nsIDocShellTreeItem> item = do_GetInterface(docShell);
1151 1 : if (IsMozBrowser()) {
1152 : // B2G allows window.name to be set by changing the name attribute on the
1153 : // <iframe mozbrowser> element. window.open calls cause this attribute to
1154 : // be set to the correct value. A normal <xul:browser> element has no such
1155 : // attribute. The data we get here comes from reading the attribute, so we
1156 : // shouldn't trust it for <xul:browser> elements.
1157 0 : item->SetName(aInfo.name());
1158 : }
1159 1 : docShell->SetFullscreenAllowed(aInfo.fullscreenAllowed());
1160 1 : if (aInfo.isPrivate()) {
1161 0 : nsCOMPtr<nsILoadContext> context = do_GetInterface(docShell);
1162 : // No need to re-set private browsing mode.
1163 0 : if (!context->UsePrivateBrowsing()) {
1164 0 : if (docShell->GetHasLoadedNonBlankURI()) {
1165 0 : nsContentUtils::ReportToConsoleNonLocalized(
1166 0 : NS_LITERAL_STRING("We should not switch to Private Browsing after loading a document."),
1167 : nsIScriptError::warningFlag,
1168 0 : NS_LITERAL_CSTRING("mozprivatebrowsing"),
1169 0 : nullptr);
1170 : } else {
1171 0 : OriginAttributes attrs(nsDocShell::Cast(docShell)->GetOriginAttributes());
1172 0 : attrs.SyncAttributesWithPrivateBrowsing(true);
1173 0 : nsDocShell::Cast(docShell)->SetOriginAttributes(attrs);
1174 : }
1175 : }
1176 : }
1177 : }
1178 1 : mDPI = aInfo.dpi();
1179 1 : mRounding = aInfo.widgetRounding();
1180 1 : mDefaultScale = aInfo.defaultScale();
1181 1 : mIsTransparent = aInfo.isTransparent();
1182 : }
1183 :
1184 : mozilla::ipc::IPCResult
1185 1 : TabChild::RecvShow(const ScreenIntSize& aSize,
1186 : const ShowInfo& aInfo,
1187 : const bool& aParentIsActive,
1188 : const nsSizeMode& aSizeMode)
1189 : {
1190 1 : bool res = true;
1191 :
1192 1 : mPuppetWidget->SetSizeMode(aSizeMode);
1193 1 : if (!mDidFakeShow) {
1194 2 : nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
1195 1 : if (!baseWindow) {
1196 0 : NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
1197 0 : return IPC_FAIL_NO_REASON(this);
1198 : }
1199 :
1200 1 : baseWindow->SetVisibility(true);
1201 1 : res = InitTabChildGlobal();
1202 : }
1203 :
1204 1 : ApplyShowInfo(aInfo);
1205 1 : RecvParentActivated(aParentIsActive);
1206 :
1207 1 : if (!res) {
1208 0 : return IPC_FAIL_NO_REASON(this);
1209 : }
1210 1 : return IPC_OK();
1211 : }
1212 :
1213 : mozilla::ipc::IPCResult
1214 1 : TabChild::RecvInitRendering(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
1215 : const uint64_t& aLayersId,
1216 : const CompositorOptions& aCompositorOptions,
1217 : const bool& aLayersConnected,
1218 : PRenderFrameChild* aRenderFrame)
1219 : {
1220 1 : MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame));
1221 :
1222 1 : mLayersConnected = aLayersConnected;
1223 1 : InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions, aRenderFrame);
1224 1 : return IPC_OK();
1225 : }
1226 :
1227 : mozilla::ipc::IPCResult
1228 3 : TabChild::RecvUpdateDimensions(const DimensionInfo& aDimensionInfo)
1229 : {
1230 3 : if (!mRemoteFrame) {
1231 0 : return IPC_OK();
1232 : }
1233 :
1234 3 : mUnscaledOuterRect = aDimensionInfo.rect();
1235 3 : mClientOffset = aDimensionInfo.clientOffset();
1236 3 : mChromeDisp = aDimensionInfo.chromeDisp();
1237 :
1238 3 : mOrientation = aDimensionInfo.orientation();
1239 3 : SetUnscaledInnerSize(aDimensionInfo.size());
1240 7 : if (!mHasValidInnerSize &&
1241 4 : aDimensionInfo.size().width != 0 &&
1242 1 : aDimensionInfo.size().height != 0) {
1243 1 : mHasValidInnerSize = true;
1244 : }
1245 :
1246 3 : ScreenIntSize screenSize = GetInnerSize();
1247 3 : ScreenIntRect screenRect = GetOuterRect();
1248 :
1249 : // Set the size on the document viewer before we update the widget and
1250 : // trigger a reflow. Otherwise the MobileViewportManager reads the stale
1251 : // size from the content viewer when it computes a new CSS viewport.
1252 6 : nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
1253 6 : baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
1254 6 : nsIBaseWindow::eRepaint);
1255 :
1256 12 : mPuppetWidget->Resize(screenRect.x + mClientOffset.x + mChromeDisp.x,
1257 3 : screenRect.y + mClientOffset.y + mChromeDisp.y,
1258 9 : screenSize.width, screenSize.height, true);
1259 :
1260 3 : return IPC_OK();
1261 : }
1262 :
1263 : mozilla::ipc::IPCResult
1264 1 : TabChild::RecvSizeModeChanged(const nsSizeMode& aSizeMode)
1265 : {
1266 1 : mPuppetWidget->SetSizeMode(aSizeMode);
1267 1 : if (!mPuppetWidget->IsVisible()) {
1268 0 : return IPC_OK();
1269 : }
1270 2 : nsCOMPtr<nsIDocument> document(GetDocument());
1271 2 : nsCOMPtr<nsIPresShell> presShell = document->GetShell();
1272 1 : if (presShell) {
1273 1 : nsPresContext* presContext = presShell->GetPresContext();
1274 1 : if (presContext) {
1275 1 : presContext->SizeModeChanged(aSizeMode);
1276 : }
1277 : }
1278 1 : return IPC_OK();
1279 : }
1280 :
1281 : bool
1282 0 : TabChild::UpdateFrame(const FrameMetrics& aFrameMetrics)
1283 : {
1284 0 : return TabChildBase::UpdateFrameHandler(aFrameMetrics);
1285 : }
1286 :
1287 : mozilla::ipc::IPCResult
1288 0 : TabChild::RecvSuppressDisplayport(const bool& aEnabled)
1289 : {
1290 0 : if (aEnabled) {
1291 0 : mActiveSuppressDisplayport++;
1292 : } else {
1293 0 : mActiveSuppressDisplayport--;
1294 : }
1295 :
1296 0 : MOZ_ASSERT(mActiveSuppressDisplayport >= 0);
1297 0 : APZCCallbackHelper::SuppressDisplayport(aEnabled, GetPresShell());
1298 0 : return IPC_OK();
1299 : }
1300 :
1301 : void
1302 0 : TabChild::HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
1303 : const ScrollableLayerGuid& aGuid)
1304 : {
1305 : TABC_LOG("Handling double tap at %s with %p %p\n",
1306 : Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
1307 :
1308 0 : if (!mGlobal || !mTabChildGlobal) {
1309 0 : return;
1310 : }
1311 :
1312 : // Note: there is nothing to do with the modifiers here, as we are not
1313 : // synthesizing any sort of mouse event.
1314 0 : nsCOMPtr<nsIDocument> document = GetDocument();
1315 0 : CSSRect zoomToRect = CalculateRectToZoomTo(document, aPoint);
1316 : // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
1317 : // the guid of any scroll frame), but the zoom-to-rect operation must be
1318 : // performed by the root content scroll frame, so query its identifiers
1319 : // for the SendZoomToRect() call rather than using the ones from |aGuid|.
1320 : uint32_t presShellId;
1321 : ViewID viewId;
1322 0 : if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
1323 0 : document->GetDocumentElement(), &presShellId, &viewId) && mApzcTreeManager) {
1324 0 : ScrollableLayerGuid guid(mLayersId, presShellId, viewId);
1325 :
1326 0 : mApzcTreeManager->ZoomToRect(guid, zoomToRect, DEFAULT_BEHAVIOR);
1327 : }
1328 : }
1329 :
1330 : mozilla::ipc::IPCResult
1331 0 : TabChild::RecvHandleTap(const GeckoContentController::TapType& aType,
1332 : const LayoutDevicePoint& aPoint,
1333 : const Modifiers& aModifiers,
1334 : const ScrollableLayerGuid& aGuid,
1335 : const uint64_t& aInputBlockId)
1336 : {
1337 0 : nsCOMPtr<nsIPresShell> presShell = GetPresShell();
1338 0 : if (!presShell) {
1339 0 : return IPC_OK();
1340 : }
1341 0 : if (!presShell->GetPresContext()) {
1342 0 : return IPC_OK();
1343 : }
1344 0 : CSSToLayoutDeviceScale scale(presShell->GetPresContext()->CSSToDevPixelScale());
1345 0 : CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint / scale, aGuid);
1346 :
1347 0 : switch (aType) {
1348 : case GeckoContentController::TapType::eSingleTap:
1349 0 : if (mGlobal && mTabChildGlobal) {
1350 0 : mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 1);
1351 : }
1352 0 : break;
1353 : case GeckoContentController::TapType::eDoubleTap:
1354 0 : HandleDoubleTap(point, aModifiers, aGuid);
1355 0 : break;
1356 : case GeckoContentController::TapType::eSecondTap:
1357 0 : if (mGlobal && mTabChildGlobal) {
1358 0 : mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 2);
1359 : }
1360 0 : break;
1361 : case GeckoContentController::TapType::eLongTap:
1362 0 : if (mGlobal && mTabChildGlobal) {
1363 0 : mAPZEventState->ProcessLongTap(presShell, point, scale, aModifiers, aGuid,
1364 0 : aInputBlockId);
1365 : }
1366 0 : break;
1367 : case GeckoContentController::TapType::eLongTapUp:
1368 0 : if (mGlobal && mTabChildGlobal) {
1369 0 : mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
1370 : }
1371 0 : break;
1372 : }
1373 0 : return IPC_OK();
1374 : }
1375 :
1376 : bool
1377 0 : TabChild::NotifyAPZStateChange(const ViewID& aViewId,
1378 : const layers::GeckoContentController::APZStateChange& aChange,
1379 : const int& aArg)
1380 : {
1381 0 : mAPZEventState->ProcessAPZStateChange(aViewId, aChange, aArg);
1382 0 : if (aChange == layers::GeckoContentController::APZStateChange::eTransformEnd) {
1383 : // This is used by tests to determine when the APZ is done doing whatever
1384 : // it's doing. XXX generify this as needed when writing additional tests.
1385 0 : nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
1386 0 : observerService->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
1387 : }
1388 0 : return true;
1389 : }
1390 :
1391 : void
1392 0 : TabChild::StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics)
1393 : {
1394 0 : ScrollableLayerGuid guid(mLayersId, aDragMetrics.mPresShellId,
1395 0 : aDragMetrics.mViewId);
1396 :
1397 0 : if (mApzcTreeManager) {
1398 0 : mApzcTreeManager->StartScrollbarDrag(guid, aDragMetrics);
1399 : }
1400 0 : }
1401 :
1402 : void
1403 0 : TabChild::ZoomToRect(const uint32_t& aPresShellId,
1404 : const FrameMetrics::ViewID& aViewId,
1405 : const CSSRect& aRect,
1406 : const uint32_t& aFlags)
1407 : {
1408 0 : ScrollableLayerGuid guid(mLayersId, aPresShellId, aViewId);
1409 :
1410 0 : if (mApzcTreeManager) {
1411 0 : mApzcTreeManager->ZoomToRect(guid, aRect, aFlags);
1412 : }
1413 0 : }
1414 :
1415 : mozilla::ipc::IPCResult
1416 1 : TabChild::RecvActivate()
1417 : {
1418 2 : nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
1419 1 : browser->Activate();
1420 2 : return IPC_OK();
1421 : }
1422 :
1423 : mozilla::ipc::IPCResult
1424 0 : TabChild::RecvDeactivate()
1425 : {
1426 0 : nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
1427 0 : browser->Deactivate();
1428 0 : return IPC_OK();
1429 : }
1430 :
1431 : mozilla::ipc::IPCResult
1432 2 : TabChild::RecvParentActivated(const bool& aActivated)
1433 : {
1434 2 : mParentIsActive = aActivated;
1435 :
1436 2 : nsFocusManager* fm = nsFocusManager::GetFocusManager();
1437 2 : NS_ENSURE_TRUE(fm, IPC_OK());
1438 :
1439 4 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
1440 2 : fm->ParentActivated(window, aActivated);
1441 2 : return IPC_OK();
1442 : }
1443 :
1444 : mozilla::ipc::IPCResult
1445 0 : TabChild::RecvSetKeyboardIndicators(const UIStateChangeType& aShowAccelerators,
1446 : const UIStateChangeType& aShowFocusRings)
1447 : {
1448 0 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
1449 0 : NS_ENSURE_TRUE(window, IPC_OK());
1450 :
1451 0 : window->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
1452 0 : return IPC_OK();
1453 : }
1454 :
1455 : mozilla::ipc::IPCResult
1456 0 : TabChild::RecvStopIMEStateManagement()
1457 : {
1458 0 : IMEStateManager::StopIMEStateManagement();
1459 0 : return IPC_OK();
1460 : }
1461 :
1462 : mozilla::ipc::IPCResult
1463 0 : TabChild::RecvMenuKeyboardListenerInstalled(const bool& aInstalled)
1464 : {
1465 0 : IMEStateManager::OnInstalledMenuKeyboardListener(aInstalled);
1466 0 : return IPC_OK();
1467 : }
1468 :
1469 : mozilla::ipc::IPCResult
1470 0 : TabChild::RecvNotifyAttachGroupedSHistory(const uint32_t& aOffset)
1471 : {
1472 : // nsISHistory uses int32_t
1473 0 : if (NS_WARN_IF(aOffset > INT32_MAX)) {
1474 0 : return IPC_FAIL_NO_REASON(this);
1475 : }
1476 :
1477 0 : nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
1478 0 : NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
1479 :
1480 0 : if (NS_FAILED(shistory->OnAttachGroupedSHistory(aOffset))) {
1481 0 : return IPC_FAIL_NO_REASON(this);
1482 : }
1483 0 : return IPC_OK();
1484 : }
1485 :
1486 : mozilla::ipc::IPCResult
1487 0 : TabChild::RecvNotifyPartialSHistoryActive(const uint32_t& aGlobalLength,
1488 : const uint32_t& aTargetLocalIndex)
1489 : {
1490 : // nsISHistory uses int32_t
1491 0 : if (NS_WARN_IF(aGlobalLength > INT32_MAX || aTargetLocalIndex > INT32_MAX)) {
1492 0 : return IPC_FAIL_NO_REASON(this);
1493 : }
1494 :
1495 0 : nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
1496 0 : NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
1497 :
1498 0 : if (NS_FAILED(shistory->OnPartialSHistoryActive(aGlobalLength,
1499 : aTargetLocalIndex))) {
1500 0 : return IPC_FAIL_NO_REASON(this);
1501 : }
1502 0 : return IPC_OK();
1503 : }
1504 :
1505 : mozilla::ipc::IPCResult
1506 0 : TabChild::RecvNotifyPartialSHistoryDeactive()
1507 : {
1508 0 : nsCOMPtr<nsISHistory> shistory = GetRelatedSHistory();
1509 0 : NS_ENSURE_TRUE(shistory, IPC_FAIL_NO_REASON(this));
1510 :
1511 0 : if (NS_FAILED(shistory->OnPartialSHistoryDeactive())) {
1512 0 : return IPC_FAIL_NO_REASON(this);
1513 : }
1514 0 : return IPC_OK();
1515 : }
1516 :
1517 : mozilla::ipc::IPCResult
1518 0 : TabChild::RecvMouseEvent(const nsString& aType,
1519 : const float& aX,
1520 : const float& aY,
1521 : const int32_t& aButton,
1522 : const int32_t& aClickCount,
1523 : const int32_t& aModifiers,
1524 : const bool& aIgnoreRootScrollFrame)
1525 : {
1526 0 : APZCCallbackHelper::DispatchMouseEvent(GetPresShell(), aType,
1527 0 : CSSPoint(aX, aY), aButton, aClickCount,
1528 0 : aModifiers, aIgnoreRootScrollFrame,
1529 : nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN,
1530 0 : 0 /* Use the default value here. */);
1531 0 : return IPC_OK();
1532 : }
1533 :
1534 : mozilla::ipc::IPCResult
1535 4 : TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& aEvent,
1536 : const ScrollableLayerGuid& aGuid,
1537 : const uint64_t& aInputBlockId)
1538 : {
1539 4 : if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
1540 0 : return IPC_FAIL_NO_REASON(this);
1541 : }
1542 4 : return IPC_OK();
1543 : }
1544 :
1545 : mozilla::ipc::IPCResult
1546 0 : TabChild::RecvSynthMouseMoveEvent(const WidgetMouseEvent& aEvent,
1547 : const ScrollableLayerGuid& aGuid,
1548 : const uint64_t& aInputBlockId)
1549 : {
1550 0 : if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
1551 0 : return IPC_FAIL_NO_REASON(this);
1552 : }
1553 0 : return IPC_OK();
1554 : }
1555 :
1556 : mozilla::ipc::IPCResult
1557 6 : TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
1558 : const ScrollableLayerGuid& aGuid,
1559 : const uint64_t& aInputBlockId)
1560 : {
1561 : // Mouse events like eMouseEnterIntoWidget, that are created in the parent
1562 : // process EventStateManager code, have an input block id which they get from
1563 : // the InputAPZContext in the parent process stack. However, they did not
1564 : // actually go through the APZ code and so their mHandledByAPZ flag is false.
1565 : // Since thos events didn't go through APZ, we don't need to send
1566 : // notifications for them.
1567 6 : bool pendingLayerization = false;
1568 6 : if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
1569 0 : nsCOMPtr<nsIDocument> document(GetDocument());
1570 : pendingLayerization =
1571 0 : APZCCallbackHelper::SendSetTargetAPZCNotification(mPuppetWidget, document,
1572 : aEvent, aGuid,
1573 0 : aInputBlockId);
1574 : }
1575 :
1576 : nsEventStatus unused;
1577 12 : InputAPZContext context(aGuid, aInputBlockId, unused);
1578 6 : if (pendingLayerization) {
1579 0 : context.SetPendingLayerization();
1580 : }
1581 :
1582 12 : WidgetMouseEvent localEvent(aEvent);
1583 6 : localEvent.mWidget = mPuppetWidget;
1584 : APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
1585 6 : mPuppetWidget->GetDefaultScale());
1586 6 : APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1587 :
1588 6 : if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
1589 0 : mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
1590 : }
1591 12 : return IPC_OK();
1592 : }
1593 :
1594 :
1595 : // In case handling repeated mouse wheel takes much time, we skip firing current
1596 : // wheel event if it may be coalesced to the next one.
1597 : bool
1598 0 : TabChild::MaybeCoalesceWheelEvent(const WidgetWheelEvent& aEvent,
1599 : const ScrollableLayerGuid& aGuid,
1600 : const uint64_t& aInputBlockId,
1601 : bool* aIsNextWheelEvent)
1602 : {
1603 0 : MOZ_ASSERT(aIsNextWheelEvent);
1604 0 : if (aEvent.mMessage == eWheel) {
1605 0 : GetIPCChannel()->PeekMessages(
1606 0 : [aIsNextWheelEvent](const IPC::Message& aMsg) -> bool {
1607 0 : if (aMsg.type() == mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID) {
1608 0 : *aIsNextWheelEvent = true;
1609 : }
1610 0 : return false; // Stop peeking.
1611 0 : });
1612 : // We only coalesce the current event when
1613 : // 1. It's eWheel (we don't coalesce eOperationStart and eWheelOperationEnd)
1614 : // 2. It's not the first wheel event.
1615 : // 3. It's not the last wheel event.
1616 : // 4. It's dispatched before the last wheel event was processed +
1617 : // the processing time of the last event.
1618 : // This way pages spending lots of time in wheel listeners get wheel
1619 : // events coalesced more aggressively.
1620 : // 5. It has same attributes as the coalesced wheel event which is not yet
1621 : // fired.
1622 0 : if (!mLastWheelProcessedTimeFromParent.IsNull() &&
1623 0 : *aIsNextWheelEvent &&
1624 0 : aEvent.mTimeStamp < (mLastWheelProcessedTimeFromParent +
1625 0 : mLastWheelProcessingDuration) &&
1626 0 : (mCoalescedWheelData.IsEmpty() ||
1627 0 : mCoalescedWheelData.CanCoalesce(aEvent, aGuid, aInputBlockId))) {
1628 0 : mCoalescedWheelData.Coalesce(aEvent, aGuid, aInputBlockId);
1629 0 : return true;
1630 : }
1631 : }
1632 0 : return false;
1633 : }
1634 :
1635 : void
1636 0 : TabChild::MaybeDispatchCoalescedWheelEvent()
1637 : {
1638 0 : if (mCoalescedWheelData.IsEmpty()) {
1639 0 : return;
1640 : }
1641 : const WidgetWheelEvent* wheelEvent =
1642 0 : mCoalescedWheelData.GetCoalescedWheelEvent();
1643 0 : MOZ_ASSERT(wheelEvent);
1644 : DispatchWheelEvent(*wheelEvent,
1645 0 : mCoalescedWheelData.GetScrollableLayerGuid(),
1646 0 : mCoalescedWheelData.GetInputBlockId());
1647 0 : mCoalescedWheelData.Reset();
1648 : }
1649 :
1650 : void
1651 0 : TabChild::DispatchWheelEvent(const WidgetWheelEvent& aEvent,
1652 : const ScrollableLayerGuid& aGuid,
1653 : const uint64_t& aInputBlockId)
1654 : {
1655 0 : WidgetWheelEvent localEvent(aEvent);
1656 0 : if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
1657 0 : nsCOMPtr<nsIDocument> document(GetDocument());
1658 0 : APZCCallbackHelper::SendSetTargetAPZCNotification(
1659 0 : mPuppetWidget, document, aEvent, aGuid, aInputBlockId);
1660 : }
1661 :
1662 0 : localEvent.mWidget = mPuppetWidget;
1663 : APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
1664 0 : mPuppetWidget->GetDefaultScale());
1665 0 : APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1666 :
1667 0 : if (localEvent.mCanTriggerSwipe) {
1668 0 : SendRespondStartSwipeEvent(aInputBlockId, localEvent.TriggersSwipe());
1669 : }
1670 :
1671 0 : if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
1672 0 : mAPZEventState->ProcessWheelEvent(localEvent, aGuid, aInputBlockId);
1673 : }
1674 0 : }
1675 :
1676 : mozilla::ipc::IPCResult
1677 0 : TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
1678 : const ScrollableLayerGuid& aGuid,
1679 : const uint64_t& aInputBlockId)
1680 : {
1681 0 : bool isNextWheelEvent = false;
1682 0 : if (MaybeCoalesceWheelEvent(aEvent, aGuid, aInputBlockId,
1683 : &isNextWheelEvent)) {
1684 0 : return IPC_OK();
1685 : }
1686 0 : if (isNextWheelEvent) {
1687 : // Update mLastWheelProcessedTimeFromParent so that we can compare the end
1688 : // time of the current event with the dispatched time of the next event.
1689 0 : mLastWheelProcessedTimeFromParent = aEvent.mTimeStamp;
1690 0 : mozilla::TimeStamp beforeDispatchingTime = TimeStamp::Now();
1691 0 : MaybeDispatchCoalescedWheelEvent();
1692 0 : DispatchWheelEvent(aEvent, aGuid, aInputBlockId);
1693 0 : mLastWheelProcessingDuration = (TimeStamp::Now() - beforeDispatchingTime);
1694 0 : mLastWheelProcessedTimeFromParent += mLastWheelProcessingDuration;
1695 : } else {
1696 : // This is the last wheel event. Set mLastWheelProcessedTimeFromParent to
1697 : // null moment to avoid coalesce the next incoming wheel event.
1698 0 : mLastWheelProcessedTimeFromParent = TimeStamp();
1699 0 : MaybeDispatchCoalescedWheelEvent();
1700 0 : DispatchWheelEvent(aEvent, aGuid, aInputBlockId);
1701 : }
1702 0 : return IPC_OK();
1703 : }
1704 :
1705 : mozilla::ipc::IPCResult
1706 0 : TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
1707 : const ScrollableLayerGuid& aGuid,
1708 : const uint64_t& aInputBlockId,
1709 : const nsEventStatus& aApzResponse)
1710 : {
1711 : TABC_LOG("Receiving touch event of type %d\n", aEvent.mMessage);
1712 :
1713 0 : WidgetTouchEvent localEvent(aEvent);
1714 0 : localEvent.mWidget = mPuppetWidget;
1715 :
1716 : APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
1717 0 : mPuppetWidget->GetDefaultScale());
1718 :
1719 0 : if (localEvent.mMessage == eTouchStart && AsyncPanZoomEnabled()) {
1720 0 : nsCOMPtr<nsIDocument> document = GetDocument();
1721 0 : if (gfxPrefs::TouchActionEnabled()) {
1722 0 : APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(
1723 : mPuppetWidget, document, localEvent, aInputBlockId,
1724 0 : mSetAllowedTouchBehaviorCallback);
1725 : }
1726 0 : APZCCallbackHelper::SendSetTargetAPZCNotification(mPuppetWidget, document,
1727 : localEvent, aGuid,
1728 0 : aInputBlockId);
1729 : }
1730 :
1731 : // Dispatch event to content (potentially a long-running operation)
1732 0 : nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1733 :
1734 0 : if (!AsyncPanZoomEnabled()) {
1735 : // We shouldn't have any e10s platforms that have touch events enabled
1736 : // without APZ.
1737 0 : MOZ_ASSERT(false);
1738 : return IPC_OK();
1739 : }
1740 :
1741 0 : mAPZEventState->ProcessTouchEvent(localEvent, aGuid, aInputBlockId,
1742 0 : aApzResponse, status);
1743 0 : return IPC_OK();
1744 : }
1745 :
1746 : mozilla::ipc::IPCResult
1747 0 : TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
1748 : const ScrollableLayerGuid& aGuid,
1749 : const uint64_t& aInputBlockId,
1750 : const nsEventStatus& aApzResponse)
1751 : {
1752 0 : if (!RecvRealTouchEvent(aEvent, aGuid, aInputBlockId, aApzResponse)) {
1753 0 : return IPC_FAIL_NO_REASON(this);
1754 : }
1755 0 : return IPC_OK();
1756 : }
1757 :
1758 : mozilla::ipc::IPCResult
1759 0 : TabChild::RecvRealDragEvent(const WidgetDragEvent& aEvent,
1760 : const uint32_t& aDragAction,
1761 : const uint32_t& aDropEffect)
1762 : {
1763 0 : WidgetDragEvent localEvent(aEvent);
1764 0 : localEvent.mWidget = mPuppetWidget;
1765 :
1766 0 : nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
1767 0 : if (dragSession) {
1768 0 : dragSession->SetDragAction(aDragAction);
1769 0 : nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
1770 0 : dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
1771 0 : if (initialDataTransfer) {
1772 0 : initialDataTransfer->SetDropEffectInt(aDropEffect);
1773 : }
1774 : }
1775 :
1776 0 : if (aEvent.mMessage == eDrop) {
1777 0 : bool canDrop = true;
1778 0 : if (!dragSession || NS_FAILED(dragSession->GetCanDrop(&canDrop)) ||
1779 0 : !canDrop) {
1780 0 : localEvent.mMessage = eDragExit;
1781 : }
1782 0 : } else if (aEvent.mMessage == eDragOver) {
1783 : nsCOMPtr<nsIDragService> dragService =
1784 0 : do_GetService("@mozilla.org/widget/dragservice;1");
1785 0 : if (dragService) {
1786 : // This will dispatch 'drag' event at the source if the
1787 : // drag transaction started in this process.
1788 0 : dragService->FireDragEventAtSource(eDrag, aEvent.mModifiers);
1789 : }
1790 : }
1791 :
1792 0 : APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1793 0 : return IPC_OK();
1794 : }
1795 :
1796 : mozilla::ipc::IPCResult
1797 0 : TabChild::RecvPluginEvent(const WidgetPluginEvent& aEvent)
1798 : {
1799 0 : WidgetPluginEvent localEvent(aEvent);
1800 0 : localEvent.mWidget = mPuppetWidget;
1801 0 : nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1802 0 : if (status != nsEventStatus_eConsumeNoDefault) {
1803 : // If not consumed, we should call default action
1804 0 : SendDefaultProcOfPluginEvent(aEvent);
1805 : }
1806 0 : return IPC_OK();
1807 : }
1808 :
1809 : void
1810 0 : TabChild::RequestEditCommands(nsIWidget::NativeKeyBindingsType aType,
1811 : const WidgetKeyboardEvent& aEvent,
1812 : nsTArray<CommandInt>& aCommands)
1813 : {
1814 0 : MOZ_ASSERT(aCommands.IsEmpty());
1815 :
1816 0 : if (NS_WARN_IF(aEvent.IsEditCommandsInitialized(aType))) {
1817 0 : aCommands = aEvent.EditCommandsConstRef(aType);
1818 0 : return;
1819 : }
1820 :
1821 0 : switch (aType) {
1822 : case nsIWidget::NativeKeyBindingsForSingleLineEditor:
1823 : case nsIWidget::NativeKeyBindingsForMultiLineEditor:
1824 : case nsIWidget::NativeKeyBindingsForRichTextEditor:
1825 0 : break;
1826 : default:
1827 0 : MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type");
1828 : }
1829 :
1830 : // Don't send aEvent to the parent process directly because it'll be marked
1831 : // as posted to remote process.
1832 0 : WidgetKeyboardEvent localEvent(aEvent);
1833 0 : SendRequestNativeKeyBindings(aType, localEvent, &aCommands);
1834 : }
1835 :
1836 : mozilla::ipc::IPCResult
1837 0 : TabChild::RecvNativeSynthesisResponse(const uint64_t& aObserverId,
1838 : const nsCString& aResponse)
1839 : {
1840 0 : mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId,
1841 0 : aResponse.get());
1842 0 : return IPC_OK();
1843 : }
1844 :
1845 : // In case handling repeated keys takes much time, we skip firing new ones.
1846 : bool
1847 0 : TabChild::SkipRepeatedKeyEvent(const WidgetKeyboardEvent& aEvent)
1848 : {
1849 0 : if (mRepeatedKeyEventTime.IsNull() ||
1850 0 : !aEvent.mIsRepeat ||
1851 0 : (aEvent.mMessage != eKeyDown && aEvent.mMessage != eKeyPress)) {
1852 0 : mRepeatedKeyEventTime = TimeStamp();
1853 0 : mSkipKeyPress = false;
1854 0 : return false;
1855 : }
1856 :
1857 0 : if ((aEvent.mMessage == eKeyDown &&
1858 0 : (mRepeatedKeyEventTime > aEvent.mTimeStamp)) ||
1859 0 : (mSkipKeyPress && (aEvent.mMessage == eKeyPress))) {
1860 : // If we skip a keydown event, also the following keypress events should be
1861 : // skipped.
1862 0 : mSkipKeyPress |= aEvent.mMessage == eKeyDown;
1863 0 : return true;
1864 : }
1865 :
1866 0 : if (aEvent.mMessage == eKeyDown) {
1867 : // If keydown wasn't skipped, nor should the possible following keypress.
1868 0 : mRepeatedKeyEventTime = TimeStamp();
1869 0 : mSkipKeyPress = false;
1870 : }
1871 0 : return false;
1872 : }
1873 :
1874 : void
1875 0 : TabChild::UpdateRepeatedKeyEventEndTime(const WidgetKeyboardEvent& aEvent)
1876 : {
1877 0 : if (aEvent.mIsRepeat &&
1878 0 : (aEvent.mMessage == eKeyDown || aEvent.mMessage == eKeyPress)) {
1879 0 : mRepeatedKeyEventTime = TimeStamp::Now();
1880 : }
1881 0 : }
1882 :
1883 : mozilla::ipc::IPCResult
1884 0 : TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent)
1885 : {
1886 0 : if (SkipRepeatedKeyEvent(aEvent)) {
1887 0 : return IPC_OK();
1888 : }
1889 :
1890 0 : MOZ_ASSERT(aEvent.mMessage != eKeyPress ||
1891 : aEvent.AreAllEditCommandsInitialized(),
1892 : "eKeyPress event should have native key binding information");
1893 :
1894 : // If content code called preventDefault() on a keydown event, then we don't
1895 : // want to process any following keypress events.
1896 0 : if (aEvent.mMessage == eKeyPress && mIgnoreKeyPressEvent) {
1897 0 : return IPC_OK();
1898 : }
1899 :
1900 0 : WidgetKeyboardEvent localEvent(aEvent);
1901 0 : localEvent.mWidget = mPuppetWidget;
1902 0 : localEvent.mUniqueId = aEvent.mUniqueId;
1903 0 : nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1904 :
1905 : // Update the end time of the possible repeated event so that we can skip
1906 : // some incoming events in case event handling took long time.
1907 0 : UpdateRepeatedKeyEventEndTime(localEvent);
1908 :
1909 0 : if (aEvent.mMessage == eKeyDown) {
1910 0 : mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
1911 : }
1912 :
1913 0 : if (localEvent.mFlags.mIsSuppressedOrDelayed) {
1914 0 : localEvent.PreventDefault();
1915 : }
1916 :
1917 : // If a response is desired from the content process, resend the key event.
1918 : // If mAccessKeyForwardedToChild is set, then don't resend the key event yet
1919 : // as RecvHandleAccessKey will do this.
1920 0 : if (localEvent.WantReplyFromContentProcess()) {
1921 0 : SendReplyKeyEvent(localEvent);
1922 : }
1923 :
1924 0 : if (localEvent.mAccessKeyForwardedToChild) {
1925 0 : SendAccessKeyNotHandled(localEvent);
1926 : }
1927 :
1928 0 : return IPC_OK();
1929 : }
1930 :
1931 : mozilla::ipc::IPCResult
1932 0 : TabChild::RecvKeyEvent(const nsString& aType,
1933 : const int32_t& aKeyCode,
1934 : const int32_t& aCharCode,
1935 : const int32_t& aModifiers,
1936 : const bool& aPreventDefault)
1937 : {
1938 0 : bool ignored = false;
1939 0 : nsContentUtils::SendKeyEvent(mPuppetWidget, aType, aKeyCode, aCharCode,
1940 0 : aModifiers, aPreventDefault, &ignored);
1941 0 : return IPC_OK();
1942 : }
1943 :
1944 : mozilla::ipc::IPCResult
1945 0 : TabChild::RecvCompositionEvent(const WidgetCompositionEvent& aEvent)
1946 : {
1947 0 : WidgetCompositionEvent localEvent(aEvent);
1948 0 : localEvent.mWidget = mPuppetWidget;
1949 0 : APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1950 0 : Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
1951 0 : return IPC_OK();
1952 : }
1953 :
1954 : mozilla::ipc::IPCResult
1955 0 : TabChild::RecvSelectionEvent(const WidgetSelectionEvent& aEvent)
1956 : {
1957 0 : WidgetSelectionEvent localEvent(aEvent);
1958 0 : localEvent.mWidget = mPuppetWidget;
1959 0 : APZCCallbackHelper::DispatchWidgetEvent(localEvent);
1960 0 : Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
1961 0 : return IPC_OK();
1962 : }
1963 :
1964 : mozilla::ipc::IPCResult
1965 0 : TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer,
1966 : const bool& aIsPrivateData,
1967 : const IPC::Principal& aRequestingPrincipal)
1968 : {
1969 : nsresult rv;
1970 : nsCOMPtr<nsITransferable> trans =
1971 0 : do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
1972 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
1973 0 : trans->Init(nullptr);
1974 :
1975 0 : rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer,
1976 : aIsPrivateData,
1977 : aRequestingPrincipal,
1978 : trans, nullptr, this);
1979 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
1980 :
1981 0 : nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
1982 0 : if (NS_WARN_IF(!ourDocShell)) {
1983 0 : return IPC_OK();
1984 : }
1985 :
1986 : nsCOMPtr<nsICommandParams> params =
1987 0 : do_CreateInstance("@mozilla.org/embedcomp/command-params;1", &rv);
1988 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
1989 :
1990 0 : rv = params->SetISupportsValue("transferable", trans);
1991 0 : NS_ENSURE_SUCCESS(rv, IPC_OK());
1992 :
1993 0 : ourDocShell->DoCommandWithParams("cmd_pasteTransferable", params);
1994 0 : return IPC_OK();
1995 : }
1996 :
1997 :
1998 : a11y::PDocAccessibleChild*
1999 0 : TabChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
2000 : const uint32_t&, const IAccessibleHolder&)
2001 : {
2002 0 : MOZ_ASSERT(false, "should never call this!");
2003 : return nullptr;
2004 : }
2005 :
2006 : bool
2007 0 : TabChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild)
2008 : {
2009 : #ifdef ACCESSIBILITY
2010 0 : delete static_cast<mozilla::a11y::DocAccessibleChild*>(aChild);
2011 : #endif
2012 0 : return true;
2013 : }
2014 :
2015 : PDocumentRendererChild*
2016 0 : TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
2017 : const mozilla::gfx::Matrix& transform,
2018 : const nsString& bgcolor,
2019 : const uint32_t& renderFlags,
2020 : const bool& flushLayout,
2021 : const nsIntSize& renderSize)
2022 : {
2023 0 : return new DocumentRendererChild();
2024 : }
2025 :
2026 : bool
2027 0 : TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor)
2028 : {
2029 0 : delete actor;
2030 0 : return true;
2031 : }
2032 :
2033 : mozilla::ipc::IPCResult
2034 0 : TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
2035 : const nsRect& documentRect,
2036 : const mozilla::gfx::Matrix& transform,
2037 : const nsString& bgcolor,
2038 : const uint32_t& renderFlags,
2039 : const bool& flushLayout,
2040 : const nsIntSize& renderSize)
2041 : {
2042 0 : DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor);
2043 :
2044 0 : nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation());
2045 0 : if (!browser)
2046 0 : return IPC_OK(); // silently ignore
2047 0 : nsCOMPtr<mozIDOMWindowProxy> window;
2048 0 : if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
2049 0 : !window)
2050 : {
2051 0 : return IPC_OK(); // silently ignore
2052 : }
2053 :
2054 0 : nsCString data;
2055 0 : bool ret = render->RenderDocument(nsPIDOMWindowOuter::From(window),
2056 : documentRect, transform,
2057 : bgcolor,
2058 0 : renderFlags, flushLayout,
2059 0 : renderSize, data);
2060 0 : if (!ret)
2061 0 : return IPC_OK(); // silently ignore
2062 :
2063 0 : if (!PDocumentRendererChild::Send__delete__(actor, renderSize, data)) {
2064 0 : return IPC_FAIL_NO_REASON(this);
2065 : }
2066 0 : return IPC_OK();
2067 : }
2068 :
2069 : PColorPickerChild*
2070 0 : TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
2071 : {
2072 0 : MOZ_CRASH("unused");
2073 : return nullptr;
2074 : }
2075 :
2076 : bool
2077 0 : TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
2078 : {
2079 0 : nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker);
2080 0 : NS_RELEASE(picker);
2081 0 : return true;
2082 : }
2083 :
2084 : PFilePickerChild*
2085 0 : TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
2086 : {
2087 0 : MOZ_CRASH("unused");
2088 : return nullptr;
2089 : }
2090 :
2091 : bool
2092 0 : TabChild::DeallocPFilePickerChild(PFilePickerChild* actor)
2093 : {
2094 0 : nsFilePickerProxy* filePicker = static_cast<nsFilePickerProxy*>(actor);
2095 0 : NS_RELEASE(filePicker);
2096 0 : return true;
2097 : }
2098 :
2099 : auto
2100 0 : TabChild::AllocPIndexedDBPermissionRequestChild(const Principal& aPrincipal)
2101 : -> PIndexedDBPermissionRequestChild*
2102 : {
2103 0 : MOZ_CRASH("PIndexedDBPermissionRequestChild actors should always be created "
2104 : "manually!");
2105 : }
2106 :
2107 : bool
2108 0 : TabChild::DeallocPIndexedDBPermissionRequestChild(
2109 : PIndexedDBPermissionRequestChild* aActor)
2110 : {
2111 0 : MOZ_ASSERT(aActor);
2112 0 : delete aActor;
2113 0 : return true;
2114 : }
2115 :
2116 : mozilla::ipc::IPCResult
2117 0 : TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
2118 : {
2119 0 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
2120 0 : NS_ENSURE_TRUE(window, IPC_OK());
2121 : nsCOMPtr<EventTarget> chromeHandler =
2122 0 : do_QueryInterface(window->GetChromeEventHandler());
2123 0 : NS_ENSURE_TRUE(chromeHandler, IPC_OK());
2124 0 : RefPtr<ContentListener> listener = new ContentListener(this);
2125 0 : chromeHandler->AddEventListener(aType, listener, capture);
2126 0 : return IPC_OK();
2127 : }
2128 :
2129 : mozilla::ipc::IPCResult
2130 12 : TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
2131 : {
2132 12 : if (!mGlobal && !InitTabChildGlobal())
2133 : // This can happen if we're half-destroyed. It's not a fatal
2134 : // error.
2135 0 : return IPC_OK();
2136 :
2137 12 : LoadScriptInternal(aURL, aRunInGlobalScope);
2138 12 : return IPC_OK();
2139 : }
2140 :
2141 : mozilla::ipc::IPCResult
2142 8 : TabChild::RecvAsyncMessage(const nsString& aMessage,
2143 : InfallibleTArray<CpowEntry>&& aCpows,
2144 : const IPC::Principal& aPrincipal,
2145 : const ClonedMessageData& aData)
2146 : {
2147 16 : NS_LossyConvertUTF16toASCII messageNameCStr(aMessage);
2148 16 : AUTO_PROFILER_LABEL_DYNAMIC("TabChild::RecvAsyncMessage", EVENTS,
2149 : messageNameCStr.get());
2150 :
2151 16 : CrossProcessCpowHolder cpows(Manager(), aCpows);
2152 8 : if (!mTabChildGlobal) {
2153 0 : return IPC_OK();
2154 : }
2155 :
2156 : // We should have a message manager if the global is alive, but it
2157 : // seems sometimes we don't. Assert in aurora/nightly, but don't
2158 : // crash in release builds.
2159 8 : MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
2160 8 : if (!mTabChildGlobal->mMessageManager) {
2161 0 : return IPC_OK();
2162 : }
2163 :
2164 16 : JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), GetGlobal());
2165 16 : StructuredCloneData data;
2166 8 : UnpackClonedMessageDataForChild(aData, data);
2167 : RefPtr<nsFrameMessageManager> mm =
2168 16 : static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
2169 8 : mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
2170 8 : aMessage, false, &data, &cpows, aPrincipal, nullptr);
2171 8 : return IPC_OK();
2172 : }
2173 :
2174 : mozilla::ipc::IPCResult
2175 0 : TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
2176 : {
2177 0 : nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
2178 0 : if (NS_WARN_IF(!ourDocShell)) {
2179 0 : return IPC_OK();
2180 : }
2181 :
2182 0 : nsCOMPtr<nsPIDOMWindowOuter> ourWindow = ourDocShell->GetWindow();
2183 0 : if (NS_WARN_IF(!ourWindow)) {
2184 0 : return IPC_OK();
2185 : }
2186 :
2187 0 : RefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(ourDocShell.get());
2188 :
2189 0 : nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
2190 :
2191 0 : docShell->SetInFrameSwap(true);
2192 :
2193 0 : nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false);
2194 0 : nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget);
2195 :
2196 : // Owner content type may have changed, so store the possibly updated context
2197 : // and notify others.
2198 0 : MaybeInvalidTabContext maybeContext(aContext);
2199 0 : if (!maybeContext.IsValid()) {
2200 0 : NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
2201 : "the parent process. (%s)",
2202 : maybeContext.GetInvalidReason()).get());
2203 0 : MOZ_CRASH("Invalid TabContext received from the parent process.");
2204 : }
2205 :
2206 0 : if (!UpdateTabContextAfterSwap(maybeContext.GetTabContext())) {
2207 0 : MOZ_CRASH("Update to TabContext after swap was denied.");
2208 : }
2209 :
2210 : // Since mIsMozBrowserElement may change in UpdateTabContextAfterSwap, so we
2211 : // call UpdateFrameType here to make sure the frameType on the docshell is
2212 : // correct.
2213 0 : UpdateFrameType();
2214 :
2215 : // Ignore previous value of mTriedBrowserInit since owner content has changed.
2216 0 : mTriedBrowserInit = true;
2217 : // Initialize the child side of the browser element machinery, if appropriate.
2218 0 : if (IsMozBrowser()) {
2219 0 : RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
2220 : }
2221 :
2222 0 : nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true);
2223 :
2224 0 : docShell->SetInFrameSwap(false);
2225 :
2226 0 : return IPC_OK();
2227 : }
2228 :
2229 : mozilla::ipc::IPCResult
2230 0 : TabChild::RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
2231 : nsTArray<uint32_t>&& aCharCodes,
2232 : const int32_t& aModifierMask)
2233 : {
2234 0 : nsCOMPtr<nsIDocument> document(GetDocument());
2235 0 : nsCOMPtr<nsIPresShell> presShell = document->GetShell();
2236 0 : if (presShell) {
2237 0 : nsPresContext* pc = presShell->GetPresContext();
2238 0 : if (pc) {
2239 0 : if (!pc->EventStateManager()->
2240 0 : HandleAccessKey(&(const_cast<WidgetKeyboardEvent&>(aEvent)),
2241 : pc, aCharCodes,
2242 : aModifierMask, true)) {
2243 : // If no accesskey was found, inform the parent so that accesskeys on
2244 : // menus can be handled.
2245 0 : WidgetKeyboardEvent localEvent(aEvent);
2246 0 : localEvent.mWidget = mPuppetWidget;
2247 0 : SendAccessKeyNotHandled(localEvent);
2248 : }
2249 : }
2250 : }
2251 :
2252 0 : return IPC_OK();
2253 : }
2254 :
2255 : mozilla::ipc::IPCResult
2256 1 : TabChild::RecvSetUseGlobalHistory(const bool& aUse)
2257 : {
2258 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
2259 1 : MOZ_ASSERT(docShell);
2260 :
2261 1 : nsresult rv = docShell->SetUseGlobalHistory(aUse);
2262 1 : if (NS_FAILED(rv)) {
2263 0 : NS_WARNING("Failed to set UseGlobalHistory on TabChild docShell");
2264 : }
2265 :
2266 2 : return IPC_OK();
2267 : }
2268 :
2269 : mozilla::ipc::IPCResult
2270 0 : TabChild::RecvPrint(const uint64_t& aOuterWindowID, const PrintData& aPrintData)
2271 : {
2272 : #ifdef NS_PRINTING
2273 : nsGlobalWindow* outerWindow =
2274 0 : nsGlobalWindow::GetOuterWindowWithId(aOuterWindowID);
2275 0 : if (NS_WARN_IF(!outerWindow)) {
2276 0 : return IPC_OK();
2277 : }
2278 :
2279 : nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint =
2280 0 : do_GetInterface(outerWindow->AsOuter());
2281 0 : if (NS_WARN_IF(!webBrowserPrint)) {
2282 0 : return IPC_OK();
2283 : }
2284 :
2285 : nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
2286 0 : do_GetService("@mozilla.org/gfx/printsettings-service;1");
2287 0 : if (NS_WARN_IF(!printSettingsSvc)) {
2288 0 : return IPC_OK();
2289 : }
2290 :
2291 0 : nsCOMPtr<nsIPrintSettings> printSettings;
2292 : nsresult rv =
2293 0 : printSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
2294 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
2295 0 : return IPC_OK();
2296 : }
2297 :
2298 : nsCOMPtr<nsIPrintSession> printSession =
2299 0 : do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
2300 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
2301 0 : return IPC_OK();
2302 : }
2303 :
2304 0 : printSettings->SetPrintSession(printSession);
2305 0 : printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings);
2306 0 : rv = webBrowserPrint->Print(printSettings, nullptr);
2307 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
2308 0 : return IPC_OK();
2309 : }
2310 :
2311 : #endif
2312 0 : return IPC_OK();
2313 : }
2314 :
2315 : mozilla::ipc::IPCResult
2316 0 : TabChild::RecvUpdateNativeWindowHandle(const uintptr_t& aNewHandle)
2317 : {
2318 : #if defined(XP_WIN) && defined(ACCESSIBILITY)
2319 : mNativeWindowHandle = aNewHandle;
2320 : return IPC_OK();
2321 : #else
2322 0 : return IPC_FAIL_NO_REASON(this);
2323 : #endif
2324 : }
2325 :
2326 : mozilla::ipc::IPCResult
2327 0 : TabChild::RecvDestroy()
2328 : {
2329 0 : MOZ_ASSERT(mDestroyed == false);
2330 0 : mDestroyed = true;
2331 :
2332 : nsTArray<PContentPermissionRequestChild*> childArray =
2333 0 : nsContentPermissionUtils::GetContentPermissionRequestChildById(GetTabId());
2334 :
2335 : // Need to close undeleted ContentPermissionRequestChilds before tab is closed.
2336 0 : for (auto& permissionRequestChild : childArray) {
2337 0 : auto child = static_cast<RemotePermissionRequest*>(permissionRequestChild);
2338 0 : child->Destroy();
2339 : }
2340 :
2341 0 : while (mActiveSuppressDisplayport > 0) {
2342 0 : APZCCallbackHelper::SuppressDisplayport(false, nullptr);
2343 0 : mActiveSuppressDisplayport--;
2344 : }
2345 :
2346 0 : if (mTabChildGlobal) {
2347 : // Message handlers are called from the event loop, so it better be safe to
2348 : // run script.
2349 0 : MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
2350 0 : mTabChildGlobal->DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
2351 : }
2352 :
2353 : nsCOMPtr<nsIObserverService> observerService =
2354 0 : mozilla::services::GetObserverService();
2355 :
2356 0 : observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
2357 :
2358 : // XXX what other code in ~TabChild() should we be running here?
2359 0 : DestroyWindow();
2360 :
2361 : // Bounce through the event loop once to allow any delayed teardown runnables
2362 : // that were just generated to have a chance to run.
2363 0 : nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedDeleteRunnable(this);
2364 0 : MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable));
2365 :
2366 0 : return IPC_OK();
2367 : }
2368 :
2369 : void
2370 0 : TabChild::AddPendingDocShellBlocker()
2371 : {
2372 0 : mPendingDocShellBlockers++;
2373 0 : }
2374 :
2375 : void
2376 0 : TabChild::RemovePendingDocShellBlocker()
2377 : {
2378 0 : mPendingDocShellBlockers--;
2379 0 : if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
2380 0 : mPendingDocShellReceivedMessage = false;
2381 0 : InternalSetDocShellIsActive(mPendingDocShellIsActive,
2382 0 : mPendingDocShellPreserveLayers);
2383 : }
2384 0 : }
2385 :
2386 : void
2387 2 : TabChild::InternalSetDocShellIsActive(bool aIsActive, bool aPreserveLayers)
2388 : {
2389 2 : auto clearForcePaint = MakeScopeExit([&] {
2390 : // We might force a paint, or we might already have painted and this is a
2391 : // no-op. In either case, once we exit this scope, we need to alert the
2392 : // ProcessHangMonitor that we've finished responding to what might have
2393 : // been a request to force paint. This is so that the BackgroundHangMonitor
2394 : // for force painting can be made to wait again.
2395 2 : if (aIsActive) {
2396 2 : ProcessHangMonitor::ClearForcePaint();
2397 : }
2398 4 : });
2399 :
2400 2 : if (mCompositorOptions) {
2401 : // Note that |GetLayerManager()| has side-effects in that it creates a layer
2402 : // manager if one doesn't exist already. Calling it inside a debug-only
2403 : // assertion is generally bad but in this case we call it unconditionally
2404 : // just below so it's ok.
2405 2 : MOZ_ASSERT(mPuppetWidget);
2406 2 : MOZ_ASSERT(mPuppetWidget->GetLayerManager());
2407 2 : MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
2408 : || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
2409 : || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
2410 :
2411 : // We send the current layer observer epoch to the compositor so that
2412 : // TabParent knows whether a layer update notification corresponds to the
2413 : // latest SetDocShellIsActive request that was made.
2414 2 : mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(mLayerObserverEpoch);
2415 : }
2416 :
2417 : // docshell is consider prerendered only if not active yet
2418 2 : mIsPrerendered &= !aIsActive;
2419 2 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
2420 2 : if (docShell) {
2421 : bool wasActive;
2422 2 : docShell->GetIsActive(&wasActive);
2423 2 : if (aIsActive && wasActive) {
2424 : // This request is a no-op. In this case, we still want a MozLayerTreeReady
2425 : // notification to fire in the parent (so that it knows that the child has
2426 : // updated its epoch). ForcePaintNoOp does that.
2427 2 : if (IPCOpen()) {
2428 2 : Unused << SendForcePaintNoOp(mLayerObserverEpoch);
2429 2 : return;
2430 : }
2431 : }
2432 :
2433 0 : docShell->SetIsActive(aIsActive);
2434 : }
2435 :
2436 0 : if (aIsActive) {
2437 0 : MakeVisible();
2438 :
2439 : // We don't use TabChildBase::GetPresShell() here because that would create
2440 : // a content viewer if one doesn't exist yet. Creating a content viewer can
2441 : // cause JS to run, which we want to avoid. nsIDocShell::GetPresShell
2442 : // returns null if no content viewer exists yet.
2443 0 : if (nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell()) {
2444 0 : if (nsIFrame* root = presShell->FrameConstructor()->GetRootFrame()) {
2445 0 : FrameLayerBuilder::InvalidateAllLayersForFrame(
2446 0 : nsLayoutUtils::GetDisplayRootFrame(root));
2447 0 : root->SchedulePaint();
2448 : }
2449 :
2450 0 : Telemetry::AutoTimer<Telemetry::TABCHILD_PAINT_TIME> timer;
2451 : // If we need to repaint, let's do that right away. No sense waiting until
2452 : // we get back to the event loop again. We suppress the display port so that
2453 : // we only paint what's visible. This ensures that the tab we're switching
2454 : // to paints as quickly as possible.
2455 0 : APZCCallbackHelper::SuppressDisplayport(true, presShell);
2456 0 : if (nsContentUtils::IsSafeToRunScript()) {
2457 0 : WebWidget()->PaintNowIfNeeded();
2458 : } else {
2459 0 : RefPtr<nsViewManager> vm = presShell->GetViewManager();
2460 0 : if (nsView* view = vm->GetRootView()) {
2461 0 : presShell->Paint(view, view->GetBounds(),
2462 0 : nsIPresShell::PAINT_LAYERS);
2463 : }
2464 : }
2465 0 : APZCCallbackHelper::SuppressDisplayport(false, presShell);
2466 : }
2467 0 : } else if (!aPreserveLayers) {
2468 0 : MakeHidden();
2469 : }
2470 : }
2471 :
2472 : mozilla::ipc::IPCResult
2473 2 : TabChild::RecvSetDocShellIsActive(const bool& aIsActive,
2474 : const bool& aPreserveLayers,
2475 : const uint64_t& aLayerObserverEpoch)
2476 : {
2477 : // Since requests to change the active docshell come in from both the hang
2478 : // monitor channel and the PContent channel, we have an ordering problem. This
2479 : // code ensures that we respect the order in which the requests were made and
2480 : // ignore stale requests.
2481 2 : if (mLayerObserverEpoch >= aLayerObserverEpoch) {
2482 0 : return IPC_OK();
2483 : }
2484 2 : mLayerObserverEpoch = aLayerObserverEpoch;
2485 :
2486 : // If we're currently waiting for window opening to complete, we need to hold
2487 : // off on setting the docshell active. We queue up the values we're receiving
2488 : // in the mWindowOpenDocShellActiveStatus.
2489 2 : if (mPendingDocShellBlockers > 0) {
2490 0 : mPendingDocShellReceivedMessage = true;
2491 0 : mPendingDocShellIsActive = aIsActive;
2492 0 : mPendingDocShellPreserveLayers = aPreserveLayers;
2493 0 : return IPC_OK();
2494 : }
2495 :
2496 2 : InternalSetDocShellIsActive(aIsActive, aPreserveLayers);
2497 2 : return IPC_OK();
2498 : }
2499 :
2500 : mozilla::ipc::IPCResult
2501 0 : TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
2502 : {
2503 0 : nsIFocusManager* fm = nsFocusManager::GetFocusManager();
2504 0 : if (fm) {
2505 0 : nsCOMPtr<nsIDOMElement> result;
2506 0 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
2507 :
2508 : // Move to the first or last document.
2509 0 : uint32_t type = aForward ?
2510 0 : (aForDocumentNavigation ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC) :
2511 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT)) :
2512 0 : (aForDocumentNavigation ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC) :
2513 0 : static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LAST));
2514 0 : fm->MoveFocus(window, nullptr, type,
2515 0 : nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
2516 :
2517 : // No valid root element was found, so move to the first focusable element.
2518 0 : if (!result && aForward && !aForDocumentNavigation) {
2519 0 : fm->MoveFocus(window, nullptr, nsIFocusManager::MOVEFOCUS_FIRST,
2520 0 : nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
2521 : }
2522 :
2523 0 : SendRequestFocus(false);
2524 : }
2525 :
2526 0 : return IPC_OK();
2527 : }
2528 :
2529 : mozilla::ipc::IPCResult
2530 0 : TabChild::RecvHandledWindowedPluginKeyEvent(
2531 : const NativeEventData& aKeyEventData,
2532 : const bool& aIsConsumed)
2533 : {
2534 0 : if (NS_WARN_IF(!mPuppetWidget)) {
2535 0 : return IPC_OK();
2536 : }
2537 0 : mPuppetWidget->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
2538 0 : return IPC_OK();
2539 : }
2540 :
2541 : PRenderFrameChild*
2542 1 : TabChild::AllocPRenderFrameChild()
2543 : {
2544 1 : return new RenderFrameChild();
2545 : }
2546 :
2547 : bool
2548 0 : TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
2549 : {
2550 0 : delete aFrame;
2551 0 : return true;
2552 : }
2553 :
2554 : bool
2555 3 : TabChild::InitTabChildGlobal()
2556 : {
2557 3 : if (!mGlobal && !mTabChildGlobal) {
2558 2 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
2559 1 : NS_ENSURE_TRUE(window, false);
2560 : nsCOMPtr<EventTarget> chromeHandler =
2561 2 : do_QueryInterface(window->GetChromeEventHandler());
2562 1 : NS_ENSURE_TRUE(chromeHandler, false);
2563 :
2564 2 : RefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
2565 :
2566 1 : nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
2567 :
2568 1 : NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
2569 1 : NS_ENSURE_TRUE(InitChildGlobalInternal(scopeSupports, globalId), false);
2570 :
2571 1 : scope->Init();
2572 :
2573 2 : nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
2574 1 : NS_ENSURE_TRUE(root, false);
2575 1 : root->SetParentTarget(scope);
2576 :
2577 1 : mTabChildGlobal = scope.forget();;
2578 : }
2579 :
2580 3 : if (!mTriedBrowserInit) {
2581 1 : mTriedBrowserInit = true;
2582 : // Initialize the child side of the browser element machinery,
2583 : // if appropriate.
2584 1 : if (IsMozBrowser()) {
2585 0 : RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
2586 : }
2587 : }
2588 :
2589 3 : return true;
2590 : }
2591 :
2592 : void
2593 1 : TabChild::InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
2594 : const uint64_t& aLayersId,
2595 : const CompositorOptions& aCompositorOptions,
2596 : PRenderFrameChild* aRenderFrame)
2597 : {
2598 1 : mPuppetWidget->InitIMEState();
2599 :
2600 1 : if (!aRenderFrame) {
2601 0 : NS_WARNING("failed to construct RenderFrame");
2602 0 : return;
2603 : }
2604 :
2605 1 : MOZ_ASSERT(aLayersId != 0);
2606 1 : mTextureFactoryIdentifier = aTextureFactoryIdentifier;
2607 :
2608 : // Pushing layers transactions directly to a separate
2609 : // compositor context.
2610 1 : PCompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
2611 1 : if (!compositorChild) {
2612 0 : NS_WARNING("failed to get CompositorBridgeChild instance");
2613 0 : return;
2614 : }
2615 :
2616 1 : mCompositorOptions = Some(aCompositorOptions);
2617 :
2618 1 : mRemoteFrame = static_cast<RenderFrameChild*>(aRenderFrame);
2619 1 : if (aLayersId != 0) {
2620 2 : StaticMutexAutoLock lock(sTabChildrenMutex);
2621 :
2622 1 : if (!sTabChildren) {
2623 1 : sTabChildren = new TabChildMap;
2624 : }
2625 1 : MOZ_ASSERT(!sTabChildren->Get(aLayersId));
2626 1 : sTabChildren->Put(aLayersId, this);
2627 1 : mLayersId = aLayersId;
2628 : }
2629 :
2630 : ShadowLayerForwarder* lf =
2631 2 : mPuppetWidget->GetLayerManager(
2632 1 : nullptr, mTextureFactoryIdentifier.mParentBackend)
2633 1 : ->AsShadowForwarder();
2634 :
2635 1 : LayerManager* lm = mPuppetWidget->GetLayerManager();
2636 1 : if (lm->AsWebRenderLayerManager()) {
2637 0 : lm->AsWebRenderLayerManager()->Initialize(compositorChild,
2638 : wr::AsPipelineId(aLayersId),
2639 0 : &mTextureFactoryIdentifier);
2640 0 : ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
2641 0 : gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
2642 0 : InitAPZState();
2643 : }
2644 :
2645 1 : if (lf) {
2646 2 : nsTArray<LayersBackend> backends;
2647 1 : backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
2648 : PLayerTransactionChild* shadowManager =
2649 1 : compositorChild->SendPLayerTransactionConstructor(backends, aLayersId);
2650 1 : if (shadowManager) {
2651 1 : lf->SetShadowManager(shadowManager);
2652 1 : lf->IdentifyTextureHost(mTextureFactoryIdentifier);
2653 1 : ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
2654 1 : gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
2655 1 : InitAPZState();
2656 : }
2657 : }
2658 :
2659 : nsCOMPtr<nsIObserverService> observerService =
2660 2 : mozilla::services::GetObserverService();
2661 :
2662 1 : if (observerService) {
2663 2 : observerService->AddObserver(this,
2664 : BEFORE_FIRST_PAINT,
2665 2 : false);
2666 : }
2667 : }
2668 :
2669 : void
2670 1 : TabChild::InitAPZState()
2671 : {
2672 1 : if (!mCompositorOptions->UseAPZ()) {
2673 0 : return;
2674 : }
2675 1 : auto cbc = CompositorBridgeChild::Get();
2676 :
2677 : // Initialize the ApzcTreeManager. This takes multiple casts because of ugly multiple inheritance.
2678 1 : PAPZCTreeManagerChild* baseProtocol = cbc->SendPAPZCTreeManagerConstructor(mLayersId);
2679 1 : APZCTreeManagerChild* derivedProtocol = static_cast<APZCTreeManagerChild*>(baseProtocol);
2680 :
2681 1 : mApzcTreeManager = RefPtr<IAPZCTreeManager>(derivedProtocol);
2682 :
2683 : // Initialize the GeckoContentController for this tab. We don't hold a reference because we don't need it.
2684 : // The ContentProcessController will hold a reference to the tab, and will be destroyed by the compositor or ipdl
2685 : // during destruction.
2686 3 : RefPtr<GeckoContentController> contentController = new ContentProcessController(this);
2687 2 : APZChild* apzChild = new APZChild(contentController);
2688 1 : cbc->SetEventTargetForActor(
2689 2 : apzChild, TabGroup()->EventTargetFor(TaskCategory::Other));
2690 1 : MOZ_ASSERT(apzChild->GetActorEventTarget());
2691 1 : cbc->SendPAPZConstructor(apzChild, mLayersId);
2692 : }
2693 :
2694 : void
2695 2 : TabChild::GetDPI(float* aDPI)
2696 : {
2697 2 : *aDPI = -1.0;
2698 2 : if (!(mDidFakeShow || mDidSetRealShowInfo)) {
2699 1 : return;
2700 : }
2701 :
2702 1 : if (mDPI > 0) {
2703 1 : *aDPI = mDPI;
2704 1 : return;
2705 : }
2706 :
2707 : // Fallback to a sync call if needed.
2708 0 : SendGetDPI(aDPI);
2709 : }
2710 :
2711 : void
2712 2 : TabChild::GetDefaultScale(double* aScale)
2713 : {
2714 2 : *aScale = -1.0;
2715 2 : if (!(mDidFakeShow || mDidSetRealShowInfo)) {
2716 1 : return;
2717 : }
2718 :
2719 1 : if (mDefaultScale > 0) {
2720 1 : *aScale = mDefaultScale;
2721 1 : return;
2722 : }
2723 :
2724 : // Fallback to a sync call if needed.
2725 0 : SendGetDefaultScale(aScale);
2726 : }
2727 :
2728 : void
2729 0 : TabChild::GetWidgetRounding(int32_t* aRounding)
2730 : {
2731 0 : *aRounding = 1;
2732 0 : if (!(mDidFakeShow || mDidSetRealShowInfo)) {
2733 0 : return;
2734 : }
2735 0 : if (mRounding > 0) {
2736 0 : *aRounding = mRounding;
2737 0 : return;
2738 : }
2739 :
2740 : // Fallback to a sync call if needed.
2741 0 : SendGetWidgetRounding(aRounding);
2742 : }
2743 :
2744 : void
2745 2 : TabChild::NotifyPainted()
2746 : {
2747 2 : if (!mNotified) {
2748 1 : mRemoteFrame->SendNotifyCompositorTransaction();
2749 1 : mNotified = true;
2750 : }
2751 2 : }
2752 :
2753 : void
2754 0 : TabChild::MakeVisible()
2755 : {
2756 0 : if (mPuppetWidget && mPuppetWidget->IsVisible()) {
2757 0 : return;
2758 : }
2759 :
2760 0 : if (mPuppetWidget) {
2761 0 : mPuppetWidget->Show(true);
2762 : }
2763 : }
2764 :
2765 : void
2766 0 : TabChild::MakeHidden()
2767 : {
2768 0 : if (mPuppetWidget && !mPuppetWidget->IsVisible()) {
2769 0 : return;
2770 : }
2771 :
2772 0 : ClearCachedResources();
2773 :
2774 : // Hide all plugins in this tab.
2775 0 : if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
2776 0 : if (nsPresContext* presContext = shell->GetPresContext()) {
2777 0 : nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
2778 0 : nsIFrame* rootFrame = shell->FrameConstructor()->GetRootFrame();
2779 0 : rootPresContext->ComputePluginGeometryUpdates(rootFrame, nullptr, nullptr);
2780 0 : rootPresContext->ApplyPluginGeometryUpdates();
2781 : }
2782 : }
2783 :
2784 0 : if (mPuppetWidget) {
2785 0 : mPuppetWidget->Show(false);
2786 : }
2787 : }
2788 :
2789 : NS_IMETHODIMP
2790 3 : TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
2791 : {
2792 3 : if (mTabChildGlobal) {
2793 3 : NS_ADDREF(*aResult = mTabChildGlobal);
2794 3 : return NS_OK;
2795 : }
2796 0 : *aResult = nullptr;
2797 0 : return NS_ERROR_FAILURE;
2798 : }
2799 :
2800 : NS_IMETHODIMP
2801 0 : TabChild::GetWebBrowserChrome(nsIWebBrowserChrome3** aWebBrowserChrome)
2802 : {
2803 0 : NS_IF_ADDREF(*aWebBrowserChrome = mWebBrowserChrome);
2804 0 : return NS_OK;
2805 : }
2806 :
2807 : NS_IMETHODIMP
2808 1 : TabChild::SetWebBrowserChrome(nsIWebBrowserChrome3* aWebBrowserChrome)
2809 : {
2810 1 : mWebBrowserChrome = aWebBrowserChrome;
2811 1 : return NS_OK;
2812 : }
2813 :
2814 : void
2815 0 : TabChild::SendRequestFocus(bool aCanFocus)
2816 : {
2817 0 : PBrowserChild::SendRequestFocus(aCanFocus);
2818 0 : }
2819 :
2820 : void
2821 0 : TabChild::SendGetTabCount(uint32_t* tabCount)
2822 : {
2823 0 : PBrowserChild::SendGetTabCount(tabCount);
2824 0 : }
2825 :
2826 : void
2827 2 : TabChild::EnableDisableCommands(const nsAString& aAction,
2828 : nsTArray<nsCString>& aEnabledCommands,
2829 : nsTArray<nsCString>& aDisabledCommands)
2830 : {
2831 4 : PBrowserChild::SendEnableDisableCommands(PromiseFlatString(aAction),
2832 2 : aEnabledCommands, aDisabledCommands);
2833 2 : }
2834 :
2835 : NS_IMETHODIMP
2836 0 : TabChild::GetTabId(uint64_t* aId)
2837 : {
2838 0 : *aId = GetTabId();
2839 0 : return NS_OK;
2840 : }
2841 :
2842 : void
2843 0 : TabChild::SetTabId(const TabId& aTabId)
2844 : {
2845 0 : MOZ_ASSERT(mUniqueId == 0);
2846 :
2847 0 : mUniqueId = aTabId;
2848 0 : NestedTabChildMap()[mUniqueId] = this;
2849 0 : }
2850 :
2851 : bool
2852 0 : TabChild::DoSendBlockingMessage(JSContext* aCx,
2853 : const nsAString& aMessage,
2854 : StructuredCloneData& aData,
2855 : JS::Handle<JSObject *> aCpows,
2856 : nsIPrincipal* aPrincipal,
2857 : nsTArray<StructuredCloneData>* aRetVal,
2858 : bool aIsSync)
2859 : {
2860 0 : ClonedMessageData data;
2861 0 : if (!BuildClonedMessageDataForChild(Manager(), aData, data)) {
2862 0 : return false;
2863 : }
2864 0 : InfallibleTArray<CpowEntry> cpows;
2865 0 : if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
2866 0 : return false;
2867 : }
2868 0 : if (aIsSync) {
2869 0 : return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
2870 0 : Principal(aPrincipal), aRetVal);
2871 : }
2872 :
2873 0 : return SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
2874 0 : Principal(aPrincipal), aRetVal);
2875 : }
2876 :
2877 : nsresult
2878 30 : TabChild::DoSendAsyncMessage(JSContext* aCx,
2879 : const nsAString& aMessage,
2880 : StructuredCloneData& aData,
2881 : JS::Handle<JSObject *> aCpows,
2882 : nsIPrincipal* aPrincipal)
2883 : {
2884 60 : ClonedMessageData data;
2885 30 : if (!BuildClonedMessageDataForChild(Manager(), aData, data)) {
2886 0 : return NS_ERROR_DOM_DATA_CLONE_ERR;
2887 : }
2888 60 : InfallibleTArray<CpowEntry> cpows;
2889 30 : if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
2890 0 : return NS_ERROR_UNEXPECTED;
2891 : }
2892 60 : if (!SendAsyncMessage(PromiseFlatString(aMessage), cpows,
2893 60 : Principal(aPrincipal), data)) {
2894 0 : return NS_ERROR_UNEXPECTED;
2895 : }
2896 30 : return NS_OK;
2897 : }
2898 :
2899 : /* static */ nsTArray<RefPtr<TabChild>>
2900 0 : TabChild::GetAll()
2901 : {
2902 0 : StaticMutexAutoLock lock(sTabChildrenMutex);
2903 :
2904 0 : nsTArray<RefPtr<TabChild>> list;
2905 0 : if (!sTabChildren) {
2906 0 : return list;
2907 : }
2908 :
2909 0 : for (auto iter = sTabChildren->Iter(); !iter.Done(); iter.Next()) {
2910 0 : list.AppendElement(iter.Data());
2911 : }
2912 :
2913 0 : return list;
2914 : }
2915 :
2916 : TabChild*
2917 0 : TabChild::GetFrom(nsIPresShell* aPresShell)
2918 : {
2919 0 : nsIDocument* doc = aPresShell->GetDocument();
2920 0 : if (!doc) {
2921 0 : return nullptr;
2922 : }
2923 0 : nsCOMPtr<nsIDocShell> docShell(doc->GetDocShell());
2924 0 : return GetFrom(docShell);
2925 : }
2926 :
2927 : TabChild*
2928 86 : TabChild::GetFrom(uint64_t aLayersId)
2929 : {
2930 172 : StaticMutexAutoLock lock(sTabChildrenMutex);
2931 86 : if (!sTabChildren) {
2932 30 : return nullptr;
2933 : }
2934 56 : return sTabChildren->Get(aLayersId);
2935 : }
2936 :
2937 : void
2938 27 : TabChild::DidComposite(uint64_t aTransactionId,
2939 : const TimeStamp& aCompositeStart,
2940 : const TimeStamp& aCompositeEnd)
2941 : {
2942 27 : MOZ_ASSERT(mPuppetWidget);
2943 27 : MOZ_ASSERT(mPuppetWidget->GetLayerManager());
2944 27 : MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
2945 : || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
2946 : || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
2947 :
2948 27 : mPuppetWidget->GetLayerManager()->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
2949 27 : }
2950 :
2951 : void
2952 4 : TabChild::DidRequestComposite(const TimeStamp& aCompositeReqStart,
2953 : const TimeStamp& aCompositeReqEnd)
2954 : {
2955 8 : nsCOMPtr<nsIDocShell> docShellComPtr = do_GetInterface(WebNavigation());
2956 4 : if (!docShellComPtr) {
2957 0 : return;
2958 : }
2959 :
2960 4 : nsDocShell* docShell = static_cast<nsDocShell*>(docShellComPtr.get());
2961 8 : RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
2962 :
2963 4 : if (timelines && timelines->HasConsumer(docShell)) {
2964 : // Since we're assuming that it's impossible for content JS to directly
2965 : // trigger a synchronous paint, we can avoid capturing a stack trace here,
2966 : // which means we won't run into JS engine reentrancy issues like bug
2967 : // 1310014.
2968 0 : timelines->AddMarkerForDocShell(docShell,
2969 : "CompositeForwardTransaction", aCompositeReqStart,
2970 0 : MarkerTracingType::START, MarkerStackRequest::NO_STACK);
2971 0 : timelines->AddMarkerForDocShell(docShell,
2972 : "CompositeForwardTransaction", aCompositeReqEnd,
2973 0 : MarkerTracingType::END, MarkerStackRequest::NO_STACK);
2974 : }
2975 : }
2976 :
2977 : void
2978 0 : TabChild::ClearCachedResources()
2979 : {
2980 0 : MOZ_ASSERT(mPuppetWidget);
2981 0 : MOZ_ASSERT(mPuppetWidget->GetLayerManager());
2982 0 : MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
2983 : || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
2984 : || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
2985 :
2986 0 : mPuppetWidget->GetLayerManager()->ClearCachedResources();
2987 0 : }
2988 :
2989 : void
2990 0 : TabChild::InvalidateLayers()
2991 : {
2992 0 : MOZ_ASSERT(mPuppetWidget);
2993 0 : MOZ_ASSERT(mPuppetWidget->GetLayerManager());
2994 0 : MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
2995 : || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
2996 : || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
2997 :
2998 0 : RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
2999 0 : FrameLayerBuilder::InvalidateAllLayers(lm);
3000 0 : }
3001 :
3002 : void
3003 0 : TabChild::ReinitRendering()
3004 : {
3005 0 : MOZ_ASSERT(mLayersId);
3006 :
3007 : // Before we establish a new PLayerTransaction, we must connect our layer tree
3008 : // id, CompositorBridge, and the widget compositor all together again.
3009 : // Normally this happens in TabParent before TabChild is given rendering
3010 : // information.
3011 : //
3012 : // In this case, we will send a sync message to our TabParent, which in turn
3013 : // will send a sync message to the Compositor of the widget owning this tab.
3014 : // This guarantees the correct association is in place before our
3015 : // PLayerTransaction constructor message arrives on the cross-process
3016 : // compositor bridge.
3017 0 : CompositorOptions options;
3018 0 : SendEnsureLayersConnected(&options);
3019 0 : mCompositorOptions = Some(options);
3020 :
3021 0 : RefPtr<CompositorBridgeChild> cb = CompositorBridgeChild::Get();
3022 0 : if (gfxVars::UseWebRender()) {
3023 0 : RefPtr<LayerManager> lm = mPuppetWidget->RecreateLayerManager(nullptr);
3024 0 : MOZ_ASSERT(lm->AsWebRenderLayerManager());
3025 0 : lm->AsWebRenderLayerManager()->Initialize(cb,
3026 : wr::AsPipelineId(mLayersId),
3027 0 : &mTextureFactoryIdentifier);
3028 : } else {
3029 0 : bool success = false;
3030 0 : nsTArray<LayersBackend> ignored;
3031 0 : PLayerTransactionChild* shadowManager = cb->SendPLayerTransactionConstructor(ignored, LayersId());
3032 0 : if (shadowManager &&
3033 0 : shadowManager->SendGetTextureFactoryIdentifier(&mTextureFactoryIdentifier) &&
3034 0 : mTextureFactoryIdentifier.mParentBackend != LayersBackend::LAYERS_NONE)
3035 : {
3036 0 : success = true;
3037 : }
3038 0 : if (!success) {
3039 0 : NS_WARNING("failed to re-allocate layer transaction");
3040 0 : return;
3041 : }
3042 :
3043 0 : RefPtr<LayerManager> lm = mPuppetWidget->RecreateLayerManager(shadowManager);
3044 0 : ShadowLayerForwarder* lf = lm->AsShadowForwarder();
3045 0 : lf->IdentifyTextureHost(mTextureFactoryIdentifier);
3046 : }
3047 :
3048 0 : ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
3049 0 : gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
3050 :
3051 0 : InitAPZState();
3052 :
3053 0 : nsCOMPtr<nsIDocument> doc(GetDocument());
3054 0 : doc->NotifyLayerManagerRecreated();
3055 : }
3056 :
3057 : void
3058 0 : TabChild::ReinitRenderingForDeviceReset()
3059 : {
3060 0 : InvalidateLayers();
3061 :
3062 0 : RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
3063 0 : if (WebRenderLayerManager* wlm = lm->AsWebRenderLayerManager()) {
3064 0 : wlm->DoDestroy(/* aIsSync */ true);
3065 0 : } else if (ClientLayerManager* clm = lm->AsClientLayerManager()) {
3066 0 : if (ShadowLayerForwarder* fwd = clm->AsShadowForwarder()) {
3067 : // Force the LayerTransactionChild to synchronously shutdown. It is
3068 : // okay to do this early, we'll simply stop sending messages. This
3069 : // step is necessary since otherwise the compositor will think we
3070 : // are trying to attach two layer trees to the same ID.
3071 0 : fwd->SynchronouslyShutdown();
3072 : }
3073 : } else {
3074 0 : return;
3075 : }
3076 :
3077 : // Proceed with destroying and recreating the layer manager.
3078 0 : ReinitRendering();
3079 : }
3080 :
3081 : void
3082 0 : TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier,
3083 : uint64_t aDeviceResetSeqNo)
3084 : {
3085 0 : MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
3086 : || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR
3087 : || (gfxPlatform::IsHeadless() && mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC));
3088 :
3089 0 : RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
3090 :
3091 0 : mTextureFactoryIdentifier = aNewIdentifier;
3092 0 : lm->UpdateTextureFactoryIdentifier(aNewIdentifier, aDeviceResetSeqNo);
3093 0 : FrameLayerBuilder::InvalidateAllLayers(lm);
3094 0 : }
3095 :
3096 : NS_IMETHODIMP
3097 0 : TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText,
3098 : const char16_t *aTipDir)
3099 : {
3100 0 : nsString str(aTipText);
3101 0 : nsString dir(aTipDir);
3102 0 : SendShowTooltip(aXCoords, aYCoords, str, dir);
3103 0 : return NS_OK;
3104 : }
3105 :
3106 : NS_IMETHODIMP
3107 0 : TabChild::OnHideTooltip()
3108 : {
3109 0 : SendHideTooltip();
3110 0 : return NS_OK;
3111 : }
3112 :
3113 : mozilla::ipc::IPCResult
3114 0 : TabChild::RecvRequestNotifyAfterRemotePaint()
3115 : {
3116 : // Get the CompositorBridgeChild instance for this content thread.
3117 0 : CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
3118 :
3119 : // Tell the CompositorBridgeChild that, when it gets a RemotePaintIsReady
3120 : // message that it should forward it us so that we can bounce it to our
3121 : // RenderFrameParent.
3122 0 : compositor->RequestNotifyAfterRemotePaint(this);
3123 0 : return IPC_OK();
3124 : }
3125 :
3126 : mozilla::ipc::IPCResult
3127 0 : TabChild::RecvUIResolutionChanged(const float& aDpi,
3128 : const int32_t& aRounding,
3129 : const double& aScale)
3130 : {
3131 0 : ScreenIntSize oldScreenSize = GetInnerSize();
3132 0 : mDPI = 0;
3133 0 : mRounding = 0;
3134 0 : mDefaultScale = 0;
3135 0 : static_cast<PuppetWidget*>(mPuppetWidget.get())->UpdateBackingScaleCache(aDpi, aRounding, aScale);
3136 0 : nsCOMPtr<nsIDocument> document(GetDocument());
3137 0 : nsCOMPtr<nsIPresShell> presShell = document->GetShell();
3138 0 : if (presShell) {
3139 0 : RefPtr<nsPresContext> presContext = presShell->GetPresContext();
3140 0 : if (presContext) {
3141 0 : presContext->UIResolutionChangedSync();
3142 : }
3143 : }
3144 :
3145 0 : ScreenIntSize screenSize = GetInnerSize();
3146 0 : if (mHasValidInnerSize && oldScreenSize != screenSize) {
3147 0 : ScreenIntRect screenRect = GetOuterRect();
3148 0 : mPuppetWidget->Resize(screenRect.x + mClientOffset.x + mChromeDisp.x,
3149 0 : screenRect.y + mClientOffset.y + mChromeDisp.y,
3150 0 : screenSize.width, screenSize.height, true);
3151 :
3152 0 : nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
3153 0 : baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
3154 0 : nsIBaseWindow::eRepaint);
3155 : }
3156 :
3157 0 : return IPC_OK();
3158 : }
3159 :
3160 : mozilla::ipc::IPCResult
3161 0 : TabChild::RecvThemeChanged(nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache)
3162 : {
3163 0 : LookAndFeel::SetIntCache(aLookAndFeelIntCache);
3164 0 : nsCOMPtr<nsIDocument> document(GetDocument());
3165 0 : nsCOMPtr<nsIPresShell> presShell = document->GetShell();
3166 0 : if (presShell) {
3167 0 : RefPtr<nsPresContext> presContext = presShell->GetPresContext();
3168 0 : if (presContext) {
3169 0 : presContext->ThemeChanged();
3170 : }
3171 : }
3172 0 : return IPC_OK();
3173 : }
3174 :
3175 : mozilla::ipc::IPCResult
3176 0 : TabChild::RecvAwaitLargeAlloc()
3177 : {
3178 0 : mAwaitingLA = true;
3179 0 : return IPC_OK();
3180 : }
3181 :
3182 : bool
3183 0 : TabChild::IsAwaitingLargeAlloc()
3184 : {
3185 0 : return mAwaitingLA;
3186 : }
3187 :
3188 : bool
3189 0 : TabChild::StopAwaitingLargeAlloc()
3190 : {
3191 0 : bool awaiting = mAwaitingLA;
3192 0 : mAwaitingLA = false;
3193 0 : return awaiting;
3194 : }
3195 :
3196 : mozilla::ipc::IPCResult
3197 0 : TabChild::RecvSetWindowName(const nsString& aName)
3198 : {
3199 0 : nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(WebNavigation());
3200 0 : if (item) {
3201 0 : item->SetName(aName);
3202 : }
3203 0 : return IPC_OK();
3204 : }
3205 :
3206 : mozilla::ipc::IPCResult
3207 0 : TabChild::RecvSetOriginAttributes(const OriginAttributes& aOriginAttributes)
3208 : {
3209 0 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
3210 0 : nsDocShell::Cast(docShell)->SetOriginAttributes(aOriginAttributes);
3211 :
3212 0 : return IPC_OK();
3213 : }
3214 :
3215 : mozilla::ipc::IPCResult
3216 1 : TabChild::RecvSetWidgetNativeData(const WindowsHandle& aWidgetNativeData)
3217 : {
3218 1 : mWidgetNativeData = aWidgetNativeData;
3219 1 : return IPC_OK();
3220 : }
3221 :
3222 : mozilla::plugins::PPluginWidgetChild*
3223 0 : TabChild::AllocPPluginWidgetChild()
3224 : {
3225 : #ifdef XP_WIN
3226 : return new mozilla::plugins::PluginWidgetChild();
3227 : #else
3228 0 : MOZ_ASSERT_UNREACHABLE();
3229 : return nullptr;
3230 : #endif
3231 : }
3232 :
3233 : bool
3234 0 : TabChild::DeallocPPluginWidgetChild(mozilla::plugins::PPluginWidgetChild* aActor)
3235 : {
3236 0 : delete aActor;
3237 0 : return true;
3238 : }
3239 :
3240 : #ifdef XP_WIN
3241 : nsresult
3242 : TabChild::CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut)
3243 : {
3244 : *aOut = nullptr;
3245 : mozilla::plugins::PluginWidgetChild* child =
3246 : static_cast<mozilla::plugins::PluginWidgetChild*>(SendPPluginWidgetConstructor());
3247 : if (!child) {
3248 : NS_ERROR("couldn't create PluginWidgetChild");
3249 : return NS_ERROR_UNEXPECTED;
3250 : }
3251 : nsCOMPtr<nsIWidget> pluginWidget = nsIWidget::CreatePluginProxyWidget(this, child);
3252 : if (!pluginWidget) {
3253 : NS_ERROR("couldn't create PluginWidgetProxy");
3254 : return NS_ERROR_UNEXPECTED;
3255 : }
3256 :
3257 : nsWidgetInitData initData;
3258 : initData.mWindowType = eWindowType_plugin_ipc_content;
3259 : initData.mUnicode = false;
3260 : initData.clipChildren = true;
3261 : initData.clipSiblings = true;
3262 : nsresult rv = pluginWidget->Create(aParent, nullptr,
3263 : LayoutDeviceIntRect(0, 0, 0, 0),
3264 : &initData);
3265 : if (NS_FAILED(rv)) {
3266 : NS_WARNING("Creating native plugin widget on the chrome side failed.");
3267 : }
3268 : pluginWidget.forget(aOut);
3269 : return rv;
3270 : }
3271 : #endif // XP_WIN
3272 :
3273 : PPaymentRequestChild*
3274 0 : TabChild::AllocPPaymentRequestChild()
3275 : {
3276 0 : MOZ_CRASH("We should never be manually allocating PPaymentRequestChild actors");
3277 : return nullptr;
3278 : }
3279 :
3280 : bool
3281 0 : TabChild::DeallocPPaymentRequestChild(PPaymentRequestChild* actor)
3282 : {
3283 0 : return true;
3284 : }
3285 :
3286 : ScreenIntSize
3287 3 : TabChild::GetInnerSize()
3288 : {
3289 : LayoutDeviceIntSize innerSize =
3290 3 : RoundedToInt(mUnscaledInnerSize * mPuppetWidget->GetDefaultScale());
3291 3 : return ViewAs<ScreenPixel>(innerSize, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
3292 : };
3293 :
3294 : ScreenIntRect
3295 3 : TabChild::GetOuterRect()
3296 : {
3297 : LayoutDeviceIntRect outerRect =
3298 3 : RoundedToInt(mUnscaledOuterRect * mPuppetWidget->GetDefaultScale());
3299 3 : return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
3300 : }
3301 :
3302 : void
3303 1 : TabChild::ForcePaint(uint64_t aLayerObserverEpoch)
3304 : {
3305 1 : if (!IPCOpen()) {
3306 : // Don't bother doing anything now. Better to wait until we receive the
3307 : // message on the PContent channel.
3308 1 : return;
3309 : }
3310 :
3311 0 : nsAutoScriptBlocker scriptBlocker;
3312 0 : RecvSetDocShellIsActive(true, false, aLayerObserverEpoch);
3313 : }
3314 :
3315 : void
3316 0 : TabChild::BeforeUnloadAdded()
3317 : {
3318 : // Don't bother notifying the parent if we don't have an IPC link open.
3319 0 : if (mBeforeUnloadListeners == 0 && IPCOpen()) {
3320 0 : SendSetHasBeforeUnload(true);
3321 : }
3322 :
3323 0 : mBeforeUnloadListeners++;
3324 0 : MOZ_ASSERT(mBeforeUnloadListeners >= 0);
3325 0 : }
3326 :
3327 : void
3328 0 : TabChild::BeforeUnloadRemoved()
3329 : {
3330 0 : mBeforeUnloadListeners--;
3331 0 : MOZ_ASSERT(mBeforeUnloadListeners >= 0);
3332 :
3333 : // Don't bother notifying the parent if we don't have an IPC link open.
3334 0 : if (mBeforeUnloadListeners == 0 && IPCOpen()) {
3335 0 : SendSetHasBeforeUnload(false);
3336 : }
3337 0 : }
3338 :
3339 : already_AddRefed<nsISHistory>
3340 0 : TabChild::GetRelatedSHistory()
3341 : {
3342 0 : nsCOMPtr<nsISHistory> shistory;
3343 0 : mWebNav->GetSessionHistory(getter_AddRefs(shistory));
3344 0 : return shistory.forget();
3345 : }
3346 :
3347 : nsresult
3348 0 : TabChildSHistoryListener::SHistoryDidUpdate(bool aTruncate /* = false */)
3349 : {
3350 0 : RefPtr<TabChild> tabChild(mTabChild);
3351 0 : if (NS_WARN_IF(!tabChild)) {
3352 0 : return NS_ERROR_FAILURE;
3353 : }
3354 :
3355 0 : nsCOMPtr<nsISHistory> shistory = tabChild->GetRelatedSHistory();
3356 0 : NS_ENSURE_TRUE(shistory, NS_ERROR_FAILURE);
3357 :
3358 : int32_t index, count;
3359 0 : nsresult rv = shistory->GetIndex(&index);
3360 0 : NS_ENSURE_SUCCESS(rv, rv);
3361 0 : rv = shistory->GetCount(&count);
3362 0 : NS_ENSURE_SUCCESS(rv, rv);
3363 :
3364 : // XXX: It would be nice if we could batch these updates like SessionStore
3365 : // does, and provide a form of `Flush` command which would allow us to trigger
3366 : // an update, and wait for the state to become consistent.
3367 0 : NS_ENSURE_TRUE(tabChild->SendSHistoryUpdate(count, index, aTruncate), NS_ERROR_FAILURE);
3368 0 : return NS_OK;
3369 : }
3370 :
3371 : mozilla::dom::TabGroup*
3372 35 : TabChild::TabGroup()
3373 : {
3374 35 : return mTabGroup;
3375 : }
3376 :
3377 : /*******************************************************************************
3378 : * nsISHistoryListener
3379 : ******************************************************************************/
3380 :
3381 : NS_IMETHODIMP
3382 0 : TabChildSHistoryListener::OnHistoryNewEntry(nsIURI *aNewURI, int32_t aOldIndex)
3383 : {
3384 0 : return NS_ERROR_NOT_IMPLEMENTED;
3385 : }
3386 :
3387 : NS_IMETHODIMP
3388 0 : TabChildSHistoryListener::OnHistoryGoBack(nsIURI *aBackURI, bool *_retval)
3389 : {
3390 0 : return NS_ERROR_NOT_IMPLEMENTED;
3391 : }
3392 :
3393 : NS_IMETHODIMP
3394 0 : TabChildSHistoryListener::OnHistoryGoForward(nsIURI *aForwardURI, bool *_retval)
3395 : {
3396 0 : return NS_ERROR_NOT_IMPLEMENTED;
3397 : }
3398 :
3399 : NS_IMETHODIMP
3400 0 : TabChildSHistoryListener::OnHistoryReload(nsIURI *aReloadURI, uint32_t aReloadFlags, bool *_retval)
3401 : {
3402 0 : return NS_ERROR_NOT_IMPLEMENTED;
3403 : }
3404 :
3405 : NS_IMETHODIMP
3406 0 : TabChildSHistoryListener::OnHistoryGotoIndex(int32_t aIndex, nsIURI *aGotoURI, bool *_retval)
3407 : {
3408 0 : return NS_ERROR_NOT_IMPLEMENTED;
3409 : }
3410 :
3411 : NS_IMETHODIMP
3412 0 : TabChildSHistoryListener::OnHistoryPurge(int32_t aNumEntries, bool *_retval)
3413 : {
3414 0 : return NS_ERROR_NOT_IMPLEMENTED;
3415 : }
3416 :
3417 : NS_IMETHODIMP
3418 0 : TabChildSHistoryListener::OnHistoryReplaceEntry(int32_t aIndex)
3419 : {
3420 0 : return NS_ERROR_NOT_IMPLEMENTED;
3421 : }
3422 :
3423 : NS_IMETHODIMP
3424 0 : TabChildSHistoryListener::OnLengthChanged(int32_t aCount)
3425 : {
3426 0 : return SHistoryDidUpdate(/* aTruncate = */ true);
3427 : }
3428 :
3429 : NS_IMETHODIMP
3430 0 : TabChildSHistoryListener::OnIndexChanged(int32_t aIndex)
3431 : {
3432 0 : return SHistoryDidUpdate(/* aTruncate = */ false);
3433 : }
3434 :
3435 : NS_IMETHODIMP
3436 0 : TabChildSHistoryListener::OnRequestCrossBrowserNavigation(uint32_t aIndex)
3437 : {
3438 0 : RefPtr<TabChild> tabChild(mTabChild);
3439 0 : if (!tabChild) {
3440 0 : return NS_ERROR_FAILURE;
3441 : }
3442 :
3443 0 : return tabChild->SendRequestCrossBrowserNavigation(aIndex) ?
3444 0 : NS_OK : NS_ERROR_FAILURE;
3445 : }
3446 :
3447 1 : TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
3448 1 : : mTabChild(aTabChild)
3449 : {
3450 1 : SetIsNotDOMBinding();
3451 1 : }
3452 :
3453 0 : TabChildGlobal::~TabChildGlobal()
3454 : {
3455 0 : }
3456 :
3457 : void
3458 1 : TabChildGlobal::Init()
3459 : {
3460 1 : NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
3461 : mMessageManager = new nsFrameMessageManager(mTabChild,
3462 : nullptr,
3463 2 : MM_CHILD);
3464 :
3465 1 : TelemetryScrollProbe::Create(this);
3466 1 : }
3467 :
3468 : NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildGlobal)
3469 :
3470 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TabChildGlobal,
3471 : DOMEventTargetHelper)
3472 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager);
3473 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild);
3474 0 : tmp->UnlinkHostObjectURIs();
3475 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
3476 :
3477 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TabChildGlobal,
3478 : DOMEventTargetHelper)
3479 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
3480 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
3481 0 : tmp->TraverseHostObjectURIs(cb);
3482 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
3483 :
3484 1180 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
3485 1179 : NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
3486 1178 : NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
3487 1177 : NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
3488 1177 : NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
3489 1173 : NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
3490 1173 : NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
3491 248 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
3492 248 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
3493 247 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
3494 :
3495 1771 : NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
3496 1763 : NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper)
3497 :
3498 : // This method isn't automatically forwarded safely because it's notxpcom, so
3499 : // the IDL binding doesn't know what value to return.
3500 : NS_IMETHODIMP_(bool)
3501 0 : TabChildGlobal::MarkForCC()
3502 : {
3503 0 : if (mTabChild) {
3504 0 : mTabChild->MarkScopesForCC();
3505 : }
3506 0 : EventListenerManager* elm = GetExistingListenerManager();
3507 0 : if (elm) {
3508 0 : elm->MarkForCC();
3509 : }
3510 0 : return mMessageManager ? mMessageManager->MarkForCC() : false;
3511 : }
3512 :
3513 : NS_IMETHODIMP
3514 78 : TabChildGlobal::GetContent(mozIDOMWindowProxy** aContent)
3515 : {
3516 78 : *aContent = nullptr;
3517 78 : if (!mTabChild)
3518 0 : return NS_ERROR_NULL_POINTER;
3519 156 : nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mTabChild->WebNavigation());
3520 78 : window.forget(aContent);
3521 78 : return NS_OK;
3522 : }
3523 :
3524 : NS_IMETHODIMP
3525 42 : TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
3526 : {
3527 42 : *aDocShell = nullptr;
3528 42 : if (!mTabChild)
3529 0 : return NS_ERROR_NULL_POINTER;
3530 84 : nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
3531 42 : docShell.swap(*aDocShell);
3532 42 : return NS_OK;
3533 : }
3534 :
3535 : nsIPrincipal*
3536 0 : TabChildGlobal::GetPrincipal()
3537 : {
3538 0 : if (!mTabChild)
3539 0 : return nullptr;
3540 0 : return mTabChild->GetPrincipal();
3541 : }
3542 :
3543 : JSObject*
3544 2070 : TabChildGlobal::GetGlobalJSObject()
3545 : {
3546 2070 : NS_ENSURE_TRUE(mTabChild, nullptr);
3547 2070 : return mTabChild->GetGlobal();
3548 : }
3549 :
3550 : nsresult
3551 0 : TabChildGlobal::Dispatch(const char* aName,
3552 : TaskCategory aCategory,
3553 : already_AddRefed<nsIRunnable>&& aRunnable)
3554 : {
3555 0 : if (mTabChild && mTabChild->TabGroup()) {
3556 0 : return mTabChild->TabGroup()->Dispatch(aName, aCategory, Move(aRunnable));
3557 : }
3558 0 : return DispatcherTrait::Dispatch(aName, aCategory, Move(aRunnable));
3559 : }
3560 :
3561 : nsISerialEventTarget*
3562 0 : TabChildGlobal::EventTargetFor(TaskCategory aCategory) const
3563 : {
3564 0 : if (mTabChild && mTabChild->TabGroup()) {
3565 0 : return mTabChild->TabGroup()->EventTargetFor(aCategory);
3566 : }
3567 0 : return DispatcherTrait::EventTargetFor(aCategory);
3568 : }
3569 :
3570 : AbstractThread*
3571 0 : TabChildGlobal::AbstractMainThreadFor(TaskCategory aCategory)
3572 : {
3573 0 : if (mTabChild && mTabChild->TabGroup()) {
3574 0 : return mTabChild->TabGroup()->AbstractMainThreadFor(aCategory);
3575 : }
3576 0 : return DispatcherTrait::AbstractMainThreadFor(aCategory);
3577 : }
|