1// Copyright (c) 2011 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 "webkit/glue/webclipboard_impl.h"
6
7#include "base/logging.h"
8#include "base/string_util.h"
9#include "base/utf_string_conversions.h"
10#include "googleurl/src/gurl.h"
11#include "net/base/escape.h"
12#include "third_party/skia/include/core/SkBitmap.h"
13#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
14#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
15#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
16#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
17#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
18#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
19#include "ui/base/clipboard/clipboard.h"
20#include "webkit/glue/scoped_clipboard_writer_glue.h"
21#include "webkit/glue/webkit_glue.h"
22
23#if WEBKIT_USING_CG
24#include "skia/ext/skia_utils_mac.h"
25#endif
26
27using WebKit::WebClipboard;
28using WebKit::WebData;
29using WebKit::WebImage;
30using WebKit::WebString;
31using WebKit::WebURL;
32using WebKit::WebVector;
33
34namespace webkit_glue {
35
36// Static
37std::string WebClipboardImpl::URLToMarkup(const WebURL& url,
38    const WebString& title) {
39  std::string markup("<a href=\"");
40  markup.append(url.spec());
41  markup.append("\">");
42  // TODO(darin): HTML escape this
43  markup.append(EscapeForHTML(UTF16ToUTF8(title)));
44  markup.append("</a>");
45  return markup;
46}
47
48// Static
49std::string WebClipboardImpl::URLToImageMarkup(const WebURL& url,
50    const WebString& title) {
51  std::string markup("<img src=\"");
52  markup.append(url.spec());
53  markup.append("\"");
54  if (!title.isEmpty()) {
55    markup.append(" alt=\"");
56    markup.append(EscapeForHTML(UTF16ToUTF8(title)));
57    markup.append("\"");
58  }
59  markup.append("/>");
60  return markup;
61}
62
63WebClipboardImpl::~WebClipboardImpl() {
64}
65
66bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
67  ui::Clipboard::FormatType format_type;
68  ui::Clipboard::Buffer buffer_type;
69
70  if (!ConvertBufferType(buffer, &buffer_type))
71    return false;
72
73  switch (format) {
74    case FormatPlainText:
75      return ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
76                                        buffer_type) ||
77          ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
78                                     buffer_type);
79    case FormatHTML:
80      format_type = ui::Clipboard::GetHtmlFormatType();
81      break;
82    case FormatSmartPaste:
83      format_type = ui::Clipboard::GetWebKitSmartPasteFormatType();
84      break;
85    case FormatBookmark:
86#if defined(OS_WIN) || defined(OS_MACOSX)
87      format_type = ui::Clipboard::GetUrlWFormatType();
88      break;
89#endif
90    default:
91      NOTREACHED();
92      return false;
93  }
94
95  return ClipboardIsFormatAvailable(format_type, buffer_type);
96}
97
98WebString WebClipboardImpl::readPlainText(Buffer buffer) {
99  ui::Clipboard::Buffer buffer_type;
100  if (!ConvertBufferType(buffer, &buffer_type))
101    return WebString();
102
103  if (ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
104                                 buffer_type)) {
105    string16 text;
106    ClipboardReadText(buffer_type, &text);
107    if (!text.empty())
108      return text;
109  }
110
111  if (ClipboardIsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
112                                 buffer_type)) {
113    std::string text;
114    ClipboardReadAsciiText(buffer_type, &text);
115    if (!text.empty())
116      return ASCIIToUTF16(text);
117  }
118
119  return WebString();
120}
121
122WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url) {
123  ui::Clipboard::Buffer buffer_type;
124  if (!ConvertBufferType(buffer, &buffer_type))
125    return WebString();
126
127  string16 html_stdstr;
128  GURL gurl;
129  ClipboardReadHTML(buffer_type, &html_stdstr, &gurl);
130  *source_url = gurl;
131  return html_stdstr;
132}
133
134WebData WebClipboardImpl::readImage(Buffer buffer) {
135  ui::Clipboard::Buffer buffer_type;
136  if (!ConvertBufferType(buffer, &buffer_type))
137    return WebData();
138
139  std::string png_data;
140  ClipboardReadImage(buffer_type, &png_data);
141  return WebData(png_data);
142}
143
144void WebClipboardImpl::writeHTML(
145    const WebString& html_text, const WebURL& source_url,
146    const WebString& plain_text, bool write_smart_paste) {
147  ScopedClipboardWriterGlue scw(ClipboardGetClipboard());
148  scw.WriteHTML(html_text, source_url.spec());
149  scw.WriteText(plain_text);
150
151  if (write_smart_paste)
152    scw.WriteWebSmartPaste();
153}
154
155void WebClipboardImpl::writePlainText(const WebString& plain_text) {
156  ScopedClipboardWriterGlue scw(ClipboardGetClipboard());
157  scw.WriteText(plain_text);
158}
159
160void WebClipboardImpl::writeURL(const WebURL& url, const WebString& title) {
161  ScopedClipboardWriterGlue scw(ClipboardGetClipboard());
162
163  scw.WriteBookmark(title, url.spec());
164  scw.WriteHTML(UTF8ToUTF16(URLToMarkup(url, title)), "");
165  scw.WriteText(UTF8ToUTF16(std::string(url.spec())));
166}
167
168void WebClipboardImpl::writeImage(
169    const WebImage& image, const WebURL& url, const WebString& title) {
170  ScopedClipboardWriterGlue scw(ClipboardGetClipboard());
171
172  if (!image.isNull()) {
173#if WEBKIT_USING_SKIA
174    const SkBitmap& bitmap = image.getSkBitmap();
175#elif WEBKIT_USING_CG
176    const SkBitmap& bitmap = gfx::CGImageToSkBitmap(image.getCGImageRef());
177#endif
178    SkAutoLockPixels locked(bitmap);
179    scw.WriteBitmapFromPixels(bitmap.getPixels(), image.size());
180  }
181
182  // When writing the image, we also write the image markup so that pasting
183  // into rich text editors, such as Gmail, reveals the image. We also don't
184  // want to call writeText(), since some applications (WordPad) don't pick the
185  // image if there is also a text format on the clipboard.
186  if (!url.isEmpty()) {
187    scw.WriteBookmark(title, url.spec());
188    scw.WriteHTML(UTF8ToUTF16(URLToImageMarkup(url, title)), "");
189  }
190}
191
192void WebClipboardImpl::writeData(const WebString& type,
193                                 const WebString& data,
194                                 const WebString& metadata) {
195  // TODO(dcheng): Implement this stub.
196}
197
198WebVector<WebString> WebClipboardImpl::readAvailableTypes(
199    Buffer buffer, bool* contains_filenames) {
200  ui::Clipboard::Buffer buffer_type;
201  std::vector<string16> types;
202  if (ConvertBufferType(buffer, &buffer_type)) {
203    ClipboardReadAvailableTypes(buffer_type, &types, contains_filenames);
204  }
205  return types;
206}
207
208bool WebClipboardImpl::readData(Buffer buffer, const WebString& type,
209                                WebString* data, WebString* metadata) {
210  ui::Clipboard::Buffer buffer_type;
211  if (!ConvertBufferType(buffer, &buffer_type))
212    return false;
213
214  string16 data_out;
215  string16 metadata_out;
216  bool result = ClipboardReadData(buffer_type, type, &data_out, &metadata_out);
217  if (result) {
218    *data = data_out;
219    *metadata = metadata_out;
220  }
221  return result;
222}
223
224WebVector<WebString> WebClipboardImpl::readFilenames(Buffer buffer) {
225  ui::Clipboard::Buffer buffer_type;
226  std::vector<string16> filenames;
227  if (ConvertBufferType(buffer, &buffer_type)) {
228    ClipboardReadFilenames(buffer_type, &filenames);
229  }
230  return filenames;
231}
232
233bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
234                                         ui::Clipboard::Buffer* result) {
235  switch (buffer) {
236    case BufferStandard:
237      *result = ui::Clipboard::BUFFER_STANDARD;
238      break;
239    case BufferDrag:
240      *result = ui::Clipboard::BUFFER_DRAG;
241    case BufferSelection:
242#if defined(USE_X11)
243      *result = ui::Clipboard::BUFFER_SELECTION;
244      break;
245#endif
246    default:
247      NOTREACHED();
248      return false;
249  }
250  return true;
251}
252
253}  // namespace webkit_glue
254