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