webclipboard_impl.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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/clipboard_utils.h"
13#include "content/renderer/drop_data_builder.h"
14#include "content/renderer/scoped_clipboard_writer_glue.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 "url/gurl.h"
26#include "webkit/glue/webkit_glue.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::sequenceNumber(Buffer buffer) {
46  ui::ClipboardType clipboard_type;
47  if (!ConvertBufferType(buffer, &clipboard_type))
48    return 0;
49
50  return client_->GetSequenceNumber(clipboard_type);
51}
52
53bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
54  ui::ClipboardType clipboard_type = ui::CLIPBOARD_TYPE_COPY_PASTE;
55
56  if (!ConvertBufferType(buffer, &clipboard_type))
57    return false;
58
59  switch (format) {
60    case FormatPlainText:
61      return client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
62                                        clipboard_type) ||
63          client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
64                                     clipboard_type);
65    case FormatHTML:
66      return client_->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(),
67                                        clipboard_type);
68    case FormatSmartPaste:
69      return client_->IsFormatAvailable(
70          ui::Clipboard::GetWebKitSmartPasteFormatType(), clipboard_type);
71    case FormatBookmark:
72#if defined(OS_WIN) || defined(OS_MACOSX)
73      return client_->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
74                                        clipboard_type);
75#endif
76    default:
77      NOTREACHED();
78  }
79
80  return false;
81}
82
83WebVector<WebString> WebClipboardImpl::readAvailableTypes(
84    Buffer buffer, bool* contains_filenames) {
85  ui::ClipboardType clipboard_type;
86  std::vector<base::string16> types;
87  if (ConvertBufferType(buffer, &clipboard_type)) {
88    client_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
89  }
90  return types;
91}
92
93WebString WebClipboardImpl::readPlainText(Buffer buffer) {
94  ui::ClipboardType clipboard_type;
95  if (!ConvertBufferType(buffer, &clipboard_type))
96    return WebString();
97
98  if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
99                                 clipboard_type)) {
100    base::string16 text;
101    client_->ReadText(clipboard_type, &text);
102    if (!text.empty())
103      return text;
104  }
105
106  if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
107                                 clipboard_type)) {
108    std::string text;
109    client_->ReadAsciiText(clipboard_type, &text);
110    if (!text.empty())
111      return ASCIIToUTF16(text);
112  }
113
114  return WebString();
115}
116
117WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
118                                     unsigned* fragment_start,
119                                     unsigned* fragment_end) {
120  ui::ClipboardType clipboard_type;
121  if (!ConvertBufferType(buffer, &clipboard_type))
122    return WebString();
123
124  base::string16 html_stdstr;
125  GURL gurl;
126  client_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
127                    static_cast<uint32*>(fragment_start),
128                    static_cast<uint32*>(fragment_end));
129  *source_url = gurl;
130  return html_stdstr;
131}
132
133WebData WebClipboardImpl::readImage(Buffer buffer) {
134  ui::ClipboardType clipboard_type;
135  if (!ConvertBufferType(buffer, &clipboard_type))
136    return WebData();
137
138  std::string png_data;
139  client_->ReadImage(clipboard_type, &png_data);
140  return WebData(png_data);
141}
142
143WebString WebClipboardImpl::readCustomData(Buffer buffer,
144                                           const WebString& type) {
145  ui::ClipboardType clipboard_type;
146  if (!ConvertBufferType(buffer, &clipboard_type))
147    return WebString();
148
149  base::string16 data;
150  client_->ReadCustomData(clipboard_type, type, &data);
151  return data;
152}
153
154void WebClipboardImpl::writePlainText(const WebString& plain_text) {
155  ScopedClipboardWriterGlue scw(client_);
156  scw.WriteText(plain_text);
157}
158
159void WebClipboardImpl::writeHTML(
160    const WebString& html_text, const WebURL& source_url,
161    const WebString& plain_text, bool write_smart_paste) {
162  ScopedClipboardWriterGlue scw(client_);
163  scw.WriteHTML(html_text, source_url.spec());
164  scw.WriteText(plain_text);
165
166  if (write_smart_paste)
167    scw.WriteWebSmartPaste();
168}
169
170void WebClipboardImpl::writeImage(const WebImage& image,
171                                  const WebURL& url,
172                                  const WebString& title) {
173  ScopedClipboardWriterGlue scw(client_);
174
175  if (!image.isNull()) {
176    const SkBitmap& bitmap = image.getSkBitmap();
177    SkAutoLockPixels locked(bitmap);
178    scw.WriteBitmapFromPixels(bitmap.getPixels(), image.size());
179  }
180
181  if (!url.isEmpty()) {
182    scw.WriteBookmark(title, url.spec());
183#if !defined(OS_MACOSX)
184    // When writing the image, we also write the image markup so that pasting
185    // into rich text editors, such as Gmail, reveals the image. We also don't
186    // want to call writeText(), since some applications (WordPad) don't pick
187    // the image if there is also a text format on the clipboard.
188    // We also don't want to write HTML on a Mac, since Mail.app prefers to use
189    // the image markup over attaching the actual image. See
190    // http://crbug.com/33016 for details.
191    scw.WriteHTML(UTF8ToUTF16(URLToImageMarkup(url, title)), std::string());
192#endif
193  }
194}
195
196void WebClipboardImpl::writeDataObject(const WebDragData& data) {
197  ScopedClipboardWriterGlue scw(client_);
198
199  const DropData& data_object = DropDataBuilder::Build(data);
200  // TODO(dcheng): Properly support text/uri-list here.
201  if (!data_object.text.is_null())
202    scw.WriteText(data_object.text.string());
203  if (!data_object.html.is_null())
204    scw.WriteHTML(data_object.html.string(), std::string());
205  // If there is no custom data, avoid calling WritePickledData. This ensures
206  // that ScopedClipboardWriterGlue's dtor remains a no-op if the page didn't
207  // modify the DataTransfer object, which is important to avoid stomping on
208  // any clipboard contents written by extension functions such as
209  // chrome.bookmarkManagerPrivate.copy.
210  if (!data_object.custom_data.empty()) {
211    Pickle pickle;
212    ui::WriteCustomDataToPickle(data_object.custom_data, &pickle);
213    scw.WritePickledData(pickle, ui::Clipboard::GetWebCustomDataFormatType());
214  }
215}
216
217bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
218                                         ui::ClipboardType* result) {
219  *result = ui::CLIPBOARD_TYPE_COPY_PASTE;
220  switch (buffer) {
221    case BufferStandard:
222      break;
223    case BufferSelection:
224#if defined(USE_X11)
225#if defined(OS_CHROMEOS)
226      //  Chrome OS only supports the standard clipboard,
227      //  but not the X selection clipboad.
228      return false;
229#else
230      *result = ui::CLIPBOARD_TYPE_SELECTION;
231      break;
232#endif
233#endif
234    default:
235      NOTREACHED();
236      return false;
237  }
238  return true;
239}
240
241}  // namespace content
242