dom/ipc/TabChild.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     7 #include "base/basictypes.h"
     9 #include "TabChild.h"
    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"
    79 #include "nsColorPickerProxy.h"
    81 #ifdef DEBUG
    82 #include "PCOMContentPermissionRequestChild.h"
    83 #endif /* DEBUG */
    85 #define BROWSER_ELEMENT_CHILD_SCRIPT \
    86     NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
    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;
    99 NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
   101 static const CSSSize kDefaultViewportSize(980, 480);
   103 static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
   104 static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
   106 static bool sCpowsEnabled = false;
   107 static int32_t sActiveDurationMs = 10;
   108 static bool sActiveDurationMsSet = false;
   110 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
   111 static TabChildMap* sTabChildren;
   113 TabChildBase::TabChildBase()
   114   : mOldViewportWidth(0.0f)
   115   , mContentDocumentIsDisplayed(false)
   116   , mTabChildGlobal(nullptr)
   117   , mInnerSize(0, 0)
   118 {
   119 }
   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
   127 NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
   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 }
   151 bool
   152 TabChildBase::HasValidInnerSize()
   153 {
   154   return (mInnerSize.width != 0) && (mInnerSize.height != 0);
   155 }
   157 void
   158 TabChildBase::SetCSSViewport(const CSSSize& aSize)
   159 {
   160   mOldViewportWidth = aSize.width;
   162   if (mContentDocumentIsDisplayed) {
   163     nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   164     utils->SetCSSViewport(aSize.width, aSize.height);
   165   }
   166 }
   168 CSSSize
   169 TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport)
   170 {
   171   nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement();
   172   HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement();
   174   if (!htmlDOMElement && !bodyDOMElement) {
   175     // For non-HTML content (e.g. SVG), just assume page size == viewport size.
   176     return aViewport;
   177   }
   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 }
   193 bool
   194 TabChildBase::HandlePossibleViewportChange()
   195 {
   196   if (!IsAsyncPanZoomEnabled()) {
   197     return false;
   198   }
   200   nsCOMPtr<nsIDocument> document(GetDocument());
   201   nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   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   }
   220   float screenW = mInnerSize.width;
   221   float screenH = mInnerSize.height;
   222   CSSSize viewport(viewportInfo.GetSize());
   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   }
   230   float oldBrowserWidth = mOldViewportWidth;
   231   mLastRootMetrics.mViewport.SizeTo(viewport);
   232   if (!oldBrowserWidth) {
   233     oldBrowserWidth = kDefaultViewportSize.width;
   234   }
   235   SetCSSViewport(viewport);
   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   }
   250   float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width;
   251   if (!oldScreenWidth) {
   252     oldScreenWidth = mInnerSize.width;
   253   }
   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);
   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);
   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     }
   290     CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
   291     MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
   292                defaultZoom <= viewportInfo.GetMaxZoom());
   293     metrics.SetZoom(defaultZoom);
   295     metrics.SetScrollId(viewId);
   296   }
   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);
   304   CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels();
   305   utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
   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.
   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);
   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();
   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);
   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);
   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   }
   350   return true;
   351 }
   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 }
   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 }
   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     }
   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 }
   396 bool
   397 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
   398 {
   399   MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
   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   }
   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 }
   428 FrameMetrics
   429 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
   430 {
   431     if (!mGlobal || !mTabChildGlobal) {
   432         return aFrameMetrics;
   433     }
   435     nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   437     FrameMetrics newMetrics = aFrameMetrics;
   438     APZCCallbackHelper::UpdateRootFrame(utils, newMetrics);
   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(" }");
   475     DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
   476     return newMetrics;
   477 }
   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);
   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;
   498   return DispatchWidgetEvent(event);
   499 }
   501 nsEventStatus
   502 TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event)
   503 {
   504   if (!event.widget)
   505     return nsEventStatus_eConsumeNoDefault;
   507   nsEventStatus status;
   508   NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status),
   509                     nsEventStatus_eConsumeNoDefault);
   510   return status;
   511 }
   513 bool
   514 TabChildBase::IsAsyncPanZoomEnabled()
   515 {
   516     return mScrolling == ASYNC_PAN_ZOOM;
   517 }
   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 }
   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     };
   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     };
   550 public:
   551     nsString mPath;
   552     FileDescriptor mFileDescriptor;
   553     nsCOMPtr<nsICachedFileDescriptorListener> mCallback;
   554     bool mCanceled;
   556     CachedFileDescriptorInfo(const nsAString& aPath)
   557       : mPath(aPath), mCanceled(false)
   558     { }
   560     CachedFileDescriptorInfo(const nsAString& aPath,
   561                              const FileDescriptor& aFileDescriptor)
   562       : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false)
   563     { }
   565     CachedFileDescriptorInfo(const nsAString& aPath,
   566                              nsICachedFileDescriptorListener* aCallback)
   567       : mPath(aPath), mCallback(aCallback), mCanceled(false)
   568     { }
   570     PathOnlyComparatorHelper PathOnlyComparator() const
   571     {
   572         return PathOnlyComparatorHelper();
   573     }
   575     PathAndCallbackComparatorHelper PathAndCallbackComparator() const
   576     {
   577         return PathAndCallbackComparatorHelper();
   578     }
   580     void FireCallback() const
   581     {
   582         mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor);
   583     }
   584 };
   586 class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable
   587 {
   588     typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo;
   590     nsAutoPtr<CachedFileDescriptorInfo> mInfo;
   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     }
   602     void Dispatch()
   603     {
   604         MOZ_ASSERT(NS_IsMainThread());
   606         nsresult rv = NS_DispatchToCurrentThread(this);
   607         NS_ENSURE_SUCCESS_VOID(rv);
   608     }
   610 private:
   611     NS_IMETHOD Run()
   612     {
   613         MOZ_ASSERT(NS_IsMainThread());
   614         MOZ_ASSERT(mInfo);
   616         mInfo->FireCallback();
   617         return NS_OK;
   618     }
   619 };
   621 StaticRefPtr<TabChild> sPreallocatedTab;
   623 /*static*/ void
   624 TabChild::PreloadSlowThings()
   625 {
   626     MOZ_ASSERT(!sPreallocatedTab);
   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);
   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     }
   653     sPreallocatedTab = tab;
   654     ClearOnShutdown(&sPreallocatedTab);
   655 }
   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()) {
   664         nsRefPtr<TabChild> child = sPreallocatedTab.get();
   665         sPreallocatedTab = nullptr;
   667         MOZ_ASSERT(!child->mTriedBrowserInit);
   669         child->SetTabContext(aContext);
   670         child->NotifyTabContextUpdated();
   671         return child.forget();
   672     }
   674     nsRefPtr<TabChild> iframe = new TabChild(aManager,
   675                                              aContext, aChromeFlags);
   676     return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
   677 }
   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 }
   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   }
   720   return NS_OK;
   721 }
   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());
   749       if (SameCOMIdentity(subject, doc)) {
   750         nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   751         utils->SetIsFirstPaint(true);
   753         mContentDocumentIsDisplayed = true;
   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);
   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   }
   774   return NS_OK;
   775 }
   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 }
   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 }
   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   }
   809   nsCOMPtr<nsIDOMWindow> window;
   810   aWebProgress->GetDOMWindow(getter_AddRefs(window));
   811   if (!window) {
   812     return NS_OK;
   813   }
   815   nsCOMPtr<nsIDOMDocument> progressDoc;
   816   window->GetDocument(getter_AddRefs(progressDoc));
   817   if (!progressDoc) {
   818     return NS_OK;
   819   }
   821   nsCOMPtr<nsIDOMDocument> domDoc;
   822   WebNavigation()->GetDocument(getter_AddRefs(domDoc));
   823   if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) {
   824     return NS_OK;
   825   }
   827   nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
   828   if (!urifixup) {
   829     return NS_OK;
   830   }
   832   nsCOMPtr<nsIURI> exposableURI;
   833   urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI));
   834   if (!exposableURI) {
   835     return NS_OK;
   836   }
   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   }
   849   return NS_OK;
   850 }
   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 }
   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 }
   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 }
   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   }
   892   webBrowser->SetContainerWindow(this);
   893   mWebNav = do_QueryInterface(webBrowser);
   894   NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
   896   nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
   897   docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
   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   }
   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   );
   917   baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0);
   918   baseWindow->Create();
   920   NotifyTabContextUpdated();
   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   }
   934   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   935   MOZ_ASSERT(docShell);
   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);
   946   nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
   947   NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
   948   webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
   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);
   964   return NS_OK;
   965 }
   967 void
   968 TabChild::NotifyTabContextUpdated()
   969 {
   970     nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   971     MOZ_ASSERT(docShell);
   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 }
   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)
   999 NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
  1000 NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
  1002 NS_IMETHODIMP
  1003 TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
  1005   return SetStatusWithContext(aStatusType,
  1006       aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
  1007               : EmptyString(),
  1008       nullptr);
  1011 NS_IMETHODIMP
  1012 TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
  1014   NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild");
  1016   return NS_ERROR_NOT_IMPLEMENTED;
  1019 NS_IMETHODIMP
  1020 TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
  1022   NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
  1024   return NS_ERROR_NOT_IMPLEMENTED;
  1027 NS_IMETHODIMP
  1028 TabChild::GetChromeFlags(uint32_t* aChromeFlags)
  1030   *aChromeFlags = mChromeFlags;
  1031   return NS_OK;
  1034 NS_IMETHODIMP
  1035 TabChild::SetChromeFlags(uint32_t aChromeFlags)
  1037   NS_NOTREACHED("trying to SetChromeFlags from content process?");
  1039   return NS_ERROR_NOT_IMPLEMENTED;
  1042 NS_IMETHODIMP
  1043 TabChild::DestroyBrowserWindow()
  1045   NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
  1047   return NS_ERROR_NOT_IMPLEMENTED;
  1050 NS_IMETHODIMP
  1051 TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
  1053   NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild");
  1055   return NS_ERROR_NOT_IMPLEMENTED;
  1058 NS_IMETHODIMP
  1059 TabChild::ShowAsModal()
  1061   NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild");
  1063   return NS_ERROR_NOT_IMPLEMENTED;
  1066 NS_IMETHODIMP
  1067 TabChild::IsWindowModal(bool* aRetVal)
  1069   *aRetVal = false;
  1070   return NS_OK;
  1073 NS_IMETHODIMP
  1074 TabChild::ExitModalEventLoop(nsresult aStatus)
  1076   NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild");
  1078   return NS_ERROR_NOT_IMPLEMENTED;
  1081 NS_IMETHODIMP
  1082 TabChild::SetStatusWithContext(uint32_t aStatusType,
  1083                                const nsAString& aStatusText,
  1084                                nsISupports* aStatusContext)
  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;
  1093 NS_IMETHODIMP
  1094 TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
  1095                              int32_t aCx, int32_t aCy)
  1097   NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild");
  1099   return NS_ERROR_NOT_IMPLEMENTED;
  1102 NS_IMETHODIMP
  1103 TabChild::GetDimensions(uint32_t aFlags, int32_t* aX,
  1104                              int32_t* aY, int32_t* aCx, int32_t* aCy)
  1106   if (aX) {
  1107     *aX = mOuterRect.x;
  1109   if (aY) {
  1110     *aY = mOuterRect.y;
  1112   if (aCx) {
  1113     *aCx = mOuterRect.width;
  1115   if (aCy) {
  1116     *aCy = mOuterRect.height;
  1119   return NS_OK;
  1122 NS_IMETHODIMP
  1123 TabChild::SetFocus()
  1125   NS_WARNING("TabChild::SetFocus not supported in TabChild");
  1127   return NS_ERROR_NOT_IMPLEMENTED;
  1130 NS_IMETHODIMP
  1131 TabChild::GetVisibility(bool* aVisibility)
  1133   *aVisibility = true;
  1134   return NS_OK;
  1137 NS_IMETHODIMP
  1138 TabChild::SetVisibility(bool aVisibility)
  1140   // should the platform support this? Bug 666365
  1141   return NS_OK;
  1144 NS_IMETHODIMP
  1145 TabChild::GetTitle(char16_t** aTitle)
  1147   NS_NOTREACHED("TabChild::GetTitle not supported in TabChild");
  1149   return NS_ERROR_NOT_IMPLEMENTED;
  1152 NS_IMETHODIMP
  1153 TabChild::SetTitle(const char16_t* aTitle)
  1155   // JavaScript sends the "DOMTitleChanged" event to the parent
  1156   // via the message manager.
  1157   return NS_OK;
  1160 NS_IMETHODIMP
  1161 TabChild::GetSiteWindow(void** aSiteWindow)
  1163   NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild");
  1165   return NS_ERROR_NOT_IMPLEMENTED;
  1168 NS_IMETHODIMP
  1169 TabChild::Blur()
  1171   NS_WARNING("TabChild::Blur not supported in TabChild");
  1173   return NS_ERROR_NOT_IMPLEMENTED;
  1176 NS_IMETHODIMP
  1177 TabChild::FocusNextElement()
  1179   SendMoveFocus(true);
  1180   return NS_OK;
  1183 NS_IMETHODIMP
  1184 TabChild::FocusPrevElement()
  1186   SendMoveFocus(false);
  1187   return NS_OK;
  1190 NS_IMETHODIMP
  1191 TabChild::GetInterface(const nsIID & aIID, void **aSink)
  1193     // XXXbz should we restrict the set of interfaces we hand out here?
  1194     // See bug 537429
  1195     return QueryInterface(aIID, aSink);
  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)
  1206     *aReturn = nullptr;
  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))) {
  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);
  1224     // Otherwise, create a new top-level window.
  1225     PBrowserChild* newChild;
  1226     if (!CallCreateWindow(&newChild)) {
  1227         return NS_ERROR_NOT_AVAILABLE;
  1230     *aWindowIsNew = true;
  1231     nsCOMPtr<nsIDOMWindow> win =
  1232         do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation());
  1233     win.forget(aReturn);
  1234     return NS_OK;
  1237 nsresult
  1238 TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
  1239                                     nsIURI* aURI,
  1240                                     const nsAString& aName,
  1241                                     const nsACString& aFeatures,
  1242                                     bool* aWindowIsNew,
  1243                                     nsIDOMWindow** aReturn)
  1245   *aReturn = nullptr;
  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;
  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();
  1262   unused << Manager()->SendPBrowserConstructor(
  1263       // We release this ref in DeallocPBrowserChild
  1264       nsRefPtr<TabChild>(newChild).forget().take(),
  1265       IPCTabContext(context, mScrolling), /* chromeFlags */ 0);
  1267   nsAutoCString spec;
  1268   if (aURI) {
  1269     aURI->GetSpec(spec);
  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;
  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();
  1286   nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
  1287   win.forget(aReturn);
  1288   return NS_OK;
  1291 #ifdef DEBUG
  1292 PContentPermissionRequestChild*
  1293 TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
  1294                                                     const InfallibleTArray<PermissionRequest>& aRequests,
  1295                                                     const IPC::Principal& aPrincipal)
  1297   PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
  1298   PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
  1299   child->mIPCOpen = true;
  1300   return request;
  1302 #endif /* DEBUG */
  1304 void
  1305 TabChild::DestroyWindow()
  1307     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
  1308     if (baseWindow)
  1309         baseWindow->Destroy();
  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();
  1318     if (mRemoteFrame) {
  1319         mRemoteFrame->Destroy();
  1320         mRemoteFrame = nullptr;
  1324     if (mLayersId != 0) {
  1325       MOZ_ASSERT(sTabChildren);
  1326       sTabChildren->Remove(mLayersId);
  1327       if (!sTabChildren->Count()) {
  1328         delete sTabChildren;
  1329         sTabChildren = nullptr;
  1331       mLayersId = 0;
  1335 bool
  1336 TabChild::UseDirectCompositor()
  1338     return !!CompositorChild::Get();
  1341 void
  1342 TabChild::ActorDestroy(ActorDestroyReason why)
  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;
  1353 TabChild::~TabChild()
  1355     DestroyWindow();
  1357     nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
  1358     if (webBrowser) {
  1359       webBrowser->SetContainerWindow(nullptr);
  1363 void
  1364 TabChild::SetProcessNameToAppName()
  1366   nsCOMPtr<mozIApplication> app = GetOwnApp();
  1367   if (!app) {
  1368     return;
  1371   nsAutoString appName;
  1372   nsresult rv = app->GetName(appName);
  1373   if (NS_FAILED(rv)) {
  1374     NS_WARNING("Failed to retrieve app name");
  1375     return;
  1378   ContentChild::GetSingleton()->SetProcessName(appName, true);
  1381 bool
  1382 TabChild::IsRootContentDocument()
  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.
  1402     return !HasAppOwnerApp();
  1405 bool
  1406 TabChild::RecvLoadURL(const nsCString& uri)
  1408     SetProcessNameToAppName();
  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?");
  1418 #ifdef MOZ_CRASHREPORTER
  1419     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
  1420 #endif
  1422     return true;
  1425 bool
  1426 TabChild::RecvCacheFileDescriptor(const nsString& aPath,
  1427                                   const FileDescriptor& aFileDescriptor)
  1429     MOZ_ASSERT(NS_IsMainThread());
  1430     MOZ_ASSERT(!aPath.IsEmpty());
  1431     MOZ_ASSERT(!mAppPackageFileDescriptorRecved);
  1433     mAppPackageFileDescriptorRecved = true;
  1435     // aFileDescriptor may be invalid here, but the callback will choose how to
  1436     // handle it.
  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;
  1451     nsAutoPtr<CachedFileDescriptorInfo>& info =
  1452         mCachedFileDescriptorInfos[index];
  1454     MOZ_ASSERT(info);
  1455     MOZ_ASSERT(info->mPath == aPath);
  1456     MOZ_ASSERT(!info->mFileDescriptor.IsValid());
  1457     MOZ_ASSERT(info->mCallback);
  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();
  1468     } else {
  1469         // Not canceled so fire the callback.
  1470         info->mFileDescriptor = aFileDescriptor;
  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();
  1477     mCachedFileDescriptorInfos.RemoveElementAt(index);
  1478     return true;
  1481 bool
  1482 TabChild::GetCachedFileDescriptor(const nsAString& aPath,
  1483                                   nsICachedFileDescriptorListener* aCallback)
  1485     MOZ_ASSERT(NS_IsMainThread());
  1486     MOZ_ASSERT(!aPath.IsEmpty());
  1487     MOZ_ASSERT(aCallback);
  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));
  1502         return false;
  1505     nsAutoPtr<CachedFileDescriptorInfo>& info =
  1506         mCachedFileDescriptorInfos[index];
  1508     MOZ_ASSERT(info);
  1509     MOZ_ASSERT(info->mPath == aPath);
  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;
  1522     MOZ_ASSERT(!info->mCallback);
  1523     info->mCallback = aCallback;
  1525     nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable =
  1526         new CachedFileDescriptorCallbackRunnable(info.forget());
  1527     runnable->Dispatch();
  1529     mCachedFileDescriptorInfos.RemoveElementAt(index);
  1530     return true;
  1533 void
  1534 TabChild::CancelCachedFileDescriptorCallback(
  1535                                      const nsAString& aPath,
  1536                                      nsICachedFileDescriptorListener* aCallback)
  1538     MOZ_ASSERT(NS_IsMainThread());
  1539     MOZ_ASSERT(!aPath.IsEmpty());
  1540     MOZ_ASSERT(aCallback);
  1542     if (mAppPackageFileDescriptorRecved) {
  1543       // Already received cached file descriptor for the app package. Nothing to do here.
  1544       return;
  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;
  1556     nsAutoPtr<CachedFileDescriptorInfo>& info =
  1557         mCachedFileDescriptorInfos[index];
  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);
  1565     // Set this flag so that we will close the file descriptor when it arrives.
  1566     info->mCanceled = true;
  1569 void
  1570 TabChild::DoFakeShow()
  1572   RecvShow(nsIntSize(0, 0));
  1573   mDidFakeShow = true;
  1576 bool
  1577 TabChild::RecvShow(const nsIntSize& size)
  1580     if (mDidFakeShow) {
  1581         return true;
  1584     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
  1585     if (!baseWindow) {
  1586         NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
  1587         return false;
  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;
  1598     baseWindow->SetVisibility(true);
  1600     return InitTabChildGlobal();
  1603 bool
  1604 TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
  1606     if (!mRemoteFrame) {
  1607         return true;
  1610     mOuterRect.x = rect.x;
  1611     mOuterRect.y = rect.y;
  1612     mOuterRect.width = rect.width;
  1613     mOuterRect.height = rect.height;
  1615     bool initialSizing = !HasValidInnerSize()
  1616                       && (size.width != 0 && size.height != 0);
  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);
  1624     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
  1625     baseWin->SetPositionAndSize(0, 0, size.width, size.height,
  1626                                 true);
  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();
  1636     HandlePossibleViewportChange();
  1638     return true;
  1641 bool
  1642 TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
  1644   return TabChildBase::UpdateFrameHandler(aFrameMetrics);
  1647 bool
  1648 TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
  1649                                       const uint32_t& aScrollGeneration)
  1651   APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
  1652   return true;
  1655 bool
  1656 TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1658     if (!mGlobal || !mTabChildGlobal) {
  1659         return true;
  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(" }");
  1670     DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
  1672     return true;
  1675 bool
  1676 TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1678   if (!mGlobal || !mTabChildGlobal) {
  1679     return true;
  1682   LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();;
  1684   MessageLoop::current()->PostDelayedTask(
  1685     FROM_HERE,
  1686     NewRunnableMethod(this, &TabChild::FireSingleTapEvent, currentPoint),
  1687     sActiveDurationMs);
  1688   return true;
  1691 void
  1692 TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
  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);
  1700 bool
  1701 TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1703   if (!mGlobal || !mTabChildGlobal) {
  1704     return true;
  1707   mContextMenuHandled =
  1708       DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
  1709                          APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
  1710                          2, 1, 0, false,
  1711                          nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
  1713   SendContentReceivedTouch(aGuid, mContextMenuHandled);
  1715   return true;
  1718 bool
  1719 TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1721   if (mContextMenuHandled) {
  1722     mContextMenuHandled = false;
  1723     return true;
  1726   RecvHandleSingleTap(aPoint, aGuid);
  1727   return true;
  1730 bool
  1731 TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
  1732                                    const APZStateChange& aChange,
  1733                                    const int& aArg)
  1735   switch (aChange)
  1737   case APZStateChange::TransformBegin:
  1739     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
  1740     nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
  1741     if (scrollbarOwner) {
  1742       scrollbarOwner->ScrollbarActivityStarted();
  1744     break;
  1746   case APZStateChange::TransformEnd:
  1748     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
  1749     nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
  1750     if (scrollbarOwner) {
  1751       scrollbarOwner->ScrollbarActivityStopped();
  1753     break;
  1755   case APZStateChange::StartTouch:
  1757     mActiveElementManager->HandleTouchStart(aArg);
  1758     break;
  1760   case APZStateChange::StartPanning:
  1762     mActiveElementManager->HandlePanStart();
  1763     break;
  1765   case APZStateChange::EndTouch:
  1767     mActiveElementManager->HandleTouchEnd(aArg);
  1768     break;
  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;
  1775   return true;
  1778 bool
  1779 TabChild::RecvActivate()
  1781   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
  1782   browser->Activate();
  1783   return true;
  1786 bool TabChild::RecvDeactivate()
  1788   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
  1789   browser->Deactivate();
  1790   return true;
  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)
  1802   DispatchMouseEvent(aType, CSSPoint(aX, aY), aButton, aClickCount, aModifiers,
  1803                      aIgnoreRootScrollFrame, nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN);
  1804   return true;
  1807 bool
  1808 TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
  1810   WidgetMouseEvent localEvent(event);
  1811   localEvent.widget = mWidget;
  1812   DispatchWidgetEvent(localEvent);
  1813   return true;
  1816 bool
  1817 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& event)
  1819   WidgetWheelEvent localEvent(event);
  1820   localEvent.widget = mWidget;
  1821   DispatchWidgetEvent(localEvent);
  1822   return true;
  1825 static Touch*
  1826 GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
  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;
  1834   return nullptr;
  1837 void
  1838 TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
  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);
  1856   if (aEvent.touches.Length() == 0) {
  1857     return;
  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;
  1868     if (aStatus == nsEventStatus_eConsumeNoDefault ||
  1869         nsIPresShell::gPreventMouseEvents ||
  1870         aEvent.mFlags.mMultipleActionsPrevented) {
  1871       return;
  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);
  1884     return;
  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;
  1892   Touch* trackedTouch = GetTouchForIdentifier(aEvent, mActivePointerId);
  1893   if (!trackedTouch) {
  1894     return;
  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();
  1905     return;
  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);
  1913     // fall through
  1914   case NS_TOUCH_CANCEL:
  1915     CancelTapTracking();
  1916     return;
  1918   default:
  1919     NS_WARNING("Unknown touch event type");
  1923 void
  1924 TabChild::FireContextMenuEvent()
  1926   double scale;
  1927   GetDefaultScale(&scale);
  1928   if (scale < 0) {
  1929     scale = 1;
  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);
  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;
  1951 void
  1952 TabChild::CancelTapTracking()
  1954   mActivePointerId = -1;
  1955   if (mTapHoldTimer) {
  1956     mTapHoldTimer->Cancel();
  1958   mTapHoldTimer = nullptr;
  1961 bool
  1962 TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
  1963                              const ScrollableLayerGuid& aGuid)
  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());
  1971   nsEventStatus status = DispatchWidgetEvent(localEvent);
  1973   if (!IsAsyncPanZoomEnabled()) {
  1974     UpdateTapState(localEvent, status);
  1975     return true;
  1978   if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
  1979     mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target());
  1982   nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
  1983   nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
  1985   if (!innerWindow || !innerWindow->HasTouchEventListeners()) {
  1986     SendContentReceivedTouch(aGuid, false);
  1987     return true;
  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;
  1999     break;
  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;
  2009     break;
  2012   default:
  2013     NS_WARNING("Unknown touch event type");
  2016   return true;
  2019 bool
  2020 TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
  2021                                  const ScrollableLayerGuid& aGuid)
  2023   return RecvRealTouchEvent(aEvent, aGuid);
  2026 void
  2027 TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache,
  2028                                    WidgetKeyboardEvent* aEvent)
  2030   MaybeNativeKeyBinding maybeBindings;
  2031   if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) {
  2032     return;
  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();
  2045 bool
  2046 TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
  2047                            const MaybeNativeKeyBinding& aBindings)
  2049   PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get());
  2050   AutoCacheNativeKeyCommands autoCache(widget);
  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();
  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;
  2068   WidgetKeyboardEvent localEvent(event);
  2069   localEvent.widget = mWidget;
  2070   nsEventStatus status = DispatchWidgetEvent(localEvent);
  2072   if (event.message == NS_KEY_DOWN) {
  2073     mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
  2076   if (localEvent.mFlags.mWantReplyFromContentProcess) {
  2077     SendReplyKeyEvent(localEvent);
  2080   return true;
  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)
  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;
  2098 bool
  2099 TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
  2101   WidgetCompositionEvent localEvent(event);
  2102   localEvent.widget = mWidget;
  2103   DispatchWidgetEvent(localEvent);
  2104   return true;
  2107 bool
  2108 TabChild::RecvTextEvent(const WidgetTextEvent& event)
  2110   WidgetTextEvent localEvent(event);
  2111   localEvent.widget = mWidget;
  2112   DispatchWidgetEvent(localEvent);
  2113   return true;
  2116 bool
  2117 TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
  2119   WidgetSelectionEvent localEvent(event);
  2120   localEvent.widget = mWidget;
  2121   DispatchWidgetEvent(localEvent);
  2122   return true;
  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)
  2133     return new DocumentRendererChild();
  2136 bool
  2137 TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor)
  2139     delete actor;
  2140     return true;
  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)
  2152     DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor);
  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)
  2161         return true; // silently ignore
  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
  2173     return PDocumentRendererChild::Send__delete__(actor, renderSize, data);
  2176 PColorPickerChild*
  2177 TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
  2179   NS_RUNTIMEABORT("unused");
  2180   return nullptr;
  2183 bool
  2184 TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
  2186   nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker);
  2187   NS_RELEASE(picker);
  2188   return true;
  2191 PContentPermissionRequestChild*
  2192 TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
  2193                                               const IPC::Principal& aPrincipal)
  2195   NS_RUNTIMEABORT("unused");
  2196   return nullptr;
  2199 bool
  2200 TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
  2202     PCOMContentPermissionRequestChild* child =
  2203         static_cast<PCOMContentPermissionRequestChild*>(actor);
  2204 #ifdef DEBUG
  2205     child->mIPCOpen = false;
  2206 #endif /* DEBUG */
  2207     child->IPDLRelease();
  2208     return true;
  2211 PFilePickerChild*
  2212 TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
  2214   NS_RUNTIMEABORT("unused");
  2215   return nullptr;
  2218 bool
  2219 TabChild::DeallocPFilePickerChild(PFilePickerChild* actor)
  2221   nsFilePickerProxy* filePicker = static_cast<nsFilePickerProxy*>(actor);
  2222   NS_RELEASE(filePicker);
  2223   return true;
  2226 bool
  2227 TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
  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;
  2239 POfflineCacheUpdateChild*
  2240 TabChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
  2241                                         const URIParams& documentURI,
  2242                                         const bool& stickDocument)
  2244   NS_RUNTIMEABORT("unused");
  2245   return nullptr;
  2248 bool
  2249 TabChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
  2251   OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor);
  2252   NS_RELEASE(offlineCacheUpdate);
  2253   return true;
  2256 bool
  2257 TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
  2259   if (!mGlobal && !InitTabChildGlobal())
  2260     // This can happen if we're half-destroyed.  It's not a fatal
  2261     // error.
  2262     return true;
  2264   LoadFrameScriptInternal(aURL, aRunInGlobalScope);
  2265   return true;
  2268 bool
  2269 TabChild::RecvAsyncMessage(const nsString& aMessage,
  2270                            const ClonedMessageData& aData,
  2271                            const InfallibleTArray<CpowEntry>& aCpows,
  2272                            const IPC::Principal& aPrincipal)
  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);
  2283   return true;
  2286 class UnloadScriptEvent : public nsRunnable
  2288 public:
  2289   UnloadScriptEvent(TabChild* aTabChild, TabChildGlobal* aTabChildGlobal)
  2290     : mTabChild(aTabChild), mTabChildGlobal(aTabChildGlobal)
  2291   { }
  2293   NS_IMETHOD Run()
  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);
  2301       bool dummy;
  2302       mTabChildGlobal->DispatchEvent(event, &dummy);
  2305     return NS_OK;
  2308   nsRefPtr<TabChild> mTabChild;
  2309   TabChildGlobal* mTabChildGlobal;
  2310 };
  2312 bool
  2313 TabChild::RecvDestroy()
  2315   if (mTabChildGlobal) {
  2316     // Let the frame scripts know the child is being closed
  2317     nsContentUtils::AddScriptRunner(
  2318       new UnloadScriptEvent(this, mTabChildGlobal)
  2319     );
  2322   nsCOMPtr<nsIObserverService> observerService =
  2323     mozilla::services::GetObserverService();
  2325   observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
  2326   observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
  2328   const InfallibleTArray<PIndexedDBChild*>& idbActors =
  2329     ManagedPIndexedDBChild();
  2330   for (uint32_t i = 0; i < idbActors.Length(); ++i) {
  2331     static_cast<IndexedDBChild*>(idbActors[i])->Disconnect();
  2334   // XXX what other code in ~TabChild() should we be running here?
  2335   DestroyWindow();
  2337   return Send__delete__(this);
  2340 bool
  2341 TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
  2343     mUpdateHitRegion = aEnabled;
  2344     return true;
  2347 bool
  2348 TabChild::RecvSetIsDocShellActive(const bool& aIsActive)
  2350     nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
  2351     if (docShell) {
  2352       docShell->SetIsActive(aIsActive);
  2354     return true;
  2357 PRenderFrameChild*
  2358 TabChild::AllocPRenderFrameChild()
  2360     return new RenderFrameChild();
  2363 bool
  2364 TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
  2366     delete aFrame;
  2367     return true;
  2370 bool
  2371 TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
  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);
  2380     nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
  2381     mTabChildGlobal = scope;
  2383     nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
  2385     NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
  2386     NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports, globalId), false);
  2388     scope->Init();
  2390     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
  2391     NS_ENSURE_TRUE(root, false);
  2392     root->SetParentTarget(scope);
  2394     chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
  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);
  2406   return true;
  2409 bool
  2410 TabChild::InitRenderingState()
  2412     static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
  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;
  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;
  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;
  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;
  2448     } else {
  2449         // Pushing transactions to the parent content.
  2450         shadowManager = remoteFrame->SendPLayerTransactionConstructor();
  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;
  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);
  2468     mRemoteFrame = remoteFrame;
  2469     if (id != 0) {
  2470       if (!sTabChildren) {
  2471         sTabChildren = new TabChildMap;
  2473       sTabChildren->Put(id, this);
  2474       mLayersId = id;
  2477     nsCOMPtr<nsIObserverService> observerService =
  2478         mozilla::services::GetObserverService();
  2480     if (observerService) {
  2481         observerService->AddObserver(this,
  2482                                      BROWSER_ZOOM_TO_RECT,
  2483                                      false);
  2484         observerService->AddObserver(this,
  2485                                      BEFORE_FIRST_PAINT,
  2486                                      false);
  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;
  2494     return true;
  2497 void
  2498 TabChild::SetBackgroundColor(const nscolor& aColor)
  2500   if (mLastBackgroundColor != aColor) {
  2501     mLastBackgroundColor = aColor;
  2502     SendSetBackgroundColor(mLastBackgroundColor);
  2506 void
  2507 TabChild::GetDPI(float* aDPI)
  2509     *aDPI = -1.0;
  2510     if (!mRemoteFrame) {
  2511         return;
  2514     SendGetDPI(aDPI);
  2517 void
  2518 TabChild::GetDefaultScale(double* aScale)
  2520     *aScale = -1.0;
  2521     if (!mRemoteFrame) {
  2522         return;
  2525     SendGetDefaultScale(aScale);
  2528 void
  2529 TabChild::NotifyPainted()
  2531     if (UseDirectCompositor() && !mNotified) {
  2532         mRemoteFrame->SendNotifyCompositorTransaction();
  2533         mNotified = true;
  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)
  2546   nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
  2547   NS_ENSURE_TRUE(utils, true);
  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;
  2555 void
  2556 TabChild::MakeVisible()
  2558     if (mWidget) {
  2559         mWidget->Show(true);
  2563 void
  2564 TabChild::MakeHidden()
  2566     if (mWidget) {
  2567         mWidget->Show(false);
  2571 void
  2572 TabChild::UpdateHitRegion(const nsRegion& aRegion)
  2574     mRemoteFrame->SendUpdateHitRegion(aRegion);
  2577 NS_IMETHODIMP
  2578 TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
  2580   if (mTabChildGlobal) {
  2581     NS_ADDREF(*aResult = mTabChildGlobal);
  2582     return NS_OK;
  2584   *aResult = nullptr;
  2585   return NS_ERROR_FAILURE;
  2588 void
  2589 TabChild::SendRequestFocus(bool aCanFocus)
  2591   PBrowserChild::SendRequestFocus(aCanFocus);
  2594 PIndexedDBChild*
  2595 TabChild::AllocPIndexedDBChild(
  2596                             const nsCString& aGroup,
  2597                             const nsCString& aASCIIOrigin, bool* /* aAllowed */)
  2599   NS_NOTREACHED("Should never get here!");
  2600   return nullptr;
  2603 bool
  2604 TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
  2606   delete aActor;
  2607   return true;
  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)
  2619   ContentChild* cc = Manager();
  2620   ClonedMessageData data;
  2621   if (!BuildClonedMessageDataForChild(cc, aData, data)) {
  2622     return false;
  2624   InfallibleTArray<CpowEntry> cpows;
  2625   if (sCpowsEnabled) {
  2626     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  2627       return false;
  2630   if (aIsSync) {
  2631     return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
  2632                            aPrincipal, aJSONRetVal);
  2635   return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
  2636                         aPrincipal, aJSONRetVal);
  2639 bool
  2640 TabChild::DoSendAsyncMessage(JSContext* aCx,
  2641                              const nsAString& aMessage,
  2642                              const StructuredCloneData& aData,
  2643                              JS::Handle<JSObject *> aCpows,
  2644                              nsIPrincipal* aPrincipal)
  2646   ContentChild* cc = Manager();
  2647   ClonedMessageData data;
  2648   if (!BuildClonedMessageDataForChild(cc, aData, data)) {
  2649     return false;
  2651   InfallibleTArray<CpowEntry> cpows;
  2652   if (sCpowsEnabled) {
  2653     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  2654       return false;
  2657   return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
  2658                           aPrincipal);
  2661 TabChild*
  2662 TabChild::GetFrom(nsIPresShell* aPresShell)
  2664   nsIDocument* doc = aPresShell->GetDocument();
  2665   if (!doc) {
  2666       return nullptr;
  2668   nsCOMPtr<nsIDocShell> docShell(doc->GetDocShell());
  2669   return GetFrom(docShell);
  2672 TabChild*
  2673 TabChild::GetFrom(uint64_t aLayersId)
  2675   if (!sTabChildren) {
  2676     return nullptr;
  2678   return sTabChildren->Get(aLayersId);
  2681 void
  2682 TabChild::DidComposite()
  2684   MOZ_ASSERT(mWidget);
  2685   MOZ_ASSERT(mWidget->GetLayerManager());
  2686   MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT);
  2688   ClientLayerManager *manager = static_cast<ClientLayerManager*>(mWidget->GetLayerManager());
  2689   manager->DidComposite();
  2692 NS_IMETHODIMP
  2693 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
  2695     nsString str(aTipText);
  2696     SendShowTooltip(aXCoords, aYCoords, str);
  2697     return NS_OK;
  2700 NS_IMETHODIMP
  2701 TabChild::OnHideTooltip()
  2703     SendHideTooltip();
  2704     return NS_OK;
  2707 TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
  2708 : mTabChild(aTabChild)
  2712 void
  2713 TabChildGlobal::Init()
  2715   NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
  2716   mMessageManager = new nsFrameMessageManager(mTabChild,
  2717                                               nullptr,
  2718                                               MM_CHILD);
  2721 NS_IMPL_CYCLE_COLLECTION_INHERITED(TabChildGlobal, DOMEventTargetHelper,
  2722                                    mMessageManager, mTabChild)
  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)
  2734 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
  2735 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper)
  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()
  2743   return mMessageManager ? mMessageManager->MarkForCC() : false;
  2746 NS_IMETHODIMP
  2747 TabChildGlobal::GetContent(nsIDOMWindow** aContent)
  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;
  2757 NS_IMETHODIMP
  2758 TabChildGlobal::PrivateNoteIntentionalCrash()
  2760     mozilla::NoteIntentionalCrash("tab");
  2761     return NS_OK;
  2764 NS_IMETHODIMP
  2765 TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
  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;
  2775 NS_IMETHODIMP
  2776 TabChildGlobal::Btoa(const nsAString& aBinaryData,
  2777                      nsAString& aAsciiBase64String)
  2779   return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
  2782 NS_IMETHODIMP
  2783 TabChildGlobal::Atob(const nsAString& aAsciiString,
  2784                      nsAString& aBinaryData)
  2786   return nsContentUtils::Atob(aAsciiString, aBinaryData);
  2789 JSContext*
  2790 TabChildGlobal::GetJSContextForEventHandlers()
  2792   return nsContentUtils::GetSafeJSContext();
  2795 nsIPrincipal*
  2796 TabChildGlobal::GetPrincipal()
  2798   if (!mTabChild)
  2799     return nullptr;
  2800   return mTabChild->GetPrincipal();
  2803 JSObject*
  2804 TabChildGlobal::GetGlobalJSObject()
  2806   NS_ENSURE_TRUE(mTabChild, nullptr);
  2807   nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mTabChild->GetGlobal();
  2808   NS_ENSURE_TRUE(ref, nullptr);
  2809   return ref->GetJSObject();

mercurial