// // FindUnicodeFromPlainText // // we are looking for text/unicode and we failed to find it on the clipboard first, // try again with text/plain. If that is present, convert it to unicode. // bool nsClipboard :: FindUnicodeFromPlainText ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen ) { bool dataFound = false; // we are looking for text/unicode and we failed to find it on the clipboard first, // try again with text/plain. If that is present, convert it to unicode. nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kTextMime), nullptr, outData, outDataLen); if ( NS_SUCCEEDED(loadResult) && *outData ) { const char* castedText = reinterpret_cast<char*>(*outData); PRUnichar* convertedText = nullptr; PRInt32 convertedTextLen = 0; nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode ( castedText, *outDataLen, &convertedText, &convertedTextLen ); if ( convertedText ) { // out with the old, in with the new nsMemory::Free(*outData); *outData = convertedText; *outDataLen = convertedTextLen * sizeof(PRUnichar); dataFound = true; } } // if plain text data on clipboard return dataFound; } // FindUnicodeFromPlainText
// // FindURLFromNativeURL // // we are looking for a URL and couldn't find it using our internal // URL flavor, so look for it using the native URL flavor, // CF_INETURLSTRW (We don't handle CF_INETURLSTRA currently) // bool nsClipboard :: FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen ) { bool dataFound = false; void* tempOutData = nullptr; PRUint32 tempDataLen = 0; nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, ::RegisterClipboardFormat(CFSTR_INETURLW), nullptr, &tempOutData, &tempDataLen); if ( NS_SUCCEEDED(loadResult) && tempOutData ) { nsDependentString urlString(static_cast<PRUnichar*>(tempOutData)); // the internal mozilla URL format, text/x-moz-url, contains // URL\ntitle. Since we don't actually have a title here, // just repeat the URL to fake it. *outData = ToNewUnicode(urlString + NS_LITERAL_STRING("\n") + urlString); *outDataLen = NS_strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); nsMemory::Free(tempOutData); dataFound = true; } else { loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, ::RegisterClipboardFormat(CFSTR_INETURLA), nullptr, &tempOutData, &tempDataLen); if ( NS_SUCCEEDED(loadResult) && tempOutData ) { // CFSTR_INETURLA is (currently) equal to CFSTR_SHELLURL which is equal to CF_TEXT // which is by definition ANSI encoded. nsCString urlUnescapedA; bool unescaped = NS_UnescapeURL(static_cast<char*>(tempOutData), tempDataLen, esc_OnlyNonASCII | esc_SkipControl, urlUnescapedA); nsString urlString; if (unescaped) NS_CopyNativeToUnicode(urlUnescapedA, urlString); else NS_CopyNativeToUnicode(nsDependentCString(static_cast<char*>(tempOutData), tempDataLen), urlString); // the internal mozilla URL format, text/x-moz-url, contains // URL\ntitle. Since we don't actually have a title here, // just repeat the URL to fake it. *outData = ToNewUnicode(urlString + NS_LITERAL_STRING("\n") + urlString); *outDataLen = NS_strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); nsMemory::Free(tempOutData); dataFound = true; } } return dataFound; } // FindURLFromNativeURL
// // FindURLFromLocalFile // // we are looking for a URL and couldn't find it, try again with looking for // a local file. If we have one, it may either be a normal file or an internet shortcut. // In both cases, however, we can get a URL (it will be a file:// url in the // local file case). // bool nsClipboard :: FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen ) { bool dataFound = false; nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kFileMime), nullptr, outData, outDataLen); if ( NS_SUCCEEDED(loadResult) && *outData ) { // we have a file path in |data|. Is it an internet shortcut or a normal file? const nsDependentString filepath(static_cast<PRUnichar*>(*outData)); nsCOMPtr<nsIFile> file; nsresult rv = NS_NewLocalFile(filepath, true, getter_AddRefs(file)); if (NS_FAILED(rv)) { nsMemory::Free(*outData); return dataFound; } if ( IsInternetShortcut(filepath) ) { nsMemory::Free(*outData); nsCAutoString url; ResolveShortcut( file, url ); if ( !url.IsEmpty() ) { // convert it to unicode and pass it out nsDependentString urlString(UTF8ToNewUnicode(url)); // the internal mozilla URL format, text/x-moz-url, contains // URL\ntitle. We can guess the title from the file's name. nsAutoString title; file->GetLeafName(title); // We rely on IsInternetShortcut check that file has a .url extension. title.SetLength(title.Length() - 4); if (title.IsEmpty()) title = urlString; *outData = ToNewUnicode(urlString + NS_LITERAL_STRING("\n") + title); *outDataLen = NS_strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); dataFound = true; } } else { // we have a normal file, use some Necko objects to get our file path nsCAutoString urlSpec; NS_GetURLSpecFromFile(file, urlSpec); // convert it to unicode and pass it out nsMemory::Free(*outData); *outData = UTF8ToNewUnicode(urlSpec); *outDataLen = NS_strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); dataFound = true; } // else regular file } return dataFound; } // FindURLFromLocalFile
// // FindURLFromLocalFile // // we are looking for a URL and couldn't find it, try again with looking for // a local file. If we have one, it may either be a normal file or an internet shortcut. // In both cases, however, we can get a URL (it will be a file:// url in the // local file case). // PRBool nsClipboard :: FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen ) { PRBool dataFound = PR_FALSE; nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kFileMime), outData, outDataLen); if ( NS_SUCCEEDED(loadResult) && *outData ) { // we have a file path in |data|. Is it an internet shortcut or a normal file? const nsDependentString filepath(static_cast<PRUnichar*>(*outData)); nsCOMPtr<nsILocalFile> file; nsresult rv = NS_NewLocalFile(filepath, PR_TRUE, getter_AddRefs(file)); if (NS_FAILED(rv)) return dataFound; if ( IsInternetShortcut(filepath) ) { nsCAutoString url; ResolveShortcut( file, url ); if ( !url.IsEmpty() ) { // convert it to unicode and pass it out nsMemory::Free(*outData); *outData = UTF8ToNewUnicode(url); *outDataLen = nsCRT::strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); dataFound = PR_TRUE; } } else { // we have a normal file, use some Necko objects to get our file path nsCAutoString urlSpec; NS_GetURLSpecFromFile(file, urlSpec); // convert it to unicode and pass it out nsMemory::Free(*outData); *outData = UTF8ToNewUnicode(urlSpec); *outDataLen = nsCRT::strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); dataFound = PR_TRUE; } // else regular file } return dataFound; } // FindURLFromLocalFile
// // FindURLFromNativeURL // // we are looking for a URL and couldn't find it using our internal // URL flavor, so look for it using the native URL flavor, // CF_INETURLSTRW (We don't handle CF_INETURLSTRA currently) // PRBool nsClipboard :: FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen ) { PRBool dataFound = PR_FALSE; void* tempOutData = nsnull; PRUint32 tempDataLen = 0; nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, ::RegisterClipboardFormat(CFSTR_INETURLW), &tempOutData, &tempDataLen); if ( NS_SUCCEEDED(loadResult) && tempOutData ) { nsDependentString urlString(static_cast<PRUnichar*>(tempOutData)); // the internal mozilla URL format, text/x-moz-url, contains // URL\ntitle. Since we don't actually have a title here, // just repeat the URL to fake it. *outData = ToNewUnicode(urlString + NS_LITERAL_STRING("\n") + urlString); *outDataLen = nsCRT::strlen(static_cast<PRUnichar*>(*outData)) * sizeof(PRUnichar); nsMemory::Free(tempOutData); dataFound = PR_TRUE; } return dataFound; } // FindURLFromNativeURL
//------------------------------------------------------------------------- nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject, UINT anIndex, nsIWidget * aWindow, nsITransferable * aTransferable) { // make sure we have a good transferable if ( !aTransferable ) return NS_ERROR_INVALID_ARG; nsresult res = NS_ERROR_FAILURE; // get flavor list that includes all flavors that can be written (including ones // obtained through conversion) nsCOMPtr<nsISupportsArray> flavorList; res = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) ); if ( NS_FAILED(res) ) return NS_ERROR_FAILURE; // Walk through flavors and see which flavor is on the clipboard them on the native clipboard, PRUint32 i; PRUint32 cnt; flavorList->Count(&cnt); for (i=0;i<cnt;i++) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) ); nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericFlavor) ); if ( currentFlavor ) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); UINT format = GetFormat(flavorStr); // Try to get the data using the desired flavor. This might fail, but all is // not lost. void* data = nullptr; PRUint32 dataLen = 0; bool dataFound = false; if (nullptr != aDataObject) { if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aDataObject, anIndex, format, flavorStr, &data, &dataLen)) ) dataFound = true; } else if (nullptr != aWindow) { if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aWindow, anIndex, format, &data, &dataLen)) ) dataFound = true; } // This is our second chance to try to find some data, having not found it // when directly asking for the flavor. Let's try digging around in other // flavors to help satisfy our craving for data. if ( !dataFound ) { if ( strcmp(flavorStr, kUnicodeMime) == 0 ) dataFound = FindUnicodeFromPlainText ( aDataObject, anIndex, &data, &dataLen ); else if ( strcmp(flavorStr, kURLMime) == 0 ) { // drags from other windows apps expose the native // CFSTR_INETURL{A,W} flavor dataFound = FindURLFromNativeURL ( aDataObject, anIndex, &data, &dataLen ); if ( !dataFound ) dataFound = FindURLFromLocalFile ( aDataObject, anIndex, &data, &dataLen ); } } // if we try one last ditch effort to find our data // Hopefully by this point we've found it and can go about our business if ( dataFound ) { nsCOMPtr<nsISupports> genericDataWrapper; if ( strcmp(flavorStr, kFileMime) == 0 ) { // we have a file path in |data|. Create an nsLocalFile object. nsDependentString filepath(reinterpret_cast<PRUnichar*>(data)); nsCOMPtr<nsIFile> file; if ( NS_SUCCEEDED(NS_NewLocalFile(filepath, false, getter_AddRefs(file))) ) genericDataWrapper = do_QueryInterface(file); nsMemory::Free(data); } else if ( strcmp(flavorStr, kNativeHTMLMime) == 0) { // the editor folks want CF_HTML exactly as it's on the clipboard, no conversions, // no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand // it back to them. if ( FindPlatformHTML(aDataObject, anIndex, &data, &dataLen) ) nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) ); else { nsMemory::Free(data); continue; // something wrong with this flavor, keep looking for other data } nsMemory::Free(data); } else if ( strcmp(flavorStr, kJPEGImageMime) == 0 || strcmp(flavorStr, kJPGImageMime) == 0 || strcmp(flavorStr, kPNGImageMime) == 0) { nsIInputStream * imageStream = reinterpret_cast<nsIInputStream*>(data); genericDataWrapper = do_QueryInterface(imageStream); NS_IF_RELEASE(imageStream); } else { // we probably have some form of text. The DOM only wants LF, so convert from Win32 line // endings to DOM line endings. PRInt32 signedLen = static_cast<PRInt32>(dataLen); nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &data, &signedLen ); dataLen = signedLen; nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) ); nsMemory::Free(data); } NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" ); aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLen); res = NS_OK; // we found one, get out of the loop break; } } } // foreach flavor return res; }