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

Side by Side Diff: chrome/renderer/resources/extensions/binding.js

Issue 12647017: Lazily require types when validating Extensions API calls (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 require('json_schema'); 5 require('json_schema');
6 require('event_bindings'); 6 require('event_bindings');
7 var chrome = requireNative('chrome').GetChrome(); 7 var chrome = requireNative('chrome').GetChrome();
8 var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); 8 var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
9 var forEach = require('utils').forEach; 9 var forEach = require('utils').forEach;
10 var GetAvailability = requireNative('v8_context').GetAvailability; 10 var GetAvailability = requireNative('v8_context').GetAvailability;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 function isManifestVersionSupported(schemaNode, manifestVersion) { 110 function isManifestVersionSupported(schemaNode, manifestVersion) {
111 return !schemaNode.maximumManifestVersion || 111 return !schemaNode.maximumManifestVersion ||
112 manifestVersion <= schemaNode.maximumManifestVersion; 112 manifestVersion <= schemaNode.maximumManifestVersion;
113 } 113 }
114 114
115 function isSchemaNodeSupported(schemaNode, platform, manifestVersion) { 115 function isSchemaNodeSupported(schemaNode, platform, manifestVersion) {
116 return isPlatformSupported(schemaNode, platform) && 116 return isPlatformSupported(schemaNode, platform) &&
117 isManifestVersionSupported(schemaNode, manifestVersion); 117 isManifestVersionSupported(schemaNode, manifestVersion);
118 } 118 }
119 119
120 function createCustomType(t) {
121 var customType = require(t['js_module'])[t['js_module']];
not at google - send to devlin 2013/03/21 00:01:13 * t -> type * save reference to t['js_module;] (al
cduvall 2013/03/21 00:59:51 Done.
122 customType.prototype = new CustomBindingsObject();
123 customType.prototype.setSchema(t);
124 return customType;
125 }
126
120 var platform = getPlatform(); 127 var platform = getPlatform();
121 128
122 function Binding(schema) { 129 function Binding(schema) {
123 this.schema_ = schema; 130 this.schema_ = schema;
124 this.apiFunctions_ = new APIFunctions(); 131 this.apiFunctions_ = new APIFunctions();
125 this.customEvent_ = null; 132 this.customEvent_ = null;
126 this.customTypes_ = {};
127 this.customHooks_ = []; 133 this.customHooks_ = [];
128 }; 134 };
129 135
130 Binding.create = function(apiName) { 136 Binding.create = function(apiName) {
131 return new Binding(schemaRegistry.GetSchema(apiName)); 137 return new Binding(schemaRegistry.GetSchema(apiName));
132 }; 138 };
133 139
134 Binding.prototype = { 140 Binding.prototype = {
135 // The API through which the ${api_name}_custom_bindings.js files customize 141 // The API through which the ${api_name}_custom_bindings.js files customize
136 // their API bindings beyond what can be generated. 142 // their API bindings beyond what can be generated.
137 // 143 //
138 // There are 2 types of customizations available: those which are required in 144 // There are 2 types of customizations available: those which are required in
139 // order to do the schema generation (registerCustomEvent and 145 // order to do the schema generation (registerCustomEvent and
140 // registerCustomType), and those which can only run after the bindings have 146 // registerCustomType), and those which can only run after the bindings have
141 // been generated (registerCustomHook). 147 // been generated (registerCustomHook).
142 //
143
144 // Registers a custom type referenced via "$ref" fields in the API schema
145 // JSON.
146 registerCustomType: function(typeName, customTypeFactory) {
147 var customType = customTypeFactory();
148 customType.prototype = new CustomBindingsObject();
149 this.customTypes_[typeName] = customType;
150 },
151 148
152 // Registers a custom event type for the API identified by |namespace|. 149 // Registers a custom event type for the API identified by |namespace|.
153 // |event| is the event's constructor. 150 // |event| is the event's constructor.
154 registerCustomEvent: function(event) { 151 registerCustomEvent: function(event) {
155 this.customEvent_ = event; 152 this.customEvent_ = event;
156 }, 153 },
157 154
158 // Registers a function |hook| to run after the schema for all APIs has been 155 // Registers a function |hook| to run after the schema for all APIs has been
159 // generated. The hook is passed as its first argument an "API" object to 156 // generated. The hook is passed as its first argument an "API" object to
160 // interact with, and second the current extension ID. See where 157 // interact with, and second the current extension ID. See where
(...skipping 16 matching lines...) Expand all
177 schema: this.schema_, 174 schema: this.schema_,
178 compiledApi: api 175 compiledApi: api
179 }, extensionId, contextType); 176 }, extensionId, contextType);
180 }, this); 177 }, this);
181 }, 178 },
182 179
183 // Generates the bindings from |this.schema_| and integrates any custom 180 // Generates the bindings from |this.schema_| and integrates any custom
184 // bindings that might be present. 181 // bindings that might be present.
185 generate: function() { 182 generate: function() {
186 var schema = this.schema_; 183 var schema = this.schema_;
187 var customTypes = this.customTypes_;
188 184
189 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the 185 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the
190 // supporting code. 186 // supporting code.
191 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) { 187 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) {
192 console.error('chrome.' + schema.namespace + ' is not supported on ' + 188 console.error('chrome.' + schema.namespace + ' is not supported on ' +
193 'this platform or manifest version'); 189 'this platform or manifest version');
194 return undefined; 190 return undefined;
195 } 191 }
196 192
197 var availability = GetAvailability(schema.namespace); 193 var availability = GetAvailability(schema.namespace);
198 if (!availability.is_available) { 194 if (!availability.is_available) {
199 console.error('chrome.' + schema.namespace + ' is not available: ' + 195 console.error('chrome.' + schema.namespace + ' is not available: ' +
200 availability.message); 196 availability.message);
201 return undefined; 197 return undefined;
202 } 198 }
203 199
204 // See comment on internalAPIs at the top. 200 // See comment on internalAPIs at the top.
205 var mod = {}; 201 var mod = {};
206 202
207 var namespaces = schema.namespace.split('.'); 203 var namespaces = schema.namespace.split('.');
208 for (var index = 0, name; name = namespaces[index]; index++) { 204 for (var index = 0, name; name = namespaces[index]; index++) {
209 mod[name] = mod[name] || {}; 205 mod[name] = mod[name] || {};
210 mod = mod[name]; 206 mod = mod[name];
211 } 207 }
212 208
213 // Add types to global schemaValidator 209 // Add types to global schemaValidator
not at google - send to devlin 2013/03/21 00:01:13 "the ones for the types we depend on will be added
cduvall 2013/03/21 00:59:51 Done.
not at google - send to devlin 2013/03/21 01:36:55 my bad grammar sorry. 'the types we depend on from
cduvall 2013/03/21 17:16:07 Done.
214 if (schema.types) { 210 if (schema.types) {
215 forEach(schema.types, function(i, t) { 211 forEach(schema.types, function(i, t) {
216 if (!isSchemaNodeSupported(t, platform, manifestVersion)) 212 if (!isSchemaNodeSupported(t, platform, manifestVersion))
217 return; 213 return;
218 214
219 schemaUtils.schemaValidator.addTypes(t); 215 schemaUtils.schemaValidator.addTypes(t);
220 if (t.type == 'object' && this.customTypes_[t.id]) { 216 if (t.type == 'object' && 'js_module' in t) {
not at google - send to devlin 2013/03/21 00:01:13 i think this type == 'object' thing isn't necessar
cduvall 2013/03/21 00:59:51 Done, took it all out.
221 var parts = t.id.split("."); 217 var parts = t.id.split('.');
222 this.customTypes_[t.id].prototype.setSchema(t); 218 mod[parts[parts.length - 1]] = createCustomType(t);
not at google - send to devlin 2013/03/21 00:01:13 looks like this splitting shenanigans also unneces
cduvall 2013/03/21 00:59:51 Done.
223 mod[parts[parts.length - 1]] = this.customTypes_[t.id];
224 } 219 }
225 }, this); 220 }, this);
226 } 221 }
227 222
228 // Returns whether access to the content of a schema should be denied, 223 // Returns whether access to the content of a schema should be denied,
229 // based on the presence of "unprivileged" and whether this is an 224 // based on the presence of "unprivileged" and whether this is an
230 // extension process (versus e.g. a content script). 225 // extension process (versus e.g. a content script).
231 function isSchemaAccessAllowed(itemSchema) { 226 function isSchemaAccessAllowed(itemSchema) {
232 return (contextType == 'BLESSED_EXTENSION') || 227 return (contextType == 'BLESSED_EXTENSION') ||
233 schema.unprivileged || 228 schema.unprivileged ||
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // Values may just have raw types as defined in the JSON, such 359 // Values may just have raw types as defined in the JSON, such
365 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here. 360 // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here.
366 // TODO(kalman): enforce that things with a "value" property can't 361 // TODO(kalman): enforce that things with a "value" property can't
367 // define their own types. 362 // define their own types.
368 var type = propertyDef.type || typeof(value); 363 var type = propertyDef.type || typeof(value);
369 if (type === 'integer' || type === 'number') { 364 if (type === 'integer' || type === 'number') {
370 value = parseInt(value); 365 value = parseInt(value);
371 } else if (type === 'boolean') { 366 } else if (type === 'boolean') {
372 value = value === 'true'; 367 value = value === 'true';
373 } else if (propertyDef['$ref']) { 368 } else if (propertyDef['$ref']) {
374 if (propertyDef['$ref'] in customTypes) { 369 var constructor;
not at google - send to devlin 2013/03/21 00:01:13 not initializing things makes me slightly uncomfor
cduvall 2013/03/21 00:59:51 Done.
375 var constructor = customTypes[propertyDef['$ref']]; 370 var type = utils.loadRefType(propertyDef['$ref'], schema);
376 } else { 371 if (type)
377 var refParts = propertyDef['$ref'].split('.'); 372 var constructor = createCustomType(type);
not at google - send to devlin 2013/03/21 00:01:13 var here doesn't make sense
cduvall 2013/03/21 00:59:51 Done.
378 // This should never try to load a $ref in the current namespace.
379 var constructor = utils.loadRefDependency(
380 propertyDef['$ref'])[refParts[refParts.length - 1]];
381 }
382 if (!constructor) 373 if (!constructor)
383 throw new Error('No custom binding for ' + propertyDef['$ref']); 374 throw new Error('No custom binding for ' + propertyDef['$ref']);
384 var args = value; 375 var args = value;
385 // For an object propertyDef, |value| is an array of constructor 376 // For an object propertyDef, |value| is an array of constructor
386 // arguments, but we want to pass the arguments directly (i.e. 377 // arguments, but we want to pass the arguments directly (i.e.
387 // not as an array), so we have to fake calling |new| on the 378 // not as an array), so we have to fake calling |new| on the
388 // constructor. 379 // constructor.
389 value = { __proto__: constructor.prototype }; 380 value = { __proto__: constructor.prototype };
390 constructor.apply(value, args); 381 constructor.apply(value, args);
391 // Recursively add properties. 382 // Recursively add properties.
(...skipping 10 matching lines...) Expand all
402 }); 393 });
403 }; 394 };
404 395
405 addProperties(mod, schema); 396 addProperties(mod, schema);
406 this.runHooks_(mod); 397 this.runHooks_(mod);
407 return mod; 398 return mod;
408 } 399 }
409 }; 400 };
410 401
411 exports.Binding = Binding; 402 exports.Binding = Binding;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698