Bug 1499821 - Introduce the FindDataFlavor helper function to nsTransferable. r=froydnj
This combines some of your ideas from D8074, in which I think is quite a big improvement to the overall code.
The code for nsTransferable::GetTransferData, especially nsIFlavorDataProvider is a bit wonky, because I tried to preserve the current behavior.
Differential Revision:
https://phabricator.services.mozilla.com/D9599
--- a/widget/nsTransferable.cpp
+++ b/widget/nsTransferable.cpp
@@ -34,28 +34,16 @@ Notes to self:
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
#include "nsIWeakReferenceUtils.h"
#include "nsILoadContext.h"
#include "mozilla/UniquePtr.h"
NS_IMPL_ISUPPORTS(nsTransferable, nsITransferable)
-size_t
-GetDataForFlavor(const nsTArray<DataStruct>& aArray, const char* aDataFlavor)
-{
- for (size_t i = 0; i < aArray.Length(); ++i) {
- if (aArray[i].GetFlavor().Equals(aDataFlavor)) {
- return i;
- }
- }
-
- return aArray.NoIndex;
-}
-
DataStruct::DataStruct(DataStruct&& aRHS)
: mData(aRHS.mData.forget())
, mDataLen(aRHS.mDataLen)
, mCacheFD(aRHS.mCacheFD)
, mFlavor(aRHS.mFlavor)
{
aRHS.mCacheFD = nullptr;
}
@@ -230,16 +218,31 @@ nsTransferable::GetTransferDataFlavors(n
MOZ_ASSERT(mInitialized);
for (size_t i = 0; i < mDataArray.Length(); ++i) {
DataStruct& data = mDataArray.ElementAt(i);
aFlavors.AppendElement(data.GetFlavor());
}
}
+Maybe<size_t>
+nsTransferable::FindDataFlavor(const char* aFlavor)
+{
+ nsDependentCString flavor(aFlavor);
+
+ for (size_t i = 0; i < mDataArray.Length(); ++i) {
+ if (mDataArray[i].GetFlavor().Equals(flavor)) {
+ return Some(i);
+ }
+ }
+
+ return Nothing();
+}
+
+
//
// GetTransferData
//
// Returns the data of the requested flavor, obtained from either having the
// data on hand or using a converter to get it. The data is wrapped in a
// nsISupports primitive so that it is accessible from JS.
//
NS_IMETHODIMP
@@ -249,47 +252,43 @@ nsTransferable::GetTransferData(const ch
{
MOZ_ASSERT(mInitialized);
*aData = nullptr;
*aDataLen = 0;
nsresult rv = NS_OK;
- // first look and see if the data is present in one of the intrinsic flavors
- for (size_t i = 0; i < mDataArray.Length(); ++i) {
- DataStruct& data = mDataArray.ElementAt(i);
- if (data.GetFlavor().Equals(aFlavor)) {
- nsCOMPtr<nsISupports> dataBytes;
- uint32_t len;
- data.GetData(getter_AddRefs(dataBytes), &len);
+ // First look and see if the data is present in one of the intrinsic flavors.
+ if (Maybe<size_t> index = FindDataFlavor(aFlavor)) {
+ nsCOMPtr<nsISupports> dataBytes;
+ uint32_t len;
+ mDataArray[index.value()].GetData(getter_AddRefs(dataBytes), &len);
- // Do we have a (lazy) data provider?
- if (nsCOMPtr<nsIFlavorDataProvider> dataProvider =
- do_QueryInterface(dataBytes)) {
- rv = dataProvider->GetFlavorData(this, aFlavor,
- getter_AddRefs(dataBytes), &len);
- if (NS_FAILED(rv)) {
- // The provider failed, fall into the converter code below.
- break;
- }
+ // Do we have a (lazy) data provider?
+ if (nsCOMPtr<nsIFlavorDataProvider> dataProvider =
+ do_QueryInterface(dataBytes)) {
+ rv = dataProvider->GetFlavorData(this, aFlavor,
+ getter_AddRefs(dataBytes), &len);
+ if (NS_FAILED(rv)) {
+ dataBytes = nullptr;
+ // The provider failed, fall into the converter code below.
}
+ }
- if (dataBytes) {
- *aDataLen = len;
- dataBytes.forget(aData);
- return NS_OK;
- }
+ if (dataBytes) {
+ *aDataLen = len;
+ dataBytes.forget(aData);
+ return NS_OK;
+ }
- // Not found.
- break;
- }
+ // Empty data
}
- // if not, try using a format converter to get the requested flavor
+ // If not, try using a format converter to get the requested flavor.
if (mFormatConv) {
for (size_t i = 0; i < mDataArray.Length(); ++i) {
DataStruct& data = mDataArray.ElementAt(i);
bool canConvert = false;
mFormatConv->CanConvert(data.GetFlavor().get(), aFlavor, &canConvert);
if (canConvert) {
nsCOMPtr<nsISupports> dataBytes;
uint32_t len;
@@ -348,22 +347,20 @@ nsTransferable::GetAnyTransferData(nsACS
NS_IMETHODIMP
nsTransferable::SetTransferData(const char* aFlavor,
nsISupports* aData,
uint32_t aDataLen)
{
MOZ_ASSERT(mInitialized);
// first check our intrinsic flavors to see if one has been registered.
- for (size_t i = 0; i < mDataArray.Length(); ++i) {
- DataStruct& data = mDataArray.ElementAt(i);
- if (data.GetFlavor().Equals(aFlavor)) {
- data.SetData(aData, aDataLen, mPrivateData);
- return NS_OK;
- }
+ if (Maybe<size_t> index = FindDataFlavor(aFlavor)) {
+ DataStruct& data = mDataArray.ElementAt(index.value());
+ data.SetData(aData, aDataLen, mPrivateData);
+ return NS_OK;
}
// if not, try using a format converter to find a flavor to put the data in
if (mFormatConv) {
for (size_t i = 0; i < mDataArray.Length(); ++i) {
DataStruct& data = mDataArray.ElementAt(i);
bool canConvert = false;
mFormatConv->CanConvert(aFlavor, data.GetFlavor().get(), &canConvert);
@@ -397,42 +394,41 @@ nsTransferable::SetTransferData(const ch
//
// Adds a data flavor to our list with no data. Error if it already exists.
//
NS_IMETHODIMP
nsTransferable::AddDataFlavor(const char* aDataFlavor)
{
MOZ_ASSERT(mInitialized);
- if (GetDataForFlavor(mDataArray, aDataFlavor) != mDataArray.NoIndex) {
+ if (FindDataFlavor(aDataFlavor).isSome()) {
return NS_ERROR_FAILURE;
}
// Create a new "slot" for the data
mDataArray.AppendElement(DataStruct(aDataFlavor));
-
return NS_OK;
}
//
// RemoveDataFlavor
//
// Removes a data flavor (and causes the data to be destroyed). Error if
// the requested flavor is not present.
//
NS_IMETHODIMP
nsTransferable::RemoveDataFlavor(const char* aDataFlavor)
{
MOZ_ASSERT(mInitialized);
- size_t idx = GetDataForFlavor(mDataArray, aDataFlavor);
- if (idx != mDataArray.NoIndex) {
- mDataArray.RemoveElementAt(idx);
+ if (Maybe<size_t> index = FindDataFlavor(aDataFlavor)) {
+ mDataArray.RemoveElementAt(index.value());
return NS_OK;
}
+
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsTransferable::SetConverter(nsIFormatConverter* aConverter)
{
MOZ_ASSERT(mInitialized);
--- a/widget/nsTransferable.h
+++ b/widget/nsTransferable.h
@@ -8,16 +8,17 @@
#include "nsIFormatConverter.h"
#include "nsITransferable.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsIPrincipal.h"
#include "prio.h"
+#include "mozilla/Maybe.h"
class nsIMutableArray;
//
// DataStruct
//
// Holds a flavor (a mime type) that describes the data and the associated data.
//
@@ -68,19 +69,22 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
NS_DECL_NSITRANSFERABLE
protected:
virtual ~nsTransferable();
- // get flavors w/out converter
+ // Get flavors w/out converter
void GetTransferDataFlavors(nsTArray<nsCString>& aFlavors);
-
+
+ // Find index for data with the matching flavor in mDataArray.
+ Maybe<size_t> FindDataFlavor(const char* aFlavor);
+
nsTArray<DataStruct> mDataArray;
nsCOMPtr<nsIFormatConverter> mFormatConv;
bool mPrivateData;
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
nsContentPolicyType mContentPolicyType;
#if DEBUG
bool mInitialized;
#endif