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

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

Issue 2947463002: [Extensions Bindings] Add a bindings/ subdirectory under renderer (Closed)
Patch Set: . Created 3 years, 5 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
(Empty)
1 // Copyright 2017 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 "extensions/renderer/declarative_event.h"
6
7 #include <algorithm>
8 #include <memory>
9
10 #include "base/memory/ptr_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/values.h"
13 #include "extensions/renderer/api_event_listeners.h"
14 #include "extensions/renderer/api_request_handler.h"
15 #include "extensions/renderer/api_signature.h"
16 #include "extensions/renderer/api_type_reference_map.h"
17 #include "extensions/renderer/argument_spec.h"
18 #include "gin/object_template_builder.h"
19 #include "gin/per_context_data.h"
20
21 namespace extensions {
22
23 namespace {
24
25 // Builds an ArgumentSpec that accepts the given |choices| as references.
26 std::unique_ptr<ArgumentSpec> BuildChoicesSpec(
27 const std::vector<std::string>& choices_list) {
28 auto item_type = base::MakeUnique<ArgumentSpec>(ArgumentType::CHOICES);
29 std::vector<std::unique_ptr<ArgumentSpec>> choices;
30 choices.reserve(choices_list.size());
31 for (const std::string& value : choices_list) {
32 auto choice = base::MakeUnique<ArgumentSpec>(ArgumentType::REF);
33 choice->set_ref(value);
34 choices.push_back(std::move(choice));
35 }
36 item_type->set_choices(std::move(choices));
37 return item_type;
38 }
39
40 // Builds the ArgumentSpec for a events.Rule type, given a list of actions and
41 // conditions. It's insufficient to use the specification in events.Rule, since
42 // that provides argument types of "any" for actions and conditions, allowing
43 // individual APIs to specify them further. Alternatively, we could lookup the
44 // events.Rule spec and only override the actions and conditions properties,
45 // but that doesn't seem any less contrived and requires JSON parsing and
46 // complex spec initialization.
47 // TODO(devlin): Another target for generating these specs. Currently, the
48 // custom JS bindings do something similar, so this is no worse off, but that
49 // doesn't make it more desirable.
50 std::unique_ptr<ArgumentSpec> BuildRulesSpec(
51 const std::vector<std::string>& actions_list,
52 const std::vector<std::string>& conditions_list) {
53 auto rule_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::OBJECT);
54 ArgumentSpec::PropertiesMap properties;
55 {
56 auto id_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::STRING);
57 id_spec->set_optional(true);
58 properties["id"] = std::move(id_spec);
59 }
60 {
61 auto tags_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::LIST);
62 tags_spec->set_list_element_type(
63 base::MakeUnique<ArgumentSpec>(ArgumentType::STRING));
64 tags_spec->set_optional(true);
65 properties["tags"] = std::move(tags_spec);
66 }
67 {
68 auto actions_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::LIST);
69 actions_spec->set_list_element_type(BuildChoicesSpec(actions_list));
70 properties["actions"] = std::move(actions_spec);
71 }
72 {
73 auto conditions_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::LIST);
74 conditions_spec->set_list_element_type(BuildChoicesSpec(conditions_list));
75 properties["conditions"] = std::move(conditions_spec);
76 }
77 {
78 auto priority_spec = base::MakeUnique<ArgumentSpec>(ArgumentType::INTEGER);
79 priority_spec->set_optional(true);
80 properties["priority"] = std::move(priority_spec);
81 }
82 rule_spec->set_properties(std::move(properties));
83 return rule_spec;
84 }
85
86 // Builds the signature for events.addRules using a specific rule.
87 std::unique_ptr<APISignature> BuildAddRulesSignature(
88 const std::string& rule_name) {
89 std::vector<std::unique_ptr<ArgumentSpec>> params;
90 params.push_back(base::MakeUnique<ArgumentSpec>(ArgumentType::STRING));
91 params.push_back(base::MakeUnique<ArgumentSpec>(ArgumentType::INTEGER));
92 {
93 auto rules = base::MakeUnique<ArgumentSpec>(ArgumentType::LIST);
94 auto ref = base::MakeUnique<ArgumentSpec>(ArgumentType::REF);
95 ref->set_ref(rule_name);
96 rules->set_list_element_type(std::move(ref));
97 params.push_back(std::move(rules));
98 }
99 {
100 auto callback = base::MakeUnique<ArgumentSpec>(ArgumentType::FUNCTION);
101 callback->set_optional(true);
102 params.push_back(std::move(callback));
103 }
104
105 return base::MakeUnique<APISignature>(std::move(params));
106 }
107
108 } // namespace
109
110 gin::WrapperInfo DeclarativeEvent::kWrapperInfo = {gin::kEmbedderNativeGin};
111
112 DeclarativeEvent::DeclarativeEvent(
113 const std::string& name,
114 APITypeReferenceMap* type_refs,
115 APIRequestHandler* request_handler,
116 const std::vector<std::string>& actions_list,
117 const std::vector<std::string>& conditions_list,
118 int webview_instance_id)
119 : event_name_(name),
120 type_refs_(type_refs),
121 request_handler_(request_handler),
122 webview_instance_id_(webview_instance_id) {
123 // In declarative events, the specification of the rules can change. This only
124 // matters for the events.addRules function. Check whether or not a
125 // specialized version for this event exists, and, if not, create it.
126 std::string add_rules_name = name + ".addRules";
127 if (!type_refs->HasTypeMethodSignature(add_rules_name)) {
128 // Create the specific rules spec and cache it under this type. This will
129 // result in e.g. declarativeContent.onPageChanged.Rule, since the Rule
130 // schema is only used for this event.
131 std::unique_ptr<ArgumentSpec> rules_spec =
132 BuildRulesSpec(actions_list, conditions_list);
133 std::string rule_type_name = name + ".Rule";
134 type_refs->AddSpec(rule_type_name, std::move(rules_spec));
135 // Build a custom signature for the method, since this would be different
136 // than adding rules for a different event.
137 std::unique_ptr<APISignature> rules_signature =
138 BuildAddRulesSignature(rule_type_name);
139 type_refs->AddTypeMethodSignature(add_rules_name,
140 std::move(rules_signature));
141 }
142 }
143
144 DeclarativeEvent::~DeclarativeEvent() {}
145
146 gin::ObjectTemplateBuilder DeclarativeEvent::GetObjectTemplateBuilder(
147 v8::Isolate* isolate) {
148 return Wrappable<DeclarativeEvent>::GetObjectTemplateBuilder(isolate)
149 .SetMethod("addRules", &DeclarativeEvent::AddRules)
150 .SetMethod("removeRules", &DeclarativeEvent::RemoveRules)
151 .SetMethod("getRules", &DeclarativeEvent::GetRules);
152 }
153
154 void DeclarativeEvent::AddRules(gin::Arguments* arguments) {
155 // When adding rules, we use the signature we built for this event (e.g.
156 // declarativeContent.onPageChanged.addRules).
157 HandleFunction(event_name_ + ".addRules", "events.addRules", arguments);
158 }
159
160 void DeclarativeEvent::RemoveRules(gin::Arguments* arguments) {
161 // The signatures for removeRules are always the same (they don't use the
162 // event's Rule schema).
163 HandleFunction("events.Event.removeRules", "events.removeRules", arguments);
164 }
165
166 void DeclarativeEvent::GetRules(gin::Arguments* arguments) {
167 // The signatures for getRules are always the same (they don't use the
168 // event's Rule schema).
169 HandleFunction("events.Event.getRules", "events.getRules", arguments);
170 }
171
172 void DeclarativeEvent::HandleFunction(const std::string& signature_name,
173 const std::string& request_name,
174 gin::Arguments* arguments) {
175 v8::Isolate* isolate = arguments->isolate();
176 v8::HandleScope handle_scope(isolate);
177 v8::Local<v8::Context> context = arguments->GetHolderCreationContext();
178
179 std::vector<v8::Local<v8::Value>> argument_list = arguments->GetAll();
180
181 // The events API has two undocumented parameters for each function: the name
182 // of the event, and the "webViewInstanceId". Currently, stub 0 for webview
183 // instance id.
184 argument_list.insert(argument_list.begin(),
185 {gin::StringToSymbol(isolate, event_name_),
186 v8::Integer::New(isolate, webview_instance_id_)});
187
188 std::unique_ptr<base::ListValue> converted_arguments;
189 v8::Local<v8::Function> callback;
190 std::string error;
191 const APISignature* signature =
192 type_refs_->GetTypeMethodSignature(signature_name);
193 DCHECK(signature);
194 if (!signature->ParseArgumentsToJSON(context, argument_list, *type_refs_,
195 &converted_arguments, &callback,
196 &error)) {
197 arguments->ThrowTypeError("Invalid invocation");
198 return;
199 }
200
201 request_handler_->StartRequest(
202 context, request_name, std::move(converted_arguments), callback,
203 v8::Local<v8::Function>(), binding::RequestThread::UI);
204 }
205
206 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/declarative_event.h ('k') | extensions/renderer/declarative_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698