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 "ppapi/tests/test_flash_clipboard.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "ppapi/cpp/instance.h"
11 #include "ppapi/cpp/module.h"
12 #include "ppapi/cpp/point.h"
13 #include "ppapi/cpp/private/flash_clipboard.h"
14 #include "ppapi/cpp/var.h"
15 #include "ppapi/cpp/var_array_buffer.h"
16 #include "ppapi/tests/testing_instance.h"
17
18 // http://crbug.com/176822
19 #if !defined(OS_WIN)
20 REGISTER_TEST_CASE(FlashClipboard);
21 #endif
22
23 // WriteData() sends an async request to the browser process. As a result, the
24 // string written may not be reflected by IsFormatAvailable() or ReadPlainText()
25 // immediately. We need to wait and retry.
26 const int kIntervalMs = 250;
27 const int kMaxIntervals = kActionTimeoutMs / kIntervalMs;
28
TestFlashClipboard(TestingInstance * instance)29 TestFlashClipboard::TestFlashClipboard(TestingInstance* instance)
30 : TestCase(instance) {
31 }
32
RunTests(const std::string & filter)33 void TestFlashClipboard::RunTests(const std::string& filter) {
34 RUN_TEST(ReadWritePlainText, filter);
35 RUN_TEST(ReadWriteHTML, filter);
36 RUN_TEST(ReadWriteRTF, filter);
37 RUN_TEST(ReadWriteCustomData, filter);
38 RUN_TEST(ReadWriteMultipleFormats, filter);
39 RUN_TEST(Clear, filter);
40 RUN_TEST(InvalidFormat, filter);
41 RUN_TEST(RegisterCustomFormat, filter);
42 RUN_TEST(GetSequenceNumber, filter);
43 }
44
ReadStringVar(uint32_t format,std::string * result)45 bool TestFlashClipboard::ReadStringVar(uint32_t format, std::string* result) {
46 pp::Var text;
47 bool success = pp::flash::Clipboard::ReadData(
48 instance_,
49 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
50 format,
51 &text);
52 if (success && text.is_string()) {
53 *result = text.AsString();
54 return true;
55 }
56 return false;
57 }
58
WriteStringVar(uint32_t format,const std::string & text)59 bool TestFlashClipboard::WriteStringVar(uint32_t format,
60 const std::string& text) {
61 std::vector<uint32_t> formats_vector(1, format);
62 std::vector<pp::Var> data_vector(1, pp::Var(text));
63 bool success = pp::flash::Clipboard::WriteData(
64 instance_,
65 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
66 formats_vector,
67 data_vector);
68 return success;
69 }
70
IsFormatAvailableMatches(uint32_t format,bool expected)71 bool TestFlashClipboard::IsFormatAvailableMatches(uint32_t format,
72 bool expected) {
73 for (int i = 0; i < kMaxIntervals; ++i) {
74 bool is_available = pp::flash::Clipboard::IsFormatAvailable(
75 instance_,
76 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
77 format);
78 if (is_available == expected)
79 return true;
80
81 PlatformSleep(kIntervalMs);
82 }
83 return false;
84 }
85
ReadPlainTextMatches(const std::string & expected)86 bool TestFlashClipboard::ReadPlainTextMatches(const std::string& expected) {
87 for (int i = 0; i < kMaxIntervals; ++i) {
88 std::string result;
89 bool success = ReadStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, &result);
90 if (success && result == expected)
91 return true;
92
93 PlatformSleep(kIntervalMs);
94 }
95 return false;
96 }
97
ReadHTMLMatches(const std::string & expected)98 bool TestFlashClipboard::ReadHTMLMatches(const std::string& expected) {
99 for (int i = 0; i < kMaxIntervals; ++i) {
100 std::string result;
101 bool success = ReadStringVar(PP_FLASH_CLIPBOARD_FORMAT_HTML, &result);
102 // Harmless markup may be inserted around the copied html on some
103 // platforms, so just check that the pasted string contains the
104 // copied string. Also check that we only paste the copied fragment, see
105 // http://code.google.com/p/chromium/issues/detail?id=130827.
106 if (success && result.find(expected) != std::string::npos &&
107 result.find("<!--StartFragment-->") == std::string::npos &&
108 result.find("<!--EndFragment-->") == std::string::npos) {
109 return true;
110 }
111
112 PlatformSleep(kIntervalMs);
113 }
114 return false;
115 }
116
GetSequenceNumber(uint64_t last_sequence_number)117 uint64_t TestFlashClipboard::GetSequenceNumber(uint64_t last_sequence_number) {
118 uint64_t next_sequence_number = last_sequence_number;
119 for (int i = 0; i < kMaxIntervals; ++i) {
120 pp::flash::Clipboard::GetSequenceNumber(
121 instance_, PP_FLASH_CLIPBOARD_TYPE_STANDARD, &next_sequence_number);
122 if (next_sequence_number != last_sequence_number)
123 return next_sequence_number;
124
125 PlatformSleep(kIntervalMs);
126 }
127 return next_sequence_number;
128 }
129
TestReadWritePlainText()130 std::string TestFlashClipboard::TestReadWritePlainText() {
131 std::string input = "Hello world plain text!";
132 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, input));
133 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT,
134 true));
135 ASSERT_TRUE(ReadPlainTextMatches(input));
136
137 PASS();
138 }
139
TestReadWriteHTML()140 std::string TestFlashClipboard::TestReadWriteHTML() {
141 std::string input = "Hello world html!";
142 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_HTML, input));
143 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_HTML, true));
144 ASSERT_TRUE(ReadHTMLMatches(input));
145
146 PASS();
147 }
148
TestReadWriteRTF()149 std::string TestFlashClipboard::TestReadWriteRTF() {
150 std::string rtf_string =
151 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n"
152 "This is some {\\b bold} text.\\par\n"
153 "}";
154 pp::VarArrayBuffer array_buffer(rtf_string.size());
155 char* bytes = static_cast<char*>(array_buffer.Map());
156 std::copy(rtf_string.data(), rtf_string.data() + rtf_string.size(), bytes);
157 std::vector<uint32_t> formats_vector(1, PP_FLASH_CLIPBOARD_FORMAT_RTF);
158 std::vector<pp::Var> data_vector(1, array_buffer);
159 ASSERT_TRUE(pp::flash::Clipboard::WriteData(
160 instance_,
161 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
162 formats_vector,
163 data_vector));
164
165 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_RTF, true));
166
167 pp::Var rtf_result;
168 ASSERT_TRUE(pp::flash::Clipboard::ReadData(
169 instance_,
170 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
171 PP_FLASH_CLIPBOARD_FORMAT_RTF,
172 &rtf_result));
173 ASSERT_TRUE(rtf_result.is_array_buffer());
174 pp::VarArrayBuffer array_buffer_result(rtf_result);
175 ASSERT_TRUE(array_buffer_result.ByteLength() == array_buffer.ByteLength());
176 char* bytes_result = static_cast<char*>(array_buffer_result.Map());
177 ASSERT_TRUE(std::equal(bytes, bytes + array_buffer.ByteLength(),
178 bytes_result));
179
180 PASS();
181 }
182
TestReadWriteCustomData()183 std::string TestFlashClipboard::TestReadWriteCustomData() {
184 std::string custom_data = "custom_data";
185 pp::VarArrayBuffer array_buffer(custom_data.size());
186 char* bytes = static_cast<char*>(array_buffer.Map());
187 std::copy(custom_data.begin(), custom_data.end(), bytes);
188 uint32_t format_id =
189 pp::flash::Clipboard::RegisterCustomFormat(instance_, "my-format");
190 ASSERT_NE(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_INVALID),
191 format_id);
192
193 std::vector<uint32_t> formats_vector(1, format_id);
194 std::vector<pp::Var> data_vector(1, array_buffer);
195 ASSERT_TRUE(pp::flash::Clipboard::WriteData(
196 instance_,
197 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
198 formats_vector,
199 data_vector));
200
201 ASSERT_TRUE(IsFormatAvailableMatches(format_id, true));
202
203 pp::Var custom_data_result;
204 ASSERT_TRUE(pp::flash::Clipboard::ReadData(
205 instance_,
206 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
207 format_id,
208 &custom_data_result));
209 ASSERT_TRUE(custom_data_result.is_array_buffer());
210 pp::VarArrayBuffer array_buffer_result(custom_data_result);
211 ASSERT_EQ(array_buffer_result.ByteLength(), array_buffer.ByteLength());
212 char* bytes_result = static_cast<char*>(array_buffer_result.Map());
213 ASSERT_TRUE(std::equal(bytes, bytes + array_buffer.ByteLength(),
214 bytes_result));
215
216 PASS();
217 }
218
TestReadWriteMultipleFormats()219 std::string TestFlashClipboard::TestReadWriteMultipleFormats() {
220 std::vector<uint32_t> formats;
221 std::vector<pp::Var> data;
222 formats.push_back(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT);
223 data.push_back(pp::Var("plain text"));
224 formats.push_back(PP_FLASH_CLIPBOARD_FORMAT_HTML);
225 data.push_back(pp::Var("html"));
226 bool success = pp::flash::Clipboard::WriteData(
227 instance_,
228 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
229 formats,
230 data);
231 ASSERT_TRUE(success);
232 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT,
233 true));
234 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_HTML, true));
235 ASSERT_TRUE(ReadPlainTextMatches(data[0].AsString()));
236 ASSERT_TRUE(ReadHTMLMatches(data[1].AsString()));
237
238 PASS();
239 }
240
TestClear()241 std::string TestFlashClipboard::TestClear() {
242 std::string input = "Hello world plain text!";
243 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, input));
244 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT,
245 true));
246 bool success = pp::flash::Clipboard::WriteData(
247 instance_,
248 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
249 std::vector<uint32_t>(),
250 std::vector<pp::Var>());
251 ASSERT_TRUE(success);
252 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT,
253 false));
254
255 PASS();
256 }
257
TestInvalidFormat()258 std::string TestFlashClipboard::TestInvalidFormat() {
259 uint32_t invalid_format = 999;
260 ASSERT_FALSE(WriteStringVar(invalid_format, "text"));
261 ASSERT_TRUE(IsFormatAvailableMatches(invalid_format, false));
262 std::string unused;
263 ASSERT_FALSE(ReadStringVar(invalid_format, &unused));
264
265 PASS();
266 }
267
TestRegisterCustomFormat()268 std::string TestFlashClipboard::TestRegisterCustomFormat() {
269 // Test an empty name is rejected.
270 uint32_t format_id =
271 pp::flash::Clipboard::RegisterCustomFormat(instance_, std::string());
272 ASSERT_EQ(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_INVALID),
273 format_id);
274
275 // Test a valid format name.
276 format_id = pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b");
277 ASSERT_NE(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_INVALID),
278 format_id);
279 // Make sure the format doesn't collide with predefined formats.
280 ASSERT_NE(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT),
281 format_id);
282 ASSERT_NE(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_HTML),
283 format_id);
284 ASSERT_NE(static_cast<uint32_t>(PP_FLASH_CLIPBOARD_FORMAT_RTF),
285 format_id);
286
287 // Check that if the same name is registered, the same id comes out.
288 uint32_t format_id2 =
289 pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b");
290 ASSERT_EQ(format_id, format_id2);
291
292 // Check that the second format registered has a different id.
293 uint32_t format_id3 =
294 pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b-c");
295 ASSERT_NE(format_id, format_id3);
296
297 PASS();
298 }
299
TestGetSequenceNumber()300 std::string TestFlashClipboard::TestGetSequenceNumber() {
301 uint64_t sequence_number_before = 0;
302 uint64_t sequence_number_after = 0;
303 ASSERT_TRUE(pp::flash::Clipboard::GetSequenceNumber(
304 instance_, PP_FLASH_CLIPBOARD_TYPE_STANDARD, &sequence_number_before));
305
306 // Test the sequence number changes after writing html.
307 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_HTML, "<html>"));
308 sequence_number_after = GetSequenceNumber(sequence_number_before);
309 ASSERT_NE(sequence_number_before, sequence_number_after);
310 sequence_number_before = sequence_number_after;
311
312 // Test the sequence number changes after writing some custom data.
313 std::string custom_data = "custom_data";
314 pp::VarArrayBuffer array_buffer(custom_data.size());
315 char* bytes = static_cast<char*>(array_buffer.Map());
316 std::copy(custom_data.begin(), custom_data.end(), bytes);
317 uint32_t format_id =
318 pp::flash::Clipboard::RegisterCustomFormat(instance_, "my-format");
319 std::vector<uint32_t> formats_vector(1, format_id);
320 std::vector<pp::Var> data_vector(1, array_buffer);
321 ASSERT_TRUE(pp::flash::Clipboard::WriteData(instance_,
322 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
323 formats_vector,
324 data_vector));
325 sequence_number_after = GetSequenceNumber(sequence_number_before);
326 ASSERT_NE(sequence_number_before, sequence_number_after);
327 sequence_number_before = sequence_number_after;
328
329 // Read the data and make sure the sequence number doesn't change.
330 pp::Var custom_data_result;
331 ASSERT_TRUE(pp::flash::Clipboard::ReadData(
332 instance_,
333 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
334 format_id,
335 &custom_data_result));
336 ASSERT_TRUE(pp::flash::Clipboard::GetSequenceNumber(
337 instance_, PP_FLASH_CLIPBOARD_TYPE_STANDARD, &sequence_number_after));
338 ASSERT_EQ(sequence_number_before, sequence_number_after);
339 sequence_number_before = sequence_number_after;
340
341 // Clear the clipboard and check the sequence number changes.
342 pp::flash::Clipboard::WriteData(instance_,
343 PP_FLASH_CLIPBOARD_TYPE_STANDARD,
344 std::vector<uint32_t>(),
345 std::vector<pp::Var>());
346 sequence_number_after = GetSequenceNumber(sequence_number_before);
347 ASSERT_NE(sequence_number_before, sequence_number_after);
348
349 PASS();
350 }
351