OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "extensions/renderer/api_signature.h" | 5 #include "extensions/renderer/api_signature.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "gin/arguments.h" | 9 #include "gin/arguments.h" |
10 | 10 |
11 namespace extensions { | 11 namespace extensions { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 // A class to help with argument parsing. Note that this uses v8::Locals and | 15 // A class to help with argument parsing. Note that this uses v8::Locals and |
16 // const&s because it's an implementation detail of the APISignature; this | 16 // const&s because it's an implementation detail of the APISignature; this |
17 // should *only* be used directly on the stack! | 17 // should *only* be used directly on the stack! |
18 class ArgumentParser { | 18 class ArgumentParser { |
19 public: | 19 public: |
20 ArgumentParser(const std::vector<std::unique_ptr<ArgumentSpec>>& signature, | 20 ArgumentParser(v8::Local<v8::Context> context, |
21 gin::Arguments* arguments, | 21 const std::vector<std::unique_ptr<ArgumentSpec>>& signature, |
22 const std::vector<v8::Local<v8::Value>>& arguments, | |
22 const ArgumentSpec::RefMap& type_refs, | 23 const ArgumentSpec::RefMap& type_refs, |
23 std::string* error) | 24 std::string* error) |
24 : context_(arguments->isolate()->GetCurrentContext()), | 25 : context_(context), |
25 signature_(signature), | 26 signature_(signature), |
26 arguments_(arguments), | 27 arguments_(arguments), |
27 type_refs_(type_refs), | 28 type_refs_(type_refs), |
28 error_(error) {} | 29 error_(error) {} |
29 | 30 |
30 // Tries to parse the arguments against the expected signature, populating a | 31 // Tries to parse the arguments against the expected signature, populating a |
31 // resulting list as it goes. | 32 // resulting list as it goes. |
32 bool ParseArguments(); | 33 bool ParseArguments(); |
33 | 34 |
34 protected: | 35 protected: |
35 v8::Isolate* GetIsolate() { return context_->GetIsolate(); } | 36 v8::Isolate* GetIsolate() { return context_->GetIsolate(); } |
36 | 37 |
37 private: | 38 private: |
39 v8::Local<v8::Value> next_argument() { | |
40 return current_index_ < arguments_.size() ? | |
41 arguments_[current_index_] : v8::Local<v8::Value>(); | |
42 } | |
43 | |
44 void consume_argument() { | |
jbroman
2016/12/23 22:37:06
nit: This doesn't look like a simple getter/setter
Devlin
2016/12/28 19:02:39
Not entirely sure I agree (it's basically just inc
| |
45 current_index_ = std::min(arguments_.size(), current_index_ + 1); | |
46 } | |
47 | |
38 // Attempts to match the next argument to the given |spec|. | 48 // Attempts to match the next argument to the given |spec|. |
39 // If the next argument does not match and |spec| is optional, uses a null | 49 // If the next argument does not match and |spec| is optional, uses a null |
40 // value. | 50 // value. |
41 // Returns true on success. | 51 // Returns true on success. |
42 bool ParseArgument(const ArgumentSpec& spec); | 52 bool ParseArgument(const ArgumentSpec& spec); |
43 | 53 |
44 // Attempts to parse the callback from the given |spec|. Returns true on | 54 // Attempts to parse the callback from the given |spec|. Returns true on |
45 // success. | 55 // success. |
46 bool ParseCallback(const ArgumentSpec& spec); | 56 bool ParseCallback(const ArgumentSpec& spec); |
47 | 57 |
48 // Adds a null value to the parsed arguments. | 58 // Adds a null value to the parsed arguments. |
49 virtual void AddNull() = 0; | 59 virtual void AddNull() = 0; |
50 // Returns a base::Value to be populated during argument matching. | 60 // Returns a base::Value to be populated during argument matching. |
51 virtual std::unique_ptr<base::Value>* GetBuffer() = 0; | 61 virtual std::unique_ptr<base::Value>* GetBuffer() = 0; |
52 // Adds a new parsed argument. | 62 // Adds a new parsed argument. |
53 virtual void AddParsedArgument(v8::Local<v8::Value> value) = 0; | 63 virtual void AddParsedArgument(v8::Local<v8::Value> value) = 0; |
54 // Adds the parsed callback. | 64 // Adds the parsed callback. |
55 virtual void SetCallback(v8::Local<v8::Function> callback) = 0; | 65 virtual void SetCallback(v8::Local<v8::Function> callback) = 0; |
56 | 66 |
57 v8::Local<v8::Context> context_; | 67 v8::Local<v8::Context> context_; |
58 const std::vector<std::unique_ptr<ArgumentSpec>>& signature_; | 68 const std::vector<std::unique_ptr<ArgumentSpec>>& signature_; |
59 gin::Arguments* arguments_; | 69 const std::vector<v8::Local<v8::Value>>& arguments_; |
60 const ArgumentSpec::RefMap& type_refs_; | 70 const ArgumentSpec::RefMap& type_refs_; |
61 std::string* error_; | 71 std::string* error_; |
72 size_t current_index_ = 0; | |
62 | 73 |
63 DISALLOW_COPY_AND_ASSIGN(ArgumentParser); | 74 DISALLOW_COPY_AND_ASSIGN(ArgumentParser); |
64 }; | 75 }; |
65 | 76 |
66 class V8ArgumentParser : public ArgumentParser { | 77 class V8ArgumentParser : public ArgumentParser { |
67 public: | 78 public: |
68 V8ArgumentParser(const std::vector<std::unique_ptr<ArgumentSpec>>& signature, | 79 V8ArgumentParser(v8::Local<v8::Context> context, |
69 gin::Arguments* arguments, | 80 const std::vector<std::unique_ptr<ArgumentSpec>>& signature, |
81 const std::vector<v8::Local<v8::Value>>& arguments, | |
70 const ArgumentSpec::RefMap& type_refs, | 82 const ArgumentSpec::RefMap& type_refs, |
71 std::string* error, | 83 std::string* error, |
72 std::vector<v8::Local<v8::Value>>* values) | 84 std::vector<v8::Local<v8::Value>>* values) |
73 : ArgumentParser(signature, arguments, type_refs, error), | 85 : ArgumentParser(context, signature, arguments, type_refs, error), |
74 values_(values) {} | 86 values_(values) {} |
75 | 87 |
76 private: | 88 private: |
77 void AddNull() override { values_->push_back(v8::Null(GetIsolate())); } | 89 void AddNull() override { values_->push_back(v8::Null(GetIsolate())); } |
78 std::unique_ptr<base::Value>* GetBuffer() override { return nullptr; } | 90 std::unique_ptr<base::Value>* GetBuffer() override { return nullptr; } |
79 void AddParsedArgument(v8::Local<v8::Value> value) override { | 91 void AddParsedArgument(v8::Local<v8::Value> value) override { |
80 values_->push_back(value); | 92 values_->push_back(value); |
81 } | 93 } |
82 void SetCallback(v8::Local<v8::Function> callback) override { | 94 void SetCallback(v8::Local<v8::Function> callback) override { |
83 values_->push_back(callback); | 95 values_->push_back(callback); |
84 } | 96 } |
85 | 97 |
86 std::vector<v8::Local<v8::Value>>* values_; | 98 std::vector<v8::Local<v8::Value>>* values_; |
87 | 99 |
88 DISALLOW_COPY_AND_ASSIGN(V8ArgumentParser); | 100 DISALLOW_COPY_AND_ASSIGN(V8ArgumentParser); |
89 }; | 101 }; |
90 | 102 |
91 class BaseValueArgumentParser : public ArgumentParser { | 103 class BaseValueArgumentParser : public ArgumentParser { |
92 public: | 104 public: |
93 BaseValueArgumentParser( | 105 BaseValueArgumentParser( |
106 v8::Local<v8::Context> context, | |
94 const std::vector<std::unique_ptr<ArgumentSpec>>& signature, | 107 const std::vector<std::unique_ptr<ArgumentSpec>>& signature, |
95 gin::Arguments* arguments, | 108 const std::vector<v8::Local<v8::Value>>& arguments, |
96 const ArgumentSpec::RefMap& type_refs, | 109 const ArgumentSpec::RefMap& type_refs, |
97 std::string* error, | 110 std::string* error, |
98 base::ListValue* list_value) | 111 base::ListValue* list_value) |
99 : ArgumentParser(signature, arguments, type_refs, error), | 112 : ArgumentParser(context, signature, arguments, type_refs, error), |
100 list_value_(list_value) {} | 113 list_value_(list_value) {} |
101 | 114 |
102 v8::Local<v8::Function> callback() { return callback_; } | 115 v8::Local<v8::Function> callback() { return callback_; } |
103 | 116 |
104 private: | 117 private: |
105 void AddNull() override { | 118 void AddNull() override { |
106 list_value_->Append(base::Value::CreateNullValue()); | 119 list_value_->Append(base::Value::CreateNullValue()); |
107 } | 120 } |
108 std::unique_ptr<base::Value>* GetBuffer() override { return &last_arg_; } | 121 std::unique_ptr<base::Value>* GetBuffer() override { return &last_arg_; } |
109 void AddParsedArgument(v8::Local<v8::Value> value) override { | 122 void AddParsedArgument(v8::Local<v8::Value> value) override { |
(...skipping 26 matching lines...) Expand all Loading... | |
136 size_t end_size = | 149 size_t end_size = |
137 signature_has_callback ? signature_.size() - 1 : signature_.size(); | 150 signature_has_callback ? signature_.size() - 1 : signature_.size(); |
138 for (size_t i = 0; i < end_size; ++i) { | 151 for (size_t i = 0; i < end_size; ++i) { |
139 if (!ParseArgument(*signature_[i])) | 152 if (!ParseArgument(*signature_[i])) |
140 return false; | 153 return false; |
141 } | 154 } |
142 | 155 |
143 if (signature_has_callback && !ParseCallback(*signature_.back())) | 156 if (signature_has_callback && !ParseCallback(*signature_.back())) |
144 return false; | 157 return false; |
145 | 158 |
146 if (!arguments_->PeekNext().IsEmpty()) | 159 if (current_index_ != arguments_.size()) |
147 return false; // Extra arguments aren't allowed. | 160 return false; // Extra arguments aren't allowed. |
148 | 161 |
149 return true; | 162 return true; |
150 } | 163 } |
151 | 164 |
152 bool ArgumentParser::ParseArgument(const ArgumentSpec& spec) { | 165 bool ArgumentParser::ParseArgument(const ArgumentSpec& spec) { |
153 v8::Local<v8::Value> value = arguments_->PeekNext(); | 166 v8::Local<v8::Value> value = next_argument(); |
154 if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) { | 167 if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) { |
155 if (!spec.optional()) { | 168 if (!spec.optional()) { |
156 *error_ = "Missing required argument: " + spec.name(); | 169 *error_ = "Missing required argument: " + spec.name(); |
157 return false; | 170 return false; |
158 } | 171 } |
159 // This is safe to call even if |arguments| is at the end (which can happen | 172 // This is safe to call even if |arguments| is at the end (which can happen |
160 // if n optional arguments are omitted at the end of the signature). | 173 // if n optional arguments are omitted at the end of the signature). |
161 arguments_->Skip(); | 174 consume_argument(); |
162 | 175 |
163 AddNull(); | 176 AddNull(); |
164 return true; | 177 return true; |
165 } | 178 } |
166 | 179 |
167 if (!spec.ParseArgument(context_, value, type_refs_, GetBuffer(), error_)) { | 180 if (!spec.ParseArgument(context_, value, type_refs_, GetBuffer(), error_)) { |
168 if (!spec.optional()) { | 181 if (!spec.optional()) { |
169 *error_ = "Missing required argument: " + spec.name(); | 182 *error_ = "Missing required argument: " + spec.name(); |
170 return false; | 183 return false; |
171 } | 184 } |
172 | 185 |
173 AddNull(); | 186 AddNull(); |
174 return true; | 187 return true; |
175 } | 188 } |
176 | 189 |
177 arguments_->Skip(); | 190 consume_argument(); |
178 AddParsedArgument(value); | 191 AddParsedArgument(value); |
179 return true; | 192 return true; |
180 } | 193 } |
181 | 194 |
182 bool ArgumentParser::ParseCallback(const ArgumentSpec& spec) { | 195 bool ArgumentParser::ParseCallback(const ArgumentSpec& spec) { |
183 v8::Local<v8::Value> value = arguments_->PeekNext(); | 196 v8::Local<v8::Value> value = next_argument(); |
184 if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) { | 197 if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) { |
185 if (!spec.optional()) { | 198 if (!spec.optional()) { |
186 *error_ = "Missing required argument: " + spec.name(); | 199 *error_ = "Missing required argument: " + spec.name(); |
187 return false; | 200 return false; |
188 } | 201 } |
189 arguments_->Skip(); | 202 consume_argument(); |
190 return true; | 203 return true; |
191 } | 204 } |
192 | 205 |
193 if (!value->IsFunction()) { | 206 if (!value->IsFunction()) { |
194 *error_ = "Argument is wrong type: " + spec.name(); | 207 *error_ = "Argument is wrong type: " + spec.name(); |
195 return false; | 208 return false; |
196 } | 209 } |
197 | 210 |
198 arguments_->Skip(); | 211 consume_argument(); |
199 SetCallback(value.As<v8::Function>()); | 212 SetCallback(value.As<v8::Function>()); |
200 return true; | 213 return true; |
201 } | 214 } |
202 | 215 |
203 } // namespace | 216 } // namespace |
204 | 217 |
205 APISignature::APISignature(const base::ListValue& specification) { | 218 APISignature::APISignature(const base::ListValue& specification) { |
206 signature_.reserve(specification.GetSize()); | 219 signature_.reserve(specification.GetSize()); |
207 for (const auto& value : specification) { | 220 for (const auto& value : specification) { |
208 const base::DictionaryValue* param = nullptr; | 221 const base::DictionaryValue* param = nullptr; |
209 CHECK(value->GetAsDictionary(¶m)); | 222 CHECK(value->GetAsDictionary(¶m)); |
210 signature_.push_back(base::MakeUnique<ArgumentSpec>(*param)); | 223 signature_.push_back(base::MakeUnique<ArgumentSpec>(*param)); |
211 } | 224 } |
212 } | 225 } |
213 | 226 |
214 APISignature::~APISignature() {} | 227 APISignature::~APISignature() {} |
215 | 228 |
216 bool APISignature::ParseArgumentsToV8(gin::Arguments* arguments, | 229 bool APISignature::ParseArgumentsToV8( |
217 const ArgumentSpec::RefMap& type_refs, | 230 v8::Local<v8::Context> context, |
218 std::vector<v8::Local<v8::Value>>* v8_out, | 231 const std::vector<v8::Local<v8::Value>>& arguments, |
219 std::string* error) const { | 232 const ArgumentSpec::RefMap& type_refs, |
233 std::vector<v8::Local<v8::Value>>* v8_out, | |
234 std::string* error) const { | |
220 DCHECK(v8_out); | 235 DCHECK(v8_out); |
221 std::vector<v8::Local<v8::Value>> v8_values; | 236 std::vector<v8::Local<v8::Value>> v8_values; |
222 V8ArgumentParser parser(signature_, arguments, type_refs, error, &v8_values); | 237 V8ArgumentParser parser( |
238 context, signature_, arguments, type_refs, error, &v8_values); | |
223 if (!parser.ParseArguments()) | 239 if (!parser.ParseArguments()) |
224 return false; | 240 return false; |
225 *v8_out = std::move(v8_values); | 241 *v8_out = std::move(v8_values); |
226 return true; | 242 return true; |
227 } | 243 } |
228 | 244 |
229 bool APISignature::ParseArgumentsToJSON( | 245 bool APISignature::ParseArgumentsToJSON( |
230 gin::Arguments* arguments, | 246 v8::Local<v8::Context> context, |
247 const std::vector<v8::Local<v8::Value>>& arguments, | |
231 const ArgumentSpec::RefMap& type_refs, | 248 const ArgumentSpec::RefMap& type_refs, |
232 std::unique_ptr<base::ListValue>* json_out, | 249 std::unique_ptr<base::ListValue>* json_out, |
233 v8::Local<v8::Function>* callback_out, | 250 v8::Local<v8::Function>* callback_out, |
234 std::string* error) const { | 251 std::string* error) const { |
235 DCHECK(json_out); | 252 DCHECK(json_out); |
236 DCHECK(callback_out); | 253 DCHECK(callback_out); |
237 std::unique_ptr<base::ListValue> json = base::MakeUnique<base::ListValue>(); | 254 std::unique_ptr<base::ListValue> json = base::MakeUnique<base::ListValue>(); |
238 BaseValueArgumentParser parser( | 255 BaseValueArgumentParser parser( |
239 signature_, arguments, type_refs, error, json.get()); | 256 context, signature_, arguments, type_refs, error, json.get()); |
240 if (!parser.ParseArguments()) | 257 if (!parser.ParseArguments()) |
241 return false; | 258 return false; |
242 *json_out = std::move(json); | 259 *json_out = std::move(json); |
243 *callback_out = parser.callback(); | 260 *callback_out = parser.callback(); |
244 return true; | 261 return true; |
245 } | 262 } |
246 | 263 |
247 } // namespace extensions | 264 } // namespace extensions |
OLD | NEW |