already_AddRefed<nsIVariant>
DataTransferItem::DataNoSecurityCheck()
{
  if (!mData) {
    FillInExternalData();
  }
  nsCOMPtr<nsIVariant> data = mData;
  return data.forget();
}
Beispiel #2
0
void
DataTransfer::FillInExternalCustomTypes(uint32_t aIndex, nsIPrincipal* aPrincipal)
{
  TransferItem item;
  item.mFormat.AssignLiteral(kCustomTypesMime);

  FillInExternalData(item, aIndex);
  if (!item.mData) {
    return;
  }

  FillInExternalCustomTypes(item.mData, aIndex, aPrincipal);
}
Beispiel #3
0
void
DataTransfer::FillAllExternalData()
{
  if (mIsExternal) {
    for (uint32_t i = 0; i < mItems.Length(); ++i) {
      nsTArray<TransferItem>& itemArray = mItems[i];
      for (uint32_t j = 0; j < itemArray.Length(); ++j) {
        if (!itemArray[j].mData) {
          FillInExternalData(itemArray[j], i);
        }
      }
    }
  }
}
Beispiel #4
0
NS_IMETHODIMP
DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
                           nsIVariant** aData)
{
  *aData = nullptr;

  if (aFormat.IsEmpty())
    return NS_OK;

  if (aIndex >= mItems.Length()) {
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
  }

  // Only the first item is valid for clipboard events
  if (aIndex > 0 &&
      (mEventType == NS_CUT || mEventType == NS_COPY || mEventType == NS_PASTE)) {
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
  }


  nsAutoString format;
  GetRealFormat(aFormat, format);

  nsTArray<TransferItem>& item = mItems[aIndex];

  // Check if the caller is allowed to access the drag data. Callers with
  // chrome privileges can always read the data. During the
  // drop event, allow retrieving the data except in the case where the
  // source of the drag is in a child frame of the caller. In that case,
  // we only allow access to data of the same principal. During other events,
  // only allow access to the data with the same principal.
  nsIPrincipal* principal = nullptr;
  if (mIsCrossDomainSubFrameDrop ||
      (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
       mEventType != NS_PASTE &&
       !nsContentUtils::IsCallerChrome())) {
    principal = nsContentUtils::SubjectPrincipal();
  }

  uint32_t count = item.Length();
  for (uint32_t i = 0; i < count; i++) {
    TransferItem& formatitem = item[i];
    if (formatitem.mFormat.Equals(format)) {
      bool subsumes;
      if (formatitem.mPrincipal && principal &&
          (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
        return NS_ERROR_DOM_SECURITY_ERR;

      if (!formatitem.mData) {
        FillInExternalData(formatitem, aIndex);
      } else {
        nsCOMPtr<nsISupports> data;
        formatitem.mData->GetAsISupports(getter_AddRefs(data));
        // Make sure the code that is calling us is same-origin with the data.
        nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
        if (pt) {
          nsresult rv = NS_OK;
          nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
          NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
          nsIGlobalObject* go = c->GetGlobalObject();
          NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
          nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
          MOZ_ASSERT(sp, "This cannot fail on the main thread.");
          nsIPrincipal* dataPrincipal = sp->GetPrincipal();
          NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
          if (!principal) {
            principal = nsContentUtils::SubjectPrincipal();
          }
          bool equals = false;
          NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
                         NS_ERROR_DOM_SECURITY_ERR);
        }
      }
      *aData = formatitem.mData;
      NS_IF_ADDREF(*aData);
      return NS_OK;
    }
  }

  return NS_OK;
}
nsresult
DataTransfer::GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
                                nsIPrincipal* aSubjectPrincipal,
                                nsIVariant** aData)
{
  *aData = nullptr;

  if (aFormat.IsEmpty()) {
    return NS_OK;
  }

  if (aIndex >= mItems.Length()) {
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
  }

  // Only the first item is valid for clipboard events
  if (aIndex > 0 &&
      (mEventMessage == eCut || mEventMessage == eCopy ||
       mEventMessage == ePaste)) {
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
  }

  nsAutoString format;
  GetRealFormat(aFormat, format);

  nsTArray<TransferItem>& item = mItems[aIndex];

  // If this is a content caller, and a file is in the data transfer, only
  // return the file type.
  if (!format.EqualsLiteral(kFileMime) &&
      !nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) {
    uint32_t count = item.Length();
    for (uint32_t i = 0; i < count; i++) {
      if (item[i].mFormat.EqualsLiteral(kFileMime)) {
        return NS_OK;
      }
    }
  }

  // Check if the caller is allowed to access the drag data. Callers with
  // chrome privileges can always read the data. During the
  // drop event, allow retrieving the data except in the case where the
  // source of the drag is in a child frame of the caller. In that case,
  // we only allow access to data of the same principal. During other events,
  // only allow access to the data with the same principal.
  bool checkFormatItemPrincipal = mIsCrossDomainSubFrameDrop ||
      (mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
       mEventMessage != ePaste);

  uint32_t count = item.Length();
  for (uint32_t i = 0; i < count; i++) {
    TransferItem& formatitem = item[i];
    if (formatitem.mFormat.Equals(format)) {
      if (formatitem.mPrincipal && checkFormatItemPrincipal &&
          !aSubjectPrincipal->Subsumes(formatitem.mPrincipal)) {
        return NS_ERROR_DOM_SECURITY_ERR;
      }

      if (!formatitem.mData) {
        FillInExternalData(formatitem, aIndex);
      } else {
        nsCOMPtr<nsISupports> data;
        formatitem.mData->GetAsISupports(getter_AddRefs(data));
        // Make sure the code that is calling us is same-origin with the data.
        nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
        if (pt) {
          nsresult rv = NS_OK;
          nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
          NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
          nsIGlobalObject* go = c->GetGlobalObject();
          NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
          nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
          MOZ_ASSERT(sp, "This cannot fail on the main thread.");
          nsIPrincipal* dataPrincipal = sp->GetPrincipal();
          NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
          NS_ENSURE_TRUE(aSubjectPrincipal->Subsumes(dataPrincipal),
                                                     NS_ERROR_DOM_SECURITY_ERR);
        }
      }
      *aData = formatitem.mData;
      NS_IF_ADDREF(*aData);
      return NS_OK;
    }
  }

  return NS_OK;
}