1// Copyright 2014 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 "mojo/services/html_viewer/webclipboard_impl.h"
6
7#include "base/bind.h"
8#include "mojo/services/html_viewer/blink_basic_type_converters.h"
9
10namespace mojo {
11namespace {
12
13void CopyUint64(uint64_t* output, uint64_t input) {
14  *output = input;
15}
16
17void CopyWebString(blink::WebString* output,
18                   const mojo::Array<uint8_t>& input) {
19  // blink does not differentiate between the requested data type not existing
20  // and the empty string.
21  if (input.is_null()) {
22    output->reset();
23  } else {
24    *output = blink::WebString::fromUTF8(
25        reinterpret_cast<const char*>(&input.front()),
26        input.size());
27  }
28}
29
30void CopyURL(blink::WebURL* pageURL,
31             const mojo::Array<uint8_t>& input) {
32  if (input.is_null()) {
33    *pageURL = blink::WebURL();
34  } else {
35    *pageURL = GURL(std::string(reinterpret_cast<const char*>(&input.front()),
36                                input.size()));
37  }
38}
39
40void CopyVectorString(std::vector<std::string>* output,
41                      const Array<String>& input) {
42  *output = input.To<std::vector<std::string> >();
43}
44
45template <typename T, typename U>
46bool Contains(const std::vector<T>& v, const U& item) {
47  return std::find(v.begin(), v.end(), item) != v.end();
48}
49
50const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
51
52}  // namespace
53
54WebClipboardImpl::WebClipboardImpl(ClipboardPtr clipboard)
55    : clipboard_(clipboard.Pass()) {
56}
57
58WebClipboardImpl::~WebClipboardImpl() {
59}
60
61uint64_t WebClipboardImpl::sequenceNumber(Buffer buffer) {
62  mojo::Clipboard::Type clipboard_type = ConvertBufferType(buffer);
63
64  uint64_t number = 0;
65  clipboard_->GetSequenceNumber(clipboard_type,
66                                base::Bind(&CopyUint64, &number));
67
68  // Force this to be synchronous.
69  clipboard_.WaitForIncomingMethodCall();
70  return number;
71}
72
73bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
74  mojo::Clipboard::Type clipboard_type = ConvertBufferType(buffer);
75
76  std::vector<std::string> types;
77  clipboard_->GetAvailableMimeTypes(
78      clipboard_type, base::Bind(&CopyVectorString, &types));
79
80  // Force this to be synchronous.
81  clipboard_.WaitForIncomingMethodCall();
82
83  switch (format) {
84    case FormatPlainText:
85      return Contains(types, mojo::Clipboard::MIME_TYPE_TEXT);
86    case FormatHTML:
87      return Contains(types, mojo::Clipboard::MIME_TYPE_HTML);
88    case FormatSmartPaste:
89      return Contains(types, kMimeTypeWebkitSmartPaste);
90    case FormatBookmark:
91      // This might be difficult.
92      return false;
93  }
94
95  return false;
96}
97
98blink::WebVector<blink::WebString> WebClipboardImpl::readAvailableTypes(
99    Buffer buffer,
100    bool* containsFilenames) {
101  mojo::Clipboard::Type clipboard_type = ConvertBufferType(buffer);
102
103  std::vector<std::string> types;
104  clipboard_->GetAvailableMimeTypes(
105      clipboard_type, base::Bind(&CopyVectorString, &types));
106
107  // Force this to be synchronous.
108  clipboard_.WaitForIncomingMethodCall();
109
110  // AFAICT, every instance of setting containsFilenames is false.
111  *containsFilenames = false;
112
113  blink::WebVector<blink::WebString> output(types.size());
114  for (size_t i = 0; i < types.size(); ++i) {
115    output[i] = blink::WebString::fromUTF8(types[i]);
116  }
117
118  return output;
119}
120
121blink::WebString WebClipboardImpl::readPlainText(Buffer buffer) {
122  mojo::Clipboard::Type type = ConvertBufferType(buffer);
123
124  blink::WebString text;
125  clipboard_->ReadMimeType(
126      type, mojo::Clipboard::MIME_TYPE_TEXT, base::Bind(&CopyWebString, &text));
127
128  // Force this to be synchronous.
129  clipboard_.WaitForIncomingMethodCall();
130
131  return text;
132}
133
134blink::WebString WebClipboardImpl::readHTML(Buffer buffer,
135                                            blink::WebURL* pageURL,
136                                            unsigned* fragmentStart,
137                                            unsigned* fragmentEnd) {
138  mojo::Clipboard::Type type = ConvertBufferType(buffer);
139
140  blink::WebString html;
141  clipboard_->ReadMimeType(
142      type, mojo::Clipboard::MIME_TYPE_HTML, base::Bind(&CopyWebString, &html));
143  clipboard_.WaitForIncomingMethodCall();
144
145  *fragmentStart = 0;
146  *fragmentEnd = static_cast<unsigned>(html.length());
147
148  clipboard_->ReadMimeType(
149      type, mojo::Clipboard::MIME_TYPE_URL, base::Bind(&CopyURL, pageURL));
150  clipboard_.WaitForIncomingMethodCall();
151
152  return html;
153}
154
155blink::WebString WebClipboardImpl::readCustomData(
156    Buffer buffer,
157    const blink::WebString& mime_type) {
158  mojo::Clipboard::Type clipboard_type = ConvertBufferType(buffer);
159
160  blink::WebString data;
161  clipboard_->ReadMimeType(
162      clipboard_type, mime_type.utf8(), base::Bind(&CopyWebString, &data));
163
164  // Force this to be synchronous.
165  clipboard_.WaitForIncomingMethodCall();
166
167  return data;
168}
169
170void WebClipboardImpl::writePlainText(const blink::WebString& text) {
171  Array<MimeTypePairPtr> data;
172  MimeTypePairPtr text_data(MimeTypePair::New());
173  text_data->mime_type = mojo::Clipboard::MIME_TYPE_TEXT;
174  text_data->data = Array<uint8_t>::From(text).Pass();
175  data.push_back(text_data.Pass());
176
177  clipboard_->WriteClipboardData(mojo::Clipboard::TYPE_COPY_PASTE, data.Pass());
178}
179
180void WebClipboardImpl::writeHTML(const blink::WebString& htmlText,
181                                 const blink::WebURL& url,
182                                 const blink::WebString& plainText,
183                                 bool writeSmartPaste) {
184  Array<MimeTypePairPtr> data;
185  MimeTypePairPtr text_data(MimeTypePair::New());
186  text_data->mime_type = mojo::Clipboard::MIME_TYPE_TEXT;
187  text_data->data = Array<uint8_t>::From(plainText).Pass();
188  data.push_back(text_data.Pass());
189
190  MimeTypePairPtr html_data(MimeTypePair::New());
191  text_data->mime_type = mojo::Clipboard::MIME_TYPE_HTML;
192  text_data->data = Array<uint8_t>::From(htmlText).Pass();
193  data.push_back(html_data.Pass());
194
195  MimeTypePairPtr url_data(MimeTypePair::New());
196  url_data->mime_type = mojo::Clipboard::MIME_TYPE_URL;
197  url_data->data = Array<uint8_t>::From(url.string()).Pass();
198  data.push_back(url_data.Pass());
199
200  if (writeSmartPaste) {
201    MimeTypePairPtr smart_paste(MimeTypePair::New());
202    url_data->mime_type = kMimeTypeWebkitSmartPaste;
203    url_data->data = Array<uint8_t>::From(blink::WebString()).Pass();
204    data.push_back(smart_paste.Pass());
205  }
206
207  clipboard_->WriteClipboardData(mojo::Clipboard::TYPE_COPY_PASTE, data.Pass());
208}
209
210mojo::Clipboard::Type WebClipboardImpl::ConvertBufferType(Buffer buffer) {
211  switch (buffer) {
212    case BufferStandard:
213      return mojo::Clipboard::TYPE_COPY_PASTE;
214    case BufferSelection:
215      return mojo::Clipboard::TYPE_SELECTION;
216  }
217
218  NOTREACHED();
219  return mojo::Clipboard::TYPE_COPY_PASTE;
220}
221
222}  // namespace mojo
223