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

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

Issue 2615773002: [Extensions Bindings] Add enum support (Closed)
Patch Set: nits Created 3 years, 11 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
« no previous file with comments | « extensions/renderer/api_binding.h ('k') | extensions/renderer/api_binding_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_binding.h" 5 #include "extensions/renderer/api_binding.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "extensions/common/extension_api.h" 15 #include "extensions/common/extension_api.h"
15 #include "extensions/renderer/api_binding_hooks.h" 16 #include "extensions/renderer/api_binding_hooks.h"
16 #include "extensions/renderer/api_event_handler.h" 17 #include "extensions/renderer/api_event_handler.h"
17 #include "extensions/renderer/api_signature.h" 18 #include "extensions/renderer/api_signature.h"
18 #include "extensions/renderer/v8_helpers.h" 19 #include "extensions/renderer/v8_helpers.h"
19 #include "gin/arguments.h" 20 #include "gin/arguments.h"
20 #include "gin/per_context_data.h" 21 #include "gin/per_context_data.h"
21 22
22 namespace extensions { 23 namespace extensions {
23 24
24 namespace { 25 namespace {
25 26
27 // Returns the name of the enum value for use in JavaScript; JS enum entries use
28 // SCREAMING_STYLE.
29 std::string GetJSEnumEntryName(const std::string& original) {
30 std::string result;
31 DCHECK(!original.empty());
32 // If the original starts with a digit, prefix it with an underscore.
33 if (base::IsAsciiDigit(original[0]))
34 result.push_back('_');
35 // Given 'myEnum-Foo':
36 for (size_t i = 0; i < original.size(); ++i) {
37 // Add an underscore between camelcased items:
38 // 'myEnum-Foo' -> 'mY_Enum-Foo'
39 if (i > 0 && base::IsAsciiLower(original[i - 1]) &&
40 base::IsAsciiUpper(original[i])) {
41 result.push_back('_');
42 result.push_back(original[i]);
43 } else if (original[i] == '-') { // 'mY_Enum-Foo' -> 'mY_Enum_Foo'
44 result.push_back('_');
45 } else { // 'mY_Enum_Foo' -> 'MY_ENUM_FOO'
46 result.push_back(base::ToUpperASCII(original[i]));
47 }
48 }
49 return result;
50 }
51
26 const char kExtensionAPIPerContextKey[] = "extension_api_binding"; 52 const char kExtensionAPIPerContextKey[] = "extension_api_binding";
27 53
28 struct APIPerContextData : public base::SupportsUserData::Data { 54 struct APIPerContextData : public base::SupportsUserData::Data {
29 std::vector<std::unique_ptr<APIBinding::HandlerCallback>> context_callbacks; 55 std::vector<std::unique_ptr<APIBinding::HandlerCallback>> context_callbacks;
30 }; 56 };
31 57
32 void CallbackHelper(const v8::FunctionCallbackInfo<v8::Value>& info) { 58 void CallbackHelper(const v8::FunctionCallbackInfo<v8::Value>& info) {
33 gin::Arguments args(info); 59 gin::Arguments args(info);
34 60
35 // If the current context (the in which this function was created) has been 61 // If the current context (the in which this function was created) has been
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 const base::DictionaryValue* func_dict = nullptr; 107 const base::DictionaryValue* func_dict = nullptr;
82 CHECK(func->GetAsDictionary(&func_dict)); 108 CHECK(func->GetAsDictionary(&func_dict));
83 std::string name; 109 std::string name;
84 CHECK(func_dict->GetString("name", &name)); 110 CHECK(func_dict->GetString("name", &name));
85 111
86 const base::ListValue* params = nullptr; 112 const base::ListValue* params = nullptr;
87 CHECK(func_dict->GetList("parameters", &params)); 113 CHECK(func_dict->GetList("parameters", &params));
88 signatures_[name] = base::MakeUnique<APISignature>(*params); 114 signatures_[name] = base::MakeUnique<APISignature>(*params);
89 } 115 }
90 } 116 }
117
91 if (type_definitions) { 118 if (type_definitions) {
92 for (const auto& type : *type_definitions) { 119 for (const auto& type : *type_definitions) {
93 const base::DictionaryValue* type_dict = nullptr; 120 const base::DictionaryValue* type_dict = nullptr;
94 CHECK(type->GetAsDictionary(&type_dict)); 121 CHECK(type->GetAsDictionary(&type_dict));
95 std::string id; 122 std::string id;
96 CHECK(type_dict->GetString("id", &id)); 123 CHECK(type_dict->GetString("id", &id));
97 DCHECK(type_refs->find(id) == type_refs->end()); 124 DCHECK(type_refs->find(id) == type_refs->end());
98 // TODO(devlin): refs are sometimes preceeded by the API namespace; we 125 // TODO(devlin): refs are sometimes preceeded by the API namespace; we
99 // might need to take that into account. 126 // might need to take that into account.
100 (*type_refs)[id] = base::MakeUnique<ArgumentSpec>(*type_dict); 127 auto argument_spec = base::MakeUnique<ArgumentSpec>(*type_dict);
128 const std::set<std::string>& enum_values = argument_spec->enum_values();
129 if (!enum_values.empty()) {
130 // Type names may be prefixed by the api name. If so, remove the prefix.
131 base::Optional<std::string> stripped_id;
132 if (base::StartsWith(id, api_name_, base::CompareCase::SENSITIVE))
133 stripped_id = id.substr(api_name_.size() + 1); // +1 for trailing '.'
134 std::vector<EnumEntry>& entries =
135 enums_[stripped_id ? *stripped_id : id];
136 entries.reserve(enum_values.size());
137 for (const auto& enum_value : enum_values) {
138 entries.push_back(
139 std::make_pair(enum_value, GetJSEnumEntryName(enum_value)));
140 }
141 }
142 (*type_refs)[id] = std::move(argument_spec);
101 } 143 }
102 } 144 }
145
103 if (event_definitions) { 146 if (event_definitions) {
104 event_names_.reserve(event_definitions->GetSize()); 147 event_names_.reserve(event_definitions->GetSize());
105 for (const auto& event : *event_definitions) { 148 for (const auto& event : *event_definitions) {
106 const base::DictionaryValue* event_dict = nullptr; 149 const base::DictionaryValue* event_dict = nullptr;
107 CHECK(event->GetAsDictionary(&event_dict)); 150 CHECK(event->GetAsDictionary(&event_dict));
108 std::string name; 151 std::string name;
109 CHECK(event_dict->GetString("name", &name)); 152 CHECK(event_dict->GetString("name", &name));
110 event_names_.push_back(std::move(name)); 153 event_names_.push_back(std::move(name));
111 } 154 }
112 } 155 }
(...skipping 14 matching lines...) Expand all
127 gin::PerContextData* per_context_data = gin::PerContextData::From(context); 170 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
128 DCHECK(per_context_data); 171 DCHECK(per_context_data);
129 APIPerContextData* data = static_cast<APIPerContextData*>( 172 APIPerContextData* data = static_cast<APIPerContextData*>(
130 per_context_data->GetUserData(kExtensionAPIPerContextKey)); 173 per_context_data->GetUserData(kExtensionAPIPerContextKey));
131 if (!data) { 174 if (!data) {
132 auto api_data = base::MakeUnique<APIPerContextData>(); 175 auto api_data = base::MakeUnique<APIPerContextData>();
133 data = api_data.get(); 176 data = api_data.get();
134 per_context_data->SetUserData(kExtensionAPIPerContextKey, 177 per_context_data->SetUserData(kExtensionAPIPerContextKey,
135 api_data.release()); 178 api_data.release());
136 } 179 }
180
137 for (const auto& sig : signatures_) { 181 for (const auto& sig : signatures_) {
138 std::string full_method_name = 182 std::string full_method_name =
139 base::StringPrintf("%s.%s", api_name_.c_str(), sig.first.c_str()); 183 base::StringPrintf("%s.%s", api_name_.c_str(), sig.first.c_str());
140 184
141 if (!is_available.Run(full_method_name)) 185 if (!is_available.Run(full_method_name))
142 continue; 186 continue;
143 187
144 auto handler_callback = base::MakeUnique<HandlerCallback>( 188 auto handler_callback = base::MakeUnique<HandlerCallback>(
145 base::Bind(&APIBinding::HandleCall, weak_factory_.GetWeakPtr(), 189 base::Bind(&APIBinding::HandleCall, weak_factory_.GetWeakPtr(),
146 full_method_name, sig.second.get())); 190 full_method_name, sig.second.get()));
(...skipping 15 matching lines...) Expand all
162 base::StringPrintf("%s.%s", api_name_.c_str(), event_name.c_str()); 206 base::StringPrintf("%s.%s", api_name_.c_str(), event_name.c_str());
163 v8::Local<v8::Object> event = 207 v8::Local<v8::Object> event =
164 event_handler->CreateEventInstance(full_event_name, context); 208 event_handler->CreateEventInstance(full_event_name, context);
165 DCHECK(!event.IsEmpty()); 209 DCHECK(!event.IsEmpty());
166 v8::Maybe<bool> success = object->CreateDataProperty( 210 v8::Maybe<bool> success = object->CreateDataProperty(
167 context, gin::StringToSymbol(isolate, event_name), event); 211 context, gin::StringToSymbol(isolate, event_name), event);
168 DCHECK(success.IsJust()); 212 DCHECK(success.IsJust());
169 DCHECK(success.FromJust()); 213 DCHECK(success.FromJust());
170 } 214 }
171 215
216 for (const auto& entry : enums_) {
217 // TODO(devlin): Store these on an ObjectTemplate.
218 v8::Local<v8::Object> enum_object = v8::Object::New(isolate);
219 for (const auto& enum_entry : entry.second) {
220 v8::Maybe<bool> success = enum_object->CreateDataProperty(
221 context, gin::StringToSymbol(isolate, enum_entry.second),
222 gin::StringToSymbol(isolate, enum_entry.first));
223 DCHECK(success.IsJust());
224 DCHECK(success.FromJust());
225 }
226 v8::Maybe<bool> success = object->CreateDataProperty(
227 context, gin::StringToSymbol(isolate, entry.first), enum_object);
228 DCHECK(success.IsJust());
229 DCHECK(success.FromJust());
230 }
231
172 binding_hooks_->InitializeInContext(context, api_name_); 232 binding_hooks_->InitializeInContext(context, api_name_);
173 233
174 return object; 234 return object;
175 } 235 }
176 236
177 v8::Local<v8::Object> APIBinding::GetJSHookInterface( 237 v8::Local<v8::Object> APIBinding::GetJSHookInterface(
178 v8::Local<v8::Context> context) { 238 v8::Local<v8::Context> context) {
179 return binding_hooks_->GetJSHookInterface(api_name_, context); 239 return binding_hooks_->GetJSHookInterface(api_name_, context);
180 } 240 }
181 241
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 arguments->ThrowTypeError("Invalid invocation"); 303 arguments->ThrowTypeError("Invalid invocation");
244 return; 304 return;
245 } 305 }
246 306
247 DCHECK(converted_arguments); 307 DCHECK(converted_arguments);
248 method_callback_.Run(name, std::move(converted_arguments), isolate, context, 308 method_callback_.Run(name, std::move(converted_arguments), isolate, context,
249 callback); 309 callback);
250 } 310 }
251 311
252 } // namespace extensions 312 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/api_binding.h ('k') | extensions/renderer/api_binding_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698