webclipboard_impl.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/webclipboard_impl.h"
6
7#include "base/logging.h"
8#include "base/pickle.h"
9#include "base/strings/string_util.h"
10#include "base/strings/utf_string_conversions.h"
11#include "content/public/common/drop_data.h"
12#include "content/renderer/drop_data_builder.h"
13#include "content/renderer/scoped_clipboard_writer_glue.h"
14#include "googleurl/src/gurl.h"
15#include "third_party/WebKit/public/platform/WebData.h"
16#include "third_party/WebKit/public/platform/WebDragData.h"
17#include "third_party/WebKit/public/platform/WebImage.h"
18#include "third_party/WebKit/public/platform/WebSize.h"
19#include "third_party/WebKit/public/platform/WebString.h"
20#include "third_party/WebKit/public/platform/WebURL.h"
21#include "third_party/WebKit/public/platform/WebVector.h"
22#include "third_party/skia/include/core/SkBitmap.h"
23#include "ui/base/clipboard/clipboard.h"
24#include "ui/base/clipboard/custom_data_helper.h"
25#include "webkit/glue/webkit_glue.h"
26#include "webkit/renderer/clipboard_utils.h"
27
28using WebKit::WebClipboard;
29using WebKit::WebData;
30using WebKit::WebDragData;
31using WebKit::WebImage;
32using WebKit::WebString;
33using WebKit::WebURL;
34using WebKit::WebVector;
35
36namespace content {
37
38WebClipboardImpl::WebClipboardImpl(ClipboardClient* client)
39    : client_(client) {
40}
41
42WebClipboardImpl::~WebClipboardImpl() {
43}
44
45uint64 WebClipboardImpl::getSequenceNumber() {
46  return sequenceNumber(BufferStandard);
47}
48
49uint64 WebClipboardImpl::sequenceNumber(Buffer buffer) {
50  ui::Clipboard::Buffer buffer_type;
51  if (!ConvertBufferType(buffer, &buffer_type))
52    return 0;
53
54  return client_->GetSequenceNumber(buffer_type);
55}
56
57bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
58  ui::Clipboard::Buffer buffer_type = ui::Clipboard::BUFFER_STANDARD;
59
60  if (!ConvertBufferType(buffer, &buffer_type))
61    return false;
62
63  switch (format) {
64    case FormatPlainText:
65      return client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
66                                        buffer_type) ||
67          client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
68                                     buffer_type);
69    case FormatHTML:
70      return client_->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(),
71                                        buffer_type);
72    case FormatSmartPaste:
73      return client_->IsFormatAvailable(
74          ui::Clipboard::GetWebKitSmartPasteFormatType(), buffer_type);
75    case FormatBookmark:
76#if defined(OS_WIN) || defined(OS_MACOSX)
77      return client_->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
78                                        buffer_type);
79#endif
80    default:
81      NOTREACHED();
82  }
83
84  return false;
85}
86
87WebVector<WebString> WebClipboardImpl::readAvailableTypes(
88    Buffer buffer, bool* contains_filenames) {
89  ui::Clipboard::Buffer buffer_type;
90  std::vector<base::string16> types;
91  if (ConvertBufferType(buffer, &buffer_type)) {
92    client_->ReadAvailableTypes(buffer_type, &types, contains_filenames);
93  }
94  return types;
95}
96
97WebString WebClipboardImpl::readPlainText(Buffer buffer) {
98  ui::Clipboard::Buffer buffer_type;
99  if (!ConvertBufferType(buffer, &buffer_type))
100    return WebString();
101
102  if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
103                                 buffer_type)) {
104    base::string16 text;
105    client_->ReadText(buffer_type, &text);
106    if (!text.empty())
107      return text;
108  }
109
110  if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
111                                 buffer_type)) {
112    std::string text;
113    client_->ReadAsciiText(buffer_type, &text);
114    if (!text.empty())
115      return ASCIIToUTF16(text);
116  }
117
118  return WebString();
119}
120
121WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
122                                     unsigned* fragment_start,
123                                     unsigned* fragment_end) {
124  ui::Clipboard::Buffer buffer_type;
125  if (!ConvertBufferType(buffer, &buffer_type))
126    return WebString();
127
128  base::string16 html_stdstr;
129  GURL gurl;
130  client_->ReadHTML(buffer_type, &html_stdstr, &gurl,
131                    static_cast<uint32*>(fragment_start),
132                    static_cast<uint32*>(fragment_end));
133  *source_url = gurl;
134  return html_stdstr;
135}
136
137WebData WebClipboardImpl::readImage(Buffer buffer) {
138  ui::Clipboard::Buffer buffer_type;
139  if (!ConvertBufferType(buffer, &buffer_type))
140    return WebData();
141
142  std::string png_data;
143  client_->ReadImage(buffer_type, &png_data);
144  return WebData(png_data);
145}
146
147WebString WebClipboardImpl::readCustomData(Buffer buffer,
148                                           const WebString& type) {
149  ui::Clipboard::Buffer buffer_type;
150  if (!ConvertBufferType(buffer, &buffer_type))
151    return WebString();
152
153  base::string16 data;
154  client_->ReadCustomData(buffer_type, type, &data);
155  return data;
156}
157
158void WebClipboardImpl::writeHTML(
159    const WebString& html_text, const WebURL& source_url,
160    const WebString& plain_text, bool write_smart_paste) {
161  ScopedClipboardWriterGlue scw(client_);
162  scw.WriteHTML(html_text, source_url.spec());
163  scw.WriteText(plain_text);
164
165  if (write_smart_paste)
166    scw.WriteWebSmartPaste();
167}
168
169void WebClipboardImpl::writePlainText(const WebString& plain_text) {
170  ScopedClipboardWriterGlue scw(client_);
171  scw.WriteText(plain_text);
172}
173
174void WebClipboardImpl::writeURL(const WebURL& url, const WebString& title) {
175  ScopedClipboardWriterGlue scw(client_);
176
177  scw.WriteBookmark(title, url.spec());
178  scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToMarkup(url, title)),
179                std::string());
180  scw.WriteText(UTF8ToUTF16(std::string(url.spec())));
181}
182
183void WebClipboardImpl::writeImage(
184    const WebImage& image, const WebURL& url, const WebString& title) {
185  ScopedClipboardWriterGlue scw(client_);
186
187  if (!image.isNull()) {
188    const SkBitmap& bitmap = image.getSkBitmap();
189    SkAutoLockPixels locked(bitmap);
190    scw.WriteBitmapFromPixels(bitmap.getPixels(), image.size());
191  }
192
193  if (!url.isEmpty()) {
194    scw.WriteBookmark(title, url.spec());
195#if !defined(OS_MACOSX)
196    // When writing the image, we also write the image markup so that pasting
197    // into rich text editors, such as Gmail, reveals the image. We also don't
198    // want to call writeText(), since some applications (WordPad) don't pick
199    // the image if there is also a text format on the clipboard.
200    // We also don't want to write HTML on a Mac, since Mail.app prefers to use
201    // the image markup over attaching the actual image. See
202    // http://crbug.com/33016 for details.
203    scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToImageMarkup(url, title)),
204                  std::string());
205#endif
206  }
207}
208
209void WebClipboardImpl::writeDataObject(const WebDragData& data) {
210  ScopedClipboardWriterGlue scw(client_);
211
212  const DropData& data_object = DropDataBuilder::Build(data);
213  // TODO(dcheng): Properly support text/uri-list here.
214  if (!data_object.text.is_null())
215    scw.WriteText(data_object.text.string());
216  if (!data_object.html.is_null())
217    scw.WriteHTML(data_object.html.string(), std::string());
218  // If there is no custom data, avoid calling WritePickledData. This ensures
219  // that ScopedClipboardWriterGlue's dtor remains a no-op if the page didn't
220  // modify the DataTransfer object, which is important to avoid stomping on
221  // any clipboard contents written by extension functions such as
222  // chrome.bookmarkManagerPrivate.copy.
223  if (!data_object.custom_data.empty()) {
224    Pickle pickle;
225    ui::WriteCustomDataToPickle(data_object.custom_data, &pickle);
226    scw.WritePickledData(pickle, ui::Clipboard::GetWebCustomDataFormatType());
227  }
228}
229
230bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
231                                         ui::Clipboard::Buffer* result) {
232  switch (buffer) {
233    case BufferStandard:
234      *result = ui::Clipboard::BUFFER_STANDARD;
235      break;
236    case BufferSelection:
237#if defined(USE_X11)
238#if defined(OS_CHROMEOS)
239      //  Chrome OS only supports the standard clipboard,
240      //  but not the X selection clipboad.
241      return false;
242#else
243      *result = ui::Clipboard::BUFFER_SELECTION;
244      break;
245#endif
246#endif
247    default:
248      NOTREACHED();
249      return false;
250  }
251  return true;
252}
253
254}  // namespace content
255
256