|
1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */ |
|
2 /* vim: set sw=2 sts=2 ts=8 et 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 "Layers.h" |
|
12 #include "ContentChild.h" |
|
13 #include "IndexedDBChild.h" |
|
14 #include "mozilla/Preferences.h" |
|
15 #include "mozilla/ClearOnShutdown.h" |
|
16 #include "mozilla/EventListenerManager.h" |
|
17 #include "mozilla/IntentionalCrash.h" |
|
18 #include "mozilla/docshell/OfflineCacheUpdateChild.h" |
|
19 #include "mozilla/ipc/DocumentRendererChild.h" |
|
20 #include "mozilla/ipc/FileDescriptorUtils.h" |
|
21 #include "mozilla/layers/ActiveElementManager.h" |
|
22 #include "mozilla/layers/APZCCallbackHelper.h" |
|
23 #include "mozilla/layers/AsyncPanZoomController.h" |
|
24 #include "mozilla/layers/CompositorChild.h" |
|
25 #include "mozilla/layers/ImageBridgeChild.h" |
|
26 #include "mozilla/layers/ShadowLayers.h" |
|
27 #include "mozilla/layout/RenderFrameChild.h" |
|
28 #include "mozilla/MouseEvents.h" |
|
29 #include "mozilla/Services.h" |
|
30 #include "mozilla/StaticPtr.h" |
|
31 #include "mozilla/TextEvents.h" |
|
32 #include "mozilla/TouchEvents.h" |
|
33 #include "mozilla/unused.h" |
|
34 #include "mozIApplication.h" |
|
35 #include "nsContentUtils.h" |
|
36 #include "nsCxPusher.h" |
|
37 #include "nsEmbedCID.h" |
|
38 #include <algorithm> |
|
39 #ifdef MOZ_CRASHREPORTER |
|
40 #include "nsExceptionHandler.h" |
|
41 #endif |
|
42 #include "nsFilePickerProxy.h" |
|
43 #include "mozilla/dom/Element.h" |
|
44 #include "nsIBaseWindow.h" |
|
45 #include "nsICachedFileDescriptorListener.h" |
|
46 #include "nsIDocumentInlines.h" |
|
47 #include "nsIDocShellTreeOwner.h" |
|
48 #include "nsIDOMEvent.h" |
|
49 #include "nsIDOMWindow.h" |
|
50 #include "nsIDOMWindowUtils.h" |
|
51 #include "nsIDocShell.h" |
|
52 #include "nsIURI.h" |
|
53 #include "nsIURIFixup.h" |
|
54 #include "nsCDefaultURIFixup.h" |
|
55 #include "nsIWebBrowser.h" |
|
56 #include "nsIWebBrowserFocus.h" |
|
57 #include "nsIWebBrowserSetup.h" |
|
58 #include "nsIWebProgress.h" |
|
59 #include "nsIXULRuntime.h" |
|
60 #include "nsInterfaceHashtable.h" |
|
61 #include "nsPIDOMWindow.h" |
|
62 #include "nsPIWindowRoot.h" |
|
63 #include "nsLayoutUtils.h" |
|
64 #include "nsPrintfCString.h" |
|
65 #include "nsThreadUtils.h" |
|
66 #include "nsWeakReference.h" |
|
67 #include "PermissionMessageUtils.h" |
|
68 #include "PCOMContentPermissionRequestChild.h" |
|
69 #include "PuppetWidget.h" |
|
70 #include "StructuredCloneUtils.h" |
|
71 #include "nsViewportInfo.h" |
|
72 #include "JavaScriptChild.h" |
|
73 #include "nsILoadContext.h" |
|
74 #include "ipc/nsGUIEventIPC.h" |
|
75 #include "mozilla/gfx/Matrix.h" |
|
76 #include "UnitTransforms.h" |
|
77 #include "ClientLayerManager.h" |
|
78 |
|
79 #include "nsColorPickerProxy.h" |
|
80 |
|
81 #ifdef DEBUG |
|
82 #include "PCOMContentPermissionRequestChild.h" |
|
83 #endif /* DEBUG */ |
|
84 |
|
85 #define BROWSER_ELEMENT_CHILD_SCRIPT \ |
|
86 NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") |
|
87 |
|
88 using namespace mozilla; |
|
89 using namespace mozilla::dom; |
|
90 using namespace mozilla::dom::ipc; |
|
91 using namespace mozilla::ipc; |
|
92 using namespace mozilla::layers; |
|
93 using namespace mozilla::layout; |
|
94 using namespace mozilla::docshell; |
|
95 using namespace mozilla::dom::indexedDB; |
|
96 using namespace mozilla::widget; |
|
97 using namespace mozilla::jsipc; |
|
98 |
|
99 NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener) |
|
100 |
|
101 static const CSSSize kDefaultViewportSize(980, 480); |
|
102 |
|
103 static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect"; |
|
104 static const char BEFORE_FIRST_PAINT[] = "before-first-paint"; |
|
105 |
|
106 static bool sCpowsEnabled = false; |
|
107 static int32_t sActiveDurationMs = 10; |
|
108 static bool sActiveDurationMsSet = false; |
|
109 |
|
110 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap; |
|
111 static TabChildMap* sTabChildren; |
|
112 |
|
113 TabChildBase::TabChildBase() |
|
114 : mOldViewportWidth(0.0f) |
|
115 , mContentDocumentIsDisplayed(false) |
|
116 , mTabChildGlobal(nullptr) |
|
117 , mInnerSize(0, 0) |
|
118 { |
|
119 } |
|
120 |
|
121 NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase) |
|
122 NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase) |
|
123 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase) |
|
124 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
125 NS_INTERFACE_MAP_END |
|
126 |
|
127 NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal) |
|
128 |
|
129 void |
|
130 TabChildBase::InitializeRootMetrics() |
|
131 { |
|
132 // Calculate a really simple resolution that we probably won't |
|
133 // be keeping, as well as putting the scroll offset back to |
|
134 // the top-left of the page. |
|
135 mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize); |
|
136 mLastRootMetrics.mCompositionBounds = ParentLayerIntRect( |
|
137 ParentLayerIntPoint(), |
|
138 ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)); |
|
139 mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale()); |
|
140 mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale(); |
|
141 // We use ScreenToLayerScale(1) below in order to turn the |
|
142 // async zoom amount into the gecko zoom amount. |
|
143 mLastRootMetrics.mCumulativeResolution = |
|
144 mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); |
|
145 // This is the root layer, so the cumulative resolution is the same |
|
146 // as the resolution. |
|
147 mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); |
|
148 mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); |
|
149 } |
|
150 |
|
151 bool |
|
152 TabChildBase::HasValidInnerSize() |
|
153 { |
|
154 return (mInnerSize.width != 0) && (mInnerSize.height != 0); |
|
155 } |
|
156 |
|
157 void |
|
158 TabChildBase::SetCSSViewport(const CSSSize& aSize) |
|
159 { |
|
160 mOldViewportWidth = aSize.width; |
|
161 |
|
162 if (mContentDocumentIsDisplayed) { |
|
163 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
164 utils->SetCSSViewport(aSize.width, aSize.height); |
|
165 } |
|
166 } |
|
167 |
|
168 CSSSize |
|
169 TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport) |
|
170 { |
|
171 nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement(); |
|
172 HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement(); |
|
173 |
|
174 if (!htmlDOMElement && !bodyDOMElement) { |
|
175 // For non-HTML content (e.g. SVG), just assume page size == viewport size. |
|
176 return aViewport; |
|
177 } |
|
178 |
|
179 int32_t htmlWidth = 0, htmlHeight = 0; |
|
180 if (htmlDOMElement) { |
|
181 htmlWidth = htmlDOMElement->ScrollWidth(); |
|
182 htmlHeight = htmlDOMElement->ScrollHeight(); |
|
183 } |
|
184 int32_t bodyWidth = 0, bodyHeight = 0; |
|
185 if (bodyDOMElement) { |
|
186 bodyWidth = bodyDOMElement->ScrollWidth(); |
|
187 bodyHeight = bodyDOMElement->ScrollHeight(); |
|
188 } |
|
189 return CSSSize(std::max(htmlWidth, bodyWidth), |
|
190 std::max(htmlHeight, bodyHeight)); |
|
191 } |
|
192 |
|
193 bool |
|
194 TabChildBase::HandlePossibleViewportChange() |
|
195 { |
|
196 if (!IsAsyncPanZoomEnabled()) { |
|
197 return false; |
|
198 } |
|
199 |
|
200 nsCOMPtr<nsIDocument> document(GetDocument()); |
|
201 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
202 |
|
203 nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize); |
|
204 uint32_t presShellId; |
|
205 mozilla::layers::FrameMetrics::ViewID viewId; |
|
206 bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers( |
|
207 document->GetDocumentElement(), &presShellId, &viewId); |
|
208 if (scrollIdentifiersValid) { |
|
209 ZoomConstraints constraints( |
|
210 viewportInfo.IsZoomAllowed(), |
|
211 viewportInfo.IsDoubleTapZoomAllowed(), |
|
212 viewportInfo.GetMinZoom(), |
|
213 viewportInfo.GetMaxZoom()); |
|
214 DoUpdateZoomConstraints(presShellId, |
|
215 viewId, |
|
216 /* isRoot = */ true, |
|
217 constraints); |
|
218 } |
|
219 |
|
220 float screenW = mInnerSize.width; |
|
221 float screenH = mInnerSize.height; |
|
222 CSSSize viewport(viewportInfo.GetSize()); |
|
223 |
|
224 // We're not being displayed in any way; don't bother doing anything because |
|
225 // that will just confuse future adjustments. |
|
226 if (!screenW || !screenH) { |
|
227 return false; |
|
228 } |
|
229 |
|
230 float oldBrowserWidth = mOldViewportWidth; |
|
231 mLastRootMetrics.mViewport.SizeTo(viewport); |
|
232 if (!oldBrowserWidth) { |
|
233 oldBrowserWidth = kDefaultViewportSize.width; |
|
234 } |
|
235 SetCSSViewport(viewport); |
|
236 |
|
237 // If this page has not been painted yet, then this must be getting run |
|
238 // because a meta-viewport element was added (via the DOMMetaAdded handler). |
|
239 // in this case, we should not do anything that forces a reflow (see bug |
|
240 // 759678) such as requesting the page size or sending a viewport update. this |
|
241 // code will get run again in the before-first-paint handler and that point we |
|
242 // will run though all of it. the reason we even bother executing up to this |
|
243 // point on the DOMMetaAdded handler is so that scripts that use |
|
244 // window.innerWidth before they are painted have a correct value (bug |
|
245 // 771575). |
|
246 if (!mContentDocumentIsDisplayed) { |
|
247 return false; |
|
248 } |
|
249 |
|
250 float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width; |
|
251 if (!oldScreenWidth) { |
|
252 oldScreenWidth = mInnerSize.width; |
|
253 } |
|
254 |
|
255 FrameMetrics metrics(mLastRootMetrics); |
|
256 metrics.mViewport = CSSRect(CSSPoint(), viewport); |
|
257 metrics.mCompositionBounds = ParentLayerIntRect( |
|
258 ParentLayerIntPoint(), |
|
259 ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)); |
|
260 metrics.SetRootCompositionSize( |
|
261 ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel); |
|
262 |
|
263 // This change to the zoom accounts for all types of changes I can conceive: |
|
264 // 1. screen size changes, CSS viewport does not (pages with no meta viewport |
|
265 // or a fixed size viewport) |
|
266 // 2. screen size changes, CSS viewport also does (pages with a device-width |
|
267 // viewport) |
|
268 // 3. screen size remains constant, but CSS viewport changes (meta viewport |
|
269 // tag is added or removed) |
|
270 // 4. neither screen size nor CSS viewport changes |
|
271 // |
|
272 // In all of these cases, we maintain how much actual content is visible |
|
273 // within the screen width. Note that "actual content" may be different with |
|
274 // respect to CSS pixels because of the CSS viewport size changing. |
|
275 float oldIntrinsicScale = oldScreenWidth / oldBrowserWidth; |
|
276 metrics.ZoomBy(metrics.CalculateIntrinsicScale().scale / oldIntrinsicScale); |
|
277 |
|
278 // Changing the zoom when we're not doing a first paint will get ignored |
|
279 // by AsyncPanZoomController and causes a blurry flash. |
|
280 bool isFirstPaint; |
|
281 nsresult rv = utils->GetIsFirstPaint(&isFirstPaint); |
|
282 if (NS_FAILED(rv) || isFirstPaint) { |
|
283 // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of |
|
284 // 0.0 to mean "did not calculate a zoom". In that case, we default |
|
285 // it to the intrinsic scale. |
|
286 if (viewportInfo.GetDefaultZoom().scale < 0.01f) { |
|
287 viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale()); |
|
288 } |
|
289 |
|
290 CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom(); |
|
291 MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom && |
|
292 defaultZoom <= viewportInfo.GetMaxZoom()); |
|
293 metrics.SetZoom(defaultZoom); |
|
294 |
|
295 metrics.SetScrollId(viewId); |
|
296 } |
|
297 |
|
298 metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); |
|
299 // This is the root layer, so the cumulative resolution is the same |
|
300 // as the resolution. |
|
301 metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); |
|
302 utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); |
|
303 |
|
304 CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); |
|
305 utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); |
|
306 |
|
307 // The call to GetPageSize forces a resize event to content, so we need to |
|
308 // make sure that we have the right CSS viewport and |
|
309 // scrollPositionClampingScrollPortSize set up before that happens. |
|
310 |
|
311 CSSSize pageSize = GetPageSize(document, viewport); |
|
312 if (!pageSize.width) { |
|
313 // Return early rather than divide by 0. |
|
314 return false; |
|
315 } |
|
316 metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize); |
|
317 |
|
318 // Calculate a display port _after_ having a scrollable rect because the |
|
319 // display port is clamped to the scrollable rect. |
|
320 metrics.SetDisplayPortMargins(AsyncPanZoomController::CalculatePendingDisplayPort( |
|
321 // The page must have been refreshed in some way such as a new document or |
|
322 // new CSS viewport, so we know that there's no velocity, acceleration, and |
|
323 // we have no idea how long painting will take. |
|
324 metrics, ScreenPoint(0.0f, 0.0f), 0.0)); |
|
325 metrics.SetUseDisplayPortMargins(); |
|
326 |
|
327 // Force a repaint with these metrics. This, among other things, sets the |
|
328 // displayport, so we start with async painting. |
|
329 mLastRootMetrics = ProcessUpdateFrame(metrics); |
|
330 |
|
331 if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) { |
|
332 // If the CSS viewport is narrower than the screen (i.e. width <= device-width) |
|
333 // then we disable double-tap-to-zoom behaviour. |
|
334 bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale); |
|
335 if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) { |
|
336 viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom); |
|
337 |
|
338 ZoomConstraints constraints( |
|
339 viewportInfo.IsZoomAllowed(), |
|
340 viewportInfo.IsDoubleTapZoomAllowed(), |
|
341 viewportInfo.GetMinZoom(), |
|
342 viewportInfo.GetMaxZoom()); |
|
343 DoUpdateZoomConstraints(presShellId, |
|
344 viewId, |
|
345 /* isRoot = */ true, |
|
346 constraints); |
|
347 } |
|
348 } |
|
349 |
|
350 return true; |
|
351 } |
|
352 |
|
353 already_AddRefed<nsIDOMWindowUtils> |
|
354 TabChildBase::GetDOMWindowUtils() |
|
355 { |
|
356 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation()); |
|
357 nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window); |
|
358 return utils.forget(); |
|
359 } |
|
360 |
|
361 already_AddRefed<nsIDocument> |
|
362 TabChildBase::GetDocument() |
|
363 { |
|
364 nsCOMPtr<nsIDOMDocument> domDoc; |
|
365 WebNavigation()->GetDocument(getter_AddRefs(domDoc)); |
|
366 nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc)); |
|
367 return doc.forget(); |
|
368 } |
|
369 |
|
370 void |
|
371 TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, |
|
372 const nsAString& aJSONData) |
|
373 { |
|
374 AutoSafeJSContext cx; |
|
375 JS::Rooted<JS::Value> json(cx, JSVAL_NULL); |
|
376 StructuredCloneData cloneData; |
|
377 JSAutoStructuredCloneBuffer buffer; |
|
378 if (JS_ParseJSON(cx, |
|
379 static_cast<const jschar*>(aJSONData.BeginReading()), |
|
380 aJSONData.Length(), |
|
381 &json)) { |
|
382 WriteStructuredClone(cx, json, buffer, cloneData.mClosure); |
|
383 cloneData.mData = buffer.data(); |
|
384 cloneData.mDataLength = buffer.nbytes(); |
|
385 } |
|
386 |
|
387 nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal()); |
|
388 // Let the BrowserElementScrolling helper (if it exists) for this |
|
389 // content manipulate the frame state. |
|
390 nsRefPtr<nsFrameMessageManager> mm = |
|
391 static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get()); |
|
392 mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), |
|
393 aMessageName, false, &cloneData, nullptr, nullptr, nullptr); |
|
394 } |
|
395 |
|
396 bool |
|
397 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics) |
|
398 { |
|
399 MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID); |
|
400 |
|
401 if (aFrameMetrics.mIsRoot) { |
|
402 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
403 if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) { |
|
404 mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics); |
|
405 APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, mLastRootMetrics); |
|
406 return true; |
|
407 } |
|
408 } else { |
|
409 // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe. |
|
410 // This requires special handling. |
|
411 nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor( |
|
412 aFrameMetrics.GetScrollId()); |
|
413 if (content) { |
|
414 FrameMetrics newSubFrameMetrics(aFrameMetrics); |
|
415 APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics); |
|
416 APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, newSubFrameMetrics); |
|
417 return true; |
|
418 } |
|
419 } |
|
420 |
|
421 // We've recieved a message that is out of date and we want to ignore. |
|
422 // However we can't reply without painting so we reply by painting the |
|
423 // exact same thing as we did before. |
|
424 mLastRootMetrics = ProcessUpdateFrame(mLastRootMetrics); |
|
425 return true; |
|
426 } |
|
427 |
|
428 FrameMetrics |
|
429 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) |
|
430 { |
|
431 if (!mGlobal || !mTabChildGlobal) { |
|
432 return aFrameMetrics; |
|
433 } |
|
434 |
|
435 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
436 |
|
437 FrameMetrics newMetrics = aFrameMetrics; |
|
438 APZCCallbackHelper::UpdateRootFrame(utils, newMetrics); |
|
439 |
|
440 CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels(); |
|
441 // The BrowserElementScrolling helper must know about these updated metrics |
|
442 // for other functions it performs, such as double tap handling. |
|
443 // Note, %f must not be used because it is locale specific! |
|
444 nsString data; |
|
445 data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.GetScrollOffset().x)); |
|
446 data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.GetScrollOffset().y)); |
|
447 data.AppendLiteral(", \"viewport\" : "); |
|
448 data.AppendLiteral("{ \"width\" : "); |
|
449 data.AppendFloat(newMetrics.mViewport.width); |
|
450 data.AppendLiteral(", \"height\" : "); |
|
451 data.AppendFloat(newMetrics.mViewport.height); |
|
452 data.AppendLiteral(" }"); |
|
453 data.AppendLiteral(", \"cssPageRect\" : "); |
|
454 data.AppendLiteral("{ \"x\" : "); |
|
455 data.AppendFloat(newMetrics.mScrollableRect.x); |
|
456 data.AppendLiteral(", \"y\" : "); |
|
457 data.AppendFloat(newMetrics.mScrollableRect.y); |
|
458 data.AppendLiteral(", \"width\" : "); |
|
459 data.AppendFloat(newMetrics.mScrollableRect.width); |
|
460 data.AppendLiteral(", \"height\" : "); |
|
461 data.AppendFloat(newMetrics.mScrollableRect.height); |
|
462 data.AppendLiteral(" }"); |
|
463 data.AppendPrintf(", \"resolution\" : "); // TODO: check if it's actually used? |
|
464 data.AppendPrintf("{ \"width\" : "); |
|
465 data.AppendFloat(newMetrics.CalculateIntrinsicScale().scale); |
|
466 data.AppendPrintf(" }"); |
|
467 data.AppendLiteral(", \"cssCompositedRect\" : "); |
|
468 data.AppendLiteral("{ \"width\" : "); |
|
469 data.AppendFloat(cssCompositedSize.width); |
|
470 data.AppendLiteral(", \"height\" : "); |
|
471 data.AppendFloat(cssCompositedSize.height); |
|
472 data.AppendLiteral(" }"); |
|
473 data.AppendLiteral(" }"); |
|
474 |
|
475 DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data); |
|
476 return newMetrics; |
|
477 } |
|
478 |
|
479 nsEventStatus |
|
480 TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime, |
|
481 const LayoutDevicePoint& aRefPoint, |
|
482 nsIWidget* aWidget) |
|
483 { |
|
484 MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN || |
|
485 aMsg == NS_MOUSE_BUTTON_UP); |
|
486 |
|
487 WidgetMouseEvent event(true, aMsg, nullptr, |
|
488 WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); |
|
489 event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y); |
|
490 event.time = aTime; |
|
491 event.button = WidgetMouseEvent::eLeftButton; |
|
492 event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; |
|
493 if (aMsg != NS_MOUSE_MOVE) { |
|
494 event.clickCount = 1; |
|
495 } |
|
496 event.widget = aWidget; |
|
497 |
|
498 return DispatchWidgetEvent(event); |
|
499 } |
|
500 |
|
501 nsEventStatus |
|
502 TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event) |
|
503 { |
|
504 if (!event.widget) |
|
505 return nsEventStatus_eConsumeNoDefault; |
|
506 |
|
507 nsEventStatus status; |
|
508 NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status), |
|
509 nsEventStatus_eConsumeNoDefault); |
|
510 return status; |
|
511 } |
|
512 |
|
513 bool |
|
514 TabChildBase::IsAsyncPanZoomEnabled() |
|
515 { |
|
516 return mScrolling == ASYNC_PAN_ZOOM; |
|
517 } |
|
518 |
|
519 NS_IMETHODIMP |
|
520 ContentListener::HandleEvent(nsIDOMEvent* aEvent) |
|
521 { |
|
522 RemoteDOMEvent remoteEvent; |
|
523 remoteEvent.mEvent = do_QueryInterface(aEvent); |
|
524 NS_ENSURE_STATE(remoteEvent.mEvent); |
|
525 mTabChild->SendEvent(remoteEvent); |
|
526 return NS_OK; |
|
527 } |
|
528 |
|
529 class TabChild::CachedFileDescriptorInfo |
|
530 { |
|
531 struct PathOnlyComparatorHelper |
|
532 { |
|
533 bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a, |
|
534 const CachedFileDescriptorInfo& b) const |
|
535 { |
|
536 return a->mPath == b.mPath; |
|
537 } |
|
538 }; |
|
539 |
|
540 struct PathAndCallbackComparatorHelper |
|
541 { |
|
542 bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a, |
|
543 const CachedFileDescriptorInfo& b) const |
|
544 { |
|
545 return a->mPath == b.mPath && |
|
546 a->mCallback == b.mCallback; |
|
547 } |
|
548 }; |
|
549 |
|
550 public: |
|
551 nsString mPath; |
|
552 FileDescriptor mFileDescriptor; |
|
553 nsCOMPtr<nsICachedFileDescriptorListener> mCallback; |
|
554 bool mCanceled; |
|
555 |
|
556 CachedFileDescriptorInfo(const nsAString& aPath) |
|
557 : mPath(aPath), mCanceled(false) |
|
558 { } |
|
559 |
|
560 CachedFileDescriptorInfo(const nsAString& aPath, |
|
561 const FileDescriptor& aFileDescriptor) |
|
562 : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false) |
|
563 { } |
|
564 |
|
565 CachedFileDescriptorInfo(const nsAString& aPath, |
|
566 nsICachedFileDescriptorListener* aCallback) |
|
567 : mPath(aPath), mCallback(aCallback), mCanceled(false) |
|
568 { } |
|
569 |
|
570 PathOnlyComparatorHelper PathOnlyComparator() const |
|
571 { |
|
572 return PathOnlyComparatorHelper(); |
|
573 } |
|
574 |
|
575 PathAndCallbackComparatorHelper PathAndCallbackComparator() const |
|
576 { |
|
577 return PathAndCallbackComparatorHelper(); |
|
578 } |
|
579 |
|
580 void FireCallback() const |
|
581 { |
|
582 mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor); |
|
583 } |
|
584 }; |
|
585 |
|
586 class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable |
|
587 { |
|
588 typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo; |
|
589 |
|
590 nsAutoPtr<CachedFileDescriptorInfo> mInfo; |
|
591 |
|
592 public: |
|
593 CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo) |
|
594 : mInfo(aInfo) |
|
595 { |
|
596 MOZ_ASSERT(NS_IsMainThread()); |
|
597 MOZ_ASSERT(aInfo); |
|
598 MOZ_ASSERT(!aInfo->mPath.IsEmpty()); |
|
599 MOZ_ASSERT(aInfo->mCallback); |
|
600 } |
|
601 |
|
602 void Dispatch() |
|
603 { |
|
604 MOZ_ASSERT(NS_IsMainThread()); |
|
605 |
|
606 nsresult rv = NS_DispatchToCurrentThread(this); |
|
607 NS_ENSURE_SUCCESS_VOID(rv); |
|
608 } |
|
609 |
|
610 private: |
|
611 NS_IMETHOD Run() |
|
612 { |
|
613 MOZ_ASSERT(NS_IsMainThread()); |
|
614 MOZ_ASSERT(mInfo); |
|
615 |
|
616 mInfo->FireCallback(); |
|
617 return NS_OK; |
|
618 } |
|
619 }; |
|
620 |
|
621 StaticRefPtr<TabChild> sPreallocatedTab; |
|
622 |
|
623 /*static*/ void |
|
624 TabChild::PreloadSlowThings() |
|
625 { |
|
626 MOZ_ASSERT(!sPreallocatedTab); |
|
627 |
|
628 nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(), |
|
629 TabContext(), /* chromeFlags */ 0)); |
|
630 if (!NS_SUCCEEDED(tab->Init()) || |
|
631 !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) { |
|
632 return; |
|
633 } |
|
634 // Just load and compile these scripts, but don't run them. |
|
635 tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true); |
|
636 // Load, compile, and run these scripts. |
|
637 tab->RecvLoadRemoteScript( |
|
638 NS_LITERAL_STRING("chrome://global/content/preload.js"), |
|
639 true); |
|
640 |
|
641 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->WebNavigation()); |
|
642 if (nsIPresShell* presShell = docShell->GetPresShell()) { |
|
643 // Initialize and do an initial reflow of the about:blank |
|
644 // PresShell to let it preload some things for us. |
|
645 presShell->Initialize(0, 0); |
|
646 nsIDocument* doc = presShell->GetDocument(); |
|
647 doc->FlushPendingNotifications(Flush_Layout); |
|
648 // ... but after it's done, make sure it doesn't do any more |
|
649 // work. |
|
650 presShell->MakeZombie(); |
|
651 } |
|
652 |
|
653 sPreallocatedTab = tab; |
|
654 ClearOnShutdown(&sPreallocatedTab); |
|
655 } |
|
656 |
|
657 /*static*/ already_AddRefed<TabChild> |
|
658 TabChild::Create(ContentChild* aManager, const TabContext &aContext, uint32_t aChromeFlags) |
|
659 { |
|
660 if (sPreallocatedTab && |
|
661 sPreallocatedTab->mChromeFlags == aChromeFlags && |
|
662 aContext.IsBrowserOrApp()) { |
|
663 |
|
664 nsRefPtr<TabChild> child = sPreallocatedTab.get(); |
|
665 sPreallocatedTab = nullptr; |
|
666 |
|
667 MOZ_ASSERT(!child->mTriedBrowserInit); |
|
668 |
|
669 child->SetTabContext(aContext); |
|
670 child->NotifyTabContextUpdated(); |
|
671 return child.forget(); |
|
672 } |
|
673 |
|
674 nsRefPtr<TabChild> iframe = new TabChild(aManager, |
|
675 aContext, aChromeFlags); |
|
676 return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr; |
|
677 } |
|
678 |
|
679 |
|
680 TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags) |
|
681 : TabContext(aContext) |
|
682 , mRemoteFrame(nullptr) |
|
683 , mManager(aManager) |
|
684 , mChromeFlags(aChromeFlags) |
|
685 , mLayersId(0) |
|
686 , mOuterRect(0, 0, 0, 0) |
|
687 , mActivePointerId(-1) |
|
688 , mTapHoldTimer(nullptr) |
|
689 , mAppPackageFileDescriptorRecved(false) |
|
690 , mLastBackgroundColor(NS_RGB(255, 255, 255)) |
|
691 , mDidFakeShow(false) |
|
692 , mNotified(false) |
|
693 , mTriedBrowserInit(false) |
|
694 , mOrientation(eScreenOrientation_PortraitPrimary) |
|
695 , mUpdateHitRegion(false) |
|
696 , mContextMenuHandled(false) |
|
697 , mWaitingTouchListeners(false) |
|
698 , mIgnoreKeyPressEvent(false) |
|
699 , mActiveElementManager(new ActiveElementManager()) |
|
700 { |
|
701 if (!sActiveDurationMsSet) { |
|
702 Preferences::AddIntVarCache(&sActiveDurationMs, |
|
703 "ui.touch_activation.duration_ms", |
|
704 sActiveDurationMs); |
|
705 sActiveDurationMsSet = true; |
|
706 } |
|
707 } |
|
708 |
|
709 NS_IMETHODIMP |
|
710 TabChild::HandleEvent(nsIDOMEvent* aEvent) |
|
711 { |
|
712 nsAutoString eventType; |
|
713 aEvent->GetType(eventType); |
|
714 if (eventType.EqualsLiteral("DOMMetaAdded")) { |
|
715 // This meta data may or may not have been a meta viewport tag. If it was, |
|
716 // we should handle it immediately. |
|
717 HandlePossibleViewportChange(); |
|
718 } |
|
719 |
|
720 return NS_OK; |
|
721 } |
|
722 |
|
723 NS_IMETHODIMP |
|
724 TabChild::Observe(nsISupports *aSubject, |
|
725 const char *aTopic, |
|
726 const char16_t *aData) |
|
727 { |
|
728 if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) { |
|
729 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject)); |
|
730 nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell)); |
|
731 if (tabChild == this) { |
|
732 nsCOMPtr<nsIDocument> doc(GetDocument()); |
|
733 uint32_t presShellId; |
|
734 ViewID viewId; |
|
735 if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(), |
|
736 &presShellId, &viewId)) { |
|
737 CSSRect rect; |
|
738 sscanf(NS_ConvertUTF16toUTF8(aData).get(), |
|
739 "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}", |
|
740 &rect.x, &rect.y, &rect.width, &rect.height); |
|
741 SendZoomToRect(presShellId, viewId, rect); |
|
742 } |
|
743 } |
|
744 } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) { |
|
745 if (IsAsyncPanZoomEnabled()) { |
|
746 nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject)); |
|
747 nsCOMPtr<nsIDocument> doc(GetDocument()); |
|
748 |
|
749 if (SameCOMIdentity(subject, doc)) { |
|
750 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
751 utils->SetIsFirstPaint(true); |
|
752 |
|
753 mContentDocumentIsDisplayed = true; |
|
754 |
|
755 // Reset CSS viewport and zoom to default on new page, then |
|
756 // calculate them properly using the actual metadata from the |
|
757 // page. |
|
758 SetCSSViewport(kDefaultViewportSize); |
|
759 |
|
760 // In some cases before-first-paint gets called before |
|
761 // RecvUpdateDimensions is called and therefore before we have an |
|
762 // mInnerSize value set. In such cases defer initializing the viewport |
|
763 // until we we get an inner size. |
|
764 if (HasValidInnerSize()) { |
|
765 InitializeRootMetrics(); |
|
766 utils->SetResolution(mLastRootMetrics.mResolution.scale, |
|
767 mLastRootMetrics.mResolution.scale); |
|
768 HandlePossibleViewportChange(); |
|
769 } |
|
770 } |
|
771 } |
|
772 } |
|
773 |
|
774 return NS_OK; |
|
775 } |
|
776 |
|
777 NS_IMETHODIMP |
|
778 TabChild::OnStateChange(nsIWebProgress* aWebProgress, |
|
779 nsIRequest* aRequest, |
|
780 uint32_t aStateFlags, |
|
781 nsresult aStatus) |
|
782 { |
|
783 NS_NOTREACHED("not implemented in TabChild"); |
|
784 return NS_OK; |
|
785 } |
|
786 |
|
787 NS_IMETHODIMP |
|
788 TabChild::OnProgressChange(nsIWebProgress* aWebProgress, |
|
789 nsIRequest* aRequest, |
|
790 int32_t aCurSelfProgress, |
|
791 int32_t aMaxSelfProgress, |
|
792 int32_t aCurTotalProgress, |
|
793 int32_t aMaxTotalProgress) |
|
794 { |
|
795 NS_NOTREACHED("not implemented in TabChild"); |
|
796 return NS_OK; |
|
797 } |
|
798 |
|
799 NS_IMETHODIMP |
|
800 TabChild::OnLocationChange(nsIWebProgress* aWebProgress, |
|
801 nsIRequest* aRequest, |
|
802 nsIURI *aLocation, |
|
803 uint32_t aFlags) |
|
804 { |
|
805 if (!IsAsyncPanZoomEnabled()) { |
|
806 return NS_OK; |
|
807 } |
|
808 |
|
809 nsCOMPtr<nsIDOMWindow> window; |
|
810 aWebProgress->GetDOMWindow(getter_AddRefs(window)); |
|
811 if (!window) { |
|
812 return NS_OK; |
|
813 } |
|
814 |
|
815 nsCOMPtr<nsIDOMDocument> progressDoc; |
|
816 window->GetDocument(getter_AddRefs(progressDoc)); |
|
817 if (!progressDoc) { |
|
818 return NS_OK; |
|
819 } |
|
820 |
|
821 nsCOMPtr<nsIDOMDocument> domDoc; |
|
822 WebNavigation()->GetDocument(getter_AddRefs(domDoc)); |
|
823 if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) { |
|
824 return NS_OK; |
|
825 } |
|
826 |
|
827 nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID)); |
|
828 if (!urifixup) { |
|
829 return NS_OK; |
|
830 } |
|
831 |
|
832 nsCOMPtr<nsIURI> exposableURI; |
|
833 urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI)); |
|
834 if (!exposableURI) { |
|
835 return NS_OK; |
|
836 } |
|
837 |
|
838 if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) { |
|
839 mContentDocumentIsDisplayed = false; |
|
840 } else if (mLastURI != nullptr) { |
|
841 bool exposableEqualsLast, exposableEqualsNew; |
|
842 exposableURI->Equals(mLastURI.get(), &exposableEqualsLast); |
|
843 exposableURI->Equals(aLocation, &exposableEqualsNew); |
|
844 if (exposableEqualsLast && !exposableEqualsNew) { |
|
845 mContentDocumentIsDisplayed = false; |
|
846 } |
|
847 } |
|
848 |
|
849 return NS_OK; |
|
850 } |
|
851 |
|
852 NS_IMETHODIMP |
|
853 TabChild::OnStatusChange(nsIWebProgress* aWebProgress, |
|
854 nsIRequest* aRequest, |
|
855 nsresult aStatus, |
|
856 const char16_t* aMessage) |
|
857 { |
|
858 NS_NOTREACHED("not implemented in TabChild"); |
|
859 return NS_OK; |
|
860 } |
|
861 |
|
862 NS_IMETHODIMP |
|
863 TabChild::OnSecurityChange(nsIWebProgress* aWebProgress, |
|
864 nsIRequest* aRequest, |
|
865 uint32_t aState) |
|
866 { |
|
867 NS_NOTREACHED("not implemented in TabChild"); |
|
868 return NS_OK; |
|
869 } |
|
870 |
|
871 bool |
|
872 TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId, |
|
873 const ViewID& aViewId, |
|
874 const bool& aIsRoot, |
|
875 const ZoomConstraints& aConstraints) |
|
876 { |
|
877 return SendUpdateZoomConstraints(aPresShellId, |
|
878 aViewId, |
|
879 aIsRoot, |
|
880 aConstraints); |
|
881 } |
|
882 |
|
883 nsresult |
|
884 TabChild::Init() |
|
885 { |
|
886 nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID); |
|
887 if (!webBrowser) { |
|
888 NS_ERROR("Couldn't create a nsWebBrowser?"); |
|
889 return NS_ERROR_FAILURE; |
|
890 } |
|
891 |
|
892 webBrowser->SetContainerWindow(this); |
|
893 mWebNav = do_QueryInterface(webBrowser); |
|
894 NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?"); |
|
895 |
|
896 nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation())); |
|
897 docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); |
|
898 |
|
899 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation()); |
|
900 if (!baseWindow) { |
|
901 NS_ERROR("mWebNav doesn't QI to nsIBaseWindow"); |
|
902 return NS_ERROR_FAILURE; |
|
903 } |
|
904 |
|
905 mWidget = nsIWidget::CreatePuppetWidget(this); |
|
906 if (!mWidget) { |
|
907 NS_ERROR("couldn't create fake widget"); |
|
908 return NS_ERROR_FAILURE; |
|
909 } |
|
910 mWidget->Create( |
|
911 nullptr, 0, // no parents |
|
912 nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)), |
|
913 nullptr, // HandleWidgetEvent |
|
914 nullptr // nsDeviceContext |
|
915 ); |
|
916 |
|
917 baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0); |
|
918 baseWindow->Create(); |
|
919 |
|
920 NotifyTabContextUpdated(); |
|
921 |
|
922 // IPC uses a WebBrowser object for which DNS prefetching is turned off |
|
923 // by default. But here we really want it, so enable it explicitly |
|
924 nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup = |
|
925 do_QueryInterface(baseWindow); |
|
926 if (webBrowserSetup) { |
|
927 webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH, |
|
928 true); |
|
929 } else { |
|
930 NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping " |
|
931 "DNS prefetching enable step."); |
|
932 } |
|
933 |
|
934 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation()); |
|
935 MOZ_ASSERT(docShell); |
|
936 |
|
937 docShell->SetAffectPrivateSessionLifetime( |
|
938 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME); |
|
939 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(WebNavigation()); |
|
940 MOZ_ASSERT(loadContext); |
|
941 loadContext->SetPrivateBrowsing( |
|
942 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW); |
|
943 loadContext->SetRemoteTabs( |
|
944 mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW); |
|
945 |
|
946 nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell); |
|
947 NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE); |
|
948 webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION); |
|
949 |
|
950 // Few lines before, baseWindow->Create() will end up creating a new |
|
951 // window root in nsGlobalWindow::SetDocShell. |
|
952 // Then this chrome event handler, will be inherited to inner windows. |
|
953 // We want to also set it to the docshell so that inner windows |
|
954 // and any code that has access to the docshell |
|
955 // can all listen to the same chrome event handler. |
|
956 // XXX: ideally, we would set a chrome event handler earlier, |
|
957 // and all windows, even the root one, will use the docshell one. |
|
958 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation()); |
|
959 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); |
|
960 nsCOMPtr<EventTarget> chromeHandler = |
|
961 do_QueryInterface(window->GetChromeEventHandler()); |
|
962 docShell->SetChromeEventHandler(chromeHandler); |
|
963 |
|
964 return NS_OK; |
|
965 } |
|
966 |
|
967 void |
|
968 TabChild::NotifyTabContextUpdated() |
|
969 { |
|
970 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation()); |
|
971 MOZ_ASSERT(docShell); |
|
972 |
|
973 if (docShell) { |
|
974 // nsDocShell will do the right thing if we pass NO_APP_ID or |
|
975 // UNKNOWN_APP_ID for aOwnOrContainingAppId. |
|
976 if (IsBrowserElement()) { |
|
977 docShell->SetIsBrowserInsideApp(BrowserOwnerAppId()); |
|
978 } else { |
|
979 docShell->SetIsApp(OwnAppId()); |
|
980 } |
|
981 } |
|
982 } |
|
983 |
|
984 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild) |
|
985 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) |
|
986 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) |
|
987 NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) |
|
988 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus) |
|
989 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) |
|
990 NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) |
|
991 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) |
|
992 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) |
|
993 NS_INTERFACE_MAP_ENTRY(nsITabChild) |
|
994 NS_INTERFACE_MAP_ENTRY(nsIObserver) |
|
995 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) |
|
996 NS_INTERFACE_MAP_ENTRY(nsITooltipListener) |
|
997 NS_INTERFACE_MAP_END_INHERITING(TabChildBase) |
|
998 |
|
999 NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase); |
|
1000 NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase); |
|
1001 |
|
1002 NS_IMETHODIMP |
|
1003 TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus) |
|
1004 { |
|
1005 return SetStatusWithContext(aStatusType, |
|
1006 aStatus ? static_cast<const nsString &>(nsDependentString(aStatus)) |
|
1007 : EmptyString(), |
|
1008 nullptr); |
|
1009 } |
|
1010 |
|
1011 NS_IMETHODIMP |
|
1012 TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser) |
|
1013 { |
|
1014 NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild"); |
|
1015 |
|
1016 return NS_ERROR_NOT_IMPLEMENTED; |
|
1017 } |
|
1018 |
|
1019 NS_IMETHODIMP |
|
1020 TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser) |
|
1021 { |
|
1022 NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild"); |
|
1023 |
|
1024 return NS_ERROR_NOT_IMPLEMENTED; |
|
1025 } |
|
1026 |
|
1027 NS_IMETHODIMP |
|
1028 TabChild::GetChromeFlags(uint32_t* aChromeFlags) |
|
1029 { |
|
1030 *aChromeFlags = mChromeFlags; |
|
1031 return NS_OK; |
|
1032 } |
|
1033 |
|
1034 NS_IMETHODIMP |
|
1035 TabChild::SetChromeFlags(uint32_t aChromeFlags) |
|
1036 { |
|
1037 NS_NOTREACHED("trying to SetChromeFlags from content process?"); |
|
1038 |
|
1039 return NS_ERROR_NOT_IMPLEMENTED; |
|
1040 } |
|
1041 |
|
1042 NS_IMETHODIMP |
|
1043 TabChild::DestroyBrowserWindow() |
|
1044 { |
|
1045 NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild"); |
|
1046 |
|
1047 return NS_ERROR_NOT_IMPLEMENTED; |
|
1048 } |
|
1049 |
|
1050 NS_IMETHODIMP |
|
1051 TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY) |
|
1052 { |
|
1053 NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild"); |
|
1054 |
|
1055 return NS_ERROR_NOT_IMPLEMENTED; |
|
1056 } |
|
1057 |
|
1058 NS_IMETHODIMP |
|
1059 TabChild::ShowAsModal() |
|
1060 { |
|
1061 NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild"); |
|
1062 |
|
1063 return NS_ERROR_NOT_IMPLEMENTED; |
|
1064 } |
|
1065 |
|
1066 NS_IMETHODIMP |
|
1067 TabChild::IsWindowModal(bool* aRetVal) |
|
1068 { |
|
1069 *aRetVal = false; |
|
1070 return NS_OK; |
|
1071 } |
|
1072 |
|
1073 NS_IMETHODIMP |
|
1074 TabChild::ExitModalEventLoop(nsresult aStatus) |
|
1075 { |
|
1076 NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild"); |
|
1077 |
|
1078 return NS_ERROR_NOT_IMPLEMENTED; |
|
1079 } |
|
1080 |
|
1081 NS_IMETHODIMP |
|
1082 TabChild::SetStatusWithContext(uint32_t aStatusType, |
|
1083 const nsAString& aStatusText, |
|
1084 nsISupports* aStatusContext) |
|
1085 { |
|
1086 // We can only send the status after the ipc machinery is set up, |
|
1087 // mRemoteFrame is a good indicator. |
|
1088 if (mRemoteFrame) |
|
1089 SendSetStatus(aStatusType, nsString(aStatusText)); |
|
1090 return NS_OK; |
|
1091 } |
|
1092 |
|
1093 NS_IMETHODIMP |
|
1094 TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, |
|
1095 int32_t aCx, int32_t aCy) |
|
1096 { |
|
1097 NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild"); |
|
1098 |
|
1099 return NS_ERROR_NOT_IMPLEMENTED; |
|
1100 } |
|
1101 |
|
1102 NS_IMETHODIMP |
|
1103 TabChild::GetDimensions(uint32_t aFlags, int32_t* aX, |
|
1104 int32_t* aY, int32_t* aCx, int32_t* aCy) |
|
1105 { |
|
1106 if (aX) { |
|
1107 *aX = mOuterRect.x; |
|
1108 } |
|
1109 if (aY) { |
|
1110 *aY = mOuterRect.y; |
|
1111 } |
|
1112 if (aCx) { |
|
1113 *aCx = mOuterRect.width; |
|
1114 } |
|
1115 if (aCy) { |
|
1116 *aCy = mOuterRect.height; |
|
1117 } |
|
1118 |
|
1119 return NS_OK; |
|
1120 } |
|
1121 |
|
1122 NS_IMETHODIMP |
|
1123 TabChild::SetFocus() |
|
1124 { |
|
1125 NS_WARNING("TabChild::SetFocus not supported in TabChild"); |
|
1126 |
|
1127 return NS_ERROR_NOT_IMPLEMENTED; |
|
1128 } |
|
1129 |
|
1130 NS_IMETHODIMP |
|
1131 TabChild::GetVisibility(bool* aVisibility) |
|
1132 { |
|
1133 *aVisibility = true; |
|
1134 return NS_OK; |
|
1135 } |
|
1136 |
|
1137 NS_IMETHODIMP |
|
1138 TabChild::SetVisibility(bool aVisibility) |
|
1139 { |
|
1140 // should the platform support this? Bug 666365 |
|
1141 return NS_OK; |
|
1142 } |
|
1143 |
|
1144 NS_IMETHODIMP |
|
1145 TabChild::GetTitle(char16_t** aTitle) |
|
1146 { |
|
1147 NS_NOTREACHED("TabChild::GetTitle not supported in TabChild"); |
|
1148 |
|
1149 return NS_ERROR_NOT_IMPLEMENTED; |
|
1150 } |
|
1151 |
|
1152 NS_IMETHODIMP |
|
1153 TabChild::SetTitle(const char16_t* aTitle) |
|
1154 { |
|
1155 // JavaScript sends the "DOMTitleChanged" event to the parent |
|
1156 // via the message manager. |
|
1157 return NS_OK; |
|
1158 } |
|
1159 |
|
1160 NS_IMETHODIMP |
|
1161 TabChild::GetSiteWindow(void** aSiteWindow) |
|
1162 { |
|
1163 NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild"); |
|
1164 |
|
1165 return NS_ERROR_NOT_IMPLEMENTED; |
|
1166 } |
|
1167 |
|
1168 NS_IMETHODIMP |
|
1169 TabChild::Blur() |
|
1170 { |
|
1171 NS_WARNING("TabChild::Blur not supported in TabChild"); |
|
1172 |
|
1173 return NS_ERROR_NOT_IMPLEMENTED; |
|
1174 } |
|
1175 |
|
1176 NS_IMETHODIMP |
|
1177 TabChild::FocusNextElement() |
|
1178 { |
|
1179 SendMoveFocus(true); |
|
1180 return NS_OK; |
|
1181 } |
|
1182 |
|
1183 NS_IMETHODIMP |
|
1184 TabChild::FocusPrevElement() |
|
1185 { |
|
1186 SendMoveFocus(false); |
|
1187 return NS_OK; |
|
1188 } |
|
1189 |
|
1190 NS_IMETHODIMP |
|
1191 TabChild::GetInterface(const nsIID & aIID, void **aSink) |
|
1192 { |
|
1193 // XXXbz should we restrict the set of interfaces we hand out here? |
|
1194 // See bug 537429 |
|
1195 return QueryInterface(aIID, aSink); |
|
1196 } |
|
1197 |
|
1198 NS_IMETHODIMP |
|
1199 TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags, |
|
1200 bool aCalledFromJS, |
|
1201 bool aPositionSpecified, bool aSizeSpecified, |
|
1202 nsIURI* aURI, const nsAString& aName, |
|
1203 const nsACString& aFeatures, bool* aWindowIsNew, |
|
1204 nsIDOMWindow** aReturn) |
|
1205 { |
|
1206 *aReturn = nullptr; |
|
1207 |
|
1208 // If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this |
|
1209 // isn't a request to open a modal-type window, we're going to create a new |
|
1210 // <iframe mozbrowser/mozapp> and return its window here. |
|
1211 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent); |
|
1212 if (docshell && docshell->GetIsInBrowserOrApp() && |
|
1213 !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL | |
|
1214 nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | |
|
1215 nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) { |
|
1216 |
|
1217 // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the |
|
1218 // open window call was canceled. It's important that we pass this error |
|
1219 // code back to our caller. |
|
1220 return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures, |
|
1221 aWindowIsNew, aReturn); |
|
1222 } |
|
1223 |
|
1224 // Otherwise, create a new top-level window. |
|
1225 PBrowserChild* newChild; |
|
1226 if (!CallCreateWindow(&newChild)) { |
|
1227 return NS_ERROR_NOT_AVAILABLE; |
|
1228 } |
|
1229 |
|
1230 *aWindowIsNew = true; |
|
1231 nsCOMPtr<nsIDOMWindow> win = |
|
1232 do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation()); |
|
1233 win.forget(aReturn); |
|
1234 return NS_OK; |
|
1235 } |
|
1236 |
|
1237 nsresult |
|
1238 TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener, |
|
1239 nsIURI* aURI, |
|
1240 const nsAString& aName, |
|
1241 const nsACString& aFeatures, |
|
1242 bool* aWindowIsNew, |
|
1243 nsIDOMWindow** aReturn) |
|
1244 { |
|
1245 *aReturn = nullptr; |
|
1246 |
|
1247 nsRefPtr<TabChild> newChild = |
|
1248 new TabChild(ContentChild::GetSingleton(), |
|
1249 /* TabContext */ *this, /* chromeFlags */ 0); |
|
1250 if (!NS_SUCCEEDED(newChild->Init())) { |
|
1251 return NS_ERROR_ABORT; |
|
1252 } |
|
1253 |
|
1254 // We must use PopupIPCTabContext here; ContentParent will not accept the |
|
1255 // result of this->AsIPCTabContext() (which will be a |
|
1256 // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security |
|
1257 // reasons. |
|
1258 PopupIPCTabContext context; |
|
1259 context.openerChild() = this; |
|
1260 context.isBrowserElement() = IsBrowserElement(); |
|
1261 |
|
1262 unused << Manager()->SendPBrowserConstructor( |
|
1263 // We release this ref in DeallocPBrowserChild |
|
1264 nsRefPtr<TabChild>(newChild).forget().take(), |
|
1265 IPCTabContext(context, mScrolling), /* chromeFlags */ 0); |
|
1266 |
|
1267 nsAutoCString spec; |
|
1268 if (aURI) { |
|
1269 aURI->GetSpec(spec); |
|
1270 } |
|
1271 |
|
1272 NS_ConvertUTF8toUTF16 url(spec); |
|
1273 nsString name(aName); |
|
1274 NS_ConvertUTF8toUTF16 features(aFeatures); |
|
1275 newChild->SendBrowserFrameOpenWindow(this, url, name, |
|
1276 features, aWindowIsNew); |
|
1277 if (!*aWindowIsNew) { |
|
1278 PBrowserChild::Send__delete__(newChild); |
|
1279 return NS_ERROR_ABORT; |
|
1280 } |
|
1281 |
|
1282 // Unfortunately we don't get a window unless we've shown the frame. That's |
|
1283 // pretty bogus; see bug 763602. |
|
1284 newChild->DoFakeShow(); |
|
1285 |
|
1286 nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation()); |
|
1287 win.forget(aReturn); |
|
1288 return NS_OK; |
|
1289 } |
|
1290 |
|
1291 #ifdef DEBUG |
|
1292 PContentPermissionRequestChild* |
|
1293 TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor, |
|
1294 const InfallibleTArray<PermissionRequest>& aRequests, |
|
1295 const IPC::Principal& aPrincipal) |
|
1296 { |
|
1297 PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor); |
|
1298 PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal); |
|
1299 child->mIPCOpen = true; |
|
1300 return request; |
|
1301 } |
|
1302 #endif /* DEBUG */ |
|
1303 |
|
1304 void |
|
1305 TabChild::DestroyWindow() |
|
1306 { |
|
1307 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation()); |
|
1308 if (baseWindow) |
|
1309 baseWindow->Destroy(); |
|
1310 |
|
1311 // NB: the order of mWidget->Destroy() and mRemoteFrame->Destroy() |
|
1312 // is important: we want to kill off remote layers before their |
|
1313 // frames |
|
1314 if (mWidget) { |
|
1315 mWidget->Destroy(); |
|
1316 } |
|
1317 |
|
1318 if (mRemoteFrame) { |
|
1319 mRemoteFrame->Destroy(); |
|
1320 mRemoteFrame = nullptr; |
|
1321 } |
|
1322 |
|
1323 |
|
1324 if (mLayersId != 0) { |
|
1325 MOZ_ASSERT(sTabChildren); |
|
1326 sTabChildren->Remove(mLayersId); |
|
1327 if (!sTabChildren->Count()) { |
|
1328 delete sTabChildren; |
|
1329 sTabChildren = nullptr; |
|
1330 } |
|
1331 mLayersId = 0; |
|
1332 } |
|
1333 } |
|
1334 |
|
1335 bool |
|
1336 TabChild::UseDirectCompositor() |
|
1337 { |
|
1338 return !!CompositorChild::Get(); |
|
1339 } |
|
1340 |
|
1341 void |
|
1342 TabChild::ActorDestroy(ActorDestroyReason why) |
|
1343 { |
|
1344 if (mTabChildGlobal) { |
|
1345 // The messageManager relays messages via the TabChild which |
|
1346 // no longer exists. |
|
1347 static_cast<nsFrameMessageManager*> |
|
1348 (mTabChildGlobal->mMessageManager.get())->Disconnect(); |
|
1349 mTabChildGlobal->mMessageManager = nullptr; |
|
1350 } |
|
1351 } |
|
1352 |
|
1353 TabChild::~TabChild() |
|
1354 { |
|
1355 DestroyWindow(); |
|
1356 |
|
1357 nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation()); |
|
1358 if (webBrowser) { |
|
1359 webBrowser->SetContainerWindow(nullptr); |
|
1360 } |
|
1361 } |
|
1362 |
|
1363 void |
|
1364 TabChild::SetProcessNameToAppName() |
|
1365 { |
|
1366 nsCOMPtr<mozIApplication> app = GetOwnApp(); |
|
1367 if (!app) { |
|
1368 return; |
|
1369 } |
|
1370 |
|
1371 nsAutoString appName; |
|
1372 nsresult rv = app->GetName(appName); |
|
1373 if (NS_FAILED(rv)) { |
|
1374 NS_WARNING("Failed to retrieve app name"); |
|
1375 return; |
|
1376 } |
|
1377 |
|
1378 ContentChild::GetSingleton()->SetProcessName(appName, true); |
|
1379 } |
|
1380 |
|
1381 bool |
|
1382 TabChild::IsRootContentDocument() |
|
1383 { |
|
1384 // A TabChild is a "root content document" if it's |
|
1385 // |
|
1386 // - <iframe mozapp> not inside another <iframe mozapp>, |
|
1387 // - <iframe mozbrowser> (not mozapp), or |
|
1388 // - a vanilla remote frame (<html:iframe remote=true> or <xul:browser |
|
1389 // remote=true>). |
|
1390 // |
|
1391 // Put another way, an iframe is /not/ a "root content document" iff it's a |
|
1392 // mozapp inside a mozapp. (This corresponds exactly to !HasAppOwnerApp.) |
|
1393 // |
|
1394 // Note that we're lying through our teeth here (thus the scare quotes). |
|
1395 // <html:iframe remote=true> or <xul:browser remote=true> inside another |
|
1396 // content iframe is not actually a root content document, but we say it is. |
|
1397 // |
|
1398 // We do this because we make a remote frame opaque iff |
|
1399 // IsRootContentDocument(), and making vanilla remote frames transparent |
|
1400 // breaks our remote reftests. |
|
1401 |
|
1402 return !HasAppOwnerApp(); |
|
1403 } |
|
1404 |
|
1405 bool |
|
1406 TabChild::RecvLoadURL(const nsCString& uri) |
|
1407 { |
|
1408 SetProcessNameToAppName(); |
|
1409 |
|
1410 nsresult rv = WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(uri).get(), |
|
1411 nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | |
|
1412 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_OWNER, |
|
1413 nullptr, nullptr, nullptr); |
|
1414 if (NS_FAILED(rv)) { |
|
1415 NS_WARNING("WebNavigation()->LoadURI failed. Eating exception, what else can I do?"); |
|
1416 } |
|
1417 |
|
1418 #ifdef MOZ_CRASHREPORTER |
|
1419 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri); |
|
1420 #endif |
|
1421 |
|
1422 return true; |
|
1423 } |
|
1424 |
|
1425 bool |
|
1426 TabChild::RecvCacheFileDescriptor(const nsString& aPath, |
|
1427 const FileDescriptor& aFileDescriptor) |
|
1428 { |
|
1429 MOZ_ASSERT(NS_IsMainThread()); |
|
1430 MOZ_ASSERT(!aPath.IsEmpty()); |
|
1431 MOZ_ASSERT(!mAppPackageFileDescriptorRecved); |
|
1432 |
|
1433 mAppPackageFileDescriptorRecved = true; |
|
1434 |
|
1435 // aFileDescriptor may be invalid here, but the callback will choose how to |
|
1436 // handle it. |
|
1437 |
|
1438 // First see if we already have a request for this path. |
|
1439 const CachedFileDescriptorInfo search(aPath); |
|
1440 uint32_t index = |
|
1441 mCachedFileDescriptorInfos.IndexOf(search, 0, |
|
1442 search.PathOnlyComparator()); |
|
1443 if (index == mCachedFileDescriptorInfos.NoIndex) { |
|
1444 // We haven't had any requests for this path yet. Assume that we will |
|
1445 // in a little while and save the file descriptor here. |
|
1446 mCachedFileDescriptorInfos.AppendElement( |
|
1447 new CachedFileDescriptorInfo(aPath, aFileDescriptor)); |
|
1448 return true; |
|
1449 } |
|
1450 |
|
1451 nsAutoPtr<CachedFileDescriptorInfo>& info = |
|
1452 mCachedFileDescriptorInfos[index]; |
|
1453 |
|
1454 MOZ_ASSERT(info); |
|
1455 MOZ_ASSERT(info->mPath == aPath); |
|
1456 MOZ_ASSERT(!info->mFileDescriptor.IsValid()); |
|
1457 MOZ_ASSERT(info->mCallback); |
|
1458 |
|
1459 // If this callback has been canceled then we can simply close the file |
|
1460 // descriptor and forget about the callback. |
|
1461 if (info->mCanceled) { |
|
1462 // Only close if this is a valid file descriptor. |
|
1463 if (aFileDescriptor.IsValid()) { |
|
1464 nsRefPtr<CloseFileRunnable> runnable = |
|
1465 new CloseFileRunnable(aFileDescriptor); |
|
1466 runnable->Dispatch(); |
|
1467 } |
|
1468 } else { |
|
1469 // Not canceled so fire the callback. |
|
1470 info->mFileDescriptor = aFileDescriptor; |
|
1471 |
|
1472 // We don't need a runnable here because we should already be at the top |
|
1473 // of the event loop. Just fire immediately. |
|
1474 info->FireCallback(); |
|
1475 } |
|
1476 |
|
1477 mCachedFileDescriptorInfos.RemoveElementAt(index); |
|
1478 return true; |
|
1479 } |
|
1480 |
|
1481 bool |
|
1482 TabChild::GetCachedFileDescriptor(const nsAString& aPath, |
|
1483 nsICachedFileDescriptorListener* aCallback) |
|
1484 { |
|
1485 MOZ_ASSERT(NS_IsMainThread()); |
|
1486 MOZ_ASSERT(!aPath.IsEmpty()); |
|
1487 MOZ_ASSERT(aCallback); |
|
1488 |
|
1489 // First see if we've already received a cached file descriptor for this |
|
1490 // path. |
|
1491 const CachedFileDescriptorInfo search(aPath); |
|
1492 uint32_t index = |
|
1493 mCachedFileDescriptorInfos.IndexOf(search, 0, |
|
1494 search.PathOnlyComparator()); |
|
1495 if (index == mCachedFileDescriptorInfos.NoIndex) { |
|
1496 // We haven't received a file descriptor for this path yet. Assume that |
|
1497 // we will in a little while and save the request here. |
|
1498 if (!mAppPackageFileDescriptorRecved) { |
|
1499 mCachedFileDescriptorInfos.AppendElement( |
|
1500 new CachedFileDescriptorInfo(aPath, aCallback)); |
|
1501 } |
|
1502 return false; |
|
1503 } |
|
1504 |
|
1505 nsAutoPtr<CachedFileDescriptorInfo>& info = |
|
1506 mCachedFileDescriptorInfos[index]; |
|
1507 |
|
1508 MOZ_ASSERT(info); |
|
1509 MOZ_ASSERT(info->mPath == aPath); |
|
1510 |
|
1511 // If we got a previous request for this file descriptor that was then |
|
1512 // canceled, insert the new request ahead of the old in the queue so that |
|
1513 // it will be serviced first. |
|
1514 if (info->mCanceled) { |
|
1515 // This insertion will change the array and invalidate |info|, so |
|
1516 // be careful not to touch |info| after this. |
|
1517 mCachedFileDescriptorInfos.InsertElementAt(index, |
|
1518 new CachedFileDescriptorInfo(aPath, aCallback)); |
|
1519 return false; |
|
1520 } |
|
1521 |
|
1522 MOZ_ASSERT(!info->mCallback); |
|
1523 info->mCallback = aCallback; |
|
1524 |
|
1525 nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable = |
|
1526 new CachedFileDescriptorCallbackRunnable(info.forget()); |
|
1527 runnable->Dispatch(); |
|
1528 |
|
1529 mCachedFileDescriptorInfos.RemoveElementAt(index); |
|
1530 return true; |
|
1531 } |
|
1532 |
|
1533 void |
|
1534 TabChild::CancelCachedFileDescriptorCallback( |
|
1535 const nsAString& aPath, |
|
1536 nsICachedFileDescriptorListener* aCallback) |
|
1537 { |
|
1538 MOZ_ASSERT(NS_IsMainThread()); |
|
1539 MOZ_ASSERT(!aPath.IsEmpty()); |
|
1540 MOZ_ASSERT(aCallback); |
|
1541 |
|
1542 if (mAppPackageFileDescriptorRecved) { |
|
1543 // Already received cached file descriptor for the app package. Nothing to do here. |
|
1544 return; |
|
1545 } |
|
1546 |
|
1547 const CachedFileDescriptorInfo search(aPath, aCallback); |
|
1548 uint32_t index = |
|
1549 mCachedFileDescriptorInfos.IndexOf(search, 0, |
|
1550 search.PathAndCallbackComparator()); |
|
1551 if (index == mCachedFileDescriptorInfos.NoIndex) { |
|
1552 // Nothing to do here. |
|
1553 return; |
|
1554 } |
|
1555 |
|
1556 nsAutoPtr<CachedFileDescriptorInfo>& info = |
|
1557 mCachedFileDescriptorInfos[index]; |
|
1558 |
|
1559 MOZ_ASSERT(info); |
|
1560 MOZ_ASSERT(info->mPath == aPath); |
|
1561 MOZ_ASSERT(!info->mFileDescriptor.IsValid()); |
|
1562 MOZ_ASSERT(info->mCallback == aCallback); |
|
1563 MOZ_ASSERT(!info->mCanceled); |
|
1564 |
|
1565 // Set this flag so that we will close the file descriptor when it arrives. |
|
1566 info->mCanceled = true; |
|
1567 } |
|
1568 |
|
1569 void |
|
1570 TabChild::DoFakeShow() |
|
1571 { |
|
1572 RecvShow(nsIntSize(0, 0)); |
|
1573 mDidFakeShow = true; |
|
1574 } |
|
1575 |
|
1576 bool |
|
1577 TabChild::RecvShow(const nsIntSize& size) |
|
1578 { |
|
1579 |
|
1580 if (mDidFakeShow) { |
|
1581 return true; |
|
1582 } |
|
1583 |
|
1584 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation()); |
|
1585 if (!baseWindow) { |
|
1586 NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow"); |
|
1587 return false; |
|
1588 } |
|
1589 |
|
1590 if (!InitRenderingState()) { |
|
1591 // We can fail to initialize our widget if the <browser |
|
1592 // remote> has already been destroyed, and we couldn't hook |
|
1593 // into the parent-process's layer system. That's not a fatal |
|
1594 // error. |
|
1595 return true; |
|
1596 } |
|
1597 |
|
1598 baseWindow->SetVisibility(true); |
|
1599 |
|
1600 return InitTabChildGlobal(); |
|
1601 } |
|
1602 |
|
1603 bool |
|
1604 TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation) |
|
1605 { |
|
1606 if (!mRemoteFrame) { |
|
1607 return true; |
|
1608 } |
|
1609 |
|
1610 mOuterRect.x = rect.x; |
|
1611 mOuterRect.y = rect.y; |
|
1612 mOuterRect.width = rect.width; |
|
1613 mOuterRect.height = rect.height; |
|
1614 |
|
1615 bool initialSizing = !HasValidInnerSize() |
|
1616 && (size.width != 0 && size.height != 0); |
|
1617 |
|
1618 mOrientation = orientation; |
|
1619 mInnerSize = ScreenIntSize::FromUnknownSize( |
|
1620 gfx::IntSize(size.width, size.height)); |
|
1621 mWidget->Resize(0, 0, size.width, size.height, |
|
1622 true); |
|
1623 |
|
1624 nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation()); |
|
1625 baseWin->SetPositionAndSize(0, 0, size.width, size.height, |
|
1626 true); |
|
1627 |
|
1628 if (initialSizing && mContentDocumentIsDisplayed) { |
|
1629 // If this is the first time we're getting a valid mInnerSize, and the |
|
1630 // before-first-paint event has already been handled, then we need to set |
|
1631 // up our default viewport here. See the corresponding call to |
|
1632 // InitializeRootMetrics in the before-first-paint handler. |
|
1633 InitializeRootMetrics(); |
|
1634 } |
|
1635 |
|
1636 HandlePossibleViewportChange(); |
|
1637 |
|
1638 return true; |
|
1639 } |
|
1640 |
|
1641 bool |
|
1642 TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) |
|
1643 { |
|
1644 return TabChildBase::UpdateFrameHandler(aFrameMetrics); |
|
1645 } |
|
1646 |
|
1647 bool |
|
1648 TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId, |
|
1649 const uint32_t& aScrollGeneration) |
|
1650 { |
|
1651 APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration); |
|
1652 return true; |
|
1653 } |
|
1654 |
|
1655 bool |
|
1656 TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
1657 { |
|
1658 if (!mGlobal || !mTabChildGlobal) { |
|
1659 return true; |
|
1660 } |
|
1661 |
|
1662 CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid); |
|
1663 nsString data; |
|
1664 data.AppendLiteral("{ \"x\" : "); |
|
1665 data.AppendFloat(point.x); |
|
1666 data.AppendLiteral(", \"y\" : "); |
|
1667 data.AppendFloat(point.y); |
|
1668 data.AppendLiteral(" }"); |
|
1669 |
|
1670 DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data); |
|
1671 |
|
1672 return true; |
|
1673 } |
|
1674 |
|
1675 bool |
|
1676 TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
1677 { |
|
1678 if (!mGlobal || !mTabChildGlobal) { |
|
1679 return true; |
|
1680 } |
|
1681 |
|
1682 LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();; |
|
1683 |
|
1684 MessageLoop::current()->PostDelayedTask( |
|
1685 FROM_HERE, |
|
1686 NewRunnableMethod(this, &TabChild::FireSingleTapEvent, currentPoint), |
|
1687 sActiveDurationMs); |
|
1688 return true; |
|
1689 } |
|
1690 |
|
1691 void |
|
1692 TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint) |
|
1693 { |
|
1694 int time = 0; |
|
1695 DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget); |
|
1696 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget); |
|
1697 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget); |
|
1698 } |
|
1699 |
|
1700 bool |
|
1701 TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
1702 { |
|
1703 if (!mGlobal || !mTabChildGlobal) { |
|
1704 return true; |
|
1705 } |
|
1706 |
|
1707 mContextMenuHandled = |
|
1708 DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"), |
|
1709 APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid), |
|
1710 2, 1, 0, false, |
|
1711 nsIDOMMouseEvent::MOZ_SOURCE_TOUCH); |
|
1712 |
|
1713 SendContentReceivedTouch(aGuid, mContextMenuHandled); |
|
1714 |
|
1715 return true; |
|
1716 } |
|
1717 |
|
1718 bool |
|
1719 TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) |
|
1720 { |
|
1721 if (mContextMenuHandled) { |
|
1722 mContextMenuHandled = false; |
|
1723 return true; |
|
1724 } |
|
1725 |
|
1726 RecvHandleSingleTap(aPoint, aGuid); |
|
1727 return true; |
|
1728 } |
|
1729 |
|
1730 bool |
|
1731 TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId, |
|
1732 const APZStateChange& aChange, |
|
1733 const int& aArg) |
|
1734 { |
|
1735 switch (aChange) |
|
1736 { |
|
1737 case APZStateChange::TransformBegin: |
|
1738 { |
|
1739 nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); |
|
1740 nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); |
|
1741 if (scrollbarOwner) { |
|
1742 scrollbarOwner->ScrollbarActivityStarted(); |
|
1743 } |
|
1744 break; |
|
1745 } |
|
1746 case APZStateChange::TransformEnd: |
|
1747 { |
|
1748 nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); |
|
1749 nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); |
|
1750 if (scrollbarOwner) { |
|
1751 scrollbarOwner->ScrollbarActivityStopped(); |
|
1752 } |
|
1753 break; |
|
1754 } |
|
1755 case APZStateChange::StartTouch: |
|
1756 { |
|
1757 mActiveElementManager->HandleTouchStart(aArg); |
|
1758 break; |
|
1759 } |
|
1760 case APZStateChange::StartPanning: |
|
1761 { |
|
1762 mActiveElementManager->HandlePanStart(); |
|
1763 break; |
|
1764 } |
|
1765 case APZStateChange::EndTouch: |
|
1766 { |
|
1767 mActiveElementManager->HandleTouchEnd(aArg); |
|
1768 break; |
|
1769 } |
|
1770 default: |
|
1771 // APZStateChange has a 'sentinel' value, and the compiler complains |
|
1772 // if an enumerator is not handled and there is no 'default' case. |
|
1773 break; |
|
1774 } |
|
1775 return true; |
|
1776 } |
|
1777 |
|
1778 bool |
|
1779 TabChild::RecvActivate() |
|
1780 { |
|
1781 nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation()); |
|
1782 browser->Activate(); |
|
1783 return true; |
|
1784 } |
|
1785 |
|
1786 bool TabChild::RecvDeactivate() |
|
1787 { |
|
1788 nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation()); |
|
1789 browser->Deactivate(); |
|
1790 return true; |
|
1791 } |
|
1792 |
|
1793 bool |
|
1794 TabChild::RecvMouseEvent(const nsString& aType, |
|
1795 const float& aX, |
|
1796 const float& aY, |
|
1797 const int32_t& aButton, |
|
1798 const int32_t& aClickCount, |
|
1799 const int32_t& aModifiers, |
|
1800 const bool& aIgnoreRootScrollFrame) |
|
1801 { |
|
1802 DispatchMouseEvent(aType, CSSPoint(aX, aY), aButton, aClickCount, aModifiers, |
|
1803 aIgnoreRootScrollFrame, nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN); |
|
1804 return true; |
|
1805 } |
|
1806 |
|
1807 bool |
|
1808 TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event) |
|
1809 { |
|
1810 WidgetMouseEvent localEvent(event); |
|
1811 localEvent.widget = mWidget; |
|
1812 DispatchWidgetEvent(localEvent); |
|
1813 return true; |
|
1814 } |
|
1815 |
|
1816 bool |
|
1817 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& event) |
|
1818 { |
|
1819 WidgetWheelEvent localEvent(event); |
|
1820 localEvent.widget = mWidget; |
|
1821 DispatchWidgetEvent(localEvent); |
|
1822 return true; |
|
1823 } |
|
1824 |
|
1825 static Touch* |
|
1826 GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId) |
|
1827 { |
|
1828 for (uint32_t i = 0; i < aEvent.touches.Length(); ++i) { |
|
1829 Touch* touch = static_cast<Touch*>(aEvent.touches[i].get()); |
|
1830 if (touch->mIdentifier == aId) { |
|
1831 return touch; |
|
1832 } |
|
1833 } |
|
1834 return nullptr; |
|
1835 } |
|
1836 |
|
1837 void |
|
1838 TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus) |
|
1839 { |
|
1840 static bool sHavePrefs; |
|
1841 static bool sClickHoldContextMenusEnabled; |
|
1842 static nsIntSize sDragThreshold; |
|
1843 static int32_t sContextMenuDelayMs; |
|
1844 if (!sHavePrefs) { |
|
1845 sHavePrefs = true; |
|
1846 Preferences::AddBoolVarCache(&sClickHoldContextMenusEnabled, |
|
1847 "ui.click_hold_context_menus", true); |
|
1848 Preferences::AddIntVarCache(&sDragThreshold.width, |
|
1849 "ui.dragThresholdX", 25); |
|
1850 Preferences::AddIntVarCache(&sDragThreshold.height, |
|
1851 "ui.dragThresholdY", 25); |
|
1852 Preferences::AddIntVarCache(&sContextMenuDelayMs, |
|
1853 "ui.click_hold_context_menus.delay", 500); |
|
1854 } |
|
1855 |
|
1856 if (aEvent.touches.Length() == 0) { |
|
1857 return; |
|
1858 } |
|
1859 |
|
1860 bool currentlyTrackingTouch = (mActivePointerId >= 0); |
|
1861 if (aEvent.message == NS_TOUCH_START) { |
|
1862 if (currentlyTrackingTouch || aEvent.touches.Length() > 1) { |
|
1863 // We're tracking a possible tap for another point, or we saw a |
|
1864 // touchstart for a later pointer after we canceled tracking of |
|
1865 // the first point. Ignore this one. |
|
1866 return; |
|
1867 } |
|
1868 if (aStatus == nsEventStatus_eConsumeNoDefault || |
|
1869 nsIPresShell::gPreventMouseEvents || |
|
1870 aEvent.mFlags.mMultipleActionsPrevented) { |
|
1871 return; |
|
1872 } |
|
1873 |
|
1874 Touch* touch = aEvent.touches[0]; |
|
1875 mGestureDownPoint = LayoutDevicePoint(touch->mRefPoint.x, touch->mRefPoint.y); |
|
1876 mActivePointerId = touch->mIdentifier; |
|
1877 if (sClickHoldContextMenusEnabled) { |
|
1878 MOZ_ASSERT(!mTapHoldTimer); |
|
1879 mTapHoldTimer = NewRunnableMethod(this, |
|
1880 &TabChild::FireContextMenuEvent); |
|
1881 MessageLoop::current()->PostDelayedTask(FROM_HERE, mTapHoldTimer, |
|
1882 sContextMenuDelayMs); |
|
1883 } |
|
1884 return; |
|
1885 } |
|
1886 |
|
1887 // If we're not tracking a touch or this event doesn't include the |
|
1888 // one we care about, bail. |
|
1889 if (!currentlyTrackingTouch) { |
|
1890 return; |
|
1891 } |
|
1892 Touch* trackedTouch = GetTouchForIdentifier(aEvent, mActivePointerId); |
|
1893 if (!trackedTouch) { |
|
1894 return; |
|
1895 } |
|
1896 |
|
1897 LayoutDevicePoint currentPoint = LayoutDevicePoint(trackedTouch->mRefPoint.x, trackedTouch->mRefPoint.y); |
|
1898 int64_t time = aEvent.time; |
|
1899 switch (aEvent.message) { |
|
1900 case NS_TOUCH_MOVE: |
|
1901 if (abs(currentPoint.x - mGestureDownPoint.x) > sDragThreshold.width || |
|
1902 abs(currentPoint.y - mGestureDownPoint.y) > sDragThreshold.height) { |
|
1903 CancelTapTracking(); |
|
1904 } |
|
1905 return; |
|
1906 |
|
1907 case NS_TOUCH_END: |
|
1908 if (!nsIPresShell::gPreventMouseEvents) { |
|
1909 DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget); |
|
1910 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget); |
|
1911 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget); |
|
1912 } |
|
1913 // fall through |
|
1914 case NS_TOUCH_CANCEL: |
|
1915 CancelTapTracking(); |
|
1916 return; |
|
1917 |
|
1918 default: |
|
1919 NS_WARNING("Unknown touch event type"); |
|
1920 } |
|
1921 } |
|
1922 |
|
1923 void |
|
1924 TabChild::FireContextMenuEvent() |
|
1925 { |
|
1926 double scale; |
|
1927 GetDefaultScale(&scale); |
|
1928 if (scale < 0) { |
|
1929 scale = 1; |
|
1930 } |
|
1931 |
|
1932 MOZ_ASSERT(mTapHoldTimer && mActivePointerId >= 0); |
|
1933 bool defaultPrevented = DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"), |
|
1934 mGestureDownPoint / CSSToLayoutDeviceScale(scale), |
|
1935 2 /* Right button */, |
|
1936 1 /* Click count */, |
|
1937 0 /* Modifiers */, |
|
1938 false /* Ignore root scroll frame */, |
|
1939 nsIDOMMouseEvent::MOZ_SOURCE_TOUCH); |
|
1940 |
|
1941 // Fire a click event if someone didn't call preventDefault() on the context |
|
1942 // menu event. |
|
1943 if (defaultPrevented) { |
|
1944 CancelTapTracking(); |
|
1945 } else if (mTapHoldTimer) { |
|
1946 mTapHoldTimer->Cancel(); |
|
1947 mTapHoldTimer = nullptr; |
|
1948 } |
|
1949 } |
|
1950 |
|
1951 void |
|
1952 TabChild::CancelTapTracking() |
|
1953 { |
|
1954 mActivePointerId = -1; |
|
1955 if (mTapHoldTimer) { |
|
1956 mTapHoldTimer->Cancel(); |
|
1957 } |
|
1958 mTapHoldTimer = nullptr; |
|
1959 } |
|
1960 |
|
1961 bool |
|
1962 TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent, |
|
1963 const ScrollableLayerGuid& aGuid) |
|
1964 { |
|
1965 WidgetTouchEvent localEvent(aEvent); |
|
1966 localEvent.widget = mWidget; |
|
1967 for (size_t i = 0; i < localEvent.touches.Length(); i++) { |
|
1968 aEvent.touches[i]->mRefPoint = APZCCallbackHelper::ApplyCallbackTransform(aEvent.touches[i]->mRefPoint, aGuid, mWidget->GetDefaultScale()); |
|
1969 } |
|
1970 |
|
1971 nsEventStatus status = DispatchWidgetEvent(localEvent); |
|
1972 |
|
1973 if (!IsAsyncPanZoomEnabled()) { |
|
1974 UpdateTapState(localEvent, status); |
|
1975 return true; |
|
1976 } |
|
1977 |
|
1978 if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) { |
|
1979 mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target()); |
|
1980 } |
|
1981 |
|
1982 nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation()); |
|
1983 nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow(); |
|
1984 |
|
1985 if (!innerWindow || !innerWindow->HasTouchEventListeners()) { |
|
1986 SendContentReceivedTouch(aGuid, false); |
|
1987 return true; |
|
1988 } |
|
1989 |
|
1990 bool isTouchPrevented = nsIPresShell::gPreventMouseEvents || |
|
1991 localEvent.mFlags.mMultipleActionsPrevented; |
|
1992 switch (aEvent.message) { |
|
1993 case NS_TOUCH_START: { |
|
1994 if (isTouchPrevented) { |
|
1995 SendContentReceivedTouch(aGuid, isTouchPrevented); |
|
1996 } else { |
|
1997 mWaitingTouchListeners = true; |
|
1998 } |
|
1999 break; |
|
2000 } |
|
2001 |
|
2002 case NS_TOUCH_MOVE: |
|
2003 case NS_TOUCH_END: |
|
2004 case NS_TOUCH_CANCEL: { |
|
2005 if (mWaitingTouchListeners) { |
|
2006 SendContentReceivedTouch(aGuid, isTouchPrevented); |
|
2007 mWaitingTouchListeners = false; |
|
2008 } |
|
2009 break; |
|
2010 } |
|
2011 |
|
2012 default: |
|
2013 NS_WARNING("Unknown touch event type"); |
|
2014 } |
|
2015 |
|
2016 return true; |
|
2017 } |
|
2018 |
|
2019 bool |
|
2020 TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent, |
|
2021 const ScrollableLayerGuid& aGuid) |
|
2022 { |
|
2023 return RecvRealTouchEvent(aEvent, aGuid); |
|
2024 } |
|
2025 |
|
2026 void |
|
2027 TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache, |
|
2028 WidgetKeyboardEvent* aEvent) |
|
2029 { |
|
2030 MaybeNativeKeyBinding maybeBindings; |
|
2031 if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) { |
|
2032 return; |
|
2033 } |
|
2034 |
|
2035 if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) { |
|
2036 const NativeKeyBinding& bindings = maybeBindings; |
|
2037 aAutoCache->Cache(bindings.singleLineCommands(), |
|
2038 bindings.multiLineCommands(), |
|
2039 bindings.richTextCommands()); |
|
2040 } else { |
|
2041 aAutoCache->CacheNoCommands(); |
|
2042 } |
|
2043 } |
|
2044 |
|
2045 bool |
|
2046 TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event, |
|
2047 const MaybeNativeKeyBinding& aBindings) |
|
2048 { |
|
2049 PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get()); |
|
2050 AutoCacheNativeKeyCommands autoCache(widget); |
|
2051 |
|
2052 if (event.message == NS_KEY_PRESS) { |
|
2053 if (aBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) { |
|
2054 const NativeKeyBinding& bindings = aBindings; |
|
2055 autoCache.Cache(bindings.singleLineCommands(), |
|
2056 bindings.multiLineCommands(), |
|
2057 bindings.richTextCommands()); |
|
2058 } else { |
|
2059 autoCache.CacheNoCommands(); |
|
2060 } |
|
2061 } |
|
2062 // If content code called preventDefault() on a keydown event, then we don't |
|
2063 // want to process any following keypress events. |
|
2064 if (event.message == NS_KEY_PRESS && mIgnoreKeyPressEvent) { |
|
2065 return true; |
|
2066 } |
|
2067 |
|
2068 WidgetKeyboardEvent localEvent(event); |
|
2069 localEvent.widget = mWidget; |
|
2070 nsEventStatus status = DispatchWidgetEvent(localEvent); |
|
2071 |
|
2072 if (event.message == NS_KEY_DOWN) { |
|
2073 mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault; |
|
2074 } |
|
2075 |
|
2076 if (localEvent.mFlags.mWantReplyFromContentProcess) { |
|
2077 SendReplyKeyEvent(localEvent); |
|
2078 } |
|
2079 |
|
2080 return true; |
|
2081 } |
|
2082 |
|
2083 bool |
|
2084 TabChild::RecvKeyEvent(const nsString& aType, |
|
2085 const int32_t& aKeyCode, |
|
2086 const int32_t& aCharCode, |
|
2087 const int32_t& aModifiers, |
|
2088 const bool& aPreventDefault) |
|
2089 { |
|
2090 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
2091 NS_ENSURE_TRUE(utils, true); |
|
2092 bool ignored = false; |
|
2093 utils->SendKeyEvent(aType, aKeyCode, aCharCode, |
|
2094 aModifiers, aPreventDefault, &ignored); |
|
2095 return true; |
|
2096 } |
|
2097 |
|
2098 bool |
|
2099 TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event) |
|
2100 { |
|
2101 WidgetCompositionEvent localEvent(event); |
|
2102 localEvent.widget = mWidget; |
|
2103 DispatchWidgetEvent(localEvent); |
|
2104 return true; |
|
2105 } |
|
2106 |
|
2107 bool |
|
2108 TabChild::RecvTextEvent(const WidgetTextEvent& event) |
|
2109 { |
|
2110 WidgetTextEvent localEvent(event); |
|
2111 localEvent.widget = mWidget; |
|
2112 DispatchWidgetEvent(localEvent); |
|
2113 return true; |
|
2114 } |
|
2115 |
|
2116 bool |
|
2117 TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event) |
|
2118 { |
|
2119 WidgetSelectionEvent localEvent(event); |
|
2120 localEvent.widget = mWidget; |
|
2121 DispatchWidgetEvent(localEvent); |
|
2122 return true; |
|
2123 } |
|
2124 |
|
2125 PDocumentRendererChild* |
|
2126 TabChild::AllocPDocumentRendererChild(const nsRect& documentRect, |
|
2127 const mozilla::gfx::Matrix& transform, |
|
2128 const nsString& bgcolor, |
|
2129 const uint32_t& renderFlags, |
|
2130 const bool& flushLayout, |
|
2131 const nsIntSize& renderSize) |
|
2132 { |
|
2133 return new DocumentRendererChild(); |
|
2134 } |
|
2135 |
|
2136 bool |
|
2137 TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor) |
|
2138 { |
|
2139 delete actor; |
|
2140 return true; |
|
2141 } |
|
2142 |
|
2143 bool |
|
2144 TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor, |
|
2145 const nsRect& documentRect, |
|
2146 const mozilla::gfx::Matrix& transform, |
|
2147 const nsString& bgcolor, |
|
2148 const uint32_t& renderFlags, |
|
2149 const bool& flushLayout, |
|
2150 const nsIntSize& renderSize) |
|
2151 { |
|
2152 DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor); |
|
2153 |
|
2154 nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation()); |
|
2155 if (!browser) |
|
2156 return true; // silently ignore |
|
2157 nsCOMPtr<nsIDOMWindow> window; |
|
2158 if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) || |
|
2159 !window) |
|
2160 { |
|
2161 return true; // silently ignore |
|
2162 } |
|
2163 |
|
2164 nsCString data; |
|
2165 bool ret = render->RenderDocument(window, |
|
2166 documentRect, transform, |
|
2167 bgcolor, |
|
2168 renderFlags, flushLayout, |
|
2169 renderSize, data); |
|
2170 if (!ret) |
|
2171 return true; // silently ignore |
|
2172 |
|
2173 return PDocumentRendererChild::Send__delete__(actor, renderSize, data); |
|
2174 } |
|
2175 |
|
2176 PColorPickerChild* |
|
2177 TabChild::AllocPColorPickerChild(const nsString&, const nsString&) |
|
2178 { |
|
2179 NS_RUNTIMEABORT("unused"); |
|
2180 return nullptr; |
|
2181 } |
|
2182 |
|
2183 bool |
|
2184 TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker) |
|
2185 { |
|
2186 nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker); |
|
2187 NS_RELEASE(picker); |
|
2188 return true; |
|
2189 } |
|
2190 |
|
2191 PContentPermissionRequestChild* |
|
2192 TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests, |
|
2193 const IPC::Principal& aPrincipal) |
|
2194 { |
|
2195 NS_RUNTIMEABORT("unused"); |
|
2196 return nullptr; |
|
2197 } |
|
2198 |
|
2199 bool |
|
2200 TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) |
|
2201 { |
|
2202 PCOMContentPermissionRequestChild* child = |
|
2203 static_cast<PCOMContentPermissionRequestChild*>(actor); |
|
2204 #ifdef DEBUG |
|
2205 child->mIPCOpen = false; |
|
2206 #endif /* DEBUG */ |
|
2207 child->IPDLRelease(); |
|
2208 return true; |
|
2209 } |
|
2210 |
|
2211 PFilePickerChild* |
|
2212 TabChild::AllocPFilePickerChild(const nsString&, const int16_t&) |
|
2213 { |
|
2214 NS_RUNTIMEABORT("unused"); |
|
2215 return nullptr; |
|
2216 } |
|
2217 |
|
2218 bool |
|
2219 TabChild::DeallocPFilePickerChild(PFilePickerChild* actor) |
|
2220 { |
|
2221 nsFilePickerProxy* filePicker = static_cast<nsFilePickerProxy*>(actor); |
|
2222 NS_RELEASE(filePicker); |
|
2223 return true; |
|
2224 } |
|
2225 |
|
2226 bool |
|
2227 TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture) |
|
2228 { |
|
2229 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation()); |
|
2230 NS_ENSURE_TRUE(window, true); |
|
2231 nsCOMPtr<EventTarget> chromeHandler = |
|
2232 do_QueryInterface(window->GetChromeEventHandler()); |
|
2233 NS_ENSURE_TRUE(chromeHandler, true); |
|
2234 nsRefPtr<ContentListener> listener = new ContentListener(this); |
|
2235 chromeHandler->AddEventListener(aType, listener, capture); |
|
2236 return true; |
|
2237 } |
|
2238 |
|
2239 POfflineCacheUpdateChild* |
|
2240 TabChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI, |
|
2241 const URIParams& documentURI, |
|
2242 const bool& stickDocument) |
|
2243 { |
|
2244 NS_RUNTIMEABORT("unused"); |
|
2245 return nullptr; |
|
2246 } |
|
2247 |
|
2248 bool |
|
2249 TabChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor) |
|
2250 { |
|
2251 OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor); |
|
2252 NS_RELEASE(offlineCacheUpdate); |
|
2253 return true; |
|
2254 } |
|
2255 |
|
2256 bool |
|
2257 TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope) |
|
2258 { |
|
2259 if (!mGlobal && !InitTabChildGlobal()) |
|
2260 // This can happen if we're half-destroyed. It's not a fatal |
|
2261 // error. |
|
2262 return true; |
|
2263 |
|
2264 LoadFrameScriptInternal(aURL, aRunInGlobalScope); |
|
2265 return true; |
|
2266 } |
|
2267 |
|
2268 bool |
|
2269 TabChild::RecvAsyncMessage(const nsString& aMessage, |
|
2270 const ClonedMessageData& aData, |
|
2271 const InfallibleTArray<CpowEntry>& aCpows, |
|
2272 const IPC::Principal& aPrincipal) |
|
2273 { |
|
2274 if (mTabChildGlobal) { |
|
2275 nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal()); |
|
2276 StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData); |
|
2277 nsRefPtr<nsFrameMessageManager> mm = |
|
2278 static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get()); |
|
2279 CpowIdHolder cpows(static_cast<ContentChild*>(Manager())->GetCPOWManager(), aCpows); |
|
2280 mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), |
|
2281 aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); |
|
2282 } |
|
2283 return true; |
|
2284 } |
|
2285 |
|
2286 class UnloadScriptEvent : public nsRunnable |
|
2287 { |
|
2288 public: |
|
2289 UnloadScriptEvent(TabChild* aTabChild, TabChildGlobal* aTabChildGlobal) |
|
2290 : mTabChild(aTabChild), mTabChildGlobal(aTabChildGlobal) |
|
2291 { } |
|
2292 |
|
2293 NS_IMETHOD Run() |
|
2294 { |
|
2295 nsCOMPtr<nsIDOMEvent> event; |
|
2296 NS_NewDOMEvent(getter_AddRefs(event), mTabChildGlobal, nullptr, nullptr); |
|
2297 if (event) { |
|
2298 event->InitEvent(NS_LITERAL_STRING("unload"), false, false); |
|
2299 event->SetTrusted(true); |
|
2300 |
|
2301 bool dummy; |
|
2302 mTabChildGlobal->DispatchEvent(event, &dummy); |
|
2303 } |
|
2304 |
|
2305 return NS_OK; |
|
2306 } |
|
2307 |
|
2308 nsRefPtr<TabChild> mTabChild; |
|
2309 TabChildGlobal* mTabChildGlobal; |
|
2310 }; |
|
2311 |
|
2312 bool |
|
2313 TabChild::RecvDestroy() |
|
2314 { |
|
2315 if (mTabChildGlobal) { |
|
2316 // Let the frame scripts know the child is being closed |
|
2317 nsContentUtils::AddScriptRunner( |
|
2318 new UnloadScriptEvent(this, mTabChildGlobal) |
|
2319 ); |
|
2320 } |
|
2321 |
|
2322 nsCOMPtr<nsIObserverService> observerService = |
|
2323 mozilla::services::GetObserverService(); |
|
2324 |
|
2325 observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT); |
|
2326 observerService->RemoveObserver(this, BEFORE_FIRST_PAINT); |
|
2327 |
|
2328 const InfallibleTArray<PIndexedDBChild*>& idbActors = |
|
2329 ManagedPIndexedDBChild(); |
|
2330 for (uint32_t i = 0; i < idbActors.Length(); ++i) { |
|
2331 static_cast<IndexedDBChild*>(idbActors[i])->Disconnect(); |
|
2332 } |
|
2333 |
|
2334 // XXX what other code in ~TabChild() should we be running here? |
|
2335 DestroyWindow(); |
|
2336 |
|
2337 return Send__delete__(this); |
|
2338 } |
|
2339 |
|
2340 bool |
|
2341 TabChild::RecvSetUpdateHitRegion(const bool& aEnabled) |
|
2342 { |
|
2343 mUpdateHitRegion = aEnabled; |
|
2344 return true; |
|
2345 } |
|
2346 |
|
2347 bool |
|
2348 TabChild::RecvSetIsDocShellActive(const bool& aIsActive) |
|
2349 { |
|
2350 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation()); |
|
2351 if (docShell) { |
|
2352 docShell->SetIsActive(aIsActive); |
|
2353 } |
|
2354 return true; |
|
2355 } |
|
2356 |
|
2357 PRenderFrameChild* |
|
2358 TabChild::AllocPRenderFrameChild() |
|
2359 { |
|
2360 return new RenderFrameChild(); |
|
2361 } |
|
2362 |
|
2363 bool |
|
2364 TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame) |
|
2365 { |
|
2366 delete aFrame; |
|
2367 return true; |
|
2368 } |
|
2369 |
|
2370 bool |
|
2371 TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading) |
|
2372 { |
|
2373 if (!mGlobal && !mTabChildGlobal) { |
|
2374 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation()); |
|
2375 NS_ENSURE_TRUE(window, false); |
|
2376 nsCOMPtr<EventTarget> chromeHandler = |
|
2377 do_QueryInterface(window->GetChromeEventHandler()); |
|
2378 NS_ENSURE_TRUE(chromeHandler, false); |
|
2379 |
|
2380 nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this); |
|
2381 mTabChildGlobal = scope; |
|
2382 |
|
2383 nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope); |
|
2384 |
|
2385 NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal"); |
|
2386 NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports, globalId), false); |
|
2387 |
|
2388 scope->Init(); |
|
2389 |
|
2390 nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler); |
|
2391 NS_ENSURE_TRUE(root, false); |
|
2392 root->SetParentTarget(scope); |
|
2393 |
|
2394 chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false); |
|
2395 } |
|
2396 |
|
2397 if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) { |
|
2398 mTriedBrowserInit = true; |
|
2399 // Initialize the child side of the browser element machinery, |
|
2400 // if appropriate. |
|
2401 if (IsBrowserOrApp()) { |
|
2402 RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true); |
|
2403 } |
|
2404 } |
|
2405 |
|
2406 return true; |
|
2407 } |
|
2408 |
|
2409 bool |
|
2410 TabChild::InitRenderingState() |
|
2411 { |
|
2412 static_cast<PuppetWidget*>(mWidget.get())->InitIMEState(); |
|
2413 |
|
2414 uint64_t id; |
|
2415 bool success; |
|
2416 RenderFrameChild* remoteFrame = |
|
2417 static_cast<RenderFrameChild*>(SendPRenderFrameConstructor()); |
|
2418 if (!remoteFrame) { |
|
2419 NS_WARNING("failed to construct RenderFrame"); |
|
2420 return false; |
|
2421 } |
|
2422 SendInitRenderFrame(remoteFrame, &mScrolling, &mTextureFactoryIdentifier, &id, &success); |
|
2423 if (!success) { |
|
2424 NS_WARNING("failed to construct RenderFrame"); |
|
2425 PRenderFrameChild::Send__delete__(remoteFrame); |
|
2426 return false; |
|
2427 } |
|
2428 |
|
2429 PLayerTransactionChild* shadowManager = nullptr; |
|
2430 if (id != 0) { |
|
2431 // Pushing layers transactions directly to a separate |
|
2432 // compositor context. |
|
2433 PCompositorChild* compositorChild = CompositorChild::Get(); |
|
2434 if (!compositorChild) { |
|
2435 NS_WARNING("failed to get CompositorChild instance"); |
|
2436 return false; |
|
2437 } |
|
2438 nsTArray<LayersBackend> backends; |
|
2439 backends.AppendElement(mTextureFactoryIdentifier.mParentBackend); |
|
2440 bool success; |
|
2441 shadowManager = |
|
2442 compositorChild->SendPLayerTransactionConstructor(backends, |
|
2443 id, &mTextureFactoryIdentifier, &success); |
|
2444 if (!success) { |
|
2445 NS_WARNING("failed to properly allocate layer transaction"); |
|
2446 return false; |
|
2447 } |
|
2448 } else { |
|
2449 // Pushing transactions to the parent content. |
|
2450 shadowManager = remoteFrame->SendPLayerTransactionConstructor(); |
|
2451 } |
|
2452 |
|
2453 if (!shadowManager) { |
|
2454 NS_WARNING("failed to construct LayersChild"); |
|
2455 // This results in |remoteFrame| being deleted. |
|
2456 PRenderFrameChild::Send__delete__(remoteFrame); |
|
2457 return false; |
|
2458 } |
|
2459 |
|
2460 ShadowLayerForwarder* lf = |
|
2461 mWidget->GetLayerManager(shadowManager, mTextureFactoryIdentifier.mParentBackend) |
|
2462 ->AsShadowForwarder(); |
|
2463 NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(), |
|
2464 "PuppetWidget should have shadow manager"); |
|
2465 lf->IdentifyTextureHost(mTextureFactoryIdentifier); |
|
2466 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier); |
|
2467 |
|
2468 mRemoteFrame = remoteFrame; |
|
2469 if (id != 0) { |
|
2470 if (!sTabChildren) { |
|
2471 sTabChildren = new TabChildMap; |
|
2472 } |
|
2473 sTabChildren->Put(id, this); |
|
2474 mLayersId = id; |
|
2475 } |
|
2476 |
|
2477 nsCOMPtr<nsIObserverService> observerService = |
|
2478 mozilla::services::GetObserverService(); |
|
2479 |
|
2480 if (observerService) { |
|
2481 observerService->AddObserver(this, |
|
2482 BROWSER_ZOOM_TO_RECT, |
|
2483 false); |
|
2484 observerService->AddObserver(this, |
|
2485 BEFORE_FIRST_PAINT, |
|
2486 false); |
|
2487 } |
|
2488 |
|
2489 // This state can't change during the lifetime of the child. |
|
2490 sCpowsEnabled = BrowserTabsRemote(); |
|
2491 if (Preferences::GetBool("dom.ipc.cpows.force-enabled", false)) |
|
2492 sCpowsEnabled = true; |
|
2493 |
|
2494 return true; |
|
2495 } |
|
2496 |
|
2497 void |
|
2498 TabChild::SetBackgroundColor(const nscolor& aColor) |
|
2499 { |
|
2500 if (mLastBackgroundColor != aColor) { |
|
2501 mLastBackgroundColor = aColor; |
|
2502 SendSetBackgroundColor(mLastBackgroundColor); |
|
2503 } |
|
2504 } |
|
2505 |
|
2506 void |
|
2507 TabChild::GetDPI(float* aDPI) |
|
2508 { |
|
2509 *aDPI = -1.0; |
|
2510 if (!mRemoteFrame) { |
|
2511 return; |
|
2512 } |
|
2513 |
|
2514 SendGetDPI(aDPI); |
|
2515 } |
|
2516 |
|
2517 void |
|
2518 TabChild::GetDefaultScale(double* aScale) |
|
2519 { |
|
2520 *aScale = -1.0; |
|
2521 if (!mRemoteFrame) { |
|
2522 return; |
|
2523 } |
|
2524 |
|
2525 SendGetDefaultScale(aScale); |
|
2526 } |
|
2527 |
|
2528 void |
|
2529 TabChild::NotifyPainted() |
|
2530 { |
|
2531 if (UseDirectCompositor() && !mNotified) { |
|
2532 mRemoteFrame->SendNotifyCompositorTransaction(); |
|
2533 mNotified = true; |
|
2534 } |
|
2535 } |
|
2536 |
|
2537 bool |
|
2538 TabChild::DispatchMouseEvent(const nsString& aType, |
|
2539 const CSSPoint& aPoint, |
|
2540 const int32_t& aButton, |
|
2541 const int32_t& aClickCount, |
|
2542 const int32_t& aModifiers, |
|
2543 const bool& aIgnoreRootScrollFrame, |
|
2544 const unsigned short& aInputSourceArg) |
|
2545 { |
|
2546 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); |
|
2547 NS_ENSURE_TRUE(utils, true); |
|
2548 |
|
2549 bool defaultPrevented = false; |
|
2550 utils->SendMouseEvent(aType, aPoint.x, aPoint.y, aButton, aClickCount, aModifiers, |
|
2551 aIgnoreRootScrollFrame, 0, aInputSourceArg, false, 4, &defaultPrevented); |
|
2552 return defaultPrevented; |
|
2553 } |
|
2554 |
|
2555 void |
|
2556 TabChild::MakeVisible() |
|
2557 { |
|
2558 if (mWidget) { |
|
2559 mWidget->Show(true); |
|
2560 } |
|
2561 } |
|
2562 |
|
2563 void |
|
2564 TabChild::MakeHidden() |
|
2565 { |
|
2566 if (mWidget) { |
|
2567 mWidget->Show(false); |
|
2568 } |
|
2569 } |
|
2570 |
|
2571 void |
|
2572 TabChild::UpdateHitRegion(const nsRegion& aRegion) |
|
2573 { |
|
2574 mRemoteFrame->SendUpdateHitRegion(aRegion); |
|
2575 } |
|
2576 |
|
2577 NS_IMETHODIMP |
|
2578 TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult) |
|
2579 { |
|
2580 if (mTabChildGlobal) { |
|
2581 NS_ADDREF(*aResult = mTabChildGlobal); |
|
2582 return NS_OK; |
|
2583 } |
|
2584 *aResult = nullptr; |
|
2585 return NS_ERROR_FAILURE; |
|
2586 } |
|
2587 |
|
2588 void |
|
2589 TabChild::SendRequestFocus(bool aCanFocus) |
|
2590 { |
|
2591 PBrowserChild::SendRequestFocus(aCanFocus); |
|
2592 } |
|
2593 |
|
2594 PIndexedDBChild* |
|
2595 TabChild::AllocPIndexedDBChild( |
|
2596 const nsCString& aGroup, |
|
2597 const nsCString& aASCIIOrigin, bool* /* aAllowed */) |
|
2598 { |
|
2599 NS_NOTREACHED("Should never get here!"); |
|
2600 return nullptr; |
|
2601 } |
|
2602 |
|
2603 bool |
|
2604 TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor) |
|
2605 { |
|
2606 delete aActor; |
|
2607 return true; |
|
2608 } |
|
2609 |
|
2610 bool |
|
2611 TabChild::DoSendBlockingMessage(JSContext* aCx, |
|
2612 const nsAString& aMessage, |
|
2613 const StructuredCloneData& aData, |
|
2614 JS::Handle<JSObject *> aCpows, |
|
2615 nsIPrincipal* aPrincipal, |
|
2616 InfallibleTArray<nsString>* aJSONRetVal, |
|
2617 bool aIsSync) |
|
2618 { |
|
2619 ContentChild* cc = Manager(); |
|
2620 ClonedMessageData data; |
|
2621 if (!BuildClonedMessageDataForChild(cc, aData, data)) { |
|
2622 return false; |
|
2623 } |
|
2624 InfallibleTArray<CpowEntry> cpows; |
|
2625 if (sCpowsEnabled) { |
|
2626 if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { |
|
2627 return false; |
|
2628 } |
|
2629 } |
|
2630 if (aIsSync) { |
|
2631 return SendSyncMessage(PromiseFlatString(aMessage), data, cpows, |
|
2632 aPrincipal, aJSONRetVal); |
|
2633 } |
|
2634 |
|
2635 return CallRpcMessage(PromiseFlatString(aMessage), data, cpows, |
|
2636 aPrincipal, aJSONRetVal); |
|
2637 } |
|
2638 |
|
2639 bool |
|
2640 TabChild::DoSendAsyncMessage(JSContext* aCx, |
|
2641 const nsAString& aMessage, |
|
2642 const StructuredCloneData& aData, |
|
2643 JS::Handle<JSObject *> aCpows, |
|
2644 nsIPrincipal* aPrincipal) |
|
2645 { |
|
2646 ContentChild* cc = Manager(); |
|
2647 ClonedMessageData data; |
|
2648 if (!BuildClonedMessageDataForChild(cc, aData, data)) { |
|
2649 return false; |
|
2650 } |
|
2651 InfallibleTArray<CpowEntry> cpows; |
|
2652 if (sCpowsEnabled) { |
|
2653 if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { |
|
2654 return false; |
|
2655 } |
|
2656 } |
|
2657 return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows, |
|
2658 aPrincipal); |
|
2659 } |
|
2660 |
|
2661 TabChild* |
|
2662 TabChild::GetFrom(nsIPresShell* aPresShell) |
|
2663 { |
|
2664 nsIDocument* doc = aPresShell->GetDocument(); |
|
2665 if (!doc) { |
|
2666 return nullptr; |
|
2667 } |
|
2668 nsCOMPtr<nsIDocShell> docShell(doc->GetDocShell()); |
|
2669 return GetFrom(docShell); |
|
2670 } |
|
2671 |
|
2672 TabChild* |
|
2673 TabChild::GetFrom(uint64_t aLayersId) |
|
2674 { |
|
2675 if (!sTabChildren) { |
|
2676 return nullptr; |
|
2677 } |
|
2678 return sTabChildren->Get(aLayersId); |
|
2679 } |
|
2680 |
|
2681 void |
|
2682 TabChild::DidComposite() |
|
2683 { |
|
2684 MOZ_ASSERT(mWidget); |
|
2685 MOZ_ASSERT(mWidget->GetLayerManager()); |
|
2686 MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT); |
|
2687 |
|
2688 ClientLayerManager *manager = static_cast<ClientLayerManager*>(mWidget->GetLayerManager()); |
|
2689 manager->DidComposite(); |
|
2690 } |
|
2691 |
|
2692 NS_IMETHODIMP |
|
2693 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) |
|
2694 { |
|
2695 nsString str(aTipText); |
|
2696 SendShowTooltip(aXCoords, aYCoords, str); |
|
2697 return NS_OK; |
|
2698 } |
|
2699 |
|
2700 NS_IMETHODIMP |
|
2701 TabChild::OnHideTooltip() |
|
2702 { |
|
2703 SendHideTooltip(); |
|
2704 return NS_OK; |
|
2705 } |
|
2706 |
|
2707 TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild) |
|
2708 : mTabChild(aTabChild) |
|
2709 { |
|
2710 } |
|
2711 |
|
2712 void |
|
2713 TabChildGlobal::Init() |
|
2714 { |
|
2715 NS_ASSERTION(!mMessageManager, "Re-initializing?!?"); |
|
2716 mMessageManager = new nsFrameMessageManager(mTabChild, |
|
2717 nullptr, |
|
2718 MM_CHILD); |
|
2719 } |
|
2720 |
|
2721 NS_IMPL_CYCLE_COLLECTION_INHERITED(TabChildGlobal, DOMEventTargetHelper, |
|
2722 mMessageManager, mTabChild) |
|
2723 |
|
2724 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal) |
|
2725 NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager) |
|
2726 NS_INTERFACE_MAP_ENTRY(nsIMessageSender) |
|
2727 NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender) |
|
2728 NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager) |
|
2729 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal) |
|
2730 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject) |
|
2731 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager) |
|
2732 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) |
|
2733 |
|
2734 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper) |
|
2735 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper) |
|
2736 |
|
2737 /* [notxpcom] boolean markForCC (); */ |
|
2738 // This method isn't automatically forwarded safely because it's notxpcom, so |
|
2739 // the IDL binding doesn't know what value to return. |
|
2740 NS_IMETHODIMP_(bool) |
|
2741 TabChildGlobal::MarkForCC() |
|
2742 { |
|
2743 return mMessageManager ? mMessageManager->MarkForCC() : false; |
|
2744 } |
|
2745 |
|
2746 NS_IMETHODIMP |
|
2747 TabChildGlobal::GetContent(nsIDOMWindow** aContent) |
|
2748 { |
|
2749 *aContent = nullptr; |
|
2750 if (!mTabChild) |
|
2751 return NS_ERROR_NULL_POINTER; |
|
2752 nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mTabChild->WebNavigation()); |
|
2753 window.swap(*aContent); |
|
2754 return NS_OK; |
|
2755 } |
|
2756 |
|
2757 NS_IMETHODIMP |
|
2758 TabChildGlobal::PrivateNoteIntentionalCrash() |
|
2759 { |
|
2760 mozilla::NoteIntentionalCrash("tab"); |
|
2761 return NS_OK; |
|
2762 } |
|
2763 |
|
2764 NS_IMETHODIMP |
|
2765 TabChildGlobal::GetDocShell(nsIDocShell** aDocShell) |
|
2766 { |
|
2767 *aDocShell = nullptr; |
|
2768 if (!mTabChild) |
|
2769 return NS_ERROR_NULL_POINTER; |
|
2770 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation()); |
|
2771 docShell.swap(*aDocShell); |
|
2772 return NS_OK; |
|
2773 } |
|
2774 |
|
2775 NS_IMETHODIMP |
|
2776 TabChildGlobal::Btoa(const nsAString& aBinaryData, |
|
2777 nsAString& aAsciiBase64String) |
|
2778 { |
|
2779 return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String); |
|
2780 } |
|
2781 |
|
2782 NS_IMETHODIMP |
|
2783 TabChildGlobal::Atob(const nsAString& aAsciiString, |
|
2784 nsAString& aBinaryData) |
|
2785 { |
|
2786 return nsContentUtils::Atob(aAsciiString, aBinaryData); |
|
2787 } |
|
2788 |
|
2789 JSContext* |
|
2790 TabChildGlobal::GetJSContextForEventHandlers() |
|
2791 { |
|
2792 return nsContentUtils::GetSafeJSContext(); |
|
2793 } |
|
2794 |
|
2795 nsIPrincipal* |
|
2796 TabChildGlobal::GetPrincipal() |
|
2797 { |
|
2798 if (!mTabChild) |
|
2799 return nullptr; |
|
2800 return mTabChild->GetPrincipal(); |
|
2801 } |
|
2802 |
|
2803 JSObject* |
|
2804 TabChildGlobal::GetGlobalJSObject() |
|
2805 { |
|
2806 NS_ENSURE_TRUE(mTabChild, nullptr); |
|
2807 nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mTabChild->GetGlobal(); |
|
2808 NS_ENSURE_TRUE(ref, nullptr); |
|
2809 return ref->GetJSObject(); |
|
2810 } |
|
2811 |