OLD | NEW |
---|---|
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; |
11 var logging = requireNative('logging'); | 11 var logging = requireNative('logging'); |
12 var process = requireNative('process'); | 12 var process = requireNative('process'); |
13 var contextType = process.GetContextType(); | 13 var contextType = process.GetContextType(); |
14 var extensionId = process.GetExtensionId(); | 14 var extensionId = process.GetExtensionId(); |
15 var manifestVersion = process.GetManifestVersion(); | 15 var manifestVersion = process.GetManifestVersion(); |
16 var schemaRegistry = requireNative('schema_registry'); | 16 var schemaRegistry = requireNative('schema_registry'); |
17 var schemaUtils = require('schemaUtils'); | 17 var schemaUtils = require('schemaUtils'); |
18 var sendRequest = require('sendRequest').sendRequest; | 18 var sendRequest = require('sendRequest').sendRequest; |
19 var utils = require('utils'); | 19 var utils = require('utils'); |
20 var CHECK = requireNative('logging').CHECK; | |
20 | 21 |
21 // Stores the name and definition of each API function, with methods to | 22 // Stores the name and definition of each API function, with methods to |
22 // modify their behaviour (such as a custom way to handle requests to the | 23 // modify their behaviour (such as a custom way to handle requests to the |
23 // API, a custom callback, etc). | 24 // API, a custom callback, etc). |
24 function APIFunctions() { | 25 function APIFunctions() { |
25 this.apiFunctions_ = {}; | 26 this.apiFunctions_ = {}; |
26 this.unavailableApiFunctions_ = {}; | 27 this.unavailableApiFunctions_ = {}; |
27 } | 28 } |
28 | 29 |
29 APIFunctions.prototype.register = function(apiName, apiFunction) { | 30 APIFunctions.prototype.register = function(apiName, apiFunction) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 function isManifestVersionSupported(schemaNode, manifestVersion) { | 111 function isManifestVersionSupported(schemaNode, manifestVersion) { |
111 return !schemaNode.maximumManifestVersion || | 112 return !schemaNode.maximumManifestVersion || |
112 manifestVersion <= schemaNode.maximumManifestVersion; | 113 manifestVersion <= schemaNode.maximumManifestVersion; |
113 } | 114 } |
114 | 115 |
115 function isSchemaNodeSupported(schemaNode, platform, manifestVersion) { | 116 function isSchemaNodeSupported(schemaNode, platform, manifestVersion) { |
116 return isPlatformSupported(schemaNode, platform) && | 117 return isPlatformSupported(schemaNode, platform) && |
117 isManifestVersionSupported(schemaNode, manifestVersion); | 118 isManifestVersionSupported(schemaNode, manifestVersion); |
118 } | 119 } |
119 | 120 |
121 function createCustomType(type) { | |
122 var jsModule = type.js_module; | |
123 CHECK(jsModule, 'Custom type has no "js_module" property.'); | |
not at google - send to devlin
2013/03/21 01:36:55
'custom type ' + type.id + ' must have a...'
cduvall
2013/03/21 17:16:07
Done.
| |
124 var customType = require(jsModule)[jsModule]; | |
not at google - send to devlin
2013/03/21 01:36:55
i don't really know how paranoid we should be here
cduvall
2013/03/21 17:16:07
Done.
| |
125 customType.prototype = new CustomBindingsObject(); | |
126 customType.prototype.setSchema(type); | |
127 return customType; | |
128 } | |
129 | |
120 var platform = getPlatform(); | 130 var platform = getPlatform(); |
121 | 131 |
122 function Binding(schema) { | 132 function Binding(schema) { |
123 this.schema_ = schema; | 133 this.schema_ = schema; |
124 this.apiFunctions_ = new APIFunctions(); | 134 this.apiFunctions_ = new APIFunctions(); |
125 this.customEvent_ = null; | 135 this.customEvent_ = null; |
126 this.customTypes_ = {}; | |
127 this.customHooks_ = []; | 136 this.customHooks_ = []; |
128 }; | 137 }; |
129 | 138 |
130 Binding.create = function(apiName) { | 139 Binding.create = function(apiName) { |
131 return new Binding(schemaRegistry.GetSchema(apiName)); | 140 return new Binding(schemaRegistry.GetSchema(apiName)); |
132 }; | 141 }; |
133 | 142 |
134 Binding.prototype = { | 143 Binding.prototype = { |
135 // The API through which the ${api_name}_custom_bindings.js files customize | 144 // The API through which the ${api_name}_custom_bindings.js files customize |
136 // their API bindings beyond what can be generated. | 145 // their API bindings beyond what can be generated. |
137 // | 146 // |
138 // There are 2 types of customizations available: those which are required in | 147 // There are 2 types of customizations available: those which are required in |
139 // order to do the schema generation (registerCustomEvent and | 148 // order to do the schema generation (registerCustomEvent and |
140 // registerCustomType), and those which can only run after the bindings have | 149 // registerCustomType), and those which can only run after the bindings have |
141 // been generated (registerCustomHook). | 150 // 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 | 151 |
152 // Registers a custom event type for the API identified by |namespace|. | 152 // Registers a custom event type for the API identified by |namespace|. |
153 // |event| is the event's constructor. | 153 // |event| is the event's constructor. |
154 registerCustomEvent: function(event) { | 154 registerCustomEvent: function(event) { |
155 this.customEvent_ = event; | 155 this.customEvent_ = event; |
156 }, | 156 }, |
157 | 157 |
158 // Registers a function |hook| to run after the schema for all APIs has been | 158 // 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 | 159 // generated. The hook is passed as its first argument an "API" object to |
160 // interact with, and second the current extension ID. See where | 160 // interact with, and second the current extension ID. See where |
(...skipping 16 matching lines...) Expand all Loading... | |
177 schema: this.schema_, | 177 schema: this.schema_, |
178 compiledApi: api | 178 compiledApi: api |
179 }, extensionId, contextType); | 179 }, extensionId, contextType); |
180 }, this); | 180 }, this); |
181 }, | 181 }, |
182 | 182 |
183 // Generates the bindings from |this.schema_| and integrates any custom | 183 // Generates the bindings from |this.schema_| and integrates any custom |
184 // bindings that might be present. | 184 // bindings that might be present. |
185 generate: function() { | 185 generate: function() { |
186 var schema = this.schema_; | 186 var schema = this.schema_; |
187 var customTypes = this.customTypes_; | |
188 | 187 |
189 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the | 188 // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the |
190 // supporting code. | 189 // supporting code. |
191 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) { | 190 if (!isSchemaNodeSupported(schema, platform, manifestVersion)) { |
192 console.error('chrome.' + schema.namespace + ' is not supported on ' + | 191 console.error('chrome.' + schema.namespace + ' is not supported on ' + |
193 'this platform or manifest version'); | 192 'this platform or manifest version'); |
194 return undefined; | 193 return undefined; |
195 } | 194 } |
196 | 195 |
197 var availability = GetAvailability(schema.namespace); | 196 var availability = GetAvailability(schema.namespace); |
198 if (!availability.is_available) { | 197 if (!availability.is_available) { |
199 console.error('chrome.' + schema.namespace + ' is not available: ' + | 198 console.error('chrome.' + schema.namespace + ' is not available: ' + |
200 availability.message); | 199 availability.message); |
201 return undefined; | 200 return undefined; |
202 } | 201 } |
203 | 202 |
204 // See comment on internalAPIs at the top. | 203 // See comment on internalAPIs at the top. |
205 var mod = {}; | 204 var mod = {}; |
206 | 205 |
207 var namespaces = schema.namespace.split('.'); | 206 var namespaces = schema.namespace.split('.'); |
208 for (var index = 0, name; name = namespaces[index]; index++) { | 207 for (var index = 0, name; name = namespaces[index]; index++) { |
209 mod[name] = mod[name] || {}; | 208 mod[name] = mod[name] || {}; |
210 mod = mod[name]; | 209 mod = mod[name]; |
211 } | 210 } |
212 | 211 |
213 // Add types to global schemaValidator | 212 // Add types to global schemaValidator, the ones for the types we depend on |
213 // will be added as needed. | |
214 if (schema.types) { | 214 if (schema.types) { |
215 forEach(schema.types, function(i, t) { | 215 forEach(schema.types, function(i, t) { |
216 if (!isSchemaNodeSupported(t, platform, manifestVersion)) | 216 if (!isSchemaNodeSupported(t, platform, manifestVersion)) |
217 return; | 217 return; |
218 | 218 |
219 schemaUtils.schemaValidator.addTypes(t); | 219 schemaUtils.schemaValidator.addTypes(t); |
220 if (t.type == 'object' && this.customTypes_[t.id]) { | |
221 var parts = t.id.split("."); | |
222 this.customTypes_[t.id].prototype.setSchema(t); | |
223 mod[parts[parts.length - 1]] = this.customTypes_[t.id]; | |
224 } | |
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 || |
234 itemSchema.unprivileged; | 229 itemSchema.unprivileged; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 = null; |
375 var constructor = customTypes[propertyDef['$ref']]; | 370 var type = utils.loadTypeSchema(propertyDef['$ref'], schema); |
376 } else { | 371 if (type) |
377 var refParts = propertyDef['$ref'].split('.'); | 372 constructor = createCustomType(type); |
not at google - send to devlin
2013/03/21 01:36:55
looks like it's actually impossible for createCust
cduvall
2013/03/21 17:16:07
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 Loading... | |
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; |
OLD | NEW |