1// Copyright 2014 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 "content/browser/renderer_host/pepper/pepper_truetype_font_host.h"
6
7#include "base/bind.h"
8#include "base/task_runner_util.h"
9#include "base/threading/sequenced_worker_pool.h"
10#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
11#include "content/public/browser/browser_ppapi_host.h"
12#include "content/public/browser/browser_thread.h"
13#include "ppapi/c/pp_errors.h"
14#include "ppapi/host/dispatch_host_message.h"
15#include "ppapi/host/ppapi_host.h"
16#include "ppapi/proxy/ppapi_messages.h"
17
18using ppapi::host::HostMessageContext;
19using ppapi::host::ReplyMessageContext;
20using ppapi::proxy::SerializedTrueTypeFontDesc;
21
22namespace content {
23
24PepperTrueTypeFontHost::PepperTrueTypeFontHost(
25    BrowserPpapiHost* host,
26    PP_Instance instance,
27    PP_Resource resource,
28    const SerializedTrueTypeFontDesc& desc)
29    : ResourceHost(host->GetPpapiHost(), instance, resource),
30      initialize_completed_(false),
31      weak_factory_(this) {
32  font_ = PepperTrueTypeFont::Create();
33  // Initialize the font on a blocking pool thread. This must complete before
34  // using |font_|.
35  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
36  task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
37  SerializedTrueTypeFontDesc* actual_desc =
38      new SerializedTrueTypeFontDesc(desc);
39  base::PostTaskAndReplyWithResult(
40      task_runner_.get(),
41      FROM_HERE,
42      base::Bind(&PepperTrueTypeFont::Initialize, font_, actual_desc),
43      base::Bind(&PepperTrueTypeFontHost::OnInitializeComplete,
44                 weak_factory_.GetWeakPtr(),
45                 base::Owned(actual_desc)));
46}
47
48PepperTrueTypeFontHost::~PepperTrueTypeFontHost() {
49  if (font_.get()) {
50    // Release the font on the task runner in case the implementation requires
51    // long blocking operations.
52    font_->AddRef();
53    PepperTrueTypeFont* raw_font = font_.get();
54    font_ = NULL;
55    task_runner_->ReleaseSoon(FROM_HERE, raw_font);
56  }
57}
58
59int32_t PepperTrueTypeFontHost::OnResourceMessageReceived(
60    const IPC::Message& msg,
61    HostMessageContext* context) {
62  if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV))
63    return PP_ERROR_FAILED;
64
65  PPAPI_BEGIN_MESSAGE_MAP(PepperTrueTypeFontHost, msg)
66  PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TrueTypeFont_GetTableTags,
67                                      OnHostMsgGetTableTags)
68  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TrueTypeFont_GetTable,
69                                    OnHostMsgGetTable)
70  PPAPI_END_MESSAGE_MAP()
71  return PP_ERROR_FAILED;
72}
73
74int32_t PepperTrueTypeFontHost::OnHostMsgGetTableTags(
75    HostMessageContext* context) {
76  if (!font_.get())
77    return PP_ERROR_FAILED;
78
79  // Get font data on a thread that allows slow blocking operations.
80  std::vector<uint32_t>* tags = new std::vector<uint32_t>();
81  base::PostTaskAndReplyWithResult(
82      task_runner_.get(),
83      FROM_HERE,
84      base::Bind(&PepperTrueTypeFont::GetTableTags, font_, tags),
85      base::Bind(&PepperTrueTypeFontHost::OnGetTableTagsComplete,
86                 weak_factory_.GetWeakPtr(),
87                 base::Owned(tags),
88                 context->MakeReplyMessageContext()));
89
90  return PP_OK_COMPLETIONPENDING;
91}
92
93int32_t PepperTrueTypeFontHost::OnHostMsgGetTable(HostMessageContext* context,
94                                                  uint32_t table,
95                                                  int32_t offset,
96                                                  int32_t max_data_length) {
97  if (!font_.get())
98    return PP_ERROR_FAILED;
99  if (offset < 0 || max_data_length < 0)
100    return PP_ERROR_BADARGUMENT;
101
102  // Get font data on a thread that allows slow blocking operations.
103  std::string* data = new std::string();
104  base::PostTaskAndReplyWithResult(
105      task_runner_.get(),
106      FROM_HERE,
107      base::Bind(&PepperTrueTypeFont::GetTable,
108                 font_,
109                 table,
110                 offset,
111                 max_data_length,
112                 data),
113      base::Bind(&PepperTrueTypeFontHost::OnGetTableComplete,
114                 weak_factory_.GetWeakPtr(),
115                 base::Owned(data),
116                 context->MakeReplyMessageContext()));
117
118  return PP_OK_COMPLETIONPENDING;
119}
120
121void PepperTrueTypeFontHost::OnInitializeComplete(
122    SerializedTrueTypeFontDesc* desc,
123    int32_t result) {
124  DCHECK(!initialize_completed_);
125  initialize_completed_ = true;
126  // Release the font if there was an error, so future calls will fail.
127  if (result != PP_OK)
128    font_ = NULL;
129  host()->SendUnsolicitedReply(
130      pp_resource(), PpapiPluginMsg_TrueTypeFont_CreateReply(*desc, result));
131}
132
133void PepperTrueTypeFontHost::OnGetTableTagsComplete(
134    std::vector<uint32_t>* tags,
135    ReplyMessageContext reply_context,
136    int32_t result) {
137  DCHECK(initialize_completed_);
138  // It's possible that Initialize failed and that |font_| is NULL. Check that
139  // the font implementation doesn't return PP_OK in that case.
140  DCHECK(font_.get() || result != PP_OK);
141  reply_context.params.set_result(result);
142  host()->SendReply(reply_context,
143                    PpapiPluginMsg_TrueTypeFont_GetTableTagsReply(*tags));
144}
145
146void PepperTrueTypeFontHost::OnGetTableComplete(
147    std::string* data,
148    ReplyMessageContext reply_context,
149    int32_t result) {
150  DCHECK(initialize_completed_);
151  // It's possible that Initialize failed and that |font_| is NULL. Check that
152  // the font implementation doesn't return PP_OK in that case.
153  DCHECK(font_.get() || result != PP_OK);
154  reply_context.params.set_result(result);
155  host()->SendReply(reply_context,
156                    PpapiPluginMsg_TrueTypeFont_GetTableReply(*data));
157}
158
159}  // namespace content
160