| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | 5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 | 297 |
| 298 // Verify decoding at an offset, to detect unaligned memory access. | 298 // Verify decoding at an offset, to detect unaligned memory access. |
| 299 v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0)); | 299 v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0)); |
| 300 slice = StringPiece(&*v.begin() + 1, v.size() - 1); | 300 slice = StringPiece(&*v.begin() + 1, v.size() - 1); |
| 301 EXPECT_TRUE(DecodeVarInt(&slice, &res)); | 301 EXPECT_TRUE(DecodeVarInt(&slice, &res)); |
| 302 EXPECT_EQ(n, res); | 302 EXPECT_EQ(n, res); |
| 303 EXPECT_TRUE(slice.empty()); | 303 EXPECT_TRUE(slice.empty()); |
| 304 } | 304 } |
| 305 } | 305 } |
| 306 | 306 |
| 307 static std::string WrappedEncodeString(string16 value) { | 307 static std::string WrappedEncodeString(base::string16 value) { |
| 308 std::string buffer; | 308 std::string buffer; |
| 309 EncodeString(value, &buffer); | 309 EncodeString(value, &buffer); |
| 310 return buffer; | 310 return buffer; |
| 311 } | 311 } |
| 312 | 312 |
| 313 TEST(IndexedDBLevelDBCodingTest, EncodeString) { | 313 TEST(IndexedDBLevelDBCodingTest, EncodeString) { |
| 314 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; | 314 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; |
| 315 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; | 315 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; |
| 316 | 316 |
| 317 EXPECT_EQ(static_cast<size_t>(0), | 317 EXPECT_EQ(static_cast<size_t>(0), |
| 318 WrappedEncodeString(ASCIIToUTF16("")).size()); | 318 WrappedEncodeString(ASCIIToUTF16("")).size()); |
| 319 EXPECT_EQ(static_cast<size_t>(2), | 319 EXPECT_EQ(static_cast<size_t>(2), |
| 320 WrappedEncodeString(ASCIIToUTF16("a")).size()); | 320 WrappedEncodeString(ASCIIToUTF16("a")).size()); |
| 321 EXPECT_EQ(static_cast<size_t>(6), | 321 EXPECT_EQ(static_cast<size_t>(6), |
| 322 WrappedEncodeString(ASCIIToUTF16("foo")).size()); | 322 WrappedEncodeString(ASCIIToUTF16("foo")).size()); |
| 323 EXPECT_EQ(static_cast<size_t>(6), | 323 EXPECT_EQ(static_cast<size_t>(6), |
| 324 WrappedEncodeString(string16(test_string_a)).size()); | 324 WrappedEncodeString(base::string16(test_string_a)).size()); |
| 325 EXPECT_EQ(static_cast<size_t>(4), | 325 EXPECT_EQ(static_cast<size_t>(4), |
| 326 WrappedEncodeString(string16(test_string_b)).size()); | 326 WrappedEncodeString(base::string16(test_string_b)).size()); |
| 327 } | 327 } |
| 328 | 328 |
| 329 TEST(IndexedDBLevelDBCodingTest, DecodeString) { | 329 TEST(IndexedDBLevelDBCodingTest, DecodeString) { |
| 330 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; | 330 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; |
| 331 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; | 331 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; |
| 332 | 332 |
| 333 std::vector<string16> test_cases; | 333 std::vector<base::string16> test_cases; |
| 334 test_cases.push_back(string16()); | 334 test_cases.push_back(base::string16()); |
| 335 test_cases.push_back(ASCIIToUTF16("a")); | 335 test_cases.push_back(ASCIIToUTF16("a")); |
| 336 test_cases.push_back(ASCIIToUTF16("foo")); | 336 test_cases.push_back(ASCIIToUTF16("foo")); |
| 337 test_cases.push_back(test_string_a); | 337 test_cases.push_back(test_string_a); |
| 338 test_cases.push_back(test_string_b); | 338 test_cases.push_back(test_string_b); |
| 339 | 339 |
| 340 for (size_t i = 0; i < test_cases.size(); ++i) { | 340 for (size_t i = 0; i < test_cases.size(); ++i) { |
| 341 const string16& test_case = test_cases[i]; | 341 const base::string16& test_case = test_cases[i]; |
| 342 std::string v = WrappedEncodeString(test_case); | 342 std::string v = WrappedEncodeString(test_case); |
| 343 | 343 |
| 344 StringPiece slice; | 344 StringPiece slice; |
| 345 if (v.size()) { | 345 if (v.size()) { |
| 346 slice = StringPiece(&*v.begin(), v.size()); | 346 slice = StringPiece(&*v.begin(), v.size()); |
| 347 } | 347 } |
| 348 | 348 |
| 349 string16 result; | 349 base::string16 result; |
| 350 EXPECT_TRUE(DecodeString(&slice, &result)); | 350 EXPECT_TRUE(DecodeString(&slice, &result)); |
| 351 EXPECT_EQ(test_case, result); | 351 EXPECT_EQ(test_case, result); |
| 352 EXPECT_TRUE(slice.empty()); | 352 EXPECT_TRUE(slice.empty()); |
| 353 | 353 |
| 354 // Verify decoding at an offset, to detect unaligned memory access. | 354 // Verify decoding at an offset, to detect unaligned memory access. |
| 355 v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0)); | 355 v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0)); |
| 356 slice = StringPiece(&*v.begin() + 1, v.size() - 1); | 356 slice = StringPiece(&*v.begin() + 1, v.size() - 1); |
| 357 EXPECT_TRUE(DecodeString(&slice, &result)); | 357 EXPECT_TRUE(DecodeString(&slice, &result)); |
| 358 EXPECT_EQ(test_case, result); | 358 EXPECT_EQ(test_case, result); |
| 359 EXPECT_TRUE(slice.empty()); | 359 EXPECT_TRUE(slice.empty()); |
| 360 } | 360 } |
| 361 } | 361 } |
| 362 | 362 |
| 363 static std::string WrappedEncodeStringWithLength(string16 value) { | 363 static std::string WrappedEncodeStringWithLength(base::string16 value) { |
| 364 std::string buffer; | 364 std::string buffer; |
| 365 EncodeStringWithLength(value, &buffer); | 365 EncodeStringWithLength(value, &buffer); |
| 366 return buffer; | 366 return buffer; |
| 367 } | 367 } |
| 368 | 368 |
| 369 TEST(IndexedDBLevelDBCodingTest, EncodeStringWithLength) { | 369 TEST(IndexedDBLevelDBCodingTest, EncodeStringWithLength) { |
| 370 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; | 370 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; |
| 371 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; | 371 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; |
| 372 | 372 |
| 373 EXPECT_EQ(static_cast<size_t>(1), | 373 EXPECT_EQ(static_cast<size_t>(1), |
| 374 WrappedEncodeStringWithLength(string16()).size()); | 374 WrappedEncodeStringWithLength(base::string16()).size()); |
| 375 EXPECT_EQ(static_cast<size_t>(3), | 375 EXPECT_EQ(static_cast<size_t>(3), |
| 376 WrappedEncodeStringWithLength(ASCIIToUTF16("a")).size()); | 376 WrappedEncodeStringWithLength(ASCIIToUTF16("a")).size()); |
| 377 EXPECT_EQ(static_cast<size_t>(7), | 377 EXPECT_EQ(static_cast<size_t>(7), |
| 378 WrappedEncodeStringWithLength(string16(test_string_a)).size()); | 378 WrappedEncodeStringWithLength( |
| 379 base::string16(test_string_a)).size()); |
| 379 EXPECT_EQ(static_cast<size_t>(5), | 380 EXPECT_EQ(static_cast<size_t>(5), |
| 380 WrappedEncodeStringWithLength(string16(test_string_b)).size()); | 381 WrappedEncodeStringWithLength( |
| 382 base::string16(test_string_b)).size()); |
| 381 } | 383 } |
| 382 | 384 |
| 383 TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) { | 385 TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) { |
| 384 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; | 386 const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; |
| 385 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; | 387 const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; |
| 386 | 388 |
| 387 const int kLongStringLen = 1234; | 389 const int kLongStringLen = 1234; |
| 388 char16 long_string[kLongStringLen + 1]; | 390 char16 long_string[kLongStringLen + 1]; |
| 389 for (int i = 0; i < kLongStringLen; ++i) | 391 for (int i = 0; i < kLongStringLen; ++i) |
| 390 long_string[i] = i; | 392 long_string[i] = i; |
| 391 long_string[kLongStringLen] = 0; | 393 long_string[kLongStringLen] = 0; |
| 392 | 394 |
| 393 std::vector<string16> test_cases; | 395 std::vector<base::string16> test_cases; |
| 394 test_cases.push_back(ASCIIToUTF16("")); | 396 test_cases.push_back(ASCIIToUTF16("")); |
| 395 test_cases.push_back(ASCIIToUTF16("a")); | 397 test_cases.push_back(ASCIIToUTF16("a")); |
| 396 test_cases.push_back(ASCIIToUTF16("foo")); | 398 test_cases.push_back(ASCIIToUTF16("foo")); |
| 397 test_cases.push_back(string16(test_string_a)); | 399 test_cases.push_back(base::string16(test_string_a)); |
| 398 test_cases.push_back(string16(test_string_b)); | 400 test_cases.push_back(base::string16(test_string_b)); |
| 399 test_cases.push_back(string16(long_string)); | 401 test_cases.push_back(base::string16(long_string)); |
| 400 | 402 |
| 401 for (size_t i = 0; i < test_cases.size(); ++i) { | 403 for (size_t i = 0; i < test_cases.size(); ++i) { |
| 402 string16 s = test_cases[i]; | 404 base::string16 s = test_cases[i]; |
| 403 std::string v = WrappedEncodeStringWithLength(s); | 405 std::string v = WrappedEncodeStringWithLength(s); |
| 404 ASSERT_GT(v.size(), static_cast<size_t>(0)); | 406 ASSERT_GT(v.size(), static_cast<size_t>(0)); |
| 405 StringPiece slice(v); | 407 StringPiece slice(v); |
| 406 string16 res; | 408 base::string16 res; |
| 407 EXPECT_TRUE(DecodeStringWithLength(&slice, &res)); | 409 EXPECT_TRUE(DecodeStringWithLength(&slice, &res)); |
| 408 EXPECT_EQ(s, res); | 410 EXPECT_EQ(s, res); |
| 409 EXPECT_TRUE(slice.empty()); | 411 EXPECT_TRUE(slice.empty()); |
| 410 | 412 |
| 411 slice = StringPiece(&*v.begin(), v.size() - 1); | 413 slice = StringPiece(&*v.begin(), v.size() - 1); |
| 412 EXPECT_FALSE(DecodeStringWithLength(&slice, &res)); | 414 EXPECT_FALSE(DecodeStringWithLength(&slice, &res)); |
| 413 | 415 |
| 414 slice = StringPiece(&*v.begin(), static_cast<size_t>(0)); | 416 slice = StringPiece(&*v.begin(), static_cast<size_t>(0)); |
| 415 EXPECT_FALSE(DecodeStringWithLength(&slice, &res)); | 417 EXPECT_FALSE(DecodeStringWithLength(&slice, &res)); |
| 416 | 418 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 437 } | 439 } |
| 438 | 440 |
| 439 TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) { | 441 TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) { |
| 440 const char16 test_string_a[] = {0x1000, 0x1000, '\0'}; | 442 const char16 test_string_a[] = {0x1000, 0x1000, '\0'}; |
| 441 const char16 test_string_b[] = {0x1000, 0x1000, 0x1000, '\0'}; | 443 const char16 test_string_b[] = {0x1000, 0x1000, 0x1000, '\0'}; |
| 442 const char16 test_string_c[] = {0x1000, 0x1000, 0x1001, '\0'}; | 444 const char16 test_string_c[] = {0x1000, 0x1000, 0x1001, '\0'}; |
| 443 const char16 test_string_d[] = {0x1001, 0x1000, 0x1000, '\0'}; | 445 const char16 test_string_d[] = {0x1001, 0x1000, 0x1000, '\0'}; |
| 444 const char16 test_string_e[] = {0xd834, 0xdd1e, '\0'}; | 446 const char16 test_string_e[] = {0xd834, 0xdd1e, '\0'}; |
| 445 const char16 test_string_f[] = {0xfffd, '\0'}; | 447 const char16 test_string_f[] = {0xfffd, '\0'}; |
| 446 | 448 |
| 447 std::vector<string16> test_cases; | 449 std::vector<base::string16> test_cases; |
| 448 test_cases.push_back(ASCIIToUTF16("")); | 450 test_cases.push_back(ASCIIToUTF16("")); |
| 449 test_cases.push_back(ASCIIToUTF16("a")); | 451 test_cases.push_back(ASCIIToUTF16("a")); |
| 450 test_cases.push_back(ASCIIToUTF16("b")); | 452 test_cases.push_back(ASCIIToUTF16("b")); |
| 451 test_cases.push_back(ASCIIToUTF16("baaa")); | 453 test_cases.push_back(ASCIIToUTF16("baaa")); |
| 452 test_cases.push_back(ASCIIToUTF16("baab")); | 454 test_cases.push_back(ASCIIToUTF16("baab")); |
| 453 test_cases.push_back(ASCIIToUTF16("c")); | 455 test_cases.push_back(ASCIIToUTF16("c")); |
| 454 test_cases.push_back(string16(test_string_a)); | 456 test_cases.push_back(base::string16(test_string_a)); |
| 455 test_cases.push_back(string16(test_string_b)); | 457 test_cases.push_back(base::string16(test_string_b)); |
| 456 test_cases.push_back(string16(test_string_c)); | 458 test_cases.push_back(base::string16(test_string_c)); |
| 457 test_cases.push_back(string16(test_string_d)); | 459 test_cases.push_back(base::string16(test_string_d)); |
| 458 test_cases.push_back(string16(test_string_e)); | 460 test_cases.push_back(base::string16(test_string_e)); |
| 459 test_cases.push_back(string16(test_string_f)); | 461 test_cases.push_back(base::string16(test_string_f)); |
| 460 | 462 |
| 461 for (size_t i = 0; i < test_cases.size() - 1; ++i) { | 463 for (size_t i = 0; i < test_cases.size() - 1; ++i) { |
| 462 string16 a = test_cases[i]; | 464 base::string16 a = test_cases[i]; |
| 463 string16 b = test_cases[i + 1]; | 465 base::string16 b = test_cases[i + 1]; |
| 464 | 466 |
| 465 EXPECT_LT(a.compare(b), 0); | 467 EXPECT_LT(a.compare(b), 0); |
| 466 EXPECT_GT(b.compare(a), 0); | 468 EXPECT_GT(b.compare(a), 0); |
| 467 EXPECT_EQ(a.compare(a), 0); | 469 EXPECT_EQ(a.compare(a), 0); |
| 468 EXPECT_EQ(b.compare(b), 0); | 470 EXPECT_EQ(b.compare(b), 0); |
| 469 | 471 |
| 470 std::string encoded_a = WrappedEncodeStringWithLength(a); | 472 std::string encoded_a = WrappedEncodeStringWithLength(a); |
| 471 EXPECT_TRUE(encoded_a.size()); | 473 EXPECT_TRUE(encoded_a.size()); |
| 472 std::string encoded_b = WrappedEncodeStringWithLength(b); | 474 std::string encoded_b = WrappedEncodeStringWithLength(b); |
| 473 EXPECT_TRUE(encoded_a.size()); | 475 EXPECT_TRUE(encoded_a.size()); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 { | 625 { |
| 624 key_paths.push_back(IndexedDBKeyPath()); | 626 key_paths.push_back(IndexedDBKeyPath()); |
| 625 char expected[] = {0, 0, // Header | 627 char expected[] = {0, 0, // Header |
| 626 0 // Type is null | 628 0 // Type is null |
| 627 }; | 629 }; |
| 628 encoded_paths.push_back( | 630 encoded_paths.push_back( |
| 629 std::string(expected, expected + arraysize(expected))); | 631 std::string(expected, expected + arraysize(expected))); |
| 630 } | 632 } |
| 631 | 633 |
| 632 { | 634 { |
| 633 key_paths.push_back(IndexedDBKeyPath(string16())); | 635 key_paths.push_back(IndexedDBKeyPath(base::string16())); |
| 634 char expected[] = {0, 0, // Header | 636 char expected[] = {0, 0, // Header |
| 635 1, // Type is string | 637 1, // Type is string |
| 636 0 // Length is 0 | 638 0 // Length is 0 |
| 637 }; | 639 }; |
| 638 encoded_paths.push_back( | 640 encoded_paths.push_back( |
| 639 std::string(expected, expected + arraysize(expected))); | 641 std::string(expected, expected + arraysize(expected))); |
| 640 } | 642 } |
| 641 | 643 |
| 642 { | 644 { |
| 643 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo"))); | 645 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo"))); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 654 char expected[] = {0, 0, // Header | 656 char expected[] = {0, 0, // Header |
| 655 1, // Type is string | 657 1, // Type is string |
| 656 7, 0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, | 658 7, 0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, |
| 657 'r' // String length 7, UTF-16BE | 659 'r' // String length 7, UTF-16BE |
| 658 }; | 660 }; |
| 659 encoded_paths.push_back( | 661 encoded_paths.push_back( |
| 660 std::string(expected, expected + arraysize(expected))); | 662 std::string(expected, expected + arraysize(expected))); |
| 661 } | 663 } |
| 662 | 664 |
| 663 { | 665 { |
| 664 std::vector<string16> array; | 666 std::vector<base::string16> array; |
| 665 array.push_back(string16()); | 667 array.push_back(base::string16()); |
| 666 array.push_back(ASCIIToUTF16("foo")); | 668 array.push_back(ASCIIToUTF16("foo")); |
| 667 array.push_back(ASCIIToUTF16("foo.bar")); | 669 array.push_back(ASCIIToUTF16("foo.bar")); |
| 668 | 670 |
| 669 key_paths.push_back(IndexedDBKeyPath(array)); | 671 key_paths.push_back(IndexedDBKeyPath(array)); |
| 670 char expected[] = {0, 0, // Header | 672 char expected[] = {0, 0, // Header |
| 671 2, 3, // Type is array, length is 3 | 673 2, 3, // Type is array, length is 3 |
| 672 0, // Member 1 (String length 0) | 674 0, // Member 1 (String length 0) |
| 673 3, 0, 'f', 0, 'o', 0, 'o', // Member 2 (String length 3) | 675 3, 0, 'f', 0, 'o', 0, 'o', // Member 2 (String length 3) |
| 674 7, 0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, | 676 7, 0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, |
| 675 'r' // Member 3 (String length 7) | 677 'r' // Member 3 (String length 7) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 693 EXPECT_TRUE(slice.empty()); | 695 EXPECT_TRUE(slice.empty()); |
| 694 } | 696 } |
| 695 } | 697 } |
| 696 | 698 |
| 697 TEST(IndexedDBLevelDBCodingTest, DecodeLegacyIDBKeyPath) { | 699 TEST(IndexedDBLevelDBCodingTest, DecodeLegacyIDBKeyPath) { |
| 698 // Legacy encoding of string key paths. | 700 // Legacy encoding of string key paths. |
| 699 std::vector<IndexedDBKeyPath> key_paths; | 701 std::vector<IndexedDBKeyPath> key_paths; |
| 700 std::vector<std::string> encoded_paths; | 702 std::vector<std::string> encoded_paths; |
| 701 | 703 |
| 702 { | 704 { |
| 703 key_paths.push_back(IndexedDBKeyPath(string16())); | 705 key_paths.push_back(IndexedDBKeyPath(base::string16())); |
| 704 encoded_paths.push_back(std::string()); | 706 encoded_paths.push_back(std::string()); |
| 705 } | 707 } |
| 706 { | 708 { |
| 707 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo"))); | 709 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo"))); |
| 708 char expected[] = {0, 'f', 0, 'o', 0, 'o'}; | 710 char expected[] = {0, 'f', 0, 'o', 0, 'o'}; |
| 709 encoded_paths.push_back(std::string(expected, arraysize(expected))); | 711 encoded_paths.push_back(std::string(expected, arraysize(expected))); |
| 710 } | 712 } |
| 711 { | 713 { |
| 712 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo.bar"))); | 714 key_paths.push_back(IndexedDBKeyPath(ASCIIToUTF16("foo.bar"))); |
| 713 char expected[] = {0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, 'r'}; | 715 char expected[] = {0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 'b', 0, 'a', 0, 'r'}; |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 std::string vB = WrappedEncodeVarInt(static_cast<int64>(n)); | 913 std::string vB = WrappedEncodeVarInt(static_cast<int64>(n)); |
| 912 | 914 |
| 913 EXPECT_EQ(vA.size(), vB.size()); | 915 EXPECT_EQ(vA.size(), vB.size()); |
| 914 EXPECT_EQ(*vA.begin(), *vB.begin()); | 916 EXPECT_EQ(*vA.begin(), *vB.begin()); |
| 915 } | 917 } |
| 916 } | 918 } |
| 917 | 919 |
| 918 } // namespace | 920 } // namespace |
| 919 | 921 |
| 920 } // namespace content | 922 } // namespace content |
| OLD | NEW |