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