dom/ipc/TabChild.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/ipc/TabChild.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2811 @@
     1.4 +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
     1.5 +/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "base/basictypes.h"
    1.11 +
    1.12 +#include "TabChild.h"
    1.13 +
    1.14 +#include "Layers.h"
    1.15 +#include "ContentChild.h"
    1.16 +#include "IndexedDBChild.h"
    1.17 +#include "mozilla/Preferences.h"
    1.18 +#include "mozilla/ClearOnShutdown.h"
    1.19 +#include "mozilla/EventListenerManager.h"
    1.20 +#include "mozilla/IntentionalCrash.h"
    1.21 +#include "mozilla/docshell/OfflineCacheUpdateChild.h"
    1.22 +#include "mozilla/ipc/DocumentRendererChild.h"
    1.23 +#include "mozilla/ipc/FileDescriptorUtils.h"
    1.24 +#include "mozilla/layers/ActiveElementManager.h"
    1.25 +#include "mozilla/layers/APZCCallbackHelper.h"
    1.26 +#include "mozilla/layers/AsyncPanZoomController.h"
    1.27 +#include "mozilla/layers/CompositorChild.h"
    1.28 +#include "mozilla/layers/ImageBridgeChild.h"
    1.29 +#include "mozilla/layers/ShadowLayers.h"
    1.30 +#include "mozilla/layout/RenderFrameChild.h"
    1.31 +#include "mozilla/MouseEvents.h"
    1.32 +#include "mozilla/Services.h"
    1.33 +#include "mozilla/StaticPtr.h"
    1.34 +#include "mozilla/TextEvents.h"
    1.35 +#include "mozilla/TouchEvents.h"
    1.36 +#include "mozilla/unused.h"
    1.37 +#include "mozIApplication.h"
    1.38 +#include "nsContentUtils.h"
    1.39 +#include "nsCxPusher.h"
    1.40 +#include "nsEmbedCID.h"
    1.41 +#include <algorithm>
    1.42 +#ifdef MOZ_CRASHREPORTER
    1.43 +#include "nsExceptionHandler.h"
    1.44 +#endif
    1.45 +#include "nsFilePickerProxy.h"
    1.46 +#include "mozilla/dom/Element.h"
    1.47 +#include "nsIBaseWindow.h"
    1.48 +#include "nsICachedFileDescriptorListener.h"
    1.49 +#include "nsIDocumentInlines.h"
    1.50 +#include "nsIDocShellTreeOwner.h"
    1.51 +#include "nsIDOMEvent.h"
    1.52 +#include "nsIDOMWindow.h"
    1.53 +#include "nsIDOMWindowUtils.h"
    1.54 +#include "nsIDocShell.h"
    1.55 +#include "nsIURI.h"
    1.56 +#include "nsIURIFixup.h"
    1.57 +#include "nsCDefaultURIFixup.h"
    1.58 +#include "nsIWebBrowser.h"
    1.59 +#include "nsIWebBrowserFocus.h"
    1.60 +#include "nsIWebBrowserSetup.h"
    1.61 +#include "nsIWebProgress.h"
    1.62 +#include "nsIXULRuntime.h"
    1.63 +#include "nsInterfaceHashtable.h"
    1.64 +#include "nsPIDOMWindow.h"
    1.65 +#include "nsPIWindowRoot.h"
    1.66 +#include "nsLayoutUtils.h"
    1.67 +#include "nsPrintfCString.h"
    1.68 +#include "nsThreadUtils.h"
    1.69 +#include "nsWeakReference.h"
    1.70 +#include "PermissionMessageUtils.h"
    1.71 +#include "PCOMContentPermissionRequestChild.h"
    1.72 +#include "PuppetWidget.h"
    1.73 +#include "StructuredCloneUtils.h"
    1.74 +#include "nsViewportInfo.h"
    1.75 +#include "JavaScriptChild.h"
    1.76 +#include "nsILoadContext.h"
    1.77 +#include "ipc/nsGUIEventIPC.h"
    1.78 +#include "mozilla/gfx/Matrix.h"
    1.79 +#include "UnitTransforms.h"
    1.80 +#include "ClientLayerManager.h"
    1.81 +
    1.82 +#include "nsColorPickerProxy.h"
    1.83 +
    1.84 +#ifdef DEBUG
    1.85 +#include "PCOMContentPermissionRequestChild.h"
    1.86 +#endif /* DEBUG */
    1.87 +
    1.88 +#define BROWSER_ELEMENT_CHILD_SCRIPT \
    1.89 +    NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
    1.90 +
    1.91 +using namespace mozilla;
    1.92 +using namespace mozilla::dom;
    1.93 +using namespace mozilla::dom::ipc;
    1.94 +using namespace mozilla::ipc;
    1.95 +using namespace mozilla::layers;
    1.96 +using namespace mozilla::layout;
    1.97 +using namespace mozilla::docshell;
    1.98 +using namespace mozilla::dom::indexedDB;
    1.99 +using namespace mozilla::widget;
   1.100 +using namespace mozilla::jsipc;
   1.101 +
   1.102 +NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
   1.103 +
   1.104 +static const CSSSize kDefaultViewportSize(980, 480);
   1.105 +
   1.106 +static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
   1.107 +static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
   1.108 +
   1.109 +static bool sCpowsEnabled = false;
   1.110 +static int32_t sActiveDurationMs = 10;
   1.111 +static bool sActiveDurationMsSet = false;
   1.112 +
   1.113 +typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
   1.114 +static TabChildMap* sTabChildren;
   1.115 +
   1.116 +TabChildBase::TabChildBase()
   1.117 +  : mOldViewportWidth(0.0f)
   1.118 +  , mContentDocumentIsDisplayed(false)
   1.119 +  , mTabChildGlobal(nullptr)
   1.120 +  , mInnerSize(0, 0)
   1.121 +{
   1.122 +}
   1.123 +
   1.124 +NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
   1.125 +NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
   1.126 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
   1.127 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
   1.128 +NS_INTERFACE_MAP_END
   1.129 +
   1.130 +NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
   1.131 +
   1.132 +void
   1.133 +TabChildBase::InitializeRootMetrics()
   1.134 +{
   1.135 +  // Calculate a really simple resolution that we probably won't
   1.136 +  // be keeping, as well as putting the scroll offset back to
   1.137 +  // the top-left of the page.
   1.138 +  mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
   1.139 +  mLastRootMetrics.mCompositionBounds = ParentLayerIntRect(
   1.140 +      ParentLayerIntPoint(),
   1.141 +      ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
   1.142 +  mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale());
   1.143 +  mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale();
   1.144 +  // We use ScreenToLayerScale(1) below in order to turn the
   1.145 +  // async zoom amount into the gecko zoom amount.
   1.146 +  mLastRootMetrics.mCumulativeResolution =
   1.147 +    mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   1.148 +  // This is the root layer, so the cumulative resolution is the same
   1.149 +  // as the resolution.
   1.150 +  mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
   1.151 +  mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
   1.152 +}
   1.153 +
   1.154 +bool
   1.155 +TabChildBase::HasValidInnerSize()
   1.156 +{
   1.157 +  return (mInnerSize.width != 0) && (mInnerSize.height != 0);
   1.158 +}
   1.159 +
   1.160 +void
   1.161 +TabChildBase::SetCSSViewport(const CSSSize& aSize)
   1.162 +{
   1.163 +  mOldViewportWidth = aSize.width;
   1.164 +
   1.165 +  if (mContentDocumentIsDisplayed) {
   1.166 +    nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   1.167 +    utils->SetCSSViewport(aSize.width, aSize.height);
   1.168 +  }
   1.169 +}
   1.170 +
   1.171 +CSSSize
   1.172 +TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport)
   1.173 +{
   1.174 +  nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement();
   1.175 +  HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement();
   1.176 +
   1.177 +  if (!htmlDOMElement && !bodyDOMElement) {
   1.178 +    // For non-HTML content (e.g. SVG), just assume page size == viewport size.
   1.179 +    return aViewport;
   1.180 +  }
   1.181 +
   1.182 +  int32_t htmlWidth = 0, htmlHeight = 0;
   1.183 +  if (htmlDOMElement) {
   1.184 +    htmlWidth = htmlDOMElement->ScrollWidth();
   1.185 +    htmlHeight = htmlDOMElement->ScrollHeight();
   1.186 +  }
   1.187 +  int32_t bodyWidth = 0, bodyHeight = 0;
   1.188 +  if (bodyDOMElement) {
   1.189 +    bodyWidth = bodyDOMElement->ScrollWidth();
   1.190 +    bodyHeight = bodyDOMElement->ScrollHeight();
   1.191 +  }
   1.192 +  return CSSSize(std::max(htmlWidth, bodyWidth),
   1.193 +                 std::max(htmlHeight, bodyHeight));
   1.194 +}
   1.195 +
   1.196 +bool
   1.197 +TabChildBase::HandlePossibleViewportChange()
   1.198 +{
   1.199 +  if (!IsAsyncPanZoomEnabled()) {
   1.200 +    return false;
   1.201 +  }
   1.202 +
   1.203 +  nsCOMPtr<nsIDocument> document(GetDocument());
   1.204 +  nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   1.205 +
   1.206 +  nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize);
   1.207 +  uint32_t presShellId;
   1.208 +  mozilla::layers::FrameMetrics::ViewID viewId;
   1.209 +  bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers(
   1.210 +        document->GetDocumentElement(), &presShellId, &viewId);
   1.211 +  if (scrollIdentifiersValid) {
   1.212 +    ZoomConstraints constraints(
   1.213 +      viewportInfo.IsZoomAllowed(),
   1.214 +      viewportInfo.IsDoubleTapZoomAllowed(),
   1.215 +      viewportInfo.GetMinZoom(),
   1.216 +      viewportInfo.GetMaxZoom());
   1.217 +    DoUpdateZoomConstraints(presShellId,
   1.218 +                            viewId,
   1.219 +                            /* isRoot = */ true,
   1.220 +                            constraints);
   1.221 +  }
   1.222 +
   1.223 +  float screenW = mInnerSize.width;
   1.224 +  float screenH = mInnerSize.height;
   1.225 +  CSSSize viewport(viewportInfo.GetSize());
   1.226 +
   1.227 +  // We're not being displayed in any way; don't bother doing anything because
   1.228 +  // that will just confuse future adjustments.
   1.229 +  if (!screenW || !screenH) {
   1.230 +    return false;
   1.231 +  }
   1.232 +
   1.233 +  float oldBrowserWidth = mOldViewportWidth;
   1.234 +  mLastRootMetrics.mViewport.SizeTo(viewport);
   1.235 +  if (!oldBrowserWidth) {
   1.236 +    oldBrowserWidth = kDefaultViewportSize.width;
   1.237 +  }
   1.238 +  SetCSSViewport(viewport);
   1.239 +
   1.240 +  // If this page has not been painted yet, then this must be getting run
   1.241 +  // because a meta-viewport element was added (via the DOMMetaAdded handler).
   1.242 +  // in this case, we should not do anything that forces a reflow (see bug
   1.243 +  // 759678) such as requesting the page size or sending a viewport update. this
   1.244 +  // code will get run again in the before-first-paint handler and that point we
   1.245 +  // will run though all of it. the reason we even bother executing up to this
   1.246 +  // point on the DOMMetaAdded handler is so that scripts that use
   1.247 +  // window.innerWidth before they are painted have a correct value (bug
   1.248 +  // 771575).
   1.249 +  if (!mContentDocumentIsDisplayed) {
   1.250 +    return false;
   1.251 +  }
   1.252 +
   1.253 +  float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width;
   1.254 +  if (!oldScreenWidth) {
   1.255 +    oldScreenWidth = mInnerSize.width;
   1.256 +  }
   1.257 +
   1.258 +  FrameMetrics metrics(mLastRootMetrics);
   1.259 +  metrics.mViewport = CSSRect(CSSPoint(), viewport);
   1.260 +  metrics.mCompositionBounds = ParentLayerIntRect(
   1.261 +      ParentLayerIntPoint(),
   1.262 +      ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
   1.263 +  metrics.SetRootCompositionSize(
   1.264 +      ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel);
   1.265 +
   1.266 +  // This change to the zoom accounts for all types of changes I can conceive:
   1.267 +  // 1. screen size changes, CSS viewport does not (pages with no meta viewport
   1.268 +  //    or a fixed size viewport)
   1.269 +  // 2. screen size changes, CSS viewport also does (pages with a device-width
   1.270 +  //    viewport)
   1.271 +  // 3. screen size remains constant, but CSS viewport changes (meta viewport
   1.272 +  //    tag is added or removed)
   1.273 +  // 4. neither screen size nor CSS viewport changes
   1.274 +  //
   1.275 +  // In all of these cases, we maintain how much actual content is visible
   1.276 +  // within the screen width. Note that "actual content" may be different with
   1.277 +  // respect to CSS pixels because of the CSS viewport size changing.
   1.278 +  float oldIntrinsicScale = oldScreenWidth / oldBrowserWidth;
   1.279 +  metrics.ZoomBy(metrics.CalculateIntrinsicScale().scale / oldIntrinsicScale);
   1.280 +
   1.281 +  // Changing the zoom when we're not doing a first paint will get ignored
   1.282 +  // by AsyncPanZoomController and causes a blurry flash.
   1.283 +  bool isFirstPaint;
   1.284 +  nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
   1.285 +  if (NS_FAILED(rv) || isFirstPaint) {
   1.286 +    // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
   1.287 +    // 0.0 to mean "did not calculate a zoom".  In that case, we default
   1.288 +    // it to the intrinsic scale.
   1.289 +    if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
   1.290 +      viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale());
   1.291 +    }
   1.292 +
   1.293 +    CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
   1.294 +    MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
   1.295 +               defaultZoom <= viewportInfo.GetMaxZoom());
   1.296 +    metrics.SetZoom(defaultZoom);
   1.297 +
   1.298 +    metrics.SetScrollId(viewId);
   1.299 +  }
   1.300 +
   1.301 +  metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   1.302 +  // This is the root layer, so the cumulative resolution is the same
   1.303 +  // as the resolution.
   1.304 +  metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
   1.305 +  utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
   1.306 +
   1.307 +  CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels();
   1.308 +  utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
   1.309 +
   1.310 +  // The call to GetPageSize forces a resize event to content, so we need to
   1.311 +  // make sure that we have the right CSS viewport and
   1.312 +  // scrollPositionClampingScrollPortSize set up before that happens.
   1.313 +
   1.314 +  CSSSize pageSize = GetPageSize(document, viewport);
   1.315 +  if (!pageSize.width) {
   1.316 +    // Return early rather than divide by 0.
   1.317 +    return false;
   1.318 +  }
   1.319 +  metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
   1.320 +
   1.321 +  // Calculate a display port _after_ having a scrollable rect because the
   1.322 +  // display port is clamped to the scrollable rect.
   1.323 +  metrics.SetDisplayPortMargins(AsyncPanZoomController::CalculatePendingDisplayPort(
   1.324 +    // The page must have been refreshed in some way such as a new document or
   1.325 +    // new CSS viewport, so we know that there's no velocity, acceleration, and
   1.326 +    // we have no idea how long painting will take.
   1.327 +    metrics, ScreenPoint(0.0f, 0.0f), 0.0));
   1.328 +  metrics.SetUseDisplayPortMargins();
   1.329 +
   1.330 +  // Force a repaint with these metrics. This, among other things, sets the
   1.331 +  // displayport, so we start with async painting.
   1.332 +  mLastRootMetrics = ProcessUpdateFrame(metrics);
   1.333 +
   1.334 +  if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
   1.335 +    // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
   1.336 +    // then we disable double-tap-to-zoom behaviour.
   1.337 +    bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale);
   1.338 +    if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) {
   1.339 +      viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom);
   1.340 +
   1.341 +      ZoomConstraints constraints(
   1.342 +        viewportInfo.IsZoomAllowed(),
   1.343 +        viewportInfo.IsDoubleTapZoomAllowed(),
   1.344 +        viewportInfo.GetMinZoom(),
   1.345 +        viewportInfo.GetMaxZoom());
   1.346 +      DoUpdateZoomConstraints(presShellId,
   1.347 +                              viewId,
   1.348 +                              /* isRoot = */ true,
   1.349 +                              constraints);
   1.350 +    }
   1.351 +  }
   1.352 +
   1.353 +  return true;
   1.354 +}
   1.355 +
   1.356 +already_AddRefed<nsIDOMWindowUtils>
   1.357 +TabChildBase::GetDOMWindowUtils()
   1.358 +{
   1.359 +  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
   1.360 +  nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
   1.361 +  return utils.forget();
   1.362 +}
   1.363 +
   1.364 +already_AddRefed<nsIDocument>
   1.365 +TabChildBase::GetDocument()
   1.366 +{
   1.367 +  nsCOMPtr<nsIDOMDocument> domDoc;
   1.368 +  WebNavigation()->GetDocument(getter_AddRefs(domDoc));
   1.369 +  nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
   1.370 +  return doc.forget();
   1.371 +}
   1.372 +
   1.373 +void
   1.374 +TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
   1.375 +                                            const nsAString& aJSONData)
   1.376 +{
   1.377 +    AutoSafeJSContext cx;
   1.378 +    JS::Rooted<JS::Value> json(cx, JSVAL_NULL);
   1.379 +    StructuredCloneData cloneData;
   1.380 +    JSAutoStructuredCloneBuffer buffer;
   1.381 +    if (JS_ParseJSON(cx,
   1.382 +                      static_cast<const jschar*>(aJSONData.BeginReading()),
   1.383 +                      aJSONData.Length(),
   1.384 +                      &json)) {
   1.385 +        WriteStructuredClone(cx, json, buffer, cloneData.mClosure);
   1.386 +        cloneData.mData = buffer.data();
   1.387 +        cloneData.mDataLength = buffer.nbytes();
   1.388 +    }
   1.389 +
   1.390 +    nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
   1.391 +    // Let the BrowserElementScrolling helper (if it exists) for this
   1.392 +    // content manipulate the frame state.
   1.393 +    nsRefPtr<nsFrameMessageManager> mm =
   1.394 +      static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
   1.395 +    mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
   1.396 +                       aMessageName, false, &cloneData, nullptr, nullptr, nullptr);
   1.397 +}
   1.398 +
   1.399 +bool
   1.400 +TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
   1.401 +{
   1.402 +  MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
   1.403 +
   1.404 +  if (aFrameMetrics.mIsRoot) {
   1.405 +    nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   1.406 +    if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
   1.407 +      mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics);
   1.408 +      APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, mLastRootMetrics);
   1.409 +      return true;
   1.410 +    }
   1.411 +  } else {
   1.412 +    // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
   1.413 +    // This requires special handling.
   1.414 +    nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
   1.415 +                                      aFrameMetrics.GetScrollId());
   1.416 +    if (content) {
   1.417 +      FrameMetrics newSubFrameMetrics(aFrameMetrics);
   1.418 +      APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
   1.419 +      APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, newSubFrameMetrics);
   1.420 +      return true;
   1.421 +    }
   1.422 +  }
   1.423 +
   1.424 +  // We've recieved a message that is out of date and we want to ignore.
   1.425 +  // However we can't reply without painting so we reply by painting the
   1.426 +  // exact same thing as we did before.
   1.427 +  mLastRootMetrics = ProcessUpdateFrame(mLastRootMetrics);
   1.428 +  return true;
   1.429 +}
   1.430 +
   1.431 +FrameMetrics
   1.432 +TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
   1.433 +{
   1.434 +    if (!mGlobal || !mTabChildGlobal) {
   1.435 +        return aFrameMetrics;
   1.436 +    }
   1.437 +
   1.438 +    nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   1.439 +
   1.440 +    FrameMetrics newMetrics = aFrameMetrics;
   1.441 +    APZCCallbackHelper::UpdateRootFrame(utils, newMetrics);
   1.442 +
   1.443 +    CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels();
   1.444 +    // The BrowserElementScrolling helper must know about these updated metrics
   1.445 +    // for other functions it performs, such as double tap handling.
   1.446 +    // Note, %f must not be used because it is locale specific!
   1.447 +    nsString data;
   1.448 +    data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.GetScrollOffset().x));
   1.449 +    data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.GetScrollOffset().y));
   1.450 +    data.AppendLiteral(", \"viewport\" : ");
   1.451 +        data.AppendLiteral("{ \"width\" : ");
   1.452 +        data.AppendFloat(newMetrics.mViewport.width);
   1.453 +        data.AppendLiteral(", \"height\" : ");
   1.454 +        data.AppendFloat(newMetrics.mViewport.height);
   1.455 +        data.AppendLiteral(" }");
   1.456 +    data.AppendLiteral(", \"cssPageRect\" : ");
   1.457 +        data.AppendLiteral("{ \"x\" : ");
   1.458 +        data.AppendFloat(newMetrics.mScrollableRect.x);
   1.459 +        data.AppendLiteral(", \"y\" : ");
   1.460 +        data.AppendFloat(newMetrics.mScrollableRect.y);
   1.461 +        data.AppendLiteral(", \"width\" : ");
   1.462 +        data.AppendFloat(newMetrics.mScrollableRect.width);
   1.463 +        data.AppendLiteral(", \"height\" : ");
   1.464 +        data.AppendFloat(newMetrics.mScrollableRect.height);
   1.465 +        data.AppendLiteral(" }");
   1.466 +        data.AppendPrintf(", \"resolution\" : "); // TODO: check if it's actually used?
   1.467 +        data.AppendPrintf("{ \"width\" : ");
   1.468 +        data.AppendFloat(newMetrics.CalculateIntrinsicScale().scale);
   1.469 +        data.AppendPrintf(" }");
   1.470 +    data.AppendLiteral(", \"cssCompositedRect\" : ");
   1.471 +        data.AppendLiteral("{ \"width\" : ");
   1.472 +        data.AppendFloat(cssCompositedSize.width);
   1.473 +        data.AppendLiteral(", \"height\" : ");
   1.474 +        data.AppendFloat(cssCompositedSize.height);
   1.475 +        data.AppendLiteral(" }");
   1.476 +    data.AppendLiteral(" }");
   1.477 +
   1.478 +    DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
   1.479 +    return newMetrics;
   1.480 +}
   1.481 +
   1.482 +nsEventStatus
   1.483 +TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
   1.484 +                                            const LayoutDevicePoint& aRefPoint,
   1.485 +                                            nsIWidget* aWidget)
   1.486 +{
   1.487 +  MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
   1.488 +             aMsg == NS_MOUSE_BUTTON_UP);
   1.489 +
   1.490 +  WidgetMouseEvent event(true, aMsg, nullptr,
   1.491 +                         WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
   1.492 +  event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
   1.493 +  event.time = aTime;
   1.494 +  event.button = WidgetMouseEvent::eLeftButton;
   1.495 +  event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
   1.496 +  if (aMsg != NS_MOUSE_MOVE) {
   1.497 +    event.clickCount = 1;
   1.498 +  }
   1.499 +  event.widget = aWidget;
   1.500 +
   1.501 +  return DispatchWidgetEvent(event);
   1.502 +}
   1.503 +
   1.504 +nsEventStatus
   1.505 +TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event)
   1.506 +{
   1.507 +  if (!event.widget)
   1.508 +    return nsEventStatus_eConsumeNoDefault;
   1.509 +
   1.510 +  nsEventStatus status;
   1.511 +  NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status),
   1.512 +                    nsEventStatus_eConsumeNoDefault);
   1.513 +  return status;
   1.514 +}
   1.515 +
   1.516 +bool
   1.517 +TabChildBase::IsAsyncPanZoomEnabled()
   1.518 +{
   1.519 +    return mScrolling == ASYNC_PAN_ZOOM;
   1.520 +}
   1.521 +
   1.522 +NS_IMETHODIMP
   1.523 +ContentListener::HandleEvent(nsIDOMEvent* aEvent)
   1.524 +{
   1.525 +  RemoteDOMEvent remoteEvent;
   1.526 +  remoteEvent.mEvent = do_QueryInterface(aEvent);
   1.527 +  NS_ENSURE_STATE(remoteEvent.mEvent);
   1.528 +  mTabChild->SendEvent(remoteEvent);
   1.529 +  return NS_OK;
   1.530 +}
   1.531 +
   1.532 +class TabChild::CachedFileDescriptorInfo
   1.533 +{
   1.534 +    struct PathOnlyComparatorHelper
   1.535 +    {
   1.536 +        bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
   1.537 +                    const CachedFileDescriptorInfo& b) const
   1.538 +        {
   1.539 +            return a->mPath == b.mPath;
   1.540 +        }
   1.541 +    };
   1.542 +
   1.543 +    struct PathAndCallbackComparatorHelper
   1.544 +    {
   1.545 +        bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
   1.546 +                    const CachedFileDescriptorInfo& b) const
   1.547 +        {
   1.548 +            return a->mPath == b.mPath &&
   1.549 +                   a->mCallback == b.mCallback;
   1.550 +        }
   1.551 +    };
   1.552 +
   1.553 +public:
   1.554 +    nsString mPath;
   1.555 +    FileDescriptor mFileDescriptor;
   1.556 +    nsCOMPtr<nsICachedFileDescriptorListener> mCallback;
   1.557 +    bool mCanceled;
   1.558 +
   1.559 +    CachedFileDescriptorInfo(const nsAString& aPath)
   1.560 +      : mPath(aPath), mCanceled(false)
   1.561 +    { }
   1.562 +
   1.563 +    CachedFileDescriptorInfo(const nsAString& aPath,
   1.564 +                             const FileDescriptor& aFileDescriptor)
   1.565 +      : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false)
   1.566 +    { }
   1.567 +
   1.568 +    CachedFileDescriptorInfo(const nsAString& aPath,
   1.569 +                             nsICachedFileDescriptorListener* aCallback)
   1.570 +      : mPath(aPath), mCallback(aCallback), mCanceled(false)
   1.571 +    { }
   1.572 +
   1.573 +    PathOnlyComparatorHelper PathOnlyComparator() const
   1.574 +    {
   1.575 +        return PathOnlyComparatorHelper();
   1.576 +    }
   1.577 +
   1.578 +    PathAndCallbackComparatorHelper PathAndCallbackComparator() const
   1.579 +    {
   1.580 +        return PathAndCallbackComparatorHelper();
   1.581 +    }
   1.582 +
   1.583 +    void FireCallback() const
   1.584 +    {
   1.585 +        mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor);
   1.586 +    }
   1.587 +};
   1.588 +
   1.589 +class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable
   1.590 +{
   1.591 +    typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo;
   1.592 +
   1.593 +    nsAutoPtr<CachedFileDescriptorInfo> mInfo;
   1.594 +
   1.595 +public:
   1.596 +    CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo)
   1.597 +      : mInfo(aInfo)
   1.598 +    {
   1.599 +        MOZ_ASSERT(NS_IsMainThread());
   1.600 +        MOZ_ASSERT(aInfo);
   1.601 +        MOZ_ASSERT(!aInfo->mPath.IsEmpty());
   1.602 +        MOZ_ASSERT(aInfo->mCallback);
   1.603 +    }
   1.604 +
   1.605 +    void Dispatch()
   1.606 +    {
   1.607 +        MOZ_ASSERT(NS_IsMainThread());
   1.608 +
   1.609 +        nsresult rv = NS_DispatchToCurrentThread(this);
   1.610 +        NS_ENSURE_SUCCESS_VOID(rv);
   1.611 +    }
   1.612 +
   1.613 +private:
   1.614 +    NS_IMETHOD Run()
   1.615 +    {
   1.616 +        MOZ_ASSERT(NS_IsMainThread());
   1.617 +        MOZ_ASSERT(mInfo);
   1.618 +
   1.619 +        mInfo->FireCallback();
   1.620 +        return NS_OK;
   1.621 +    }
   1.622 +};
   1.623 +
   1.624 +StaticRefPtr<TabChild> sPreallocatedTab;
   1.625 +
   1.626 +/*static*/ void
   1.627 +TabChild::PreloadSlowThings()
   1.628 +{
   1.629 +    MOZ_ASSERT(!sPreallocatedTab);
   1.630 +
   1.631 +    nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(),
   1.632 +                                        TabContext(), /* chromeFlags */ 0));
   1.633 +    if (!NS_SUCCEEDED(tab->Init()) ||
   1.634 +        !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
   1.635 +        return;
   1.636 +    }
   1.637 +    // Just load and compile these scripts, but don't run them.
   1.638 +    tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
   1.639 +    // Load, compile, and run these scripts.
   1.640 +    tab->RecvLoadRemoteScript(
   1.641 +        NS_LITERAL_STRING("chrome://global/content/preload.js"),
   1.642 +        true);
   1.643 +
   1.644 +    nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->WebNavigation());
   1.645 +    if (nsIPresShell* presShell = docShell->GetPresShell()) {
   1.646 +        // Initialize and do an initial reflow of the about:blank
   1.647 +        // PresShell to let it preload some things for us.
   1.648 +        presShell->Initialize(0, 0);
   1.649 +        nsIDocument* doc = presShell->GetDocument();
   1.650 +        doc->FlushPendingNotifications(Flush_Layout);
   1.651 +        // ... but after it's done, make sure it doesn't do any more
   1.652 +        // work.
   1.653 +        presShell->MakeZombie();
   1.654 +    }
   1.655 +
   1.656 +    sPreallocatedTab = tab;
   1.657 +    ClearOnShutdown(&sPreallocatedTab);
   1.658 +}
   1.659 +
   1.660 +/*static*/ already_AddRefed<TabChild>
   1.661 +TabChild::Create(ContentChild* aManager, const TabContext &aContext, uint32_t aChromeFlags)
   1.662 +{
   1.663 +    if (sPreallocatedTab &&
   1.664 +        sPreallocatedTab->mChromeFlags == aChromeFlags &&
   1.665 +        aContext.IsBrowserOrApp()) {
   1.666 +
   1.667 +        nsRefPtr<TabChild> child = sPreallocatedTab.get();
   1.668 +        sPreallocatedTab = nullptr;
   1.669 +
   1.670 +        MOZ_ASSERT(!child->mTriedBrowserInit);
   1.671 +
   1.672 +        child->SetTabContext(aContext);
   1.673 +        child->NotifyTabContextUpdated();
   1.674 +        return child.forget();
   1.675 +    }
   1.676 +
   1.677 +    nsRefPtr<TabChild> iframe = new TabChild(aManager,
   1.678 +                                             aContext, aChromeFlags);
   1.679 +    return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
   1.680 +}
   1.681 +
   1.682 +
   1.683 +TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags)
   1.684 +  : TabContext(aContext)
   1.685 +  , mRemoteFrame(nullptr)
   1.686 +  , mManager(aManager)
   1.687 +  , mChromeFlags(aChromeFlags)
   1.688 +  , mLayersId(0)
   1.689 +  , mOuterRect(0, 0, 0, 0)
   1.690 +  , mActivePointerId(-1)
   1.691 +  , mTapHoldTimer(nullptr)
   1.692 +  , mAppPackageFileDescriptorRecved(false)
   1.693 +  , mLastBackgroundColor(NS_RGB(255, 255, 255))
   1.694 +  , mDidFakeShow(false)
   1.695 +  , mNotified(false)
   1.696 +  , mTriedBrowserInit(false)
   1.697 +  , mOrientation(eScreenOrientation_PortraitPrimary)
   1.698 +  , mUpdateHitRegion(false)
   1.699 +  , mContextMenuHandled(false)
   1.700 +  , mWaitingTouchListeners(false)
   1.701 +  , mIgnoreKeyPressEvent(false)
   1.702 +  , mActiveElementManager(new ActiveElementManager())
   1.703 +{
   1.704 +  if (!sActiveDurationMsSet) {
   1.705 +    Preferences::AddIntVarCache(&sActiveDurationMs,
   1.706 +                                "ui.touch_activation.duration_ms",
   1.707 +                                sActiveDurationMs);
   1.708 +    sActiveDurationMsSet = true;
   1.709 +  }
   1.710 +}
   1.711 +
   1.712 +NS_IMETHODIMP
   1.713 +TabChild::HandleEvent(nsIDOMEvent* aEvent)
   1.714 +{
   1.715 +  nsAutoString eventType;
   1.716 +  aEvent->GetType(eventType);
   1.717 +  if (eventType.EqualsLiteral("DOMMetaAdded")) {
   1.718 +    // This meta data may or may not have been a meta viewport tag. If it was,
   1.719 +    // we should handle it immediately.
   1.720 +    HandlePossibleViewportChange();
   1.721 +  }
   1.722 +
   1.723 +  return NS_OK;
   1.724 +}
   1.725 +
   1.726 +NS_IMETHODIMP
   1.727 +TabChild::Observe(nsISupports *aSubject,
   1.728 +                  const char *aTopic,
   1.729 +                  const char16_t *aData)
   1.730 +{
   1.731 +  if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
   1.732 +    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
   1.733 +    nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
   1.734 +    if (tabChild == this) {
   1.735 +      nsCOMPtr<nsIDocument> doc(GetDocument());
   1.736 +      uint32_t presShellId;
   1.737 +      ViewID viewId;
   1.738 +      if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(),
   1.739 +                                                    &presShellId, &viewId)) {
   1.740 +        CSSRect rect;
   1.741 +        sscanf(NS_ConvertUTF16toUTF8(aData).get(),
   1.742 +               "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}",
   1.743 +               &rect.x, &rect.y, &rect.width, &rect.height);
   1.744 +        SendZoomToRect(presShellId, viewId, rect);
   1.745 +      }
   1.746 +    }
   1.747 +  } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
   1.748 +    if (IsAsyncPanZoomEnabled()) {
   1.749 +      nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
   1.750 +      nsCOMPtr<nsIDocument> doc(GetDocument());
   1.751 +
   1.752 +      if (SameCOMIdentity(subject, doc)) {
   1.753 +        nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
   1.754 +        utils->SetIsFirstPaint(true);
   1.755 +
   1.756 +        mContentDocumentIsDisplayed = true;
   1.757 +
   1.758 +        // Reset CSS viewport and zoom to default on new page, then
   1.759 +        // calculate them properly using the actual metadata from the
   1.760 +        // page.
   1.761 +        SetCSSViewport(kDefaultViewportSize);
   1.762 +
   1.763 +        // In some cases before-first-paint gets called before
   1.764 +        // RecvUpdateDimensions is called and therefore before we have an
   1.765 +        // mInnerSize value set. In such cases defer initializing the viewport
   1.766 +        // until we we get an inner size.
   1.767 +        if (HasValidInnerSize()) {
   1.768 +          InitializeRootMetrics();
   1.769 +          utils->SetResolution(mLastRootMetrics.mResolution.scale,
   1.770 +                               mLastRootMetrics.mResolution.scale);
   1.771 +          HandlePossibleViewportChange();
   1.772 +        }
   1.773 +      }
   1.774 +    }
   1.775 +  }
   1.776 +
   1.777 +  return NS_OK;
   1.778 +}
   1.779 +
   1.780 +NS_IMETHODIMP
   1.781 +TabChild::OnStateChange(nsIWebProgress* aWebProgress,
   1.782 +                        nsIRequest* aRequest,
   1.783 +                        uint32_t aStateFlags,
   1.784 +                        nsresult aStatus)
   1.785 +{
   1.786 +  NS_NOTREACHED("not implemented in TabChild");
   1.787 +  return NS_OK;
   1.788 +}
   1.789 +
   1.790 +NS_IMETHODIMP
   1.791 +TabChild::OnProgressChange(nsIWebProgress* aWebProgress,
   1.792 +                           nsIRequest* aRequest,
   1.793 +                           int32_t aCurSelfProgress,
   1.794 +                           int32_t aMaxSelfProgress,
   1.795 +                           int32_t aCurTotalProgress,
   1.796 +                           int32_t aMaxTotalProgress)
   1.797 +{
   1.798 +  NS_NOTREACHED("not implemented in TabChild");
   1.799 +  return NS_OK;
   1.800 +}
   1.801 +
   1.802 +NS_IMETHODIMP
   1.803 +TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
   1.804 +                           nsIRequest* aRequest,
   1.805 +                           nsIURI *aLocation,
   1.806 +                           uint32_t aFlags)
   1.807 +{
   1.808 +  if (!IsAsyncPanZoomEnabled()) {
   1.809 +    return NS_OK;
   1.810 +  }
   1.811 +
   1.812 +  nsCOMPtr<nsIDOMWindow> window;
   1.813 +  aWebProgress->GetDOMWindow(getter_AddRefs(window));
   1.814 +  if (!window) {
   1.815 +    return NS_OK;
   1.816 +  }
   1.817 +
   1.818 +  nsCOMPtr<nsIDOMDocument> progressDoc;
   1.819 +  window->GetDocument(getter_AddRefs(progressDoc));
   1.820 +  if (!progressDoc) {
   1.821 +    return NS_OK;
   1.822 +  }
   1.823 +
   1.824 +  nsCOMPtr<nsIDOMDocument> domDoc;
   1.825 +  WebNavigation()->GetDocument(getter_AddRefs(domDoc));
   1.826 +  if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) {
   1.827 +    return NS_OK;
   1.828 +  }
   1.829 +
   1.830 +  nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
   1.831 +  if (!urifixup) {
   1.832 +    return NS_OK;
   1.833 +  }
   1.834 +
   1.835 +  nsCOMPtr<nsIURI> exposableURI;
   1.836 +  urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI));
   1.837 +  if (!exposableURI) {
   1.838 +    return NS_OK;
   1.839 +  }
   1.840 +
   1.841 +  if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
   1.842 +    mContentDocumentIsDisplayed = false;
   1.843 +  } else if (mLastURI != nullptr) {
   1.844 +    bool exposableEqualsLast, exposableEqualsNew;
   1.845 +    exposableURI->Equals(mLastURI.get(), &exposableEqualsLast);
   1.846 +    exposableURI->Equals(aLocation, &exposableEqualsNew);
   1.847 +    if (exposableEqualsLast && !exposableEqualsNew) {
   1.848 +      mContentDocumentIsDisplayed = false;
   1.849 +    }
   1.850 +  }
   1.851 +
   1.852 +  return NS_OK;
   1.853 +}
   1.854 +
   1.855 +NS_IMETHODIMP
   1.856 +TabChild::OnStatusChange(nsIWebProgress* aWebProgress,
   1.857 +                         nsIRequest* aRequest,
   1.858 +                         nsresult aStatus,
   1.859 +                         const char16_t* aMessage)
   1.860 +{
   1.861 +  NS_NOTREACHED("not implemented in TabChild");
   1.862 +  return NS_OK;
   1.863 +}
   1.864 +
   1.865 +NS_IMETHODIMP
   1.866 +TabChild::OnSecurityChange(nsIWebProgress* aWebProgress,
   1.867 +                           nsIRequest* aRequest,
   1.868 +                           uint32_t aState)
   1.869 +{
   1.870 +  NS_NOTREACHED("not implemented in TabChild");
   1.871 +  return NS_OK;
   1.872 +}
   1.873 +
   1.874 +bool
   1.875 +TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
   1.876 +                                  const ViewID& aViewId,
   1.877 +                                  const bool& aIsRoot,
   1.878 +                                  const ZoomConstraints& aConstraints)
   1.879 +{
   1.880 +  return SendUpdateZoomConstraints(aPresShellId,
   1.881 +                                   aViewId,
   1.882 +                                   aIsRoot,
   1.883 +                                   aConstraints);
   1.884 +}
   1.885 +
   1.886 +nsresult
   1.887 +TabChild::Init()
   1.888 +{
   1.889 +  nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   1.890 +  if (!webBrowser) {
   1.891 +    NS_ERROR("Couldn't create a nsWebBrowser?");
   1.892 +    return NS_ERROR_FAILURE;
   1.893 +  }
   1.894 +
   1.895 +  webBrowser->SetContainerWindow(this);
   1.896 +  mWebNav = do_QueryInterface(webBrowser);
   1.897 +  NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
   1.898 +
   1.899 +  nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
   1.900 +  docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
   1.901 +  
   1.902 +  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
   1.903 +  if (!baseWindow) {
   1.904 +    NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
   1.905 +    return NS_ERROR_FAILURE;
   1.906 +  }
   1.907 +
   1.908 +  mWidget = nsIWidget::CreatePuppetWidget(this);
   1.909 +  if (!mWidget) {
   1.910 +    NS_ERROR("couldn't create fake widget");
   1.911 +    return NS_ERROR_FAILURE;
   1.912 +  }
   1.913 +  mWidget->Create(
   1.914 +    nullptr, 0,              // no parents
   1.915 +    nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
   1.916 +    nullptr,                 // HandleWidgetEvent
   1.917 +    nullptr                  // nsDeviceContext
   1.918 +  );
   1.919 +
   1.920 +  baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0);
   1.921 +  baseWindow->Create();
   1.922 +
   1.923 +  NotifyTabContextUpdated();
   1.924 +
   1.925 +  // IPC uses a WebBrowser object for which DNS prefetching is turned off
   1.926 +  // by default. But here we really want it, so enable it explicitly
   1.927 +  nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup =
   1.928 +    do_QueryInterface(baseWindow);
   1.929 +  if (webBrowserSetup) {
   1.930 +    webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH,
   1.931 +                                 true);
   1.932 +  } else {
   1.933 +    NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping "
   1.934 +               "DNS prefetching enable step.");
   1.935 +  }
   1.936 +
   1.937 +  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   1.938 +  MOZ_ASSERT(docShell);
   1.939 +
   1.940 +  docShell->SetAffectPrivateSessionLifetime(
   1.941 +      mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME);
   1.942 +  nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(WebNavigation());
   1.943 +  MOZ_ASSERT(loadContext);
   1.944 +  loadContext->SetPrivateBrowsing(
   1.945 +      mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW);
   1.946 +  loadContext->SetRemoteTabs(
   1.947 +      mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
   1.948 +
   1.949 +  nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
   1.950 +  NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
   1.951 +  webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
   1.952 +
   1.953 +  // Few lines before, baseWindow->Create() will end up creating a new
   1.954 +  // window root in nsGlobalWindow::SetDocShell.
   1.955 +  // Then this chrome event handler, will be inherited to inner windows.
   1.956 +  // We want to also set it to the docshell so that inner windows
   1.957 +  // and any code that has access to the docshell
   1.958 +  // can all listen to the same chrome event handler.
   1.959 +  // XXX: ideally, we would set a chrome event handler earlier,
   1.960 +  // and all windows, even the root one, will use the docshell one.
   1.961 +  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
   1.962 +  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
   1.963 +  nsCOMPtr<EventTarget> chromeHandler =
   1.964 +    do_QueryInterface(window->GetChromeEventHandler());
   1.965 +  docShell->SetChromeEventHandler(chromeHandler);
   1.966 +
   1.967 +  return NS_OK;
   1.968 +}
   1.969 +
   1.970 +void
   1.971 +TabChild::NotifyTabContextUpdated()
   1.972 +{
   1.973 +    nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   1.974 +    MOZ_ASSERT(docShell);
   1.975 +
   1.976 +    if (docShell) {
   1.977 +        // nsDocShell will do the right thing if we pass NO_APP_ID or
   1.978 +        // UNKNOWN_APP_ID for aOwnOrContainingAppId.
   1.979 +        if (IsBrowserElement()) {
   1.980 +          docShell->SetIsBrowserInsideApp(BrowserOwnerAppId());
   1.981 +        } else {
   1.982 +          docShell->SetIsApp(OwnAppId());
   1.983 +        }
   1.984 +    }
   1.985 +}
   1.986 +
   1.987 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
   1.988 +  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   1.989 +  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
   1.990 +  NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
   1.991 +  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
   1.992 +  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   1.993 +  NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
   1.994 +  NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   1.995 +  NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
   1.996 +  NS_INTERFACE_MAP_ENTRY(nsITabChild)
   1.997 +  NS_INTERFACE_MAP_ENTRY(nsIObserver)
   1.998 +  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   1.999 +  NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
  1.1000 +NS_INTERFACE_MAP_END_INHERITING(TabChildBase)
  1.1001 +
  1.1002 +NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
  1.1003 +NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
  1.1004 +
  1.1005 +NS_IMETHODIMP
  1.1006 +TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
  1.1007 +{
  1.1008 +  return SetStatusWithContext(aStatusType,
  1.1009 +      aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
  1.1010 +              : EmptyString(),
  1.1011 +      nullptr);
  1.1012 +}
  1.1013 +
  1.1014 +NS_IMETHODIMP
  1.1015 +TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
  1.1016 +{
  1.1017 +  NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild");
  1.1018 +
  1.1019 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1020 +}
  1.1021 +
  1.1022 +NS_IMETHODIMP
  1.1023 +TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
  1.1024 +{
  1.1025 +  NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
  1.1026 +
  1.1027 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1028 +}
  1.1029 +
  1.1030 +NS_IMETHODIMP
  1.1031 +TabChild::GetChromeFlags(uint32_t* aChromeFlags)
  1.1032 +{
  1.1033 +  *aChromeFlags = mChromeFlags;
  1.1034 +  return NS_OK;
  1.1035 +}
  1.1036 +
  1.1037 +NS_IMETHODIMP
  1.1038 +TabChild::SetChromeFlags(uint32_t aChromeFlags)
  1.1039 +{
  1.1040 +  NS_NOTREACHED("trying to SetChromeFlags from content process?");
  1.1041 +
  1.1042 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1043 +}
  1.1044 +
  1.1045 +NS_IMETHODIMP
  1.1046 +TabChild::DestroyBrowserWindow()
  1.1047 +{
  1.1048 +  NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
  1.1049 +
  1.1050 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1051 +}
  1.1052 +
  1.1053 +NS_IMETHODIMP
  1.1054 +TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
  1.1055 +{
  1.1056 +  NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild");
  1.1057 +
  1.1058 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1059 +}
  1.1060 +
  1.1061 +NS_IMETHODIMP
  1.1062 +TabChild::ShowAsModal()
  1.1063 +{
  1.1064 +  NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild");
  1.1065 +
  1.1066 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1067 +}
  1.1068 +
  1.1069 +NS_IMETHODIMP
  1.1070 +TabChild::IsWindowModal(bool* aRetVal)
  1.1071 +{
  1.1072 +  *aRetVal = false;
  1.1073 +  return NS_OK;
  1.1074 +}
  1.1075 +
  1.1076 +NS_IMETHODIMP
  1.1077 +TabChild::ExitModalEventLoop(nsresult aStatus)
  1.1078 +{
  1.1079 +  NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild");
  1.1080 +
  1.1081 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1082 +}
  1.1083 +
  1.1084 +NS_IMETHODIMP
  1.1085 +TabChild::SetStatusWithContext(uint32_t aStatusType,
  1.1086 +                               const nsAString& aStatusText,
  1.1087 +                               nsISupports* aStatusContext)
  1.1088 +{
  1.1089 +  // We can only send the status after the ipc machinery is set up,
  1.1090 +  // mRemoteFrame is a good indicator.
  1.1091 +  if (mRemoteFrame)
  1.1092 +    SendSetStatus(aStatusType, nsString(aStatusText));
  1.1093 +  return NS_OK;
  1.1094 +}
  1.1095 +
  1.1096 +NS_IMETHODIMP
  1.1097 +TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
  1.1098 +                             int32_t aCx, int32_t aCy)
  1.1099 +{
  1.1100 +  NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild");
  1.1101 +
  1.1102 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1103 +}
  1.1104 +
  1.1105 +NS_IMETHODIMP
  1.1106 +TabChild::GetDimensions(uint32_t aFlags, int32_t* aX,
  1.1107 +                             int32_t* aY, int32_t* aCx, int32_t* aCy)
  1.1108 +{
  1.1109 +  if (aX) {
  1.1110 +    *aX = mOuterRect.x;
  1.1111 +  }
  1.1112 +  if (aY) {
  1.1113 +    *aY = mOuterRect.y;
  1.1114 +  }
  1.1115 +  if (aCx) {
  1.1116 +    *aCx = mOuterRect.width;
  1.1117 +  }
  1.1118 +  if (aCy) {
  1.1119 +    *aCy = mOuterRect.height;
  1.1120 +  }
  1.1121 +
  1.1122 +  return NS_OK;
  1.1123 +}
  1.1124 +
  1.1125 +NS_IMETHODIMP
  1.1126 +TabChild::SetFocus()
  1.1127 +{
  1.1128 +  NS_WARNING("TabChild::SetFocus not supported in TabChild");
  1.1129 +
  1.1130 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1131 +}
  1.1132 +
  1.1133 +NS_IMETHODIMP
  1.1134 +TabChild::GetVisibility(bool* aVisibility)
  1.1135 +{
  1.1136 +  *aVisibility = true;
  1.1137 +  return NS_OK;
  1.1138 +}
  1.1139 +
  1.1140 +NS_IMETHODIMP
  1.1141 +TabChild::SetVisibility(bool aVisibility)
  1.1142 +{
  1.1143 +  // should the platform support this? Bug 666365
  1.1144 +  return NS_OK;
  1.1145 +}
  1.1146 +
  1.1147 +NS_IMETHODIMP
  1.1148 +TabChild::GetTitle(char16_t** aTitle)
  1.1149 +{
  1.1150 +  NS_NOTREACHED("TabChild::GetTitle not supported in TabChild");
  1.1151 +
  1.1152 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1153 +}
  1.1154 +
  1.1155 +NS_IMETHODIMP
  1.1156 +TabChild::SetTitle(const char16_t* aTitle)
  1.1157 +{
  1.1158 +  // JavaScript sends the "DOMTitleChanged" event to the parent
  1.1159 +  // via the message manager.
  1.1160 +  return NS_OK;
  1.1161 +}
  1.1162 +
  1.1163 +NS_IMETHODIMP
  1.1164 +TabChild::GetSiteWindow(void** aSiteWindow)
  1.1165 +{
  1.1166 +  NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild");
  1.1167 +
  1.1168 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1169 +}
  1.1170 +
  1.1171 +NS_IMETHODIMP
  1.1172 +TabChild::Blur()
  1.1173 +{
  1.1174 +  NS_WARNING("TabChild::Blur not supported in TabChild");
  1.1175 +
  1.1176 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1177 +}
  1.1178 +
  1.1179 +NS_IMETHODIMP
  1.1180 +TabChild::FocusNextElement()
  1.1181 +{
  1.1182 +  SendMoveFocus(true);
  1.1183 +  return NS_OK;
  1.1184 +}
  1.1185 +
  1.1186 +NS_IMETHODIMP
  1.1187 +TabChild::FocusPrevElement()
  1.1188 +{
  1.1189 +  SendMoveFocus(false);
  1.1190 +  return NS_OK;
  1.1191 +}
  1.1192 +
  1.1193 +NS_IMETHODIMP
  1.1194 +TabChild::GetInterface(const nsIID & aIID, void **aSink)
  1.1195 +{
  1.1196 +    // XXXbz should we restrict the set of interfaces we hand out here?
  1.1197 +    // See bug 537429
  1.1198 +    return QueryInterface(aIID, aSink);
  1.1199 +}
  1.1200 +
  1.1201 +NS_IMETHODIMP
  1.1202 +TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags,
  1.1203 +                        bool aCalledFromJS,
  1.1204 +                        bool aPositionSpecified, bool aSizeSpecified,
  1.1205 +                        nsIURI* aURI, const nsAString& aName,
  1.1206 +                        const nsACString& aFeatures, bool* aWindowIsNew,
  1.1207 +                        nsIDOMWindow** aReturn)
  1.1208 +{
  1.1209 +    *aReturn = nullptr;
  1.1210 +
  1.1211 +    // If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this
  1.1212 +    // isn't a request to open a modal-type window, we're going to create a new
  1.1213 +    // <iframe mozbrowser/mozapp> and return its window here.
  1.1214 +    nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
  1.1215 +    if (docshell && docshell->GetIsInBrowserOrApp() &&
  1.1216 +        !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
  1.1217 +                          nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
  1.1218 +                          nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
  1.1219 +
  1.1220 +      // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
  1.1221 +      // open window call was canceled.  It's important that we pass this error
  1.1222 +      // code back to our caller.
  1.1223 +      return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
  1.1224 +                                       aWindowIsNew, aReturn);
  1.1225 +    }
  1.1226 +
  1.1227 +    // Otherwise, create a new top-level window.
  1.1228 +    PBrowserChild* newChild;
  1.1229 +    if (!CallCreateWindow(&newChild)) {
  1.1230 +        return NS_ERROR_NOT_AVAILABLE;
  1.1231 +    }
  1.1232 +
  1.1233 +    *aWindowIsNew = true;
  1.1234 +    nsCOMPtr<nsIDOMWindow> win =
  1.1235 +        do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation());
  1.1236 +    win.forget(aReturn);
  1.1237 +    return NS_OK;
  1.1238 +}
  1.1239 +
  1.1240 +nsresult
  1.1241 +TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
  1.1242 +                                    nsIURI* aURI,
  1.1243 +                                    const nsAString& aName,
  1.1244 +                                    const nsACString& aFeatures,
  1.1245 +                                    bool* aWindowIsNew,
  1.1246 +                                    nsIDOMWindow** aReturn)
  1.1247 +{
  1.1248 +  *aReturn = nullptr;
  1.1249 +
  1.1250 +  nsRefPtr<TabChild> newChild =
  1.1251 +      new TabChild(ContentChild::GetSingleton(),
  1.1252 +                   /* TabContext */ *this, /* chromeFlags */ 0);
  1.1253 +  if (!NS_SUCCEEDED(newChild->Init())) {
  1.1254 +      return NS_ERROR_ABORT;
  1.1255 +  }
  1.1256 +
  1.1257 +  // We must use PopupIPCTabContext here; ContentParent will not accept the
  1.1258 +  // result of this->AsIPCTabContext() (which will be a
  1.1259 +  // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
  1.1260 +  // reasons.
  1.1261 +  PopupIPCTabContext context;
  1.1262 +  context.openerChild() = this;
  1.1263 +  context.isBrowserElement() = IsBrowserElement();
  1.1264 +
  1.1265 +  unused << Manager()->SendPBrowserConstructor(
  1.1266 +      // We release this ref in DeallocPBrowserChild
  1.1267 +      nsRefPtr<TabChild>(newChild).forget().take(),
  1.1268 +      IPCTabContext(context, mScrolling), /* chromeFlags */ 0);
  1.1269 +
  1.1270 +  nsAutoCString spec;
  1.1271 +  if (aURI) {
  1.1272 +    aURI->GetSpec(spec);
  1.1273 +  }
  1.1274 +
  1.1275 +  NS_ConvertUTF8toUTF16 url(spec);
  1.1276 +  nsString name(aName);
  1.1277 +  NS_ConvertUTF8toUTF16 features(aFeatures);
  1.1278 +  newChild->SendBrowserFrameOpenWindow(this, url, name,
  1.1279 +                                       features, aWindowIsNew);
  1.1280 +  if (!*aWindowIsNew) {
  1.1281 +    PBrowserChild::Send__delete__(newChild);
  1.1282 +    return NS_ERROR_ABORT;
  1.1283 +  }
  1.1284 +
  1.1285 +  // Unfortunately we don't get a window unless we've shown the frame.  That's
  1.1286 +  // pretty bogus; see bug 763602.
  1.1287 +  newChild->DoFakeShow();
  1.1288 +
  1.1289 +  nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
  1.1290 +  win.forget(aReturn);
  1.1291 +  return NS_OK;
  1.1292 +}
  1.1293 +
  1.1294 +#ifdef DEBUG
  1.1295 +PContentPermissionRequestChild*
  1.1296 +TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
  1.1297 +                                                    const InfallibleTArray<PermissionRequest>& aRequests,
  1.1298 +                                                    const IPC::Principal& aPrincipal)
  1.1299 +{
  1.1300 +  PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
  1.1301 +  PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
  1.1302 +  child->mIPCOpen = true;
  1.1303 +  return request;
  1.1304 +}
  1.1305 +#endif /* DEBUG */
  1.1306 +
  1.1307 +void
  1.1308 +TabChild::DestroyWindow()
  1.1309 +{
  1.1310 +    nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
  1.1311 +    if (baseWindow)
  1.1312 +        baseWindow->Destroy();
  1.1313 +
  1.1314 +    // NB: the order of mWidget->Destroy() and mRemoteFrame->Destroy()
  1.1315 +    // is important: we want to kill off remote layers before their
  1.1316 +    // frames
  1.1317 +    if (mWidget) {
  1.1318 +        mWidget->Destroy();
  1.1319 +    }
  1.1320 +
  1.1321 +    if (mRemoteFrame) {
  1.1322 +        mRemoteFrame->Destroy();
  1.1323 +        mRemoteFrame = nullptr;
  1.1324 +    }
  1.1325 +
  1.1326 +
  1.1327 +    if (mLayersId != 0) {
  1.1328 +      MOZ_ASSERT(sTabChildren);
  1.1329 +      sTabChildren->Remove(mLayersId);
  1.1330 +      if (!sTabChildren->Count()) {
  1.1331 +        delete sTabChildren;
  1.1332 +        sTabChildren = nullptr;
  1.1333 +      }
  1.1334 +      mLayersId = 0;
  1.1335 +    }
  1.1336 +}
  1.1337 +
  1.1338 +bool
  1.1339 +TabChild::UseDirectCompositor()
  1.1340 +{
  1.1341 +    return !!CompositorChild::Get();
  1.1342 +}
  1.1343 +
  1.1344 +void
  1.1345 +TabChild::ActorDestroy(ActorDestroyReason why)
  1.1346 +{
  1.1347 +  if (mTabChildGlobal) {
  1.1348 +    // The messageManager relays messages via the TabChild which
  1.1349 +    // no longer exists.
  1.1350 +    static_cast<nsFrameMessageManager*>
  1.1351 +      (mTabChildGlobal->mMessageManager.get())->Disconnect();
  1.1352 +    mTabChildGlobal->mMessageManager = nullptr;
  1.1353 +  }
  1.1354 +}
  1.1355 +
  1.1356 +TabChild::~TabChild()
  1.1357 +{
  1.1358 +    DestroyWindow();
  1.1359 +
  1.1360 +    nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
  1.1361 +    if (webBrowser) {
  1.1362 +      webBrowser->SetContainerWindow(nullptr);
  1.1363 +    }
  1.1364 +}
  1.1365 +
  1.1366 +void
  1.1367 +TabChild::SetProcessNameToAppName()
  1.1368 +{
  1.1369 +  nsCOMPtr<mozIApplication> app = GetOwnApp();
  1.1370 +  if (!app) {
  1.1371 +    return;
  1.1372 +  }
  1.1373 +
  1.1374 +  nsAutoString appName;
  1.1375 +  nsresult rv = app->GetName(appName);
  1.1376 +  if (NS_FAILED(rv)) {
  1.1377 +    NS_WARNING("Failed to retrieve app name");
  1.1378 +    return;
  1.1379 +  }
  1.1380 +
  1.1381 +  ContentChild::GetSingleton()->SetProcessName(appName, true);
  1.1382 +}
  1.1383 +
  1.1384 +bool
  1.1385 +TabChild::IsRootContentDocument()
  1.1386 +{
  1.1387 +    // A TabChild is a "root content document" if it's
  1.1388 +    //
  1.1389 +    //  - <iframe mozapp> not inside another <iframe mozapp>,
  1.1390 +    //  - <iframe mozbrowser> (not mozapp), or
  1.1391 +    //  - a vanilla remote frame (<html:iframe remote=true> or <xul:browser
  1.1392 +    //    remote=true>).
  1.1393 +    //
  1.1394 +    // Put another way, an iframe is /not/ a "root content document" iff it's a
  1.1395 +    // mozapp inside a mozapp.  (This corresponds exactly to !HasAppOwnerApp.)
  1.1396 +    //
  1.1397 +    // Note that we're lying through our teeth here (thus the scare quotes).
  1.1398 +    // <html:iframe remote=true> or <xul:browser remote=true> inside another
  1.1399 +    // content iframe is not actually a root content document, but we say it is.
  1.1400 +    //
  1.1401 +    // We do this because we make a remote frame opaque iff
  1.1402 +    // IsRootContentDocument(), and making vanilla remote frames transparent
  1.1403 +    // breaks our remote reftests.
  1.1404 +
  1.1405 +    return !HasAppOwnerApp();
  1.1406 +}
  1.1407 +
  1.1408 +bool
  1.1409 +TabChild::RecvLoadURL(const nsCString& uri)
  1.1410 +{
  1.1411 +    SetProcessNameToAppName();
  1.1412 +
  1.1413 +    nsresult rv = WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
  1.1414 +                                           nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
  1.1415 +                                           nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_OWNER,
  1.1416 +                                           nullptr, nullptr, nullptr);
  1.1417 +    if (NS_FAILED(rv)) {
  1.1418 +        NS_WARNING("WebNavigation()->LoadURI failed. Eating exception, what else can I do?");
  1.1419 +    }
  1.1420 +
  1.1421 +#ifdef MOZ_CRASHREPORTER
  1.1422 +    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
  1.1423 +#endif
  1.1424 +
  1.1425 +    return true;
  1.1426 +}
  1.1427 +
  1.1428 +bool
  1.1429 +TabChild::RecvCacheFileDescriptor(const nsString& aPath,
  1.1430 +                                  const FileDescriptor& aFileDescriptor)
  1.1431 +{
  1.1432 +    MOZ_ASSERT(NS_IsMainThread());
  1.1433 +    MOZ_ASSERT(!aPath.IsEmpty());
  1.1434 +    MOZ_ASSERT(!mAppPackageFileDescriptorRecved);
  1.1435 +
  1.1436 +    mAppPackageFileDescriptorRecved = true;
  1.1437 +
  1.1438 +    // aFileDescriptor may be invalid here, but the callback will choose how to
  1.1439 +    // handle it.
  1.1440 +
  1.1441 +    // First see if we already have a request for this path.
  1.1442 +    const CachedFileDescriptorInfo search(aPath);
  1.1443 +    uint32_t index =
  1.1444 +        mCachedFileDescriptorInfos.IndexOf(search, 0,
  1.1445 +                                           search.PathOnlyComparator());
  1.1446 +    if (index == mCachedFileDescriptorInfos.NoIndex) {
  1.1447 +        // We haven't had any requests for this path yet. Assume that we will
  1.1448 +        // in a little while and save the file descriptor here.
  1.1449 +        mCachedFileDescriptorInfos.AppendElement(
  1.1450 +            new CachedFileDescriptorInfo(aPath, aFileDescriptor));
  1.1451 +        return true;
  1.1452 +    }
  1.1453 +
  1.1454 +    nsAutoPtr<CachedFileDescriptorInfo>& info =
  1.1455 +        mCachedFileDescriptorInfos[index];
  1.1456 +
  1.1457 +    MOZ_ASSERT(info);
  1.1458 +    MOZ_ASSERT(info->mPath == aPath);
  1.1459 +    MOZ_ASSERT(!info->mFileDescriptor.IsValid());
  1.1460 +    MOZ_ASSERT(info->mCallback);
  1.1461 +
  1.1462 +    // If this callback has been canceled then we can simply close the file
  1.1463 +    // descriptor and forget about the callback.
  1.1464 +    if (info->mCanceled) {
  1.1465 +        // Only close if this is a valid file descriptor.
  1.1466 +        if (aFileDescriptor.IsValid()) {
  1.1467 +            nsRefPtr<CloseFileRunnable> runnable =
  1.1468 +                new CloseFileRunnable(aFileDescriptor);
  1.1469 +            runnable->Dispatch();
  1.1470 +        }
  1.1471 +    } else {
  1.1472 +        // Not canceled so fire the callback.
  1.1473 +        info->mFileDescriptor = aFileDescriptor;
  1.1474 +
  1.1475 +        // We don't need a runnable here because we should already be at the top
  1.1476 +        // of the event loop. Just fire immediately.
  1.1477 +        info->FireCallback();
  1.1478 +    }
  1.1479 +
  1.1480 +    mCachedFileDescriptorInfos.RemoveElementAt(index);
  1.1481 +    return true;
  1.1482 +}
  1.1483 +
  1.1484 +bool
  1.1485 +TabChild::GetCachedFileDescriptor(const nsAString& aPath,
  1.1486 +                                  nsICachedFileDescriptorListener* aCallback)
  1.1487 +{
  1.1488 +    MOZ_ASSERT(NS_IsMainThread());
  1.1489 +    MOZ_ASSERT(!aPath.IsEmpty());
  1.1490 +    MOZ_ASSERT(aCallback);
  1.1491 +
  1.1492 +    // First see if we've already received a cached file descriptor for this
  1.1493 +    // path.
  1.1494 +    const CachedFileDescriptorInfo search(aPath);
  1.1495 +    uint32_t index =
  1.1496 +        mCachedFileDescriptorInfos.IndexOf(search, 0,
  1.1497 +                                           search.PathOnlyComparator());
  1.1498 +    if (index == mCachedFileDescriptorInfos.NoIndex) {
  1.1499 +        // We haven't received a file descriptor for this path yet. Assume that
  1.1500 +        // we will in a little while and save the request here.
  1.1501 +        if (!mAppPackageFileDescriptorRecved) {
  1.1502 +          mCachedFileDescriptorInfos.AppendElement(
  1.1503 +              new CachedFileDescriptorInfo(aPath, aCallback));
  1.1504 +        }
  1.1505 +        return false;
  1.1506 +    }
  1.1507 +
  1.1508 +    nsAutoPtr<CachedFileDescriptorInfo>& info =
  1.1509 +        mCachedFileDescriptorInfos[index];
  1.1510 +
  1.1511 +    MOZ_ASSERT(info);
  1.1512 +    MOZ_ASSERT(info->mPath == aPath);
  1.1513 +
  1.1514 +    // If we got a previous request for this file descriptor that was then
  1.1515 +    // canceled, insert the new request ahead of the old in the queue so that
  1.1516 +    // it will be serviced first.
  1.1517 +    if (info->mCanceled) {
  1.1518 +        // This insertion will change the array and invalidate |info|, so
  1.1519 +        // be careful not to touch |info| after this.
  1.1520 +        mCachedFileDescriptorInfos.InsertElementAt(index,
  1.1521 +            new CachedFileDescriptorInfo(aPath, aCallback));
  1.1522 +        return false;
  1.1523 +    }
  1.1524 +
  1.1525 +    MOZ_ASSERT(!info->mCallback);
  1.1526 +    info->mCallback = aCallback;
  1.1527 +
  1.1528 +    nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable =
  1.1529 +        new CachedFileDescriptorCallbackRunnable(info.forget());
  1.1530 +    runnable->Dispatch();
  1.1531 +
  1.1532 +    mCachedFileDescriptorInfos.RemoveElementAt(index);
  1.1533 +    return true;
  1.1534 +}
  1.1535 +
  1.1536 +void
  1.1537 +TabChild::CancelCachedFileDescriptorCallback(
  1.1538 +                                     const nsAString& aPath,
  1.1539 +                                     nsICachedFileDescriptorListener* aCallback)
  1.1540 +{
  1.1541 +    MOZ_ASSERT(NS_IsMainThread());
  1.1542 +    MOZ_ASSERT(!aPath.IsEmpty());
  1.1543 +    MOZ_ASSERT(aCallback);
  1.1544 +
  1.1545 +    if (mAppPackageFileDescriptorRecved) {
  1.1546 +      // Already received cached file descriptor for the app package. Nothing to do here.
  1.1547 +      return;
  1.1548 +    }
  1.1549 +
  1.1550 +    const CachedFileDescriptorInfo search(aPath, aCallback);
  1.1551 +    uint32_t index =
  1.1552 +        mCachedFileDescriptorInfos.IndexOf(search, 0,
  1.1553 +                                           search.PathAndCallbackComparator());
  1.1554 +    if (index == mCachedFileDescriptorInfos.NoIndex) {
  1.1555 +        // Nothing to do here.
  1.1556 +        return;
  1.1557 +    }
  1.1558 +
  1.1559 +    nsAutoPtr<CachedFileDescriptorInfo>& info =
  1.1560 +        mCachedFileDescriptorInfos[index];
  1.1561 +
  1.1562 +    MOZ_ASSERT(info);
  1.1563 +    MOZ_ASSERT(info->mPath == aPath);
  1.1564 +    MOZ_ASSERT(!info->mFileDescriptor.IsValid());
  1.1565 +    MOZ_ASSERT(info->mCallback == aCallback);
  1.1566 +    MOZ_ASSERT(!info->mCanceled);
  1.1567 +
  1.1568 +    // Set this flag so that we will close the file descriptor when it arrives.
  1.1569 +    info->mCanceled = true;
  1.1570 +}
  1.1571 +
  1.1572 +void
  1.1573 +TabChild::DoFakeShow()
  1.1574 +{
  1.1575 +  RecvShow(nsIntSize(0, 0));
  1.1576 +  mDidFakeShow = true;
  1.1577 +}
  1.1578 +
  1.1579 +bool
  1.1580 +TabChild::RecvShow(const nsIntSize& size)
  1.1581 +{
  1.1582 +
  1.1583 +    if (mDidFakeShow) {
  1.1584 +        return true;
  1.1585 +    }
  1.1586 +
  1.1587 +    nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
  1.1588 +    if (!baseWindow) {
  1.1589 +        NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
  1.1590 +        return false;
  1.1591 +    }
  1.1592 +
  1.1593 +    if (!InitRenderingState()) {
  1.1594 +        // We can fail to initialize our widget if the <browser
  1.1595 +        // remote> has already been destroyed, and we couldn't hook
  1.1596 +        // into the parent-process's layer system.  That's not a fatal
  1.1597 +        // error.
  1.1598 +        return true;
  1.1599 +    }
  1.1600 +
  1.1601 +    baseWindow->SetVisibility(true);
  1.1602 +
  1.1603 +    return InitTabChildGlobal();
  1.1604 +}
  1.1605 +
  1.1606 +bool
  1.1607 +TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
  1.1608 +{
  1.1609 +    if (!mRemoteFrame) {
  1.1610 +        return true;
  1.1611 +    }
  1.1612 +
  1.1613 +    mOuterRect.x = rect.x;
  1.1614 +    mOuterRect.y = rect.y;
  1.1615 +    mOuterRect.width = rect.width;
  1.1616 +    mOuterRect.height = rect.height;
  1.1617 +
  1.1618 +    bool initialSizing = !HasValidInnerSize()
  1.1619 +                      && (size.width != 0 && size.height != 0);
  1.1620 +
  1.1621 +    mOrientation = orientation;
  1.1622 +    mInnerSize = ScreenIntSize::FromUnknownSize(
  1.1623 +      gfx::IntSize(size.width, size.height));
  1.1624 +    mWidget->Resize(0, 0, size.width, size.height,
  1.1625 +                    true);
  1.1626 +
  1.1627 +    nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
  1.1628 +    baseWin->SetPositionAndSize(0, 0, size.width, size.height,
  1.1629 +                                true);
  1.1630 +
  1.1631 +    if (initialSizing && mContentDocumentIsDisplayed) {
  1.1632 +      // If this is the first time we're getting a valid mInnerSize, and the
  1.1633 +      // before-first-paint event has already been handled, then we need to set
  1.1634 +      // up our default viewport here. See the corresponding call to
  1.1635 +      // InitializeRootMetrics in the before-first-paint handler.
  1.1636 +      InitializeRootMetrics();
  1.1637 +    }
  1.1638 +
  1.1639 +    HandlePossibleViewportChange();
  1.1640 +
  1.1641 +    return true;
  1.1642 +}
  1.1643 +
  1.1644 +bool
  1.1645 +TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
  1.1646 +{
  1.1647 +  return TabChildBase::UpdateFrameHandler(aFrameMetrics);
  1.1648 +}
  1.1649 +
  1.1650 +bool
  1.1651 +TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
  1.1652 +                                      const uint32_t& aScrollGeneration)
  1.1653 +{
  1.1654 +  APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
  1.1655 +  return true;
  1.1656 +}
  1.1657 +
  1.1658 +bool
  1.1659 +TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1.1660 +{
  1.1661 +    if (!mGlobal || !mTabChildGlobal) {
  1.1662 +        return true;
  1.1663 +    }
  1.1664 +
  1.1665 +    CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
  1.1666 +    nsString data;
  1.1667 +    data.AppendLiteral("{ \"x\" : ");
  1.1668 +    data.AppendFloat(point.x);
  1.1669 +    data.AppendLiteral(", \"y\" : ");
  1.1670 +    data.AppendFloat(point.y);
  1.1671 +    data.AppendLiteral(" }");
  1.1672 +
  1.1673 +    DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
  1.1674 +
  1.1675 +    return true;
  1.1676 +}
  1.1677 +
  1.1678 +bool
  1.1679 +TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1.1680 +{
  1.1681 +  if (!mGlobal || !mTabChildGlobal) {
  1.1682 +    return true;
  1.1683 +  }
  1.1684 +
  1.1685 +  LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();;
  1.1686 +
  1.1687 +  MessageLoop::current()->PostDelayedTask(
  1.1688 +    FROM_HERE,
  1.1689 +    NewRunnableMethod(this, &TabChild::FireSingleTapEvent, currentPoint),
  1.1690 +    sActiveDurationMs);
  1.1691 +  return true;
  1.1692 +}
  1.1693 +
  1.1694 +void
  1.1695 +TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
  1.1696 +{
  1.1697 +  int time = 0;
  1.1698 +  DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
  1.1699 +  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
  1.1700 +  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget);
  1.1701 +}
  1.1702 +
  1.1703 +bool
  1.1704 +TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1.1705 +{
  1.1706 +  if (!mGlobal || !mTabChildGlobal) {
  1.1707 +    return true;
  1.1708 +  }
  1.1709 +
  1.1710 +  mContextMenuHandled =
  1.1711 +      DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
  1.1712 +                         APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
  1.1713 +                         2, 1, 0, false,
  1.1714 +                         nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
  1.1715 +
  1.1716 +  SendContentReceivedTouch(aGuid, mContextMenuHandled);
  1.1717 +
  1.1718 +  return true;
  1.1719 +}
  1.1720 +
  1.1721 +bool
  1.1722 +TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
  1.1723 +{
  1.1724 +  if (mContextMenuHandled) {
  1.1725 +    mContextMenuHandled = false;
  1.1726 +    return true;
  1.1727 +  }
  1.1728 +
  1.1729 +  RecvHandleSingleTap(aPoint, aGuid);
  1.1730 +  return true;
  1.1731 +}
  1.1732 +
  1.1733 +bool
  1.1734 +TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
  1.1735 +                                   const APZStateChange& aChange,
  1.1736 +                                   const int& aArg)
  1.1737 +{
  1.1738 +  switch (aChange)
  1.1739 +  {
  1.1740 +  case APZStateChange::TransformBegin:
  1.1741 +  {
  1.1742 +    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
  1.1743 +    nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
  1.1744 +    if (scrollbarOwner) {
  1.1745 +      scrollbarOwner->ScrollbarActivityStarted();
  1.1746 +    }
  1.1747 +    break;
  1.1748 +  }
  1.1749 +  case APZStateChange::TransformEnd:
  1.1750 +  {
  1.1751 +    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
  1.1752 +    nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
  1.1753 +    if (scrollbarOwner) {
  1.1754 +      scrollbarOwner->ScrollbarActivityStopped();
  1.1755 +    }
  1.1756 +    break;
  1.1757 +  }
  1.1758 +  case APZStateChange::StartTouch:
  1.1759 +  {
  1.1760 +    mActiveElementManager->HandleTouchStart(aArg);
  1.1761 +    break;
  1.1762 +  }
  1.1763 +  case APZStateChange::StartPanning:
  1.1764 +  {
  1.1765 +    mActiveElementManager->HandlePanStart();
  1.1766 +    break;
  1.1767 +  }
  1.1768 +  case APZStateChange::EndTouch:
  1.1769 +  {
  1.1770 +    mActiveElementManager->HandleTouchEnd(aArg);
  1.1771 +    break;
  1.1772 +  }
  1.1773 +  default:
  1.1774 +    // APZStateChange has a 'sentinel' value, and the compiler complains
  1.1775 +    // if an enumerator is not handled and there is no 'default' case.
  1.1776 +    break;
  1.1777 +  }
  1.1778 +  return true;
  1.1779 +}
  1.1780 +
  1.1781 +bool
  1.1782 +TabChild::RecvActivate()
  1.1783 +{
  1.1784 +  nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
  1.1785 +  browser->Activate();
  1.1786 +  return true;
  1.1787 +}
  1.1788 +
  1.1789 +bool TabChild::RecvDeactivate()
  1.1790 +{
  1.1791 +  nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
  1.1792 +  browser->Deactivate();
  1.1793 +  return true;
  1.1794 +}
  1.1795 +
  1.1796 +bool
  1.1797 +TabChild::RecvMouseEvent(const nsString& aType,
  1.1798 +                         const float&    aX,
  1.1799 +                         const float&    aY,
  1.1800 +                         const int32_t&  aButton,
  1.1801 +                         const int32_t&  aClickCount,
  1.1802 +                         const int32_t&  aModifiers,
  1.1803 +                         const bool&     aIgnoreRootScrollFrame)
  1.1804 +{
  1.1805 +  DispatchMouseEvent(aType, CSSPoint(aX, aY), aButton, aClickCount, aModifiers,
  1.1806 +                     aIgnoreRootScrollFrame, nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN);
  1.1807 +  return true;
  1.1808 +}
  1.1809 +
  1.1810 +bool
  1.1811 +TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
  1.1812 +{
  1.1813 +  WidgetMouseEvent localEvent(event);
  1.1814 +  localEvent.widget = mWidget;
  1.1815 +  DispatchWidgetEvent(localEvent);
  1.1816 +  return true;
  1.1817 +}
  1.1818 +
  1.1819 +bool
  1.1820 +TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& event)
  1.1821 +{
  1.1822 +  WidgetWheelEvent localEvent(event);
  1.1823 +  localEvent.widget = mWidget;
  1.1824 +  DispatchWidgetEvent(localEvent);
  1.1825 +  return true;
  1.1826 +}
  1.1827 +
  1.1828 +static Touch*
  1.1829 +GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
  1.1830 +{
  1.1831 +  for (uint32_t i = 0; i < aEvent.touches.Length(); ++i) {
  1.1832 +    Touch* touch = static_cast<Touch*>(aEvent.touches[i].get());
  1.1833 +    if (touch->mIdentifier == aId) {
  1.1834 +      return touch;
  1.1835 +    }
  1.1836 +  }
  1.1837 +  return nullptr;
  1.1838 +}
  1.1839 +
  1.1840 +void
  1.1841 +TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
  1.1842 +{
  1.1843 +  static bool sHavePrefs;
  1.1844 +  static bool sClickHoldContextMenusEnabled;
  1.1845 +  static nsIntSize sDragThreshold;
  1.1846 +  static int32_t sContextMenuDelayMs;
  1.1847 +  if (!sHavePrefs) {
  1.1848 +    sHavePrefs = true;
  1.1849 +    Preferences::AddBoolVarCache(&sClickHoldContextMenusEnabled,
  1.1850 +                                 "ui.click_hold_context_menus", true);
  1.1851 +    Preferences::AddIntVarCache(&sDragThreshold.width,
  1.1852 +                                "ui.dragThresholdX", 25);
  1.1853 +    Preferences::AddIntVarCache(&sDragThreshold.height,
  1.1854 +                                "ui.dragThresholdY", 25);
  1.1855 +    Preferences::AddIntVarCache(&sContextMenuDelayMs,
  1.1856 +                                "ui.click_hold_context_menus.delay", 500);
  1.1857 +  }
  1.1858 +
  1.1859 +  if (aEvent.touches.Length() == 0) {
  1.1860 +    return;
  1.1861 +  }
  1.1862 +
  1.1863 +  bool currentlyTrackingTouch = (mActivePointerId >= 0);
  1.1864 +  if (aEvent.message == NS_TOUCH_START) {
  1.1865 +    if (currentlyTrackingTouch || aEvent.touches.Length() > 1) {
  1.1866 +      // We're tracking a possible tap for another point, or we saw a
  1.1867 +      // touchstart for a later pointer after we canceled tracking of
  1.1868 +      // the first point.  Ignore this one.
  1.1869 +      return;
  1.1870 +    }
  1.1871 +    if (aStatus == nsEventStatus_eConsumeNoDefault ||
  1.1872 +        nsIPresShell::gPreventMouseEvents ||
  1.1873 +        aEvent.mFlags.mMultipleActionsPrevented) {
  1.1874 +      return;
  1.1875 +    }
  1.1876 +
  1.1877 +    Touch* touch = aEvent.touches[0];
  1.1878 +    mGestureDownPoint = LayoutDevicePoint(touch->mRefPoint.x, touch->mRefPoint.y);
  1.1879 +    mActivePointerId = touch->mIdentifier;
  1.1880 +    if (sClickHoldContextMenusEnabled) {
  1.1881 +      MOZ_ASSERT(!mTapHoldTimer);
  1.1882 +      mTapHoldTimer = NewRunnableMethod(this,
  1.1883 +                                        &TabChild::FireContextMenuEvent);
  1.1884 +      MessageLoop::current()->PostDelayedTask(FROM_HERE, mTapHoldTimer,
  1.1885 +                                              sContextMenuDelayMs);
  1.1886 +    }
  1.1887 +    return;
  1.1888 +  }
  1.1889 +
  1.1890 +  // If we're not tracking a touch or this event doesn't include the
  1.1891 +  // one we care about, bail.
  1.1892 +  if (!currentlyTrackingTouch) {
  1.1893 +    return;
  1.1894 +  }
  1.1895 +  Touch* trackedTouch = GetTouchForIdentifier(aEvent, mActivePointerId);
  1.1896 +  if (!trackedTouch) {
  1.1897 +    return;
  1.1898 +  }
  1.1899 +
  1.1900 +  LayoutDevicePoint currentPoint = LayoutDevicePoint(trackedTouch->mRefPoint.x, trackedTouch->mRefPoint.y);
  1.1901 +  int64_t time = aEvent.time;
  1.1902 +  switch (aEvent.message) {
  1.1903 +  case NS_TOUCH_MOVE:
  1.1904 +    if (abs(currentPoint.x - mGestureDownPoint.x) > sDragThreshold.width ||
  1.1905 +        abs(currentPoint.y - mGestureDownPoint.y) > sDragThreshold.height) {
  1.1906 +      CancelTapTracking();
  1.1907 +    }
  1.1908 +    return;
  1.1909 +
  1.1910 +  case NS_TOUCH_END:
  1.1911 +    if (!nsIPresShell::gPreventMouseEvents) {
  1.1912 +      DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
  1.1913 +      DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
  1.1914 +      DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
  1.1915 +    }
  1.1916 +    // fall through
  1.1917 +  case NS_TOUCH_CANCEL:
  1.1918 +    CancelTapTracking();
  1.1919 +    return;
  1.1920 +
  1.1921 +  default:
  1.1922 +    NS_WARNING("Unknown touch event type");
  1.1923 +  }
  1.1924 +}
  1.1925 +
  1.1926 +void
  1.1927 +TabChild::FireContextMenuEvent()
  1.1928 +{
  1.1929 +  double scale;
  1.1930 +  GetDefaultScale(&scale);
  1.1931 +  if (scale < 0) {
  1.1932 +    scale = 1;
  1.1933 +  }
  1.1934 +
  1.1935 +  MOZ_ASSERT(mTapHoldTimer && mActivePointerId >= 0);
  1.1936 +  bool defaultPrevented = DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
  1.1937 +                                             mGestureDownPoint / CSSToLayoutDeviceScale(scale),
  1.1938 +                                             2 /* Right button */,
  1.1939 +                                             1 /* Click count */,
  1.1940 +                                             0 /* Modifiers */,
  1.1941 +                                             false /* Ignore root scroll frame */,
  1.1942 +                                             nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
  1.1943 +
  1.1944 +  // Fire a click event if someone didn't call preventDefault() on the context
  1.1945 +  // menu event.
  1.1946 +  if (defaultPrevented) {
  1.1947 +    CancelTapTracking();
  1.1948 +  } else if (mTapHoldTimer) {
  1.1949 +    mTapHoldTimer->Cancel();
  1.1950 +    mTapHoldTimer = nullptr;
  1.1951 +  }
  1.1952 +}
  1.1953 +
  1.1954 +void
  1.1955 +TabChild::CancelTapTracking()
  1.1956 +{
  1.1957 +  mActivePointerId = -1;
  1.1958 +  if (mTapHoldTimer) {
  1.1959 +    mTapHoldTimer->Cancel();
  1.1960 +  }
  1.1961 +  mTapHoldTimer = nullptr;
  1.1962 +}
  1.1963 +
  1.1964 +bool
  1.1965 +TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
  1.1966 +                             const ScrollableLayerGuid& aGuid)
  1.1967 +{
  1.1968 +  WidgetTouchEvent localEvent(aEvent);
  1.1969 +  localEvent.widget = mWidget;
  1.1970 +  for (size_t i = 0; i < localEvent.touches.Length(); i++) {
  1.1971 +    aEvent.touches[i]->mRefPoint = APZCCallbackHelper::ApplyCallbackTransform(aEvent.touches[i]->mRefPoint, aGuid, mWidget->GetDefaultScale());
  1.1972 +  }
  1.1973 +
  1.1974 +  nsEventStatus status = DispatchWidgetEvent(localEvent);
  1.1975 +
  1.1976 +  if (!IsAsyncPanZoomEnabled()) {
  1.1977 +    UpdateTapState(localEvent, status);
  1.1978 +    return true;
  1.1979 +  }
  1.1980 +
  1.1981 +  if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
  1.1982 +    mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target());
  1.1983 +  }
  1.1984 +
  1.1985 +  nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
  1.1986 +  nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
  1.1987 +
  1.1988 +  if (!innerWindow || !innerWindow->HasTouchEventListeners()) {
  1.1989 +    SendContentReceivedTouch(aGuid, false);
  1.1990 +    return true;
  1.1991 +  }
  1.1992 +
  1.1993 +  bool isTouchPrevented = nsIPresShell::gPreventMouseEvents ||
  1.1994 +                          localEvent.mFlags.mMultipleActionsPrevented;
  1.1995 +  switch (aEvent.message) {
  1.1996 +  case NS_TOUCH_START: {
  1.1997 +    if (isTouchPrevented) {
  1.1998 +      SendContentReceivedTouch(aGuid, isTouchPrevented);
  1.1999 +    } else {
  1.2000 +      mWaitingTouchListeners = true;
  1.2001 +    }
  1.2002 +    break;
  1.2003 +  }
  1.2004 +
  1.2005 +  case NS_TOUCH_MOVE:
  1.2006 +  case NS_TOUCH_END:
  1.2007 +  case NS_TOUCH_CANCEL: {
  1.2008 +    if (mWaitingTouchListeners) {
  1.2009 +      SendContentReceivedTouch(aGuid, isTouchPrevented);
  1.2010 +      mWaitingTouchListeners = false;
  1.2011 +    }
  1.2012 +    break;
  1.2013 +  }
  1.2014 +
  1.2015 +  default:
  1.2016 +    NS_WARNING("Unknown touch event type");
  1.2017 +  }
  1.2018 +
  1.2019 +  return true;
  1.2020 +}
  1.2021 +
  1.2022 +bool
  1.2023 +TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
  1.2024 +                                 const ScrollableLayerGuid& aGuid)
  1.2025 +{
  1.2026 +  return RecvRealTouchEvent(aEvent, aGuid);
  1.2027 +}
  1.2028 +
  1.2029 +void
  1.2030 +TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache,
  1.2031 +                                   WidgetKeyboardEvent* aEvent)
  1.2032 +{
  1.2033 +  MaybeNativeKeyBinding maybeBindings;
  1.2034 +  if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) {
  1.2035 +    return;
  1.2036 +  }
  1.2037 +
  1.2038 +  if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
  1.2039 +    const NativeKeyBinding& bindings = maybeBindings;
  1.2040 +    aAutoCache->Cache(bindings.singleLineCommands(),
  1.2041 +                      bindings.multiLineCommands(),
  1.2042 +                      bindings.richTextCommands());
  1.2043 +  } else {
  1.2044 +    aAutoCache->CacheNoCommands();
  1.2045 +  }
  1.2046 +}
  1.2047 +
  1.2048 +bool
  1.2049 +TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
  1.2050 +                           const MaybeNativeKeyBinding& aBindings)
  1.2051 +{
  1.2052 +  PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get());
  1.2053 +  AutoCacheNativeKeyCommands autoCache(widget);
  1.2054 +
  1.2055 +  if (event.message == NS_KEY_PRESS) {
  1.2056 +    if (aBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
  1.2057 +      const NativeKeyBinding& bindings = aBindings;
  1.2058 +      autoCache.Cache(bindings.singleLineCommands(),
  1.2059 +                      bindings.multiLineCommands(),
  1.2060 +                      bindings.richTextCommands());
  1.2061 +    } else {
  1.2062 +      autoCache.CacheNoCommands();
  1.2063 +    }
  1.2064 +  }
  1.2065 +  // If content code called preventDefault() on a keydown event, then we don't
  1.2066 +  // want to process any following keypress events.
  1.2067 +  if (event.message == NS_KEY_PRESS && mIgnoreKeyPressEvent) {
  1.2068 +    return true;
  1.2069 +  }
  1.2070 +
  1.2071 +  WidgetKeyboardEvent localEvent(event);
  1.2072 +  localEvent.widget = mWidget;
  1.2073 +  nsEventStatus status = DispatchWidgetEvent(localEvent);
  1.2074 +
  1.2075 +  if (event.message == NS_KEY_DOWN) {
  1.2076 +    mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
  1.2077 +  }
  1.2078 +
  1.2079 +  if (localEvent.mFlags.mWantReplyFromContentProcess) {
  1.2080 +    SendReplyKeyEvent(localEvent);
  1.2081 +  }
  1.2082 +
  1.2083 +  return true;
  1.2084 +}
  1.2085 +
  1.2086 +bool
  1.2087 +TabChild::RecvKeyEvent(const nsString& aType,
  1.2088 +                       const int32_t& aKeyCode,
  1.2089 +                       const int32_t& aCharCode,
  1.2090 +                       const int32_t& aModifiers,
  1.2091 +                       const bool& aPreventDefault)
  1.2092 +{
  1.2093 +  nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
  1.2094 +  NS_ENSURE_TRUE(utils, true);
  1.2095 +  bool ignored = false;
  1.2096 +  utils->SendKeyEvent(aType, aKeyCode, aCharCode,
  1.2097 +                      aModifiers, aPreventDefault, &ignored);
  1.2098 +  return true;
  1.2099 +}
  1.2100 +
  1.2101 +bool
  1.2102 +TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
  1.2103 +{
  1.2104 +  WidgetCompositionEvent localEvent(event);
  1.2105 +  localEvent.widget = mWidget;
  1.2106 +  DispatchWidgetEvent(localEvent);
  1.2107 +  return true;
  1.2108 +}
  1.2109 +
  1.2110 +bool
  1.2111 +TabChild::RecvTextEvent(const WidgetTextEvent& event)
  1.2112 +{
  1.2113 +  WidgetTextEvent localEvent(event);
  1.2114 +  localEvent.widget = mWidget;
  1.2115 +  DispatchWidgetEvent(localEvent);
  1.2116 +  return true;
  1.2117 +}
  1.2118 +
  1.2119 +bool
  1.2120 +TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
  1.2121 +{
  1.2122 +  WidgetSelectionEvent localEvent(event);
  1.2123 +  localEvent.widget = mWidget;
  1.2124 +  DispatchWidgetEvent(localEvent);
  1.2125 +  return true;
  1.2126 +}
  1.2127 +
  1.2128 +PDocumentRendererChild*
  1.2129 +TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
  1.2130 +                                      const mozilla::gfx::Matrix& transform,
  1.2131 +                                      const nsString& bgcolor,
  1.2132 +                                      const uint32_t& renderFlags,
  1.2133 +                                      const bool& flushLayout,
  1.2134 +                                      const nsIntSize& renderSize)
  1.2135 +{
  1.2136 +    return new DocumentRendererChild();
  1.2137 +}
  1.2138 +
  1.2139 +bool
  1.2140 +TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor)
  1.2141 +{
  1.2142 +    delete actor;
  1.2143 +    return true;
  1.2144 +}
  1.2145 +
  1.2146 +bool
  1.2147 +TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
  1.2148 +                                           const nsRect& documentRect,
  1.2149 +                                           const mozilla::gfx::Matrix& transform,
  1.2150 +                                           const nsString& bgcolor,
  1.2151 +                                           const uint32_t& renderFlags,
  1.2152 +                                           const bool& flushLayout,
  1.2153 +                                           const nsIntSize& renderSize)
  1.2154 +{
  1.2155 +    DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor);
  1.2156 +
  1.2157 +    nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation());
  1.2158 +    if (!browser)
  1.2159 +        return true; // silently ignore
  1.2160 +    nsCOMPtr<nsIDOMWindow> window;
  1.2161 +    if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
  1.2162 +        !window)
  1.2163 +    {
  1.2164 +        return true; // silently ignore
  1.2165 +    }
  1.2166 +
  1.2167 +    nsCString data;
  1.2168 +    bool ret = render->RenderDocument(window,
  1.2169 +                                      documentRect, transform,
  1.2170 +                                      bgcolor,
  1.2171 +                                      renderFlags, flushLayout,
  1.2172 +                                      renderSize, data);
  1.2173 +    if (!ret)
  1.2174 +        return true; // silently ignore
  1.2175 +
  1.2176 +    return PDocumentRendererChild::Send__delete__(actor, renderSize, data);
  1.2177 +}
  1.2178 +
  1.2179 +PColorPickerChild*
  1.2180 +TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
  1.2181 +{
  1.2182 +  NS_RUNTIMEABORT("unused");
  1.2183 +  return nullptr;
  1.2184 +}
  1.2185 +
  1.2186 +bool
  1.2187 +TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
  1.2188 +{
  1.2189 +  nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker);
  1.2190 +  NS_RELEASE(picker);
  1.2191 +  return true;
  1.2192 +}
  1.2193 +
  1.2194 +PContentPermissionRequestChild*
  1.2195 +TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
  1.2196 +                                              const IPC::Principal& aPrincipal)
  1.2197 +{
  1.2198 +  NS_RUNTIMEABORT("unused");
  1.2199 +  return nullptr;
  1.2200 +}
  1.2201 +
  1.2202 +bool
  1.2203 +TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
  1.2204 +{
  1.2205 +    PCOMContentPermissionRequestChild* child =
  1.2206 +        static_cast<PCOMContentPermissionRequestChild*>(actor);
  1.2207 +#ifdef DEBUG
  1.2208 +    child->mIPCOpen = false;
  1.2209 +#endif /* DEBUG */
  1.2210 +    child->IPDLRelease();
  1.2211 +    return true;
  1.2212 +}
  1.2213 +
  1.2214 +PFilePickerChild*
  1.2215 +TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
  1.2216 +{
  1.2217 +  NS_RUNTIMEABORT("unused");
  1.2218 +  return nullptr;
  1.2219 +}
  1.2220 +
  1.2221 +bool
  1.2222 +TabChild::DeallocPFilePickerChild(PFilePickerChild* actor)
  1.2223 +{
  1.2224 +  nsFilePickerProxy* filePicker = static_cast<nsFilePickerProxy*>(actor);
  1.2225 +  NS_RELEASE(filePicker);
  1.2226 +  return true;
  1.2227 +}
  1.2228 +
  1.2229 +bool
  1.2230 +TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
  1.2231 +{
  1.2232 +  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
  1.2233 +  NS_ENSURE_TRUE(window, true);
  1.2234 +  nsCOMPtr<EventTarget> chromeHandler =
  1.2235 +    do_QueryInterface(window->GetChromeEventHandler());
  1.2236 +  NS_ENSURE_TRUE(chromeHandler, true);
  1.2237 +  nsRefPtr<ContentListener> listener = new ContentListener(this);
  1.2238 +  chromeHandler->AddEventListener(aType, listener, capture);
  1.2239 +  return true;
  1.2240 +}
  1.2241 +
  1.2242 +POfflineCacheUpdateChild*
  1.2243 +TabChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
  1.2244 +                                        const URIParams& documentURI,
  1.2245 +                                        const bool& stickDocument)
  1.2246 +{
  1.2247 +  NS_RUNTIMEABORT("unused");
  1.2248 +  return nullptr;
  1.2249 +}
  1.2250 +
  1.2251 +bool
  1.2252 +TabChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
  1.2253 +{
  1.2254 +  OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor);
  1.2255 +  NS_RELEASE(offlineCacheUpdate);
  1.2256 +  return true;
  1.2257 +}
  1.2258 +
  1.2259 +bool
  1.2260 +TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
  1.2261 +{
  1.2262 +  if (!mGlobal && !InitTabChildGlobal())
  1.2263 +    // This can happen if we're half-destroyed.  It's not a fatal
  1.2264 +    // error.
  1.2265 +    return true;
  1.2266 +
  1.2267 +  LoadFrameScriptInternal(aURL, aRunInGlobalScope);
  1.2268 +  return true;
  1.2269 +}
  1.2270 +
  1.2271 +bool
  1.2272 +TabChild::RecvAsyncMessage(const nsString& aMessage,
  1.2273 +                           const ClonedMessageData& aData,
  1.2274 +                           const InfallibleTArray<CpowEntry>& aCpows,
  1.2275 +                           const IPC::Principal& aPrincipal)
  1.2276 +{
  1.2277 +  if (mTabChildGlobal) {
  1.2278 +    nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
  1.2279 +    StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData);
  1.2280 +    nsRefPtr<nsFrameMessageManager> mm =
  1.2281 +      static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
  1.2282 +    CpowIdHolder cpows(static_cast<ContentChild*>(Manager())->GetCPOWManager(), aCpows);
  1.2283 +    mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
  1.2284 +                       aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
  1.2285 +  }
  1.2286 +  return true;
  1.2287 +}
  1.2288 +
  1.2289 +class UnloadScriptEvent : public nsRunnable
  1.2290 +{
  1.2291 +public:
  1.2292 +  UnloadScriptEvent(TabChild* aTabChild, TabChildGlobal* aTabChildGlobal)
  1.2293 +    : mTabChild(aTabChild), mTabChildGlobal(aTabChildGlobal)
  1.2294 +  { }
  1.2295 +
  1.2296 +  NS_IMETHOD Run()
  1.2297 +  {
  1.2298 +    nsCOMPtr<nsIDOMEvent> event;
  1.2299 +    NS_NewDOMEvent(getter_AddRefs(event), mTabChildGlobal, nullptr, nullptr);
  1.2300 +    if (event) {
  1.2301 +      event->InitEvent(NS_LITERAL_STRING("unload"), false, false);
  1.2302 +      event->SetTrusted(true);
  1.2303 +
  1.2304 +      bool dummy;
  1.2305 +      mTabChildGlobal->DispatchEvent(event, &dummy);
  1.2306 +    }
  1.2307 +
  1.2308 +    return NS_OK;
  1.2309 +  }
  1.2310 +
  1.2311 +  nsRefPtr<TabChild> mTabChild;
  1.2312 +  TabChildGlobal* mTabChildGlobal;
  1.2313 +};
  1.2314 +
  1.2315 +bool
  1.2316 +TabChild::RecvDestroy()
  1.2317 +{
  1.2318 +  if (mTabChildGlobal) {
  1.2319 +    // Let the frame scripts know the child is being closed
  1.2320 +    nsContentUtils::AddScriptRunner(
  1.2321 +      new UnloadScriptEvent(this, mTabChildGlobal)
  1.2322 +    );
  1.2323 +  }
  1.2324 +
  1.2325 +  nsCOMPtr<nsIObserverService> observerService =
  1.2326 +    mozilla::services::GetObserverService();
  1.2327 +
  1.2328 +  observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
  1.2329 +  observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
  1.2330 +
  1.2331 +  const InfallibleTArray<PIndexedDBChild*>& idbActors =
  1.2332 +    ManagedPIndexedDBChild();
  1.2333 +  for (uint32_t i = 0; i < idbActors.Length(); ++i) {
  1.2334 +    static_cast<IndexedDBChild*>(idbActors[i])->Disconnect();
  1.2335 +  }
  1.2336 +
  1.2337 +  // XXX what other code in ~TabChild() should we be running here?
  1.2338 +  DestroyWindow();
  1.2339 +
  1.2340 +  return Send__delete__(this);
  1.2341 +}
  1.2342 +
  1.2343 +bool
  1.2344 +TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
  1.2345 +{
  1.2346 +    mUpdateHitRegion = aEnabled;
  1.2347 +    return true;
  1.2348 +}
  1.2349 +
  1.2350 +bool
  1.2351 +TabChild::RecvSetIsDocShellActive(const bool& aIsActive)
  1.2352 +{
  1.2353 +    nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
  1.2354 +    if (docShell) {
  1.2355 +      docShell->SetIsActive(aIsActive);
  1.2356 +    }
  1.2357 +    return true;
  1.2358 +}
  1.2359 +
  1.2360 +PRenderFrameChild*
  1.2361 +TabChild::AllocPRenderFrameChild()
  1.2362 +{
  1.2363 +    return new RenderFrameChild();
  1.2364 +}
  1.2365 +
  1.2366 +bool
  1.2367 +TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
  1.2368 +{
  1.2369 +    delete aFrame;
  1.2370 +    return true;
  1.2371 +}
  1.2372 +
  1.2373 +bool
  1.2374 +TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
  1.2375 +{
  1.2376 +  if (!mGlobal && !mTabChildGlobal) {
  1.2377 +    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
  1.2378 +    NS_ENSURE_TRUE(window, false);
  1.2379 +    nsCOMPtr<EventTarget> chromeHandler =
  1.2380 +      do_QueryInterface(window->GetChromeEventHandler());
  1.2381 +    NS_ENSURE_TRUE(chromeHandler, false);
  1.2382 +
  1.2383 +    nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
  1.2384 +    mTabChildGlobal = scope;
  1.2385 +
  1.2386 +    nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
  1.2387 +
  1.2388 +    NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
  1.2389 +    NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports, globalId), false);
  1.2390 +
  1.2391 +    scope->Init();
  1.2392 +
  1.2393 +    nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
  1.2394 +    NS_ENSURE_TRUE(root, false);
  1.2395 +    root->SetParentTarget(scope);
  1.2396 +
  1.2397 +    chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
  1.2398 +  }
  1.2399 +
  1.2400 +  if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
  1.2401 +    mTriedBrowserInit = true;
  1.2402 +    // Initialize the child side of the browser element machinery,
  1.2403 +    // if appropriate.
  1.2404 +    if (IsBrowserOrApp()) {
  1.2405 +      RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
  1.2406 +    }
  1.2407 +  }
  1.2408 +
  1.2409 +  return true;
  1.2410 +}
  1.2411 +
  1.2412 +bool
  1.2413 +TabChild::InitRenderingState()
  1.2414 +{
  1.2415 +    static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
  1.2416 +
  1.2417 +    uint64_t id;
  1.2418 +    bool success;
  1.2419 +    RenderFrameChild* remoteFrame =
  1.2420 +        static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
  1.2421 +    if (!remoteFrame) {
  1.2422 +        NS_WARNING("failed to construct RenderFrame");
  1.2423 +        return false;
  1.2424 +    }
  1.2425 +    SendInitRenderFrame(remoteFrame, &mScrolling, &mTextureFactoryIdentifier, &id, &success);
  1.2426 +    if (!success) {
  1.2427 +        NS_WARNING("failed to construct RenderFrame");
  1.2428 +        PRenderFrameChild::Send__delete__(remoteFrame);
  1.2429 +        return false;
  1.2430 +    }
  1.2431 +
  1.2432 +    PLayerTransactionChild* shadowManager = nullptr;
  1.2433 +    if (id != 0) {
  1.2434 +        // Pushing layers transactions directly to a separate
  1.2435 +        // compositor context.
  1.2436 +        PCompositorChild* compositorChild = CompositorChild::Get();
  1.2437 +        if (!compositorChild) {
  1.2438 +          NS_WARNING("failed to get CompositorChild instance");
  1.2439 +          return false;
  1.2440 +        }
  1.2441 +        nsTArray<LayersBackend> backends;
  1.2442 +        backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
  1.2443 +        bool success;
  1.2444 +        shadowManager =
  1.2445 +            compositorChild->SendPLayerTransactionConstructor(backends,
  1.2446 +                                                              id, &mTextureFactoryIdentifier, &success);
  1.2447 +        if (!success) {
  1.2448 +          NS_WARNING("failed to properly allocate layer transaction");
  1.2449 +          return false;
  1.2450 +        }
  1.2451 +    } else {
  1.2452 +        // Pushing transactions to the parent content.
  1.2453 +        shadowManager = remoteFrame->SendPLayerTransactionConstructor();
  1.2454 +    }
  1.2455 +
  1.2456 +    if (!shadowManager) {
  1.2457 +      NS_WARNING("failed to construct LayersChild");
  1.2458 +      // This results in |remoteFrame| being deleted.
  1.2459 +      PRenderFrameChild::Send__delete__(remoteFrame);
  1.2460 +      return false;
  1.2461 +    }
  1.2462 +
  1.2463 +    ShadowLayerForwarder* lf =
  1.2464 +        mWidget->GetLayerManager(shadowManager, mTextureFactoryIdentifier.mParentBackend)
  1.2465 +               ->AsShadowForwarder();
  1.2466 +    NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
  1.2467 +                      "PuppetWidget should have shadow manager");
  1.2468 +    lf->IdentifyTextureHost(mTextureFactoryIdentifier);
  1.2469 +    ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
  1.2470 +
  1.2471 +    mRemoteFrame = remoteFrame;
  1.2472 +    if (id != 0) {
  1.2473 +      if (!sTabChildren) {
  1.2474 +        sTabChildren = new TabChildMap;
  1.2475 +      }
  1.2476 +      sTabChildren->Put(id, this);
  1.2477 +      mLayersId = id;
  1.2478 +    }
  1.2479 +
  1.2480 +    nsCOMPtr<nsIObserverService> observerService =
  1.2481 +        mozilla::services::GetObserverService();
  1.2482 +
  1.2483 +    if (observerService) {
  1.2484 +        observerService->AddObserver(this,
  1.2485 +                                     BROWSER_ZOOM_TO_RECT,
  1.2486 +                                     false);
  1.2487 +        observerService->AddObserver(this,
  1.2488 +                                     BEFORE_FIRST_PAINT,
  1.2489 +                                     false);
  1.2490 +    }
  1.2491 +
  1.2492 +    // This state can't change during the lifetime of the child.
  1.2493 +    sCpowsEnabled = BrowserTabsRemote();
  1.2494 +    if (Preferences::GetBool("dom.ipc.cpows.force-enabled", false))
  1.2495 +      sCpowsEnabled = true;
  1.2496 +
  1.2497 +    return true;
  1.2498 +}
  1.2499 +
  1.2500 +void
  1.2501 +TabChild::SetBackgroundColor(const nscolor& aColor)
  1.2502 +{
  1.2503 +  if (mLastBackgroundColor != aColor) {
  1.2504 +    mLastBackgroundColor = aColor;
  1.2505 +    SendSetBackgroundColor(mLastBackgroundColor);
  1.2506 +  }
  1.2507 +}
  1.2508 +
  1.2509 +void
  1.2510 +TabChild::GetDPI(float* aDPI)
  1.2511 +{
  1.2512 +    *aDPI = -1.0;
  1.2513 +    if (!mRemoteFrame) {
  1.2514 +        return;
  1.2515 +    }
  1.2516 +
  1.2517 +    SendGetDPI(aDPI);
  1.2518 +}
  1.2519 +
  1.2520 +void
  1.2521 +TabChild::GetDefaultScale(double* aScale)
  1.2522 +{
  1.2523 +    *aScale = -1.0;
  1.2524 +    if (!mRemoteFrame) {
  1.2525 +        return;
  1.2526 +    }
  1.2527 +
  1.2528 +    SendGetDefaultScale(aScale);
  1.2529 +}
  1.2530 +
  1.2531 +void
  1.2532 +TabChild::NotifyPainted()
  1.2533 +{
  1.2534 +    if (UseDirectCompositor() && !mNotified) {
  1.2535 +        mRemoteFrame->SendNotifyCompositorTransaction();
  1.2536 +        mNotified = true;
  1.2537 +    }
  1.2538 +}
  1.2539 +
  1.2540 +bool
  1.2541 +TabChild::DispatchMouseEvent(const nsString&       aType,
  1.2542 +                             const CSSPoint&       aPoint,
  1.2543 +                             const int32_t&        aButton,
  1.2544 +                             const int32_t&        aClickCount,
  1.2545 +                             const int32_t&        aModifiers,
  1.2546 +                             const bool&           aIgnoreRootScrollFrame,
  1.2547 +                             const unsigned short& aInputSourceArg)
  1.2548 +{
  1.2549 +  nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
  1.2550 +  NS_ENSURE_TRUE(utils, true);
  1.2551 +  
  1.2552 +  bool defaultPrevented = false;
  1.2553 +  utils->SendMouseEvent(aType, aPoint.x, aPoint.y, aButton, aClickCount, aModifiers,
  1.2554 +                        aIgnoreRootScrollFrame, 0, aInputSourceArg, false, 4, &defaultPrevented);
  1.2555 +  return defaultPrevented;
  1.2556 +}
  1.2557 +
  1.2558 +void
  1.2559 +TabChild::MakeVisible()
  1.2560 +{
  1.2561 +    if (mWidget) {
  1.2562 +        mWidget->Show(true);
  1.2563 +    }
  1.2564 +}
  1.2565 +
  1.2566 +void
  1.2567 +TabChild::MakeHidden()
  1.2568 +{
  1.2569 +    if (mWidget) {
  1.2570 +        mWidget->Show(false);
  1.2571 +    }
  1.2572 +}
  1.2573 +
  1.2574 +void
  1.2575 +TabChild::UpdateHitRegion(const nsRegion& aRegion)
  1.2576 +{
  1.2577 +    mRemoteFrame->SendUpdateHitRegion(aRegion);
  1.2578 +}
  1.2579 +
  1.2580 +NS_IMETHODIMP
  1.2581 +TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
  1.2582 +{
  1.2583 +  if (mTabChildGlobal) {
  1.2584 +    NS_ADDREF(*aResult = mTabChildGlobal);
  1.2585 +    return NS_OK;
  1.2586 +  }
  1.2587 +  *aResult = nullptr;
  1.2588 +  return NS_ERROR_FAILURE;
  1.2589 +}
  1.2590 +
  1.2591 +void
  1.2592 +TabChild::SendRequestFocus(bool aCanFocus)
  1.2593 +{
  1.2594 +  PBrowserChild::SendRequestFocus(aCanFocus);
  1.2595 +}
  1.2596 +
  1.2597 +PIndexedDBChild*
  1.2598 +TabChild::AllocPIndexedDBChild(
  1.2599 +                            const nsCString& aGroup,
  1.2600 +                            const nsCString& aASCIIOrigin, bool* /* aAllowed */)
  1.2601 +{
  1.2602 +  NS_NOTREACHED("Should never get here!");
  1.2603 +  return nullptr;
  1.2604 +}
  1.2605 +
  1.2606 +bool
  1.2607 +TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
  1.2608 +{
  1.2609 +  delete aActor;
  1.2610 +  return true;
  1.2611 +}
  1.2612 +
  1.2613 +bool
  1.2614 +TabChild::DoSendBlockingMessage(JSContext* aCx,
  1.2615 +                                const nsAString& aMessage,
  1.2616 +                                const StructuredCloneData& aData,
  1.2617 +                                JS::Handle<JSObject *> aCpows,
  1.2618 +                                nsIPrincipal* aPrincipal,
  1.2619 +                                InfallibleTArray<nsString>* aJSONRetVal,
  1.2620 +                                bool aIsSync)
  1.2621 +{
  1.2622 +  ContentChild* cc = Manager();
  1.2623 +  ClonedMessageData data;
  1.2624 +  if (!BuildClonedMessageDataForChild(cc, aData, data)) {
  1.2625 +    return false;
  1.2626 +  }
  1.2627 +  InfallibleTArray<CpowEntry> cpows;
  1.2628 +  if (sCpowsEnabled) {
  1.2629 +    if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  1.2630 +      return false;
  1.2631 +    }
  1.2632 +  }
  1.2633 +  if (aIsSync) {
  1.2634 +    return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
  1.2635 +                           aPrincipal, aJSONRetVal);
  1.2636 +  }
  1.2637 +
  1.2638 +  return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
  1.2639 +                        aPrincipal, aJSONRetVal);
  1.2640 +}
  1.2641 +
  1.2642 +bool
  1.2643 +TabChild::DoSendAsyncMessage(JSContext* aCx,
  1.2644 +                             const nsAString& aMessage,
  1.2645 +                             const StructuredCloneData& aData,
  1.2646 +                             JS::Handle<JSObject *> aCpows,
  1.2647 +                             nsIPrincipal* aPrincipal)
  1.2648 +{
  1.2649 +  ContentChild* cc = Manager();
  1.2650 +  ClonedMessageData data;
  1.2651 +  if (!BuildClonedMessageDataForChild(cc, aData, data)) {
  1.2652 +    return false;
  1.2653 +  }
  1.2654 +  InfallibleTArray<CpowEntry> cpows;
  1.2655 +  if (sCpowsEnabled) {
  1.2656 +    if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  1.2657 +      return false;
  1.2658 +    }
  1.2659 +  }
  1.2660 +  return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
  1.2661 +                          aPrincipal);
  1.2662 +}
  1.2663 +
  1.2664 +TabChild*
  1.2665 +TabChild::GetFrom(nsIPresShell* aPresShell)
  1.2666 +{
  1.2667 +  nsIDocument* doc = aPresShell->GetDocument();
  1.2668 +  if (!doc) {
  1.2669 +      return nullptr;
  1.2670 +  }
  1.2671 +  nsCOMPtr<nsIDocShell> docShell(doc->GetDocShell());
  1.2672 +  return GetFrom(docShell);
  1.2673 +}
  1.2674 +
  1.2675 +TabChild*
  1.2676 +TabChild::GetFrom(uint64_t aLayersId)
  1.2677 +{
  1.2678 +  if (!sTabChildren) {
  1.2679 +    return nullptr;
  1.2680 +  }
  1.2681 +  return sTabChildren->Get(aLayersId);
  1.2682 +}
  1.2683 +
  1.2684 +void
  1.2685 +TabChild::DidComposite()
  1.2686 +{
  1.2687 +  MOZ_ASSERT(mWidget);
  1.2688 +  MOZ_ASSERT(mWidget->GetLayerManager());
  1.2689 +  MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT);
  1.2690 +
  1.2691 +  ClientLayerManager *manager = static_cast<ClientLayerManager*>(mWidget->GetLayerManager());
  1.2692 +  manager->DidComposite();
  1.2693 +}
  1.2694 +
  1.2695 +NS_IMETHODIMP
  1.2696 +TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
  1.2697 +{
  1.2698 +    nsString str(aTipText);
  1.2699 +    SendShowTooltip(aXCoords, aYCoords, str);
  1.2700 +    return NS_OK;
  1.2701 +}
  1.2702 +
  1.2703 +NS_IMETHODIMP
  1.2704 +TabChild::OnHideTooltip()
  1.2705 +{
  1.2706 +    SendHideTooltip();
  1.2707 +    return NS_OK;
  1.2708 +}
  1.2709 +
  1.2710 +TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
  1.2711 +: mTabChild(aTabChild)
  1.2712 +{
  1.2713 +}
  1.2714 +
  1.2715 +void
  1.2716 +TabChildGlobal::Init()
  1.2717 +{
  1.2718 +  NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
  1.2719 +  mMessageManager = new nsFrameMessageManager(mTabChild,
  1.2720 +                                              nullptr,
  1.2721 +                                              MM_CHILD);
  1.2722 +}
  1.2723 +
  1.2724 +NS_IMPL_CYCLE_COLLECTION_INHERITED(TabChildGlobal, DOMEventTargetHelper,
  1.2725 +                                   mMessageManager, mTabChild)
  1.2726 +
  1.2727 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
  1.2728 +  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
  1.2729 +  NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
  1.2730 +  NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
  1.2731 +  NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
  1.2732 +  NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
  1.2733 +  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
  1.2734 +  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
  1.2735 +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
  1.2736 +
  1.2737 +NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
  1.2738 +NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper)
  1.2739 +
  1.2740 +/* [notxpcom] boolean markForCC (); */
  1.2741 +// This method isn't automatically forwarded safely because it's notxpcom, so
  1.2742 +// the IDL binding doesn't know what value to return.
  1.2743 +NS_IMETHODIMP_(bool)
  1.2744 +TabChildGlobal::MarkForCC()
  1.2745 +{
  1.2746 +  return mMessageManager ? mMessageManager->MarkForCC() : false;
  1.2747 +}
  1.2748 +
  1.2749 +NS_IMETHODIMP
  1.2750 +TabChildGlobal::GetContent(nsIDOMWindow** aContent)
  1.2751 +{
  1.2752 +  *aContent = nullptr;
  1.2753 +  if (!mTabChild)
  1.2754 +    return NS_ERROR_NULL_POINTER;
  1.2755 +  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mTabChild->WebNavigation());
  1.2756 +  window.swap(*aContent);
  1.2757 +  return NS_OK;
  1.2758 +}
  1.2759 +
  1.2760 +NS_IMETHODIMP
  1.2761 +TabChildGlobal::PrivateNoteIntentionalCrash()
  1.2762 +{
  1.2763 +    mozilla::NoteIntentionalCrash("tab");
  1.2764 +    return NS_OK;
  1.2765 +}
  1.2766 +
  1.2767 +NS_IMETHODIMP
  1.2768 +TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
  1.2769 +{
  1.2770 +  *aDocShell = nullptr;
  1.2771 +  if (!mTabChild)
  1.2772 +    return NS_ERROR_NULL_POINTER;
  1.2773 +  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
  1.2774 +  docShell.swap(*aDocShell);
  1.2775 +  return NS_OK;
  1.2776 +}
  1.2777 +
  1.2778 +NS_IMETHODIMP
  1.2779 +TabChildGlobal::Btoa(const nsAString& aBinaryData,
  1.2780 +                     nsAString& aAsciiBase64String)
  1.2781 +{
  1.2782 +  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
  1.2783 +}
  1.2784 +
  1.2785 +NS_IMETHODIMP
  1.2786 +TabChildGlobal::Atob(const nsAString& aAsciiString,
  1.2787 +                     nsAString& aBinaryData)
  1.2788 +{
  1.2789 +  return nsContentUtils::Atob(aAsciiString, aBinaryData);
  1.2790 +}
  1.2791 +
  1.2792 +JSContext*
  1.2793 +TabChildGlobal::GetJSContextForEventHandlers()
  1.2794 +{
  1.2795 +  return nsContentUtils::GetSafeJSContext();
  1.2796 +}
  1.2797 +
  1.2798 +nsIPrincipal*
  1.2799 +TabChildGlobal::GetPrincipal()
  1.2800 +{
  1.2801 +  if (!mTabChild)
  1.2802 +    return nullptr;
  1.2803 +  return mTabChild->GetPrincipal();
  1.2804 +}
  1.2805 +
  1.2806 +JSObject*
  1.2807 +TabChildGlobal::GetGlobalJSObject()
  1.2808 +{
  1.2809 +  NS_ENSURE_TRUE(mTabChild, nullptr);
  1.2810 +  nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mTabChild->GetGlobal();
  1.2811 +  NS_ENSURE_TRUE(ref, nullptr);
  1.2812 +  return ref->GetJSObject();
  1.2813 +}
  1.2814 +

mercurial