Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / certificate_provider_custom_bindings.js
blob6089677b2a8f6e7a1db4bbc2c091e46f0e3105fc
1 // Copyright 2015 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.
5 var binding = require('binding').Binding.create('certificateProvider');
6 var certificateProviderInternal = require('binding').Binding.create(
7     'certificateProviderInternal').generate();
8 var eventBindings = require('event_bindings');
10 var certificateProviderSchema =
11     requireNative('schema_registry').GetSchema('certificateProvider')
12 var utils = require('utils');
13 var validate = require('schemaUtils').validate;
15 // Custom bindings for chrome.certificateProvider API.
16 // The bindings are used to implement callbacks for the API events. Internally
17 // each event is passed a requestId argument used to identify the callback
18 // associated with the event. This argument is massaged out from the event
19 // arguments before dispatching the event to consumers. A callback is appended
20 // to the event arguments. The callback wraps an appropriate
21 // chrome.certificateProviderInternal API function that is used to report the
22 // event result from the extension. The function is passed the requestId and
23 // values provided by the extension. It validates that the values provided by
24 // the extension match chrome.certificateProvider event callback schemas. It
25 // also ensures that a callback is run at most once. In case there is an
26 // exception during event dispatching, the chrome.certificateProviderInternal
27 // function is called with a default error value.
29 // Handles a chrome.certificateProvider event as described in the file comment.
30 // |eventName|: The event name. The first argument of the event must be a
31 //     request id.
32 // |internalReportFunc|: The function that should be called to report results in
33 //     reply to an event. The first argument of the function must be the request
34 //     id that was received with the event.
35 function handleEvent(eventName, internalReportFunc) {
36   var eventSchema =
37       utils.lookup(certificateProviderSchema.events, 'name', eventName);
38   var callbackSchema = utils.lookup(eventSchema.parameters, 'type', 'function');
40   eventBindings.registerArgumentMassager(
41       'certificateProvider.' + eventName,
42       function(args, dispatch) {
43         var responded = false;
45         // Function provided to the extension as the event callback argument.
46         // The extension calls this to report results in reply to the event.
47         // It throws an exception if called more than once and if the provided
48         // results don't match the callback schema.
49         var reportFunc = function(reportArg1, reportArg2) {
50           if (responded) {
51             throw new Error(
52                 'Event callback must not be called more than once.');
53           }
55           var reportArgs = [reportArg1];
56           if (reportArg2 !== undefined)
57             reportArgs.push(reportArg2);
58           var finalArgs = [];
59           try {
60             // Validates that the results reported by the extension matche the
61             // callback schema of the event. Throws an exception in case of an
62             // error.
63             validate(reportArgs, callbackSchema.parameters);
64             finalArgs = reportArgs;
65           } finally {
66             responded = true;
67             internalReportFunc.apply(
68                 null, [args[0] /* requestId */].concat(finalArgs));
69           }
70         };
71         dispatch(args.slice(1).concat(reportFunc));
72       });
75 handleEvent('onCertificatesRequested',
76             certificateProviderInternal.reportCertificates);
78 handleEvent('onSignDigestRequested',
79             certificateProviderInternal.reportSignature);
81 exports.binding = binding.generate();