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 29 TestFlashClipboard::TestFlashClipboard(TestingInstance* instance) 30 : TestCase(instance) { 31 } 32 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 } 43 44 bool TestFlashClipboard::ReadStringVar(uint32_t format, std::string* result) { 45 pp::Var text; 46 bool success = pp::flash::Clipboard::ReadData( 47 instance_, 48 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 49 format, 50 &text); 51 if (success && text.is_string()) { 52 *result = text.AsString(); 53 return true; 54 } 55 return false; 56 } 57 58 bool TestFlashClipboard::WriteStringVar(uint32_t format, 59 const std::string& text) { 60 std::vector<uint32_t> formats_vector(1, format); 61 std::vector<pp::Var> data_vector(1, pp::Var(text)); 62 bool success = pp::flash::Clipboard::WriteData( 63 instance_, 64 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 65 formats_vector, 66 data_vector); 67 return success; 68 } 69 70 bool TestFlashClipboard::IsFormatAvailableMatches(uint32_t format, 71 bool expected) { 72 for (int i = 0; i < kMaxIntervals; ++i) { 73 bool is_available = pp::flash::Clipboard::IsFormatAvailable( 74 instance_, 75 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 76 format); 77 if (is_available == expected) 78 return true; 79 80 PlatformSleep(kIntervalMs); 81 } 82 return false; 83 } 84 85 bool TestFlashClipboard::ReadPlainTextMatches(const std::string& expected) { 86 for (int i = 0; i < kMaxIntervals; ++i) { 87 std::string result; 88 bool success = ReadStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, &result); 89 if (success && result == expected) 90 return true; 91 92 PlatformSleep(kIntervalMs); 93 } 94 return false; 95 } 96 97 bool TestFlashClipboard::ReadHTMLMatches(const std::string& expected) { 98 for (int i = 0; i < kMaxIntervals; ++i) { 99 std::string result; 100 bool success = ReadStringVar(PP_FLASH_CLIPBOARD_FORMAT_HTML, &result); 101 // Harmless markup may be inserted around the copied html on some 102 // platforms, so just check that the pasted string contains the 103 // copied string. Also check that we only paste the copied fragment, see 104 // http://code.google.com/p/chromium/issues/detail?id=130827. 105 if (success && result.find(expected) != std::string::npos && 106 result.find("<!--StartFragment-->") == std::string::npos && 107 result.find("<!--EndFragment-->") == std::string::npos) { 108 return true; 109 } 110 111 PlatformSleep(kIntervalMs); 112 } 113 return false; 114 } 115 116 std::string TestFlashClipboard::TestReadWritePlainText() { 117 std::string input = "Hello world plain text!"; 118 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, input)); 119 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, 120 true)); 121 ASSERT_TRUE(ReadPlainTextMatches(input)); 122 123 PASS(); 124 } 125 126 std::string TestFlashClipboard::TestReadWriteHTML() { 127 std::string input = "Hello world html!"; 128 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_HTML, input)); 129 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_HTML, true)); 130 ASSERT_TRUE(ReadHTMLMatches(input)); 131 132 PASS(); 133 } 134 135 std::string TestFlashClipboard::TestReadWriteRTF() { 136 std::string rtf_string = 137 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n" 138 "This is some {\\b bold} text.\\par\n" 139 "}"; 140 pp::VarArrayBuffer array_buffer(rtf_string.size()); 141 char* bytes = static_cast<char*>(array_buffer.Map()); 142 std::copy(rtf_string.data(), rtf_string.data() + rtf_string.size(), bytes); 143 std::vector<uint32_t> formats_vector(1, PP_FLASH_CLIPBOARD_FORMAT_RTF); 144 std::vector<pp::Var> data_vector(1, array_buffer); 145 ASSERT_TRUE(pp::flash::Clipboard::WriteData( 146 instance_, 147 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 148 formats_vector, 149 data_vector)); 150 151 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_RTF, true)); 152 153 pp::Var rtf_result; 154 ASSERT_TRUE(pp::flash::Clipboard::ReadData( 155 instance_, 156 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 157 PP_FLASH_CLIPBOARD_FORMAT_RTF, 158 &rtf_result)); 159 ASSERT_TRUE(rtf_result.is_array_buffer()); 160 pp::VarArrayBuffer array_buffer_result(rtf_result); 161 ASSERT_TRUE(array_buffer_result.ByteLength() == array_buffer.ByteLength()); 162 char* bytes_result = static_cast<char*>(array_buffer_result.Map()); 163 ASSERT_TRUE(std::equal(bytes, bytes + array_buffer.ByteLength(), 164 bytes_result)); 165 166 PASS(); 167 } 168 169 std::string TestFlashClipboard::TestReadWriteCustomData() { 170 std::string custom_data = "custom_data"; 171 pp::VarArrayBuffer array_buffer(custom_data.size()); 172 char* bytes = static_cast<char*>(array_buffer.Map()); 173 std::copy(custom_data.begin(), custom_data.end(), bytes); 174 uint32_t format_id = 175 pp::flash::Clipboard::RegisterCustomFormat(instance_, "my-format"); 176 ASSERT_NE(format_id, PP_FLASH_CLIPBOARD_FORMAT_INVALID); 177 178 std::vector<uint32_t> formats_vector(1, format_id); 179 std::vector<pp::Var> data_vector(1, array_buffer); 180 ASSERT_TRUE(pp::flash::Clipboard::WriteData( 181 instance_, 182 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 183 formats_vector, 184 data_vector)); 185 186 ASSERT_TRUE(IsFormatAvailableMatches(format_id, true)); 187 188 pp::Var custom_data_result; 189 ASSERT_TRUE(pp::flash::Clipboard::ReadData( 190 instance_, 191 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 192 format_id, 193 &custom_data_result)); 194 ASSERT_TRUE(custom_data_result.is_array_buffer()); 195 pp::VarArrayBuffer array_buffer_result(custom_data_result); 196 ASSERT_EQ(array_buffer_result.ByteLength(), array_buffer.ByteLength()); 197 char* bytes_result = static_cast<char*>(array_buffer_result.Map()); 198 ASSERT_TRUE(std::equal(bytes, bytes + array_buffer.ByteLength(), 199 bytes_result)); 200 201 PASS(); 202 } 203 204 std::string TestFlashClipboard::TestReadWriteMultipleFormats() { 205 std::vector<uint32_t> formats; 206 std::vector<pp::Var> data; 207 formats.push_back(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT); 208 data.push_back(pp::Var("plain text")); 209 formats.push_back(PP_FLASH_CLIPBOARD_FORMAT_HTML); 210 data.push_back(pp::Var("html")); 211 bool success = pp::flash::Clipboard::WriteData( 212 instance_, 213 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 214 formats, 215 data); 216 ASSERT_TRUE(success); 217 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, 218 true)); 219 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_HTML, true)); 220 ASSERT_TRUE(ReadPlainTextMatches(data[0].AsString())); 221 ASSERT_TRUE(ReadHTMLMatches(data[1].AsString())); 222 223 PASS(); 224 } 225 226 std::string TestFlashClipboard::TestClear() { 227 std::string input = "Hello world plain text!"; 228 ASSERT_TRUE(WriteStringVar(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, input)); 229 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, 230 true)); 231 bool success = pp::flash::Clipboard::WriteData( 232 instance_, 233 PP_FLASH_CLIPBOARD_TYPE_STANDARD, 234 std::vector<uint32_t>(), 235 std::vector<pp::Var>()); 236 ASSERT_TRUE(success); 237 ASSERT_TRUE(IsFormatAvailableMatches(PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT, 238 false)); 239 240 PASS(); 241 } 242 243 std::string TestFlashClipboard::TestInvalidFormat() { 244 uint32_t invalid_format = 999; 245 ASSERT_FALSE(WriteStringVar(invalid_format, "text")); 246 ASSERT_TRUE(IsFormatAvailableMatches(invalid_format, false)); 247 std::string unused; 248 ASSERT_FALSE(ReadStringVar(invalid_format, &unused)); 249 250 PASS(); 251 } 252 253 std::string TestFlashClipboard::TestRegisterCustomFormat() { 254 // Test an empty name is rejected. 255 uint32_t format_id = 256 pp::flash::Clipboard::RegisterCustomFormat(instance_, std::string()); 257 ASSERT_EQ(format_id, PP_FLASH_CLIPBOARD_FORMAT_INVALID); 258 259 // Test a valid format name. 260 format_id = pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b"); 261 ASSERT_NE(format_id, PP_FLASH_CLIPBOARD_FORMAT_INVALID); 262 // Make sure the format doesn't collide with predefined formats. 263 ASSERT_NE(format_id, PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT); 264 ASSERT_NE(format_id, PP_FLASH_CLIPBOARD_FORMAT_HTML); 265 ASSERT_NE(format_id, PP_FLASH_CLIPBOARD_FORMAT_RTF); 266 267 // Check that if the same name is registered, the same id comes out. 268 uint32_t format_id2 = 269 pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b"); 270 ASSERT_EQ(format_id, format_id2); 271 272 // Check that the second format registered has a different id. 273 uint32_t format_id3 = 274 pp::flash::Clipboard::RegisterCustomFormat(instance_, "a-b-c"); 275 ASSERT_NE(format_id, format_id3); 276 277 PASS(); 278 } 279