[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / renderer / pepper / pepper_flash_clipboard_host.cc
blob686d7f98f9ad567b45400480541aac8fc5cf9ea9
1 // Copyright (c) 2012 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.
5 #include "content/renderer/pepper/pepper_flash_clipboard_host.h"
7 #include "base/pickle.h"
8 #include "base/utf_string_conversions.h"
9 #include "content/public/renderer/renderer_ppapi_host.h"
10 #include "content/renderer/renderer_clipboard_client.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/private/ppb_flash_clipboard.h"
14 #include "ppapi/host/dispatch_host_message.h"
15 #include "ppapi/host/ppapi_host.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/proxy/resource_message_params.h"
18 #include "webkit/glue/clipboard_client.h"
19 #include "webkit/glue/scoped_clipboard_writer_glue.h"
21 namespace content {
23 namespace {
25 const size_t kMaxClipboardWriteSize = 1000000;
27 ui::Clipboard::Buffer ConvertClipboardType(uint32_t type) {
28 switch (type) {
29 case PP_FLASH_CLIPBOARD_TYPE_STANDARD:
30 return ui::Clipboard::BUFFER_STANDARD;
31 case PP_FLASH_CLIPBOARD_TYPE_SELECTION:
32 return ui::Clipboard::BUFFER_SELECTION;
34 NOTREACHED();
35 return ui::Clipboard::BUFFER_STANDARD;
38 // Functions to pack/unpack custom data from a pickle. See the header file for
39 // more detail on custom formats in Pepper.
40 // TODO(raymes): Currently pepper custom formats are stored in their own
41 // native format type. However we should be able to store them in the same way
42 // as "Web Custom" formats are. This would allow clipboard data to be shared
43 // between pepper applications and web applications. However currently web apps
44 // assume all data that is placed on the clipboard is UTF16 and pepper allows
45 // arbitrary data so this change would require some reworking of the chrome
46 // clipboard interface for custom data.
47 bool JumpToFormatInPickle(const string16& format, PickleIterator* iter) {
48 uint64 size = 0;
49 if (!iter->ReadUInt64(&size))
50 return false;
51 for (uint64 i = 0; i < size; ++i) {
52 string16 stored_format;
53 if (!iter->ReadString16(&stored_format))
54 return false;
55 if (stored_format == format)
56 return true;
57 int skip_length;
58 if (!iter->ReadLength(&skip_length))
59 return false;
60 if (!iter->SkipBytes(skip_length))
61 return false;
63 return false;
66 bool IsFormatAvailableInPickle(const string16& format, const Pickle& pickle) {
67 PickleIterator iter(pickle);
68 return JumpToFormatInPickle(format, &iter);
71 std::string ReadDataFromPickle(const string16& format, const Pickle& pickle) {
72 std::string result;
73 PickleIterator iter(pickle);
74 if (!JumpToFormatInPickle(format, &iter) || !iter.ReadString(&result))
75 return std::string();
76 return result;
79 bool WriteDataToPickle(const std::map<string16, std::string>& data,
80 Pickle* pickle) {
81 pickle->WriteUInt64(data.size());
82 for (std::map<string16, std::string>::const_iterator it = data.begin();
83 it != data.end(); ++it) {
84 if (!pickle->WriteString16(it->first))
85 return false;
86 if (!pickle->WriteString(it->second))
87 return false;
89 return true;
92 } // namespace
94 PepperFlashClipboardHost::PepperFlashClipboardHost(
95 RendererPpapiHost* host,
96 PP_Instance instance,
97 PP_Resource resource)
98 : ResourceHost(host->GetPpapiHost(), instance, resource),
99 clipboard_client_(new RendererClipboardClient) {
102 PepperFlashClipboardHost::~PepperFlashClipboardHost() {
105 int32_t PepperFlashClipboardHost::OnResourceMessageReceived(
106 const IPC::Message& msg,
107 ppapi::host::HostMessageContext* context) {
108 IPC_BEGIN_MESSAGE_MAP(PepperFlashClipboardHost, msg)
109 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
110 PpapiHostMsg_FlashClipboard_RegisterCustomFormat,
111 OnMsgRegisterCustomFormat);
112 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
113 PpapiHostMsg_FlashClipboard_IsFormatAvailable,
114 OnMsgIsFormatAvailable);
115 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
116 PpapiHostMsg_FlashClipboard_ReadData,
117 OnMsgReadData);
118 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
119 PpapiHostMsg_FlashClipboard_WriteData,
120 OnMsgWriteData);
121 IPC_END_MESSAGE_MAP()
122 return PP_ERROR_FAILED;
125 int32_t PepperFlashClipboardHost::OnMsgRegisterCustomFormat(
126 ppapi::host::HostMessageContext* host_context,
127 const std::string& format_name) {
128 uint32_t format = custom_formats_.RegisterFormat(format_name);
129 if (format == PP_FLASH_CLIPBOARD_FORMAT_INVALID)
130 return PP_ERROR_FAILED;
131 host_context->reply_msg =
132 PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply(format);
133 return PP_OK;
136 int32_t PepperFlashClipboardHost::OnMsgIsFormatAvailable(
137 ppapi::host::HostMessageContext* host_context,
138 uint32_t clipboard_type,
139 uint32_t format) {
140 if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
141 NOTIMPLEMENTED();
142 return PP_ERROR_FAILED;
145 ui::Clipboard::Buffer buffer_type = ConvertClipboardType(clipboard_type);
146 bool available = false;
147 switch (format) {
148 case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
149 bool plain = clipboard_client_->IsFormatAvailable(
150 ui::Clipboard::GetPlainTextFormatType(), buffer_type);
151 bool plainw = clipboard_client_->IsFormatAvailable(
152 ui::Clipboard::GetPlainTextWFormatType(), buffer_type);
153 available = plain || plainw;
154 break;
156 case PP_FLASH_CLIPBOARD_FORMAT_HTML:
157 available = clipboard_client_->IsFormatAvailable(
158 ui::Clipboard::GetHtmlFormatType(), buffer_type);
159 break;
160 case PP_FLASH_CLIPBOARD_FORMAT_RTF:
161 available = clipboard_client_->IsFormatAvailable(
162 ui::Clipboard::GetRtfFormatType(), buffer_type);
163 break;
164 case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
165 break;
166 default:
167 if (custom_formats_.IsFormatRegistered(format)) {
168 std::string format_name = custom_formats_.GetFormatName(format);
169 std::string clipboard_data;
170 clipboard_client_->ReadData(
171 ui::Clipboard::GetPepperCustomDataFormatType(), &clipboard_data);
172 Pickle pickle(clipboard_data.data(), clipboard_data.size());
173 available = IsFormatAvailableInPickle(UTF8ToUTF16(format_name), pickle);
175 break;
178 return available ? PP_OK : PP_ERROR_FAILED;
181 int32_t PepperFlashClipboardHost::OnMsgReadData(
182 ppapi::host::HostMessageContext* host_context,
183 uint32_t clipboard_type,
184 uint32_t format) {
185 if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
186 NOTIMPLEMENTED();
187 return PP_ERROR_FAILED;
190 ui::Clipboard::Buffer buffer_type = ConvertClipboardType(clipboard_type);
191 std::string clipboard_string;
192 int32_t result = PP_ERROR_FAILED;
193 switch (format) {
194 case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
195 if (clipboard_client_->IsFormatAvailable(
196 ui::Clipboard::GetPlainTextWFormatType(), buffer_type)) {
197 string16 text;
198 clipboard_client_->ReadText(buffer_type, &text);
199 if (!text.empty()) {
200 result = PP_OK;
201 clipboard_string = UTF16ToUTF8(text);
202 break;
205 // If the PlainTextW format isn't available or is empty, take the
206 // ASCII text format.
207 if (clipboard_client_->IsFormatAvailable(
208 ui::Clipboard::GetPlainTextFormatType(), buffer_type)) {
209 result = PP_OK;
210 clipboard_client_->ReadAsciiText(buffer_type, &clipboard_string);
212 break;
214 case PP_FLASH_CLIPBOARD_FORMAT_HTML: {
215 if (!clipboard_client_->IsFormatAvailable(
216 ui::Clipboard::GetHtmlFormatType(), buffer_type)) {
217 break;
220 string16 html;
221 GURL gurl;
222 uint32 fragment_start;
223 uint32 fragment_end;
224 clipboard_client_->ReadHTML(buffer_type, &html, &gurl, &fragment_start,
225 &fragment_end);
226 result = PP_OK;
227 clipboard_string = UTF16ToUTF8(
228 html.substr(fragment_start, fragment_end - fragment_start));
229 break;
231 case PP_FLASH_CLIPBOARD_FORMAT_RTF: {
232 if (!clipboard_client_->IsFormatAvailable(
233 ui::Clipboard::GetRtfFormatType(), buffer_type)) {
234 break;
236 result = PP_OK;
237 clipboard_client_->ReadRTF(buffer_type, &clipboard_string);
238 break;
240 case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
241 break;
242 default: {
243 if (custom_formats_.IsFormatRegistered(format)) {
244 string16 format_name = UTF8ToUTF16(
245 custom_formats_.GetFormatName(format));
246 std::string clipboard_data;
247 clipboard_client_->ReadData(
248 ui::Clipboard::GetPepperCustomDataFormatType(), &clipboard_data);
249 Pickle pickle(clipboard_data.data(), clipboard_data.size());
250 if (IsFormatAvailableInPickle(format_name, pickle)) {
251 result = PP_OK;
252 clipboard_string = ReadDataFromPickle(format_name, pickle);
255 break;
259 if (result == PP_OK) {
260 host_context->reply_msg =
261 PpapiPluginMsg_FlashClipboard_ReadDataReply(clipboard_string);
263 return result;
266 int32_t PepperFlashClipboardHost::OnMsgWriteData(
267 ppapi::host::HostMessageContext* host_context,
268 uint32_t clipboard_type,
269 const std::vector<uint32_t>& formats,
270 const std::vector<std::string>& data) {
271 if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
272 NOTIMPLEMENTED();
273 return PP_ERROR_FAILED;
276 DCHECK(formats.size() == data.size());
277 // If no formats are passed in clear the clipboard.
278 if (formats.size() == 0) {
279 clipboard_client_->Clear(ConvertClipboardType(clipboard_type));
280 return PP_OK;
283 webkit_glue::ScopedClipboardWriterGlue scw(clipboard_client_.get());
284 std::map<string16, std::string> custom_data_map;
285 int32_t res = PP_OK;
286 for (uint32_t i = 0; i < formats.size(); ++i) {
287 if (data[i].length() > kMaxClipboardWriteSize) {
288 res = PP_ERROR_NOSPACE;
289 break;
292 switch (formats[i]) {
293 case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT:
294 scw.WriteText(UTF8ToUTF16(data[i]));
295 break;
296 case PP_FLASH_CLIPBOARD_FORMAT_HTML:
297 scw.WriteHTML(UTF8ToUTF16(data[i]), "");
298 break;
299 case PP_FLASH_CLIPBOARD_FORMAT_RTF:
300 scw.WriteRTF(data[i]);
301 break;
302 case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
303 res = PP_ERROR_BADARGUMENT;
304 break;
305 default:
306 if (custom_formats_.IsFormatRegistered(formats[i])) {
307 std::string format_name = custom_formats_.GetFormatName(formats[i]);
308 custom_data_map[UTF8ToUTF16(format_name)] = data[i];
309 } else {
310 // Invalid format.
311 res = PP_ERROR_BADARGUMENT;
312 break;
316 if (res != PP_OK)
317 break;
320 if (custom_data_map.size() > 0) {
321 Pickle pickle;
322 if (WriteDataToPickle(custom_data_map, &pickle)) {
323 scw.WritePickledData(pickle,
324 ui::Clipboard::GetPepperCustomDataFormatType());
325 } else {
326 res = PP_ERROR_BADARGUMENT;
330 if (res != PP_OK) {
331 // Need to clear the objects so nothing is written.
332 scw.Reset();
335 return res;
338 } // namespace content