Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: extensions/renderer/api_signature.cc

Issue 2598123002: [Extensions Bindings] Add support for updateArgumentsPreValidate (Closed)
Patch Set: . Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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(&param)); 222 CHECK(value->GetAsDictionary(&param));
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698