widget/nsDragServiceProxy.cpp
author Andreas Tolfsen <ato@sny.no>
Thu, 11 Oct 2018 16:40:36 +0000
changeset 443621 9ca2c179e63e292808918158eb778b16bf18e67f
parent 430649 8727297a02487d109bf96fecd992375b5e1d31bb
child 448656 df022f193cb4b6d8f87504223adc2a2f8789be31
permissions -rw-r--r--
bug 1492499: marionette: warn on TimedPromise bailing; r=automatedtester We often use TimedPromise to ensure Marionette does not unexpectedly block on a promise that, for whatever reason, does not resolve. It can however be useful to be alerted when they don't, as it quite often means there is an underlying problem. Depends on D8406 Differential Revision: https://phabricator.services.mozilla.com/D8407

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsDragServiceProxy.h"
#include "nsIDocument.h"
#include "nsISupportsPrimitives.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"

using mozilla::ipc::Shmem;
using mozilla::dom::TabChild;
using mozilla::dom::OptionalShmem;
using mozilla::LayoutDeviceIntRect;
using mozilla::Maybe;

nsDragServiceProxy::nsDragServiceProxy()
{
}

nsDragServiceProxy::~nsDragServiceProxy()
{
}

static void
GetPrincipalURIFromNode(nsCOMPtr<nsINode>& sourceNode,
                        nsCString& aPrincipalURISpec)
{
  if (!sourceNode) {
    return;
  }

  nsCOMPtr<nsIPrincipal> principal = sourceNode->NodePrincipal();
  nsCOMPtr<nsIURI> principalURI;
  nsresult rv = principal->GetURI(getter_AddRefs(principalURI));
  if (NS_FAILED(rv) || !principalURI) {
    return;
  }

  principalURI->GetSpec(aPrincipalURISpec);
}

nsresult
nsDragServiceProxy::InvokeDragSessionImpl(nsIArray* aArrayTransferables,
                                          const Maybe<CSSIntRegion>& aRegion,
                                          uint32_t aActionType)
{
  NS_ENSURE_STATE(mSourceDocument->GetDocShell());
  TabChild* child = TabChild::GetFrom(mSourceDocument->GetDocShell());
  NS_ENSURE_STATE(child);
  nsTArray<mozilla::dom::IPCDataTransfer> dataTransfers;
  nsContentUtils::TransferablesToIPCTransferables(aArrayTransferables,
                                                  dataTransfers,
                                                  false,
                                                  child->Manager(),
                                                  nullptr);

  nsCString principalURISpec;
  GetPrincipalURIFromNode(mSourceNode, principalURISpec);

  LayoutDeviceIntRect dragRect;
  if (mHasImage || mSelection) {
    nsPresContext* pc;
    RefPtr<mozilla::gfx::SourceSurface> surface;
    DrawDrag(mSourceNode, aRegion, mScreenPosition, &dragRect, &surface, &pc);

    if (surface) {
      RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
        surface->GetDataSurface();
      if (dataSurface) {
        size_t length;
        int32_t stride;
        Maybe<Shmem> maybeShm = nsContentUtils::GetSurfaceData(dataSurface,
                                                               &length,
                                                               &stride,
                                                               child);
        if (maybeShm.isNothing()) {
          return NS_ERROR_FAILURE;
        }

        auto surfaceData = maybeShm.value();

        // Save the surface data to shared memory.
        if (!surfaceData.IsReadable() || !surfaceData.get<char>()) {
          NS_WARNING("Failed to create shared memory for drag session.");
          return NS_ERROR_FAILURE;
        }

        mozilla::Unused <<
          child->SendInvokeDragSession(dataTransfers, aActionType, surfaceData,
                                       stride, dataSurface->GetFormat(),
                                       dragRect, principalURISpec);
        StartDragSession();
        return NS_OK;
      }
    }
  }

  mozilla::Unused << child->SendInvokeDragSession(dataTransfers, aActionType,
                                                  mozilla::void_t(), 0, static_cast<gfx::SurfaceFormat>(0), dragRect,
                                                  principalURISpec);
  StartDragSession();
  return NS_OK;
}