blob: 60d7bc105337654369e33de9e856172c6d8e0fef [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/webclipboard_impl.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/common/clipboard_format.h"
#include "content/public/common/drop_data.h"
#include "content/renderer/clipboard_utils.h"
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/renderer_clipboard_delegate.h"
#include "third_party/WebKit/public/platform/WebDragData.h"
#include "third_party/WebKit/public/platform/WebImage.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "url/gurl.h"
using blink::WebBlobInfo;
using blink::WebClipboard;
using blink::WebDragData;
using blink::WebImage;
using blink::WebString;
using blink::WebURL;
using blink::WebVector;
namespace content {
WebClipboardImpl::WebClipboardImpl(RendererClipboardDelegate* delegate)
: delegate_(delegate) {
DCHECK(delegate);
}
WebClipboardImpl::~WebClipboardImpl() {
}
uint64_t WebClipboardImpl::sequenceNumber(Buffer buffer) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return 0;
return delegate_->GetSequenceNumber(clipboard_type);
}
bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
ui::ClipboardType clipboard_type = ui::CLIPBOARD_TYPE_COPY_PASTE;
if (!ConvertBufferType(buffer, &clipboard_type))
return false;
switch (format) {
case FormatPlainText:
return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_PLAINTEXT,
clipboard_type);
case FormatHTML:
return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_HTML,
clipboard_type);
case FormatSmartPaste:
return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_SMART_PASTE,
clipboard_type);
case FormatBookmark:
return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_BOOKMARK,
clipboard_type);
default:
NOTREACHED();
}
return false;
}
WebVector<WebString> WebClipboardImpl::readAvailableTypes(
Buffer buffer, bool* contains_filenames) {
ui::ClipboardType clipboard_type;
std::vector<base::string16> types;
if (ConvertBufferType(buffer, &clipboard_type)) {
delegate_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
}
WebVector<WebString> web_types(types.size());
std::transform(
types.begin(), types.end(), web_types.begin(),
[](const base::string16& s) { return WebString::fromUTF16(s); });
return web_types;
}
WebString WebClipboardImpl::readPlainText(Buffer buffer) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
base::string16 text;
delegate_->ReadText(clipboard_type, &text);
return WebString::fromUTF16(text);
}
WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
unsigned* fragment_start,
unsigned* fragment_end) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
base::string16 html_stdstr;
GURL gurl;
delegate_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
static_cast<uint32_t*>(fragment_start),
static_cast<uint32_t*>(fragment_end));
*source_url = gurl;
return WebString::fromUTF16(html_stdstr);
}
WebString WebClipboardImpl::readRTF(Buffer buffer) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
std::string rtf;
delegate_->ReadRTF(clipboard_type, &rtf);
return WebString::fromLatin1(rtf);
}
WebBlobInfo WebClipboardImpl::readImage(Buffer buffer) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return WebBlobInfo();
std::string blob_uuid;
std::string type;
int64_t size;
delegate_->ReadImage(clipboard_type, &blob_uuid, &type, &size);
if (size < 0)
return WebBlobInfo();
return WebBlobInfo(WebString::fromASCII(blob_uuid), WebString::fromUTF8(type),
size);
}
WebString WebClipboardImpl::readCustomData(Buffer buffer,
const WebString& type) {
ui::ClipboardType clipboard_type;
if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
base::string16 data;
delegate_->ReadCustomData(clipboard_type, type.utf16(), &data);
return WebString::fromUTF16(data);
}
void WebClipboardImpl::writePlainText(const WebString& plain_text) {
delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, plain_text.utf16());
delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeHTML(
const WebString& html_text, const WebURL& source_url,
const WebString& plain_text, bool write_smart_paste) {
delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE, html_text.utf16(),
source_url);
delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, plain_text.utf16());
if (write_smart_paste)
delegate_->WriteSmartPasteMarker(ui::CLIPBOARD_TYPE_COPY_PASTE);
delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeImage(const WebImage& image,
const WebURL& url,
const WebString& title) {
DCHECK(!image.isNull());
const SkBitmap& bitmap = image.getSkBitmap();
if (!delegate_->WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap))
return;
if (!url.isEmpty()) {
delegate_->WriteBookmark(ui::CLIPBOARD_TYPE_COPY_PASTE, url, title.utf16());
#if !defined(OS_MACOSX)
// When writing the image, we also write the image markup so that pasting
// into rich text editors, such as Gmail, reveals the image. We also don't
// want to call writeText(), since some applications (WordPad) don't pick
// the image if there is also a text format on the clipboard.
// We also don't want to write HTML on a Mac, since Mail.app prefers to use
// the image markup over attaching the actual image. See
// http://crbug.com/33016 for details.
delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE,
base::UTF8ToUTF16(URLToImageMarkup(url, title)),
GURL());
#endif
}
delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeDataObject(const WebDragData& data) {
const DropData& data_object = DropDataBuilder::Build(data);
// TODO(dcheng): Properly support text/uri-list here.
// Avoid calling the WriteFoo functions if there is no data associated with a
// type. This prevents stomping on clipboard contents that might have been
// written by extension functions such as chrome.bookmarkManagerPrivate.copy.
if (!data_object.text.is_null())
delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE,
data_object.text.string());
if (!data_object.html.is_null())
delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE,
data_object.html.string(), GURL());
if (!data_object.custom_data.empty())
delegate_->WriteCustomData(ui::CLIPBOARD_TYPE_COPY_PASTE,
data_object.custom_data);
delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
ui::ClipboardType* result) {
*result = ui::CLIPBOARD_TYPE_COPY_PASTE;
switch (buffer) {
case BufferStandard:
break;
case BufferSelection:
#if defined(USE_X11) && !defined(OS_CHROMEOS)
*result = ui::CLIPBOARD_TYPE_SELECTION;
break;
#else
// Chrome OS and non-X11 unix builds do not support
// the X selection clipboad.
// TODO: remove the need for this case, see http://crbug.com/361753
return false;
#endif
default:
NOTREACHED();
return false;
}
return true;
}
} // namespace content