1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/xpwidgets/nsTransferable.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,632 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +Notes to self: 1.11 + 1.12 +- at some point, strings will be accessible from JS, so we won't have to wrap 1.13 + flavors in an nsISupportsCString. Until then, we're kinda stuck with 1.14 + this crappy API of nsISupportsArrays. 1.15 + 1.16 +*/ 1.17 + 1.18 + 1.19 +#include "nsTransferable.h" 1.20 +#include "nsString.h" 1.21 +#include "nsReadableUtils.h" 1.22 +#include "nsTArray.h" 1.23 +#include "nsIFormatConverter.h" 1.24 +#include "nsIComponentManager.h" 1.25 +#include "nsCOMPtr.h" 1.26 +#include "nsXPCOM.h" 1.27 +#include "nsISupportsPrimitives.h" 1.28 +#include "nsMemory.h" 1.29 +#include "nsPrimitiveHelpers.h" 1.30 +#include "nsXPIDLString.h" 1.31 +#include "nsDirectoryServiceDefs.h" 1.32 +#include "nsDirectoryService.h" 1.33 +#include "nsCRT.h" 1.34 +#include "nsNetUtil.h" 1.35 +#include "nsIOutputStream.h" 1.36 +#include "nsIInputStream.h" 1.37 +#include "nsIFile.h" 1.38 +#include "nsILoadContext.h" 1.39 +#include "nsAutoPtr.h" 1.40 + 1.41 +NS_IMPL_ISUPPORTS(nsTransferable, nsITransferable) 1.42 + 1.43 +uint32_t GetDataForFlavor (const nsTArray<DataStruct>& aArray, 1.44 + const char* aDataFlavor) 1.45 +{ 1.46 + for (uint32_t i = 0 ; i < aArray.Length () ; ++i) { 1.47 + if (aArray[i].GetFlavor().Equals (aDataFlavor)) 1.48 + return i; 1.49 + } 1.50 + 1.51 + return aArray.NoIndex; 1.52 +} 1.53 + 1.54 +//------------------------------------------------------------------------- 1.55 +DataStruct::~DataStruct() 1.56 +{ 1.57 + if (mCacheFileName) free(mCacheFileName); 1.58 +} 1.59 + 1.60 +//------------------------------------------------------------------------- 1.61 +void 1.62 +DataStruct::SetData ( nsISupports* aData, uint32_t aDataLen ) 1.63 +{ 1.64 +#if 0 // Remove unnecessary disk caching to accommodate https://www.torproject.org/projects/torbrowser/design/#disk-avoidance 1.65 + // Now, check to see if we consider the data to be "too large" 1.66 + if (aDataLen > kLargeDatasetSize) { 1.67 + // if so, cache it to disk instead of memory 1.68 + if ( NS_SUCCEEDED(WriteCache(aData, aDataLen)) ) 1.69 + return; 1.70 + else 1.71 + NS_WARNING("Oh no, couldn't write data to the cache file"); 1.72 + } 1.73 +#endif // #if 0 1.74 + 1.75 + mData = aData; 1.76 + mDataLen = aDataLen; 1.77 +} 1.78 + 1.79 + 1.80 +//------------------------------------------------------------------------- 1.81 +void 1.82 +DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen ) 1.83 +{ 1.84 + // check here to see if the data is cached on disk 1.85 + if ( !mData && mCacheFileName ) { 1.86 + // if so, read it in and pass it back 1.87 + // ReadCache creates memory and copies the data into it. 1.88 + if ( NS_SUCCEEDED(ReadCache(aData, aDataLen)) ) 1.89 + return; 1.90 + else { 1.91 + // oh shit, something went horribly wrong here. 1.92 + NS_WARNING("Oh no, couldn't read data in from the cache file"); 1.93 + *aData = nullptr; 1.94 + *aDataLen = 0; 1.95 + return; 1.96 + } 1.97 + } 1.98 + 1.99 + *aData = mData; 1.100 + if ( mData ) 1.101 + NS_ADDREF(*aData); 1.102 + *aDataLen = mDataLen; 1.103 +} 1.104 + 1.105 + 1.106 +//------------------------------------------------------------------------- 1.107 +already_AddRefed<nsIFile> 1.108 +DataStruct::GetFileSpec(const char* aFileName) 1.109 +{ 1.110 + nsCOMPtr<nsIFile> cacheFile; 1.111 + NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(cacheFile)); 1.112 + 1.113 + if (!cacheFile) 1.114 + return nullptr; 1.115 + 1.116 + // if the param aFileName contains a name we should use that 1.117 + // because the file probably already exists 1.118 + // otherwise create a unique name 1.119 + if (!aFileName) { 1.120 + cacheFile->AppendNative(NS_LITERAL_CSTRING("clipboardcache")); 1.121 + cacheFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); 1.122 + } else { 1.123 + cacheFile->AppendNative(nsDependentCString(aFileName)); 1.124 + } 1.125 + 1.126 + return cacheFile.forget(); 1.127 +} 1.128 + 1.129 + 1.130 +//------------------------------------------------------------------------- 1.131 +nsresult 1.132 +DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen) 1.133 +{ 1.134 + // Get a new path and file to the temp directory 1.135 + nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName); 1.136 + if (cacheFile) { 1.137 + // remember the file name 1.138 + if (!mCacheFileName) { 1.139 + nsXPIDLCString fName; 1.140 + cacheFile->GetNativeLeafName(fName); 1.141 + mCacheFileName = strdup(fName); 1.142 + } 1.143 + 1.144 + // write out the contents of the clipboard 1.145 + // to the file 1.146 + //uint32_t bytes; 1.147 + nsCOMPtr<nsIOutputStream> outStr; 1.148 + 1.149 + NS_NewLocalFileOutputStream(getter_AddRefs(outStr), 1.150 + cacheFile); 1.151 + 1.152 + if (!outStr) return NS_ERROR_FAILURE; 1.153 + 1.154 + void* buff = nullptr; 1.155 + nsPrimitiveHelpers::CreateDataFromPrimitive ( mFlavor.get(), aData, &buff, aDataLen ); 1.156 + if ( buff ) { 1.157 + uint32_t ignored; 1.158 + outStr->Write(reinterpret_cast<char*>(buff), aDataLen, &ignored); 1.159 + nsMemory::Free(buff); 1.160 + return NS_OK; 1.161 + } 1.162 + } 1.163 + return NS_ERROR_FAILURE; 1.164 +} 1.165 + 1.166 + 1.167 +//------------------------------------------------------------------------- 1.168 +nsresult 1.169 +DataStruct::ReadCache(nsISupports** aData, uint32_t* aDataLen) 1.170 +{ 1.171 + // if we don't have a cache filename we are out of luck 1.172 + if (!mCacheFileName) 1.173 + return NS_ERROR_FAILURE; 1.174 + 1.175 + // get the path and file name 1.176 + nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName); 1.177 + bool exists; 1.178 + if ( cacheFile && NS_SUCCEEDED(cacheFile->Exists(&exists)) && exists ) { 1.179 + // get the size of the file 1.180 + int64_t fileSize; 1.181 + int64_t max32 = 0xFFFFFFFF; 1.182 + cacheFile->GetFileSize(&fileSize); 1.183 + if (fileSize > max32) 1.184 + return NS_ERROR_OUT_OF_MEMORY; 1.185 + 1.186 + uint32_t size = uint32_t(fileSize); 1.187 + // create new memory for the large clipboard data 1.188 + nsAutoArrayPtr<char> data(new char[size]); 1.189 + if ( !data ) 1.190 + return NS_ERROR_OUT_OF_MEMORY; 1.191 + 1.192 + // now read it all in 1.193 + nsCOMPtr<nsIInputStream> inStr; 1.194 + NS_NewLocalFileInputStream( getter_AddRefs(inStr), 1.195 + cacheFile); 1.196 + 1.197 + if (!cacheFile) return NS_ERROR_FAILURE; 1.198 + 1.199 + nsresult rv = inStr->Read(data, fileSize, aDataLen); 1.200 + 1.201 + // make sure we got all the data ok 1.202 + if (NS_SUCCEEDED(rv) && *aDataLen == size) { 1.203 + nsPrimitiveHelpers::CreatePrimitiveForData ( mFlavor.get(), data, fileSize, aData ); 1.204 + return *aData ? NS_OK : NS_ERROR_FAILURE; 1.205 + } 1.206 + 1.207 + // zero the return params 1.208 + *aData = nullptr; 1.209 + *aDataLen = 0; 1.210 + } 1.211 + 1.212 + return NS_ERROR_FAILURE; 1.213 +} 1.214 + 1.215 + 1.216 +//------------------------------------------------------------------------- 1.217 +// 1.218 +// Transferable constructor 1.219 +// 1.220 +//------------------------------------------------------------------------- 1.221 +nsTransferable::nsTransferable() 1.222 + : mPrivateData(false) 1.223 +#ifdef DEBUG 1.224 + , mInitialized(false) 1.225 +#endif 1.226 +{ 1.227 +} 1.228 + 1.229 +//------------------------------------------------------------------------- 1.230 +// 1.231 +// Transferable destructor 1.232 +// 1.233 +//------------------------------------------------------------------------- 1.234 +nsTransferable::~nsTransferable() 1.235 +{ 1.236 +} 1.237 + 1.238 + 1.239 +NS_IMETHODIMP 1.240 +nsTransferable::Init(nsILoadContext* aContext) 1.241 +{ 1.242 + MOZ_ASSERT(!mInitialized); 1.243 + 1.244 + if (aContext) { 1.245 + mPrivateData = aContext->UsePrivateBrowsing(); 1.246 + } 1.247 +#ifdef DEBUG 1.248 + mInitialized = true; 1.249 +#endif 1.250 + return NS_OK; 1.251 +} 1.252 + 1.253 +// 1.254 +// GetTransferDataFlavors 1.255 +// 1.256 +// Returns a copy of the internal list of flavors. This does NOT take into 1.257 +// account any converter that may be registered. This list consists of 1.258 +// nsISupportsCString objects so that the flavor list can be accessed from JS. 1.259 +// 1.260 +nsresult 1.261 +nsTransferable::GetTransferDataFlavors(nsISupportsArray ** aDataFlavorList) 1.262 +{ 1.263 + MOZ_ASSERT(mInitialized); 1.264 + 1.265 + nsresult rv = NS_NewISupportsArray ( aDataFlavorList ); 1.266 + if (NS_FAILED(rv)) return rv; 1.267 + 1.268 + for ( uint32_t i=0; i<mDataArray.Length(); ++i ) { 1.269 + DataStruct& data = mDataArray.ElementAt(i); 1.270 + nsCOMPtr<nsISupportsCString> flavorWrapper = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID); 1.271 + if ( flavorWrapper ) { 1.272 + flavorWrapper->SetData ( data.GetFlavor() ); 1.273 + nsCOMPtr<nsISupports> genericWrapper ( do_QueryInterface(flavorWrapper) ); 1.274 + (*aDataFlavorList)->AppendElement( genericWrapper ); 1.275 + } 1.276 + } 1.277 + 1.278 + return NS_OK; 1.279 +} 1.280 + 1.281 + 1.282 +// 1.283 +// GetTransferData 1.284 +// 1.285 +// Returns the data of the requested flavor, obtained from either having the data on hand or 1.286 +// using a converter to get it. The data is wrapped in a nsISupports primitive so that it is 1.287 +// accessible from JS. 1.288 +// 1.289 +NS_IMETHODIMP 1.290 +nsTransferable::GetTransferData(const char *aFlavor, nsISupports **aData, uint32_t *aDataLen) 1.291 +{ 1.292 + MOZ_ASSERT(mInitialized); 1.293 + 1.294 + NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen); 1.295 + 1.296 + nsresult rv = NS_OK; 1.297 + nsCOMPtr<nsISupports> savedData; 1.298 + 1.299 + // first look and see if the data is present in one of the intrinsic flavors 1.300 + uint32_t i; 1.301 + for (i = 0; i < mDataArray.Length(); ++i ) { 1.302 + DataStruct& data = mDataArray.ElementAt(i); 1.303 + if ( data.GetFlavor().Equals(aFlavor) ) { 1.304 + nsCOMPtr<nsISupports> dataBytes; 1.305 + uint32_t len; 1.306 + data.GetData(getter_AddRefs(dataBytes), &len); 1.307 + if (len == kFlavorHasDataProvider && dataBytes) { 1.308 + // do we have a data provider? 1.309 + nsCOMPtr<nsIFlavorDataProvider> dataProvider = do_QueryInterface(dataBytes); 1.310 + if (dataProvider) { 1.311 + rv = dataProvider->GetFlavorData(this, aFlavor, 1.312 + getter_AddRefs(dataBytes), &len); 1.313 + if (NS_FAILED(rv)) 1.314 + break; // the provider failed. fall into the converter code below. 1.315 + } 1.316 + } 1.317 + if (dataBytes && len > 0) { // XXXmats why is zero length not ok? 1.318 + *aDataLen = len; 1.319 + dataBytes.forget(aData); 1.320 + return NS_OK; 1.321 + } 1.322 + savedData = dataBytes; // return this if format converter fails 1.323 + break; 1.324 + } 1.325 + } 1.326 + 1.327 + bool found = false; 1.328 + 1.329 + // if not, try using a format converter to get the requested flavor 1.330 + if ( mFormatConv ) { 1.331 + for (i = 0; i < mDataArray.Length(); ++i) { 1.332 + DataStruct& data = mDataArray.ElementAt(i); 1.333 + bool canConvert = false; 1.334 + mFormatConv->CanConvert(data.GetFlavor().get(), aFlavor, &canConvert); 1.335 + if ( canConvert ) { 1.336 + nsCOMPtr<nsISupports> dataBytes; 1.337 + uint32_t len; 1.338 + data.GetData(getter_AddRefs(dataBytes), &len); 1.339 + if (len == kFlavorHasDataProvider && dataBytes) { 1.340 + // do we have a data provider? 1.341 + nsCOMPtr<nsIFlavorDataProvider> dataProvider = do_QueryInterface(dataBytes); 1.342 + if (dataProvider) { 1.343 + rv = dataProvider->GetFlavorData(this, aFlavor, 1.344 + getter_AddRefs(dataBytes), &len); 1.345 + if (NS_FAILED(rv)) 1.346 + break; // give up 1.347 + } 1.348 + } 1.349 + mFormatConv->Convert(data.GetFlavor().get(), dataBytes, len, aFlavor, aData, aDataLen); 1.350 + found = true; 1.351 + break; 1.352 + } 1.353 + } 1.354 + } 1.355 + 1.356 + // for backward compatibility 1.357 + if (!found) { 1.358 + savedData.forget(aData); 1.359 + *aDataLen = 0; 1.360 + } 1.361 + 1.362 + return found ? NS_OK : NS_ERROR_FAILURE; 1.363 +} 1.364 + 1.365 + 1.366 +// 1.367 +// GetAnyTransferData 1.368 +// 1.369 +// Returns the data of the first flavor found. Caller is responsible for deleting the 1.370 +// flavor string. 1.371 +// 1.372 +NS_IMETHODIMP 1.373 +nsTransferable::GetAnyTransferData(char **aFlavor, nsISupports **aData, uint32_t *aDataLen) 1.374 +{ 1.375 + MOZ_ASSERT(mInitialized); 1.376 + 1.377 + NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen); 1.378 + 1.379 + for ( uint32_t i=0; i < mDataArray.Length(); ++i ) { 1.380 + DataStruct& data = mDataArray.ElementAt(i); 1.381 + if (data.IsDataAvailable()) { 1.382 + *aFlavor = ToNewCString(data.GetFlavor()); 1.383 + data.GetData(aData, aDataLen); 1.384 + return NS_OK; 1.385 + } 1.386 + } 1.387 + 1.388 + return NS_ERROR_FAILURE; 1.389 +} 1.390 + 1.391 + 1.392 +// 1.393 +// SetTransferData 1.394 +// 1.395 +// 1.396 +// 1.397 +NS_IMETHODIMP 1.398 +nsTransferable::SetTransferData(const char *aFlavor, nsISupports *aData, uint32_t aDataLen) 1.399 +{ 1.400 + MOZ_ASSERT(mInitialized); 1.401 + 1.402 + NS_ENSURE_ARG(aFlavor); 1.403 + 1.404 + // first check our intrinsic flavors to see if one has been registered. 1.405 + uint32_t i = 0; 1.406 + for (i = 0; i < mDataArray.Length(); ++i) { 1.407 + DataStruct& data = mDataArray.ElementAt(i); 1.408 + if ( data.GetFlavor().Equals(aFlavor) ) { 1.409 + data.SetData ( aData, aDataLen ); 1.410 + return NS_OK; 1.411 + } 1.412 + } 1.413 + 1.414 + // if not, try using a format converter to find a flavor to put the data in 1.415 + if ( mFormatConv ) { 1.416 + for (i = 0; i < mDataArray.Length(); ++i) { 1.417 + DataStruct& data = mDataArray.ElementAt(i); 1.418 + bool canConvert = false; 1.419 + mFormatConv->CanConvert(aFlavor, data.GetFlavor().get(), &canConvert); 1.420 + 1.421 + if ( canConvert ) { 1.422 + nsCOMPtr<nsISupports> ConvertedData; 1.423 + uint32_t ConvertedLen; 1.424 + mFormatConv->Convert(aFlavor, aData, aDataLen, data.GetFlavor().get(), getter_AddRefs(ConvertedData), &ConvertedLen); 1.425 + data.SetData(ConvertedData, ConvertedLen); 1.426 + return NS_OK; 1.427 + } 1.428 + } 1.429 + } 1.430 + 1.431 + // Can't set data neither directly nor through converter. Just add this flavor and try again 1.432 + nsresult result = NS_ERROR_FAILURE; 1.433 + if ( NS_SUCCEEDED(AddDataFlavor(aFlavor)) ) 1.434 + result = SetTransferData (aFlavor, aData, aDataLen); 1.435 + 1.436 + return result; 1.437 +} 1.438 + 1.439 + 1.440 +// 1.441 +// AddDataFlavor 1.442 +// 1.443 +// Adds a data flavor to our list with no data. Error if it already exists. 1.444 +// 1.445 +NS_IMETHODIMP 1.446 +nsTransferable::AddDataFlavor(const char *aDataFlavor) 1.447 +{ 1.448 + MOZ_ASSERT(mInitialized); 1.449 + 1.450 + if (GetDataForFlavor (mDataArray, aDataFlavor) != mDataArray.NoIndex) 1.451 + return NS_ERROR_FAILURE; 1.452 + 1.453 + // Create a new "slot" for the data 1.454 + mDataArray.AppendElement(DataStruct ( aDataFlavor )); 1.455 + 1.456 + return NS_OK; 1.457 +} 1.458 + 1.459 + 1.460 +// 1.461 +// RemoveDataFlavor 1.462 +// 1.463 +// Removes a data flavor (and causes the data to be destroyed). Error if 1.464 +// the requested flavor is not present. 1.465 +// 1.466 +NS_IMETHODIMP 1.467 +nsTransferable::RemoveDataFlavor(const char *aDataFlavor) 1.468 +{ 1.469 + MOZ_ASSERT(mInitialized); 1.470 + 1.471 + uint32_t idx; 1.472 + if ((idx = GetDataForFlavor(mDataArray, aDataFlavor)) != mDataArray.NoIndex) { 1.473 + mDataArray.RemoveElementAt (idx); 1.474 + return NS_OK; 1.475 + } 1.476 + return NS_ERROR_FAILURE; 1.477 +} 1.478 + 1.479 + 1.480 +/** 1.481 + * 1.482 + * 1.483 + */ 1.484 +NS_IMETHODIMP 1.485 +nsTransferable::IsLargeDataSet(bool *_retval) 1.486 +{ 1.487 + MOZ_ASSERT(mInitialized); 1.488 + 1.489 + NS_ENSURE_ARG_POINTER(_retval); 1.490 + *_retval = false; 1.491 + return NS_OK; 1.492 +} 1.493 + 1.494 + 1.495 +/** 1.496 + * 1.497 + * 1.498 + */ 1.499 +NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter) 1.500 +{ 1.501 + MOZ_ASSERT(mInitialized); 1.502 + 1.503 + mFormatConv = aConverter; 1.504 + return NS_OK; 1.505 +} 1.506 + 1.507 + 1.508 +/** 1.509 + * 1.510 + * 1.511 + */ 1.512 +NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter) 1.513 +{ 1.514 + MOZ_ASSERT(mInitialized); 1.515 + 1.516 + NS_ENSURE_ARG_POINTER(aConverter); 1.517 + *aConverter = mFormatConv; 1.518 + NS_IF_ADDREF(*aConverter); 1.519 + return NS_OK; 1.520 +} 1.521 + 1.522 + 1.523 +// 1.524 +// FlavorsTransferableCanImport 1.525 +// 1.526 +// Computes a list of flavors that the transferable can accept into it, either through 1.527 +// intrinsic knowledge or input data converters. 1.528 +// 1.529 +NS_IMETHODIMP 1.530 +nsTransferable::FlavorsTransferableCanImport(nsISupportsArray **_retval) 1.531 +{ 1.532 + MOZ_ASSERT(mInitialized); 1.533 + 1.534 + NS_ENSURE_ARG_POINTER(_retval); 1.535 + 1.536 + // Get the flavor list, and on to the end of it, append the list of flavors we 1.537 + // can also get to through a converter. This is so that we can just walk the list 1.538 + // in one go, looking for the desired flavor. 1.539 + GetTransferDataFlavors(_retval); // addrefs 1.540 + nsCOMPtr<nsIFormatConverter> converter; 1.541 + GetConverter(getter_AddRefs(converter)); 1.542 + if ( converter ) { 1.543 + nsCOMPtr<nsISupportsArray> convertedList; 1.544 + converter->GetInputDataFlavors(getter_AddRefs(convertedList)); 1.545 + 1.546 + if ( convertedList ) { 1.547 + uint32_t importListLen; 1.548 + convertedList->Count(&importListLen); 1.549 + 1.550 + for ( uint32_t i=0; i < importListLen; ++i ) { 1.551 + nsCOMPtr<nsISupports> genericFlavor; 1.552 + convertedList->GetElementAt ( i, getter_AddRefs(genericFlavor) ); 1.553 + 1.554 + nsCOMPtr<nsISupportsCString> flavorWrapper ( do_QueryInterface (genericFlavor) ); 1.555 + nsAutoCString flavorStr; 1.556 + flavorWrapper->GetData( flavorStr ); 1.557 + 1.558 + if (GetDataForFlavor (mDataArray, flavorStr.get()) 1.559 + == mDataArray.NoIndex) // Don't append if already in intrinsic list 1.560 + (*_retval)->AppendElement (genericFlavor); 1.561 + } // foreach flavor that can be converted to 1.562 + } 1.563 + } // if a converter exists 1.564 + 1.565 + return NS_OK; 1.566 +} // FlavorsTransferableCanImport 1.567 + 1.568 + 1.569 +// 1.570 +// FlavorsTransferableCanExport 1.571 +// 1.572 +// Computes a list of flavors that the transferable can export, either through 1.573 +// intrinsic knowledge or output data converters. 1.574 +// 1.575 +NS_IMETHODIMP 1.576 +nsTransferable::FlavorsTransferableCanExport(nsISupportsArray **_retval) 1.577 +{ 1.578 + MOZ_ASSERT(mInitialized); 1.579 + 1.580 + NS_ENSURE_ARG_POINTER(_retval); 1.581 + 1.582 + // Get the flavor list, and on to the end of it, append the list of flavors we 1.583 + // can also get to through a converter. This is so that we can just walk the list 1.584 + // in one go, looking for the desired flavor. 1.585 + GetTransferDataFlavors(_retval); // addrefs 1.586 + nsCOMPtr<nsIFormatConverter> converter; 1.587 + GetConverter(getter_AddRefs(converter)); 1.588 + if ( converter ) { 1.589 + nsCOMPtr<nsISupportsArray> convertedList; 1.590 + converter->GetOutputDataFlavors(getter_AddRefs(convertedList)); 1.591 + 1.592 + if ( convertedList ) { 1.593 + uint32_t importListLen; 1.594 + convertedList->Count(&importListLen); 1.595 + 1.596 + for ( uint32_t i=0; i < importListLen; ++i ) { 1.597 + nsCOMPtr<nsISupports> genericFlavor; 1.598 + convertedList->GetElementAt ( i, getter_AddRefs(genericFlavor) ); 1.599 + 1.600 + nsCOMPtr<nsISupportsCString> flavorWrapper ( do_QueryInterface (genericFlavor) ); 1.601 + nsAutoCString flavorStr; 1.602 + flavorWrapper->GetData( flavorStr ); 1.603 + 1.604 + if (GetDataForFlavor (mDataArray, flavorStr.get()) 1.605 + == mDataArray.NoIndex) // Don't append if already in intrinsic list 1.606 + (*_retval)->AppendElement (genericFlavor); 1.607 + } // foreach flavor that can be converted to 1.608 + } 1.609 + } // if a converter exists 1.610 + 1.611 + return NS_OK; 1.612 +} // FlavorsTransferableCanExport 1.613 + 1.614 +NS_IMETHODIMP 1.615 +nsTransferable::GetIsPrivateData(bool *aIsPrivateData) 1.616 +{ 1.617 + MOZ_ASSERT(mInitialized); 1.618 + 1.619 + NS_ENSURE_ARG_POINTER(aIsPrivateData); 1.620 + 1.621 + *aIsPrivateData = mPrivateData; 1.622 + 1.623 + return NS_OK; 1.624 +} 1.625 + 1.626 +NS_IMETHODIMP 1.627 +nsTransferable::SetIsPrivateData(bool aIsPrivateData) 1.628 +{ 1.629 + MOZ_ASSERT(mInitialized); 1.630 + 1.631 + mPrivateData = aIsPrivateData; 1.632 + 1.633 + return NS_OK; 1.634 +} 1.635 +