OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/renderer/pepper/pepper_flash_clipboard_host.h" | |
6 | |
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" | |
20 | |
21 namespace content { | |
22 | |
23 namespace { | |
24 | |
25 const size_t kMaxClipboardWriteSize = 1000000; | |
26 | |
27 ui::Clipboard::Buffer ConvertClipboardType( | |
28 uint32_t type) { | |
29 switch (type) { | |
30 case PP_FLASH_CLIPBOARD_TYPE_STANDARD: | |
31 return ui::Clipboard::BUFFER_STANDARD; | |
32 case PP_FLASH_CLIPBOARD_TYPE_SELECTION: | |
33 return ui::Clipboard::BUFFER_SELECTION; | |
34 } | |
35 NOTREACHED(); | |
36 return ui::Clipboard::BUFFER_STANDARD; | |
37 } | |
38 | |
39 // Functions to pack/unpack custom data from a pickle. See the header file for | |
40 // more detail on custom formats in Pepper. | |
41 // TODO(raymes): This code is very similar to the code in | |
dcheng
2012/10/29 20:26:29
We should probably address this sooner rather than
raymes
2012/10/29 23:30:00
I filed a bug and added a TODO. As discussed, I've
| |
42 // ui/base/clipboard/custom_data_helper.cc except that it operates on custom | |
43 // data represented as std::strings rather than string16s. This could be unified | |
44 // by changing that code (and its uses) to read/write custom data as arbitrary | |
45 // bytes rather than string16s. This would also allow interoperability between | |
46 // the web clipboard and the pepper clipboard. | |
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; | |
62 } | |
63 return false; | |
64 } | |
65 | |
66 bool IsFormatAvailableInPickle(const string16& format, const Pickle& pickle) { | |
67 PickleIterator iter(pickle); | |
68 return JumpToFormatInPickle(format, &iter); | |
69 } | |
70 | |
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 ""; | |
dcheng
2012/10/29 20:26:29
std::string() is preferred over "".
raymes
2012/10/29 23:30:00
Done.
| |
76 return result; | |
77 } | |
78 | |
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; | |
88 } | |
89 return true; | |
90 } | |
91 | |
92 } // namespace | |
93 | |
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) { | |
100 } | |
101 | |
102 PepperFlashClipboardHost::~PepperFlashClipboardHost() { | |
103 } | |
104 | |
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; | |
123 } | |
124 | |
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; | |
134 } | |
135 | |
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; | |
143 } | |
144 | |
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; | |
155 } | |
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::GetWebCustomDataFormatType(), &clipboard_data); | |
172 Pickle pickle(clipboard_data.data(), clipboard_data.size()); | |
173 available = IsFormatAvailableInPickle(UTF8ToUTF16(format_name), pickle); | |
174 } | |
175 break; | |
176 } | |
177 | |
178 return available ? PP_OK : PP_ERROR_FAILED; | |
179 } | |
180 | |
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; | |
188 } | |
189 | |
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; | |
203 } | |
204 } | |
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); | |
211 } | |
212 break; | |
213 } | |
214 case PP_FLASH_CLIPBOARD_FORMAT_HTML: { | |
215 if (!clipboard_client_->IsFormatAvailable( | |
216 ui::Clipboard::GetHtmlFormatType(), buffer_type)) { | |
217 break; | |
218 } | |
219 | |
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; | |
230 } | |
231 case PP_FLASH_CLIPBOARD_FORMAT_RTF: { | |
232 if (!clipboard_client_->IsFormatAvailable( | |
233 ui::Clipboard::GetRtfFormatType(), buffer_type)) { | |
234 break; | |
235 } | |
236 result = PP_OK; | |
237 clipboard_client_->ReadRTF(buffer_type, &clipboard_string); | |
238 break; | |
239 } | |
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::GetWebCustomDataFormatType(), &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); | |
253 } | |
254 } | |
255 break; | |
256 } | |
257 } | |
258 | |
259 if (result == PP_OK) { | |
260 host_context->reply_msg = | |
261 PpapiPluginMsg_FlashClipboard_ReadDataReply(clipboard_string); | |
262 } | |
263 return result; | |
264 } | |
265 | |
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; | |
274 } | |
275 | |
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; | |
281 } | |
282 | |
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; | |
290 } | |
291 | |
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; | |
313 } | |
314 } | |
315 | |
316 if (res != PP_OK) | |
317 break; | |
318 } | |
319 | |
320 if (custom_data_map.size() > 0) { | |
321 Pickle pickle; | |
322 if (WriteDataToPickle(custom_data_map, &pickle)) { | |
323 scw.WritePickledData(pickle, | |
324 ui::Clipboard::GetWebCustomDataFormatType()); | |
325 } else { | |
326 res = PP_ERROR_BADARGUMENT; | |
327 } | |
328 } | |
329 | |
330 if (res != PP_OK) { | |
331 // Need to clear the objects so nothing is written. | |
332 scw.Reset(); | |
333 } | |
334 | |
335 return res; | |
336 } | |
337 | |
338 } // namespace content | |
339 | |
OLD | NEW |