fixup! [M120 Migration][NaCl][PPFWK] Upgradable pepper plugin requirement
[platform/framework/web/chromium-efl.git] / pdf / post_message_receiver.cc
1 // Copyright 2021 The Chromium Authors
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 "pdf/post_message_receiver.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "base/check_op.h"
13 #include "base/functional/bind.h"
14 #include "base/location.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/task/sequenced_task_runner.h"
18 #include "base/values.h"
19 #include "gin/function_template.h"
20 #include "gin/handle.h"
21 #include "gin/interceptor.h"
22 #include "gin/object_template_builder.h"
23 #include "gin/public/wrapper_info.h"
24 #include "gin/wrappable.h"
25 #include "pdf/v8_value_converter.h"
26 #include "v8/include/v8.h"
27
28 namespace chrome_pdf {
29
30 namespace {
31
32 constexpr char kPropertyName[] = "postMessage";
33
34 }  // namespace
35
36 // static
37 gin::WrapperInfo PostMessageReceiver::kWrapperInfo = {gin::kEmbedderNativeGin};
38
39 // static
40 v8::Local<v8::Object> PostMessageReceiver::Create(
41     v8::Isolate* isolate,
42     base::WeakPtr<V8ValueConverter> v8_value_converter,
43     base::WeakPtr<Client> client,
44     scoped_refptr<base::SequencedTaskRunner> client_task_runner) {
45   return gin::CreateHandle(
46              isolate, new PostMessageReceiver(
47                           isolate, std::move(v8_value_converter),
48                           std::move(client), std::move(client_task_runner)))
49       .ToV8()
50       .As<v8::Object>();
51 }
52
53 PostMessageReceiver::~PostMessageReceiver() = default;
54
55 PostMessageReceiver::PostMessageReceiver(
56     v8::Isolate* isolate,
57     base::WeakPtr<V8ValueConverter> v8_value_converter,
58     base::WeakPtr<Client> client,
59     scoped_refptr<base::SequencedTaskRunner> client_task_runner)
60     : gin::NamedPropertyInterceptor(isolate, this),
61       v8_value_converter_(std::move(v8_value_converter)),
62       isolate_(isolate),
63       client_(std::move(client)),
64       client_task_runner_(std::move(client_task_runner)) {}
65
66 gin::ObjectTemplateBuilder PostMessageReceiver::GetObjectTemplateBuilder(
67     v8::Isolate* isolate) {
68   // `gin::ObjectTemplateBuilder::SetMethod()` can't be used here because it
69   // would create a function template which expects the first parameter to a
70   // member function pointer to be the JavaScript `this` object corresponding
71   // to this scriptable object exposed through Blink. However, the actual
72   // receiving object for a plugin is an HTMLEmbedElement and Blink internally
73   // forwards the parameters to this scriptable object.
74   //
75   // Also, passing a callback would cause Gin to ignore the target. Because Gin
76   // creates the object template of a type only once per isolate, the member
77   // method of the first `PostMessageReceiver` instance would get effectively
78   // treated like a static method for all other instances.
79   //
80   // An interceptor allows for the creation of a function template per instance.
81   return gin::Wrappable<PostMessageReceiver>::GetObjectTemplateBuilder(isolate)
82       .AddNamedPropertyInterceptor();
83 }
84
85 const char* PostMessageReceiver::GetTypeName() {
86   return "ChromePdfPostMessageReceiver";
87 }
88
89 v8::Local<v8::Value> PostMessageReceiver::GetNamedProperty(
90     v8::Isolate* isolate,
91     const std::string& property) {
92   DCHECK_EQ(isolate_, isolate);
93
94   if (property != kPropertyName)
95     return v8::Local<v8::Value>();
96
97   return GetFunctionTemplate()
98       ->GetFunction(isolate->GetCurrentContext())
99       .ToLocalChecked();
100 }
101
102 std::vector<std::string> PostMessageReceiver::EnumerateNamedProperties(
103     v8::Isolate* isolate) {
104   DCHECK_EQ(isolate_, isolate);
105   return {kPropertyName};
106 }
107
108 v8::Local<v8::FunctionTemplate> PostMessageReceiver::GetFunctionTemplate() {
109   if (function_template_.IsEmpty()) {
110     function_template_.Reset(
111         isolate_,
112         gin::CreateFunctionTemplate(
113             isolate_, base::BindRepeating(&PostMessageReceiver::PostMessage,
114                                           weak_factory_.GetWeakPtr())));
115   }
116
117   return function_template_.Get(isolate_);
118 }
119
120 void PostMessageReceiver::PostMessage(v8::Local<v8::Value> message) {
121   if (!client_ || !v8_value_converter_)
122     return;
123
124   std::unique_ptr<base::Value> converted_message =
125       v8_value_converter_->FromV8Value(message, isolate_->GetCurrentContext());
126   // The PDF Viewer UI should not be sending messages that cannot be converted.
127   DCHECK(converted_message);
128   DCHECK(converted_message->is_dict());
129
130   client_task_runner_->PostTask(
131       FROM_HERE, base::BindOnce(&Client::OnMessage, client_,
132                                 std::move(*converted_message).TakeDict()));
133 }
134
135 }  // namespace chrome_pdf