| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/renderer_host/render_sandbox_host_linux.h" | 5 #include "content/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 <fontconfig/fontconfig.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 #include <sys/poll.h> | 10 #include <sys/poll.h> |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "base/pickle.h" | 23 #include "base/pickle.h" |
| 24 #include "base/posix/eintr_wrapper.h" | 24 #include "base/posix/eintr_wrapper.h" |
| 25 #include "base/posix/unix_domain_socket_linux.h" | 25 #include "base/posix/unix_domain_socket_linux.h" |
| 26 #include "base/process_util.h" | 26 #include "base/process_util.h" |
| 27 #include "base/shared_memory.h" | 27 #include "base/shared_memory.h" |
| 28 #include "base/string_number_conversions.h" | 28 #include "base/string_number_conversions.h" |
| 29 #include "base/string_util.h" | 29 #include "base/string_util.h" |
| 30 #include "content/common/font_config_ipc_linux.h" | 30 #include "content/common/font_config_ipc_linux.h" |
| 31 #include "content/common/sandbox_linux.h" | 31 #include "content/common/sandbox_linux.h" |
| 32 #include "content/common/webkitplatformsupport_impl.h" | 32 #include "content/common/webkitplatformsupport_impl.h" |
| 33 #include "skia/ext/skia_utils_base.h" | 33 #include "skia/ext/SkFontHost_fontconfig_direct.h" |
| 34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" | 34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" |
| 35 #include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontInfo.h" | 35 #include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontInfo.h" |
| 36 #include "third_party/npapi/bindings/npapi_extensions.h" | 36 #include "third_party/npapi/bindings/npapi_extensions.h" |
| 37 #include "third_party/skia/include/ports/SkFontConfigInterface.h" | |
| 38 #include "ui/gfx/font_render_params_linux.h" | 37 #include "ui/gfx/font_render_params_linux.h" |
| 39 | 38 |
| 40 using WebKit::WebCString; | 39 using WebKit::WebCString; |
| 41 using WebKit::WebFontInfo; | 40 using WebKit::WebFontInfo; |
| 42 using WebKit::WebUChar; | 41 using WebKit::WebUChar; |
| 43 | 42 |
| 44 namespace content { | 43 namespace content { |
| 45 | 44 |
| 46 // http://code.google.com/p/chromium/wiki/LinuxSandboxIPC | 45 // http://code.google.com/p/chromium/wiki/LinuxSandboxIPC |
| 47 | 46 |
| 48 // BEWARE: code in this file run across *processes* (not just threads). | 47 // BEWARE: code in this file run across *processes* (not just threads). |
| 49 | 48 |
| 50 // This code runs in a child process | 49 // This code runs in a child process |
| 51 class SandboxIPCProcess { | 50 class SandboxIPCProcess { |
| 52 public: | 51 public: |
| 53 // lifeline_fd: this is the read end of a pipe which the browser process | 52 // lifeline_fd: this is the read end of a pipe which the browser process |
| 54 // holds the other end of. If the browser process dies, its descriptors are | 53 // holds the other end of. If the browser process dies, its descriptors are |
| 55 // closed and we will noticed an EOF on the pipe. That's our signal to exit. | 54 // closed and we will noticed an EOF on the pipe. That's our signal to exit. |
| 56 // browser_socket: the browser's end of the sandbox IPC socketpair. From the | 55 // browser_socket: the browser's end of the sandbox IPC socketpair. From the |
| 57 // point of view of the renderer, it's talking to the browser but this | 56 // point of view of the renderer, it's talking to the browser but this |
| 58 // object actually services the requests. | 57 // object actually services the requests. |
| 59 // sandbox_cmd: the path of the sandbox executable | 58 // sandbox_cmd: the path of the sandbox executable |
| 60 SandboxIPCProcess(int lifeline_fd, int browser_socket, | 59 SandboxIPCProcess(int lifeline_fd, int browser_socket, |
| 61 std::string sandbox_cmd) | 60 std::string sandbox_cmd) |
| 62 : lifeline_fd_(lifeline_fd), | 61 : lifeline_fd_(lifeline_fd), |
| 63 browser_socket_(browser_socket) { | 62 browser_socket_(browser_socket), |
| 63 font_config_(new FontConfigDirect()) { |
| 64 if (!sandbox_cmd.empty()) { | 64 if (!sandbox_cmd.empty()) { |
| 65 sandbox_cmd_.push_back(sandbox_cmd); | 65 sandbox_cmd_.push_back(sandbox_cmd); |
| 66 sandbox_cmd_.push_back(base::kFindInodeSwitch); | 66 sandbox_cmd_.push_back(base::kFindInodeSwitch); |
| 67 } | 67 } |
| 68 | 68 |
| 69 // FontConfig doesn't provide a standard property to control subpixel | 69 // FontConfig doesn't provide a standard property to control subpixel |
| 70 // positioning, so we pass the current setting through to WebKit. | 70 // positioning, so we pass the current setting through to WebKit. |
| 71 WebFontInfo::setSubpixelPositioning( | 71 WebFontInfo::setSubpixelPositioning( |
| 72 gfx::GetDefaultWebkitSubpixelPositioning()); | 72 gfx::GetDefaultWebkitSubpixelPositioning()); |
| 73 } | 73 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 // --------------------------------------------------------------------------- | 112 // --------------------------------------------------------------------------- |
| 113 // Requests from the renderer... | 113 // Requests from the renderer... |
| 114 | 114 |
| 115 void HandleRequestFromRenderer(int fd) { | 115 void HandleRequestFromRenderer(int fd) { |
| 116 std::vector<int> fds; | 116 std::vector<int> fds; |
| 117 | 117 |
| 118 // A FontConfigIPC::METHOD_MATCH message could be kMaxFontFamilyLength | 118 // A FontConfigIPC::METHOD_MATCH message could be kMaxFontFamilyLength |
| 119 // bytes long (this is the largest message type). | 119 // bytes long (this is the largest message type). |
| 120 // 128 bytes padding are necessary so recvmsg() does not return MSG_TRUNC | 120 // 128 bytes padding are necessary so recvmsg() does not return MSG_TRUNC |
| 121 // error for a maximum length message. | 121 // error for a maximum length message. |
| 122 char buf[FontConfigIPC::kMaxFontFamilyLength + 128]; | 122 char buf[FontConfigInterface::kMaxFontFamilyLength + 128]; |
| 123 | 123 |
| 124 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds); | 124 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds); |
| 125 if (len == -1) { | 125 if (len == -1) { |
| 126 // TODO: should send an error reply, or the sender might block forever. | 126 // TODO: should send an error reply, or the sender might block forever. |
| 127 NOTREACHED() | 127 NOTREACHED() |
| 128 << "Sandbox host message is larger than kMaxFontFamilyLength"; | 128 << "Sandbox host message is larger than kMaxFontFamilyLength"; |
| 129 return; | 129 return; |
| 130 } | 130 } |
| 131 if (fds.empty()) | 131 if (fds.empty()) |
| 132 return; | 132 return; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 156 HandleMatchWithFallback(fd, pickle, iter, fds); | 156 HandleMatchWithFallback(fd, pickle, iter, fds); |
| 157 } | 157 } |
| 158 | 158 |
| 159 error: | 159 error: |
| 160 for (std::vector<int>::const_iterator | 160 for (std::vector<int>::const_iterator |
| 161 i = fds.begin(); i != fds.end(); ++i) { | 161 i = fds.begin(); i != fds.end(); ++i) { |
| 162 close(*i); | 162 close(*i); |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 int FindOrAddPath(const SkString& path) { | |
| 167 int count = paths_.count(); | |
| 168 for (int i = 0; i < count; ++i) { | |
| 169 if (path == *paths_[i]) | |
| 170 return i; | |
| 171 } | |
| 172 *paths_.append() = new SkString(path); | |
| 173 return count; | |
| 174 } | |
| 175 | |
| 176 void HandleFontMatchRequest(int fd, const Pickle& pickle, PickleIterator iter, | 166 void HandleFontMatchRequest(int fd, const Pickle& pickle, PickleIterator iter, |
| 177 std::vector<int>& fds) { | 167 std::vector<int>& fds) { |
| 178 uint32_t requested_style; | 168 bool filefaceid_valid; |
| 169 uint32_t filefaceid = 0; |
| 170 |
| 171 if (!pickle.ReadBool(&iter, &filefaceid_valid)) |
| 172 return; |
| 173 if (filefaceid_valid) { |
| 174 if (!pickle.ReadUInt32(&iter, &filefaceid)) |
| 175 return; |
| 176 } |
| 177 bool is_bold, is_italic; |
| 178 if (!pickle.ReadBool(&iter, &is_bold) || |
| 179 !pickle.ReadBool(&iter, &is_italic)) { |
| 180 return; |
| 181 } |
| 182 |
| 183 uint32_t characters_bytes; |
| 184 if (!pickle.ReadUInt32(&iter, &characters_bytes)) |
| 185 return; |
| 186 const char* characters = NULL; |
| 187 if (characters_bytes > 0) { |
| 188 const uint32_t kMaxCharactersBytes = 1 << 10; |
| 189 if (characters_bytes % 2 != 0 || // We expect UTF-16. |
| 190 characters_bytes > kMaxCharactersBytes || |
| 191 !pickle.ReadBytes(&iter, &characters, characters_bytes)) |
| 192 return; |
| 193 } |
| 194 |
| 179 std::string family; | 195 std::string family; |
| 180 if (!pickle.ReadString(&iter, &family) || | 196 if (!pickle.ReadString(&iter, &family)) |
| 181 !pickle.ReadUInt32(&iter, &requested_style)) | |
| 182 return; | 197 return; |
| 183 | 198 |
| 184 SkFontConfigInterface::FontIdentity result_identity; | 199 std::string result_family; |
| 185 SkString result_family; | 200 unsigned result_filefaceid; |
| 186 SkTypeface::Style result_style; | 201 const bool r = font_config_->Match( |
| 187 SkFontConfigInterface* fc = | 202 &result_family, &result_filefaceid, filefaceid_valid, filefaceid, |
| 188 SkFontConfigInterface::GetSingletonDirectInterface(); | 203 family, characters, characters_bytes, &is_bold, &is_italic); |
| 189 const bool r = fc->matchFamilyName( | |
| 190 family.c_str(), static_cast<SkTypeface::Style>(requested_style), | |
| 191 &result_identity, &result_family, &result_style); | |
| 192 | 204 |
| 193 Pickle reply; | 205 Pickle reply; |
| 194 if (!r) { | 206 if (!r) { |
| 195 reply.WriteBool(false); | 207 reply.WriteBool(false); |
| 196 } else { | 208 } else { |
| 197 // Stash away the returned path, so we can give it an ID (index) | |
| 198 // which will later be given to us in a request to open the file. | |
| 199 int index = FindOrAddPath(result_identity.fString); | |
| 200 result_identity.fID = static_cast<uint32_t>(index); | |
| 201 | |
| 202 reply.WriteBool(true); | 209 reply.WriteBool(true); |
| 203 skia::WriteSkString(&reply, result_family); | 210 reply.WriteUInt32(result_filefaceid); |
| 204 skia::WriteSkFontIdentity(&reply, result_identity); | 211 reply.WriteString(result_family); |
| 205 reply.WriteUInt32(result_style); | 212 reply.WriteBool(is_bold); |
| 213 reply.WriteBool(is_italic); |
| 206 } | 214 } |
| 207 SendRendererReply(fds, reply, -1); | 215 SendRendererReply(fds, reply, -1); |
| 208 } | 216 } |
| 209 | 217 |
| 210 void HandleFontOpenRequest(int fd, const Pickle& pickle, PickleIterator iter, | 218 void HandleFontOpenRequest(int fd, const Pickle& pickle, PickleIterator iter, |
| 211 std::vector<int>& fds) { | 219 std::vector<int>& fds) { |
| 212 uint32_t index; | 220 uint32_t filefaceid; |
| 213 if (!pickle.ReadUInt32(&iter, &index)) | 221 if (!pickle.ReadUInt32(&iter, &filefaceid)) |
| 214 return; | 222 return; |
| 215 if (index >= static_cast<uint32_t>(paths_.count())) | 223 const int result_fd = font_config_->Open(filefaceid); |
| 216 return; | |
| 217 const int result_fd = open(paths_[index]->c_str(), O_RDONLY); | |
| 218 | 224 |
| 219 Pickle reply; | 225 Pickle reply; |
| 220 if (result_fd == -1) { | 226 if (result_fd == -1) { |
| 221 reply.WriteBool(false); | 227 reply.WriteBool(false); |
| 222 } else { | 228 } else { |
| 223 reply.WriteBool(true); | 229 reply.WriteBool(true); |
| 224 } | 230 } |
| 225 | 231 |
| 226 SendRendererReply(fds, reply, result_fd); | 232 SendRendererReply(fds, reply, result_fd); |
| 233 |
| 234 if (result_fd >= 0) |
| 235 close(result_fd); |
| 227 } | 236 } |
| 228 | 237 |
| 229 void HandleGetFontFamilyForChars(int fd, const Pickle& pickle, | 238 void HandleGetFontFamilyForChars(int fd, const Pickle& pickle, |
| 230 PickleIterator iter, | 239 PickleIterator iter, |
| 231 std::vector<int>& fds) { | 240 std::vector<int>& fds) { |
| 232 // The other side of this call is | 241 // The other side of this call is |
| 233 // chrome/renderer/renderer_sandbox_support_linux.cc | 242 // chrome/renderer/renderer_sandbox_support_linux.cc |
| 234 | 243 |
| 235 int num_chars; | 244 int num_chars; |
| 236 if (!pickle.ReadInt(&iter, &num_chars)) | 245 if (!pickle.ReadInt(&iter, &num_chars)) |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 } | 652 } |
| 644 | 653 |
| 645 if (HANDLE_EINTR(sendmsg(fds[0], &msg, MSG_DONTWAIT)) < 0) | 654 if (HANDLE_EINTR(sendmsg(fds[0], &msg, MSG_DONTWAIT)) < 0) |
| 646 PLOG(ERROR) << "sendmsg"; | 655 PLOG(ERROR) << "sendmsg"; |
| 647 } | 656 } |
| 648 | 657 |
| 649 // --------------------------------------------------------------------------- | 658 // --------------------------------------------------------------------------- |
| 650 | 659 |
| 651 const int lifeline_fd_; | 660 const int lifeline_fd_; |
| 652 const int browser_socket_; | 661 const int browser_socket_; |
| 662 scoped_ptr<FontConfigDirect> font_config_; |
| 653 std::vector<std::string> sandbox_cmd_; | 663 std::vector<std::string> sandbox_cmd_; |
| 654 scoped_ptr<WebKitPlatformSupportImpl> webkit_platform_support_; | 664 scoped_ptr<WebKitPlatformSupportImpl> webkit_platform_support_; |
| 655 SkTDArray<SkString*> paths_; | |
| 656 }; | 665 }; |
| 657 | 666 |
| 658 SandboxIPCProcess::~SandboxIPCProcess() { | 667 SandboxIPCProcess::~SandboxIPCProcess() { |
| 659 paths_.deleteAll(); | |
| 660 if (webkit_platform_support_.get()) | 668 if (webkit_platform_support_.get()) |
| 661 WebKit::shutdown(); | 669 WebKit::shutdown(); |
| 662 } | 670 } |
| 663 | 671 |
| 664 void SandboxIPCProcess::EnsureWebKitInitialized() { | 672 void SandboxIPCProcess::EnsureWebKitInitialized() { |
| 665 if (webkit_platform_support_.get()) | 673 if (webkit_platform_support_.get()) |
| 666 return; | 674 return; |
| 667 webkit_platform_support_.reset(new WebKitPlatformSupportImpl); | 675 webkit_platform_support_.reset(new WebKitPlatformSupportImpl); |
| 668 WebKit::initializeWithoutV8(webkit_platform_support_.get()); | 676 WebKit::initializeWithoutV8(webkit_platform_support_.get()); |
| 669 } | 677 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 RenderSandboxHostLinux::~RenderSandboxHostLinux() { | 735 RenderSandboxHostLinux::~RenderSandboxHostLinux() { |
| 728 if (initialized_) { | 736 if (initialized_) { |
| 729 if (HANDLE_EINTR(close(renderer_socket_)) < 0) | 737 if (HANDLE_EINTR(close(renderer_socket_)) < 0) |
| 730 PLOG(ERROR) << "close"; | 738 PLOG(ERROR) << "close"; |
| 731 if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) | 739 if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) |
| 732 PLOG(ERROR) << "close"; | 740 PLOG(ERROR) << "close"; |
| 733 } | 741 } |
| 734 } | 742 } |
| 735 | 743 |
| 736 } // namespace content | 744 } // namespace content |
| OLD | NEW |