OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/renderer_host/render_sandbox_host_linux.h" | 5 #include "chrome/browser/renderer_host/render_sandbox_host_linux.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <unistd.h> | 8 #include <unistd.h> |
| 9 #include <fcntl.h> |
9 #include <sys/uio.h> | 10 #include <sys/uio.h> |
10 #include <sys/socket.h> | 11 #include <sys/socket.h> |
11 #include <sys/poll.h> | 12 #include <sys/poll.h> |
12 #include <time.h> | 13 #include <time.h> |
13 | 14 |
14 #include <vector> | 15 #include <vector> |
15 | 16 |
16 #include "base/command_line.h" | 17 #include "base/command_line.h" |
17 #include "base/eintr_wrapper.h" | 18 #include "base/eintr_wrapper.h" |
18 #include "base/linux_util.h" | 19 #include "base/linux_util.h" |
19 #include "base/pickle.h" | 20 #include "base/pickle.h" |
20 #include "base/process_util.h" | 21 #include "base/process_util.h" |
21 #include "base/scoped_ptr.h" | 22 #include "base/scoped_ptr.h" |
22 #include "base/shared_memory.h" | 23 #include "base/shared_memory.h" |
23 #include "base/string_util.h" | 24 #include "base/string_util.h" |
24 #include "base/unix_domain_socket_posix.h" | 25 #include "base/unix_domain_socket_posix.h" |
25 #include "chrome/common/sandbox_methods_linux.h" | 26 #include "chrome/common/sandbox_methods_linux.h" |
26 #include "third_party/WebKit/WebKit/chromium/public/gtk/WebFontInfo.h" | 27 #include "third_party/WebKit/WebKit/chromium/public/gtk/WebFontInfo.h" |
27 | 28 |
28 #include "SkFontHost_fontconfig_direct.h" | 29 #include "SkFontHost_fontconfig_direct.h" |
29 #include "SkFontHost_fontconfig_ipc.h" | 30 #include "SkFontHost_fontconfig_ipc.h" |
30 | 31 |
| 32 #include <fontconfig/fontconfig.h> |
| 33 |
31 using WebKit::WebCString; | 34 using WebKit::WebCString; |
32 using WebKit::WebFontInfo; | 35 using WebKit::WebFontInfo; |
33 using WebKit::WebUChar; | 36 using WebKit::WebUChar; |
34 | 37 |
35 // http://code.google.com/p/chromium/wiki/LinuxSandboxIPC | 38 // http://code.google.com/p/chromium/wiki/LinuxSandboxIPC |
36 | 39 |
37 // BEWARE: code in this file run across *processes* (not just threads). | 40 // BEWARE: code in this file run across *processes* (not just threads). |
38 | 41 |
39 // This code runs in a child process | 42 // This code runs in a child process |
40 class SandboxIPCProcess { | 43 class SandboxIPCProcess { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 } else if (kind == LinuxSandbox::METHOD_GET_FONT_FAMILY_FOR_CHARS) { | 135 } else if (kind == LinuxSandbox::METHOD_GET_FONT_FAMILY_FOR_CHARS) { |
133 HandleGetFontFamilyForChars(fd, pickle, iter, fds); | 136 HandleGetFontFamilyForChars(fd, pickle, iter, fds); |
134 } else if (kind == LinuxSandbox::METHOD_LOCALTIME) { | 137 } else if (kind == LinuxSandbox::METHOD_LOCALTIME) { |
135 HandleLocaltime(fd, pickle, iter, fds); | 138 HandleLocaltime(fd, pickle, iter, fds); |
136 } else if (kind == LinuxSandbox::METHOD_GET_CHILD_WITH_INODE) { | 139 } else if (kind == LinuxSandbox::METHOD_GET_CHILD_WITH_INODE) { |
137 HandleGetChildWithInode(fd, pickle, iter, fds); | 140 HandleGetChildWithInode(fd, pickle, iter, fds); |
138 } else if (kind == LinuxSandbox::METHOD_GET_STYLE_FOR_STRIKE) { | 141 } else if (kind == LinuxSandbox::METHOD_GET_STYLE_FOR_STRIKE) { |
139 HandleGetStyleForStrike(fd, pickle, iter, fds); | 142 HandleGetStyleForStrike(fd, pickle, iter, fds); |
140 } else if (kind == LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT) { | 143 } else if (kind == LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT) { |
141 HandleMakeSharedMemorySegment(fd, pickle, iter, fds); | 144 HandleMakeSharedMemorySegment(fd, pickle, iter, fds); |
| 145 } else if (kind == LinuxSandbox::METHOD_MATCH_WITH_FALLBACK) { |
| 146 HandleMatchWithFallback(fd, pickle, iter, fds); |
142 } | 147 } |
143 | 148 |
144 error: | 149 error: |
145 for (std::vector<int>::const_iterator | 150 for (std::vector<int>::const_iterator |
146 i = fds.begin(); i != fds.end(); ++i) { | 151 i = fds.begin(); i != fds.end(); ++i) { |
147 close(*i); | 152 close(*i); |
148 } | 153 } |
149 } | 154 } |
150 | 155 |
151 void HandleFontMatchRequest(int fd, const Pickle& pickle, void* iter, | 156 void HandleFontMatchRequest(int fd, const Pickle& pickle, void* iter, |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 if (!pickle.ReadUInt32(&iter, &shm_size)) | 356 if (!pickle.ReadUInt32(&iter, &shm_size)) |
352 return; | 357 return; |
353 int shm_fd = -1; | 358 int shm_fd = -1; |
354 base::SharedMemory shm; | 359 base::SharedMemory shm; |
355 if (shm.Create(L"", false, false, shm_size)) | 360 if (shm.Create(L"", false, false, shm_size)) |
356 shm_fd = shm.handle().fd; | 361 shm_fd = shm.handle().fd; |
357 Pickle reply; | 362 Pickle reply; |
358 SendRendererReply(fds, reply, shm_fd); | 363 SendRendererReply(fds, reply, shm_fd); |
359 } | 364 } |
360 | 365 |
| 366 void HandleMatchWithFallback(int fd, const Pickle& pickle, void* iter, |
| 367 std::vector<int>& fds) { |
| 368 // Unlike the other calls, for which we are an indirection in front of |
| 369 // WebKit or Skia, this call is always made via this sandbox helper |
| 370 // process. Therefore the fontconfig code goes in here directly. |
| 371 |
| 372 std::string family; |
| 373 bool is_bold, is_italic; |
| 374 uint32 microsoft_charset; |
| 375 |
| 376 if (!pickle.ReadString(&iter, &family) || |
| 377 family.empty() || |
| 378 !pickle.ReadBool(&iter, &is_bold) || |
| 379 !pickle.ReadBool(&iter, &is_italic) || |
| 380 !pickle.ReadUInt32(&iter, µsoft_charset)) { |
| 381 return; |
| 382 } |
| 383 |
| 384 FcLangSet* langset = FcLangSetCreate(); |
| 385 MSCharSetToFontconfig(langset, microsoft_charset); |
| 386 |
| 387 FcPattern* pattern = FcPatternCreate(); |
| 388 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*) family.c_str()); |
| 389 if (is_bold) |
| 390 FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); |
| 391 if (is_italic) |
| 392 FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); |
| 393 FcPatternAddLangSet(pattern, FC_LANG, langset); |
| 394 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
| 395 FcConfigSubstitute(NULL, pattern, FcMatchPattern); |
| 396 FcDefaultSubstitute(pattern); |
| 397 |
| 398 FcResult result; |
| 399 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
| 400 int font_fd = -1; |
| 401 int good_enough_index = -1; |
| 402 bool good_enough_index_set = false; |
| 403 |
| 404 if (font_set) { |
| 405 for (int i = 0; i < font_set->nfont; ++i) { |
| 406 FcPattern* current = font_set->fonts[i]; |
| 407 |
| 408 // Older versions of fontconfig have a bug where they cannot select |
| 409 // only scalable fonts so we have to manually filter the results. |
| 410 FcBool is_scalable; |
| 411 if (FcPatternGetBool(current, FC_SCALABLE, 0, |
| 412 &is_scalable) != FcResultMatch || |
| 413 !is_scalable) { |
| 414 continue; |
| 415 } |
| 416 |
| 417 FcChar8* c_filename; |
| 418 if (FcPatternGetString(current, FC_FILE, 0, &c_filename) != FcResultMatc
h) |
| 419 continue; |
| 420 |
| 421 // We only want to return sfnt (TrueType) based fonts. We don't have a |
| 422 // very good way of detecting this so we'll filter based on the |
| 423 // filename. |
| 424 bool is_sfnt = false; |
| 425 static const char kSFNTExtensions[][5] = { |
| 426 ".ttf", ".otc", ".TTF", ".ttc", "" |
| 427 }; |
| 428 const size_t filename_len = strlen(reinterpret_cast<char*>(c_filename)); |
| 429 for (unsigned j = 0; ; j++) { |
| 430 if (kSFNTExtensions[j][0] == 0) { |
| 431 // None of the extensions matched. |
| 432 break; |
| 433 } |
| 434 const size_t ext_len = strlen(kSFNTExtensions[j]); |
| 435 if (filename_len > ext_len && |
| 436 memcmp(c_filename + filename_len - ext_len, |
| 437 kSFNTExtensions[j], ext_len) == 0) { |
| 438 is_sfnt = true; |
| 439 break; |
| 440 } |
| 441 } |
| 442 |
| 443 if (!is_sfnt) |
| 444 continue; |
| 445 |
| 446 // This font is good enough to pass muster, but we might be able to do |
| 447 // better with subsequent ones. |
| 448 if (!good_enough_index_set) { |
| 449 good_enough_index = i; |
| 450 good_enough_index_set = true; |
| 451 } |
| 452 |
| 453 FcValue matrix; |
| 454 bool have_matrix = FcPatternGet(current, FC_MATRIX, 0, &matrix) == 0; |
| 455 |
| 456 if (is_italic && have_matrix) { |
| 457 // we asked for an italic font, but fontconfig is giving us a |
| 458 // non-italic font with a transformation matrix. |
| 459 continue; |
| 460 } |
| 461 |
| 462 FcValue embolden; |
| 463 const bool have_embolden = |
| 464 FcPatternGet(current, FC_EMBOLDEN, 0, &embolden) == 0; |
| 465 |
| 466 if (is_bold && have_embolden) { |
| 467 // we asked for a bold font, but fontconfig gave us a non-bold font |
| 468 // and asked us to apply fake bolding. |
| 469 continue; |
| 470 } |
| 471 |
| 472 font_fd = open(reinterpret_cast<char*>(c_filename), O_RDONLY); |
| 473 if (font_fd >= 0) |
| 474 break; |
| 475 } |
| 476 } |
| 477 |
| 478 if (font_fd == -1 && good_enough_index_set) { |
| 479 // We didn't find a font that we liked, so we fallback to something |
| 480 // acceptable. |
| 481 FcPattern* current = font_set->fonts[good_enough_index]; |
| 482 FcChar8* c_filename; |
| 483 FcPatternGetString(current, FC_FILE, 0, &c_filename); |
| 484 font_fd = open(reinterpret_cast<char*>(c_filename), O_RDONLY); |
| 485 } |
| 486 |
| 487 if (font_set) |
| 488 FcFontSetDestroy(font_set); |
| 489 FcPatternDestroy(pattern); |
| 490 |
| 491 Pickle reply; |
| 492 SendRendererReply(fds, reply, font_fd); |
| 493 |
| 494 if (font_fd >= 0) |
| 495 HANDLE_EINTR(close(font_fd)); |
| 496 } |
| 497 |
| 498 // MSCharSetToFontconfig translates a Microsoft fdwCharSet value into a |
| 499 // fontconfig language set by appending to |langset|. |
| 500 static void MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) { |
| 501 // We have need to translate raw fdwCharSet values into terms that fontconfi
g |
| 502 // can understand. (See the description of fdwCharSet in the MSDN |
| 503 // documentation for CreateFont: |
| 504 // http://msdn.microsoft.com/en-us/library/dd183499(VS.85).aspx ) |
| 505 // |
| 506 // Although the argument is /called/ 'charset', the actual values conflate |
| 507 // character sets (which are sets of Unicode code points) and character |
| 508 // encodings (which are algorithms for turning a series of bits into a |
| 509 // series of code points.) Sometimes the values will name a language, |
| 510 // sometimes they'll name an encoding. In the latter case I'm assuming that |
| 511 // they mean the set of code points in the domain of that encoding. |
| 512 // |
| 513 // fontconfig deals with ISO 639-1 language codes: |
| 514 // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes |
| 515 // |
| 516 // So, for each of the documented fdwCharSet values I've had to take a |
| 517 // guess at the set of ISO 639-1 languages intended. |
| 518 // |
| 519 // Firstly, we need to know the raw integer values for the Microsoft |
| 520 // constants, which I'm taking from |
| 521 // http://www.microsoft.com/mspress/books/sampchap/2344b.aspx |
| 522 |
| 523 enum { |
| 524 ANSI_CHARSET = 0, |
| 525 DEFAULT_CHARSET = 1, |
| 526 SYMBOL_CHARSET = 2, |
| 527 MAC_CHARSET = 77, |
| 528 SHIFTJIS_CHARSET = 128, |
| 529 HANGUL_CHARSET = 129, |
| 530 JOHAB_CHARSET = 130, |
| 531 GB2312_CHARSET = 134, |
| 532 CHINESEBIG5_CHARSET = 136, |
| 533 GREEK_CHARSET = 161, |
| 534 TURKISH_CHARSET = 162, |
| 535 VIETNAMESE_CHARSET = 163, |
| 536 HEBREW_CHARSET = 177, |
| 537 ARABIC_CHARSET = 178, |
| 538 BALTIC_CHARSET = 186, |
| 539 RUSSIAN_CHARSET = 204, |
| 540 THAI_CHARSET = 222, |
| 541 EASTEUROPE_CHARSET = 238, |
| 542 OEM_CHARSET = 255, |
| 543 }; |
| 544 |
| 545 switch (fdwCharSet) { |
| 546 case ANSI_CHARSET: |
| 547 // These values I don't really know what to do with, so I'm going to map |
| 548 // them to English also. |
| 549 case DEFAULT_CHARSET: |
| 550 case MAC_CHARSET: |
| 551 case OEM_CHARSET: |
| 552 case SYMBOL_CHARSET: |
| 553 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en")); |
| 554 break; |
| 555 case BALTIC_CHARSET: |
| 556 // The three baltic languages. |
| 557 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et")); |
| 558 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv")); |
| 559 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt")); |
| 560 break; |
| 561 case CHINESEBIG5_CHARSET: |
| 562 case GB2312_CHARSET: |
| 563 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh")); |
| 564 break; |
| 565 case EASTEUROPE_CHARSET: |
| 566 // A scattering of eastern European languages. |
| 567 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl")); |
| 568 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs")); |
| 569 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk")); |
| 570 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu")); |
| 571 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr")); |
| 572 case GREEK_CHARSET: |
| 573 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el")); |
| 574 break; |
| 575 case HANGUL_CHARSET: |
| 576 case JOHAB_CHARSET: |
| 577 // Korean |
| 578 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko")); |
| 579 break; |
| 580 case RUSSIAN_CHARSET: |
| 581 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru")); |
| 582 break; |
| 583 case SHIFTJIS_CHARSET: |
| 584 // Japanese |
| 585 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("jp")); |
| 586 break; |
| 587 case TURKISH_CHARSET: |
| 588 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr")); |
| 589 break; |
| 590 case VIETNAMESE_CHARSET: |
| 591 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi")); |
| 592 break; |
| 593 case ARABIC_CHARSET: |
| 594 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar")); |
| 595 break; |
| 596 case HEBREW_CHARSET: |
| 597 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he")); |
| 598 break; |
| 599 case THAI_CHARSET: |
| 600 FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th")); |
| 601 break; |
| 602 // default: |
| 603 // Don't add any languages in that case that we don't recognise the |
| 604 // constant. |
| 605 } |
| 606 } |
| 607 |
361 void SendRendererReply(const std::vector<int>& fds, const Pickle& reply, | 608 void SendRendererReply(const std::vector<int>& fds, const Pickle& reply, |
362 int reply_fd) { | 609 int reply_fd) { |
363 struct msghdr msg; | 610 struct msghdr msg; |
364 memset(&msg, 0, sizeof(msg)); | 611 memset(&msg, 0, sizeof(msg)); |
365 struct iovec iov = {const_cast<void*>(reply.data()), reply.size()}; | 612 struct iovec iov = {const_cast<void*>(reply.data()), reply.size()}; |
366 msg.msg_iov = &iov; | 613 msg.msg_iov = &iov; |
367 msg.msg_iovlen = 1; | 614 msg.msg_iovlen = 1; |
368 | 615 |
369 char control_buffer[CMSG_SPACE(sizeof(int))]; | 616 char control_buffer[CMSG_SPACE(sizeof(int))]; |
370 | 617 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 } | 677 } |
431 | 678 |
432 RenderSandboxHostLinux::~RenderSandboxHostLinux() { | 679 RenderSandboxHostLinux::~RenderSandboxHostLinux() { |
433 if (init_) { | 680 if (init_) { |
434 if (HANDLE_EINTR(close(renderer_socket_)) < 0) | 681 if (HANDLE_EINTR(close(renderer_socket_)) < 0) |
435 PLOG(ERROR) << "close"; | 682 PLOG(ERROR) << "close"; |
436 if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) | 683 if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) |
437 PLOG(ERROR) << "close"; | 684 PLOG(ERROR) << "close"; |
438 } | 685 } |
439 } | 686 } |
OLD | NEW |