Source code
Revision control
Copy as Markdown
Other Tools
/* 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
#include "mozilla/java/ClipboardWrappers.h"
#include "mozilla/java/GeckoAppShellWrappers.h"
#include "nsClipboard.h"
#include "nsISupportsPrimitives.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsMemory.h"
#include "nsStringStream.h"
#include "nsPrimitiveHelpers.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS_INHERITED0(nsClipboard, nsBaseClipboard)
/* The Android clipboard only supports text and doesn't support mime types
* so we assume all clipboard data is text/plain for now. Documentation
* indicates that support for other data types is planned for future
* releases.
*/
nsClipboard::nsClipboard()
: nsBaseClipboard(mozilla::dom::ClipboardCapabilities(
false /* supportsSelectionClipboard */,
false /* supportsFindClipboard */,
false /* supportsSelectionCache */)) {
java::Clipboard::StartTrackingClipboardData(
java::GeckoAppShell::GetApplicationContext());
}
nsClipboard::~nsClipboard() {
java::Clipboard::StopTrackingClipboardData(
java::GeckoAppShell::GetApplicationContext());
}
// static
nsresult nsClipboard::GetTextFromTransferable(nsITransferable* aTransferable,
nsString& aText,
nsString& aHTML) {
nsTArray<nsCString> flavors;
nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
if (NS_FAILED(rv)) {
return rv;
}
for (auto& flavorStr : flavors) {
if (flavorStr.EqualsLiteral(kTextMime)) {
nsCOMPtr<nsISupports> item;
nsresult rv =
aTransferable->GetTransferData(kTextMime, getter_AddRefs(item));
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(item);
if (supportsString) {
supportsString->GetData(aText);
}
} else if (flavorStr.EqualsLiteral(kHTMLMime)) {
nsCOMPtr<nsISupports> item;
nsresult rv =
aTransferable->GetTransferData(kHTMLMime, getter_AddRefs(item));
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(item);
if (supportsString) {
supportsString->GetData(aHTML);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::SetNativeClipboardData(nsITransferable* aTransferable,
ClipboardType aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(aTransferable);
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
if (!jni::IsAvailable()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsString text;
nsString html;
nsresult rv = GetTextFromTransferable(aTransferable, text, html);
if (NS_FAILED(rv)) {
return rv;
}
bool isPrivate = aTransferable->GetIsPrivateData();
if (!html.IsEmpty() &&
java::Clipboard::SetHTML(java::GeckoAppShell::GetApplicationContext(),
text, html, isPrivate)) {
return NS_OK;
}
if (!text.IsEmpty() &&
java::Clipboard::SetText(java::GeckoAppShell::GetApplicationContext(),
text, isPrivate)) {
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable,
ClipboardType aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(aTransferable);
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
if (!jni::IsAvailable()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsTArray<nsCString> flavors;
aTransferable->FlavorsTransferableCanImport(flavors);
for (auto& flavorStr : flavors) {
if (flavorStr.EqualsLiteral(kTextMime) ||
flavorStr.EqualsLiteral(kHTMLMime)) {
auto text = java::Clipboard::GetTextData(
java::GeckoAppShell::GetApplicationContext(), flavorStr);
if (!text) {
continue;
}
nsString buffer = text->ToString();
if (buffer.IsEmpty()) {
continue;
}
nsCOMPtr<nsISupports> wrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, buffer.get(),
buffer.Length() * 2,
getter_AddRefs(wrapper));
if (wrapper) {
aTransferable->SetTransferData(flavorStr.get(), wrapper);
return NS_OK;
}
continue;
}
mozilla::jni::ByteArray::LocalRef bytes;
nsresult rv = java::Clipboard::GetRawData(flavorStr, &bytes);
if (NS_FAILED(rv) || !bytes) {
continue;
}
nsCOMPtr<nsIInputStream> byteStream;
rv = NS_NewByteInputStream(
getter_AddRefs(byteStream),
mozilla::Span(
reinterpret_cast<const char*>(bytes->GetElements().Elements()),
bytes->Length()),
NS_ASSIGNMENT_COPY);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
rv = aTransferable->SetTransferData(flavorStr.get(), byteStream);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
}
return NS_OK;
}
nsresult nsClipboard::EmptyNativeClipboardData(ClipboardType aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
if (!jni::IsAvailable()) {
return NS_ERROR_NOT_AVAILABLE;
}
java::Clipboard::Clear(java::GeckoAppShell::GetApplicationContext());
return NS_OK;
}
mozilla::Result<int32_t, nsresult>
nsClipboard::GetNativeClipboardSequenceNumber(ClipboardType aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
if (!jni::IsAvailable()) {
return Err(NS_ERROR_NOT_AVAILABLE);
}
return java::Clipboard::GetSequenceNumber(
java::GeckoAppShell::GetApplicationContext());
}
mozilla::Result<bool, nsresult>
nsClipboard::HasNativeClipboardDataMatchingFlavors(
const nsTArray<nsCString>& aFlavorList, ClipboardType aWhichClipboard) {
MOZ_DIAGNOSTIC_ASSERT(
nsIClipboard::IsClipboardTypeSupported(aWhichClipboard));
if (!jni::IsAvailable()) {
return Err(NS_ERROR_NOT_AVAILABLE);
}
for (auto& flavor : aFlavorList) {
if (java::Clipboard::HasData(java::GeckoAppShell::GetApplicationContext(),
NS_ConvertASCIItoUTF16(flavor))) {
return true;
}
}
return false;
}