1// Copyright 2014 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// Custom binding for the Permissions API.
6
7var binding = require('binding').Binding.create('permissions');
8
9var Event = require('event_bindings').Event;
10
11// These custom binding are only necessary because it is not currently
12// possible to have a union of types as the type of the items in an array.
13// Once that is fixed, this entire file should go away.
14// See,
15// https://code.google.com/p/chromium/issues/detail?id=162044
16// https://code.google.com/p/chromium/issues/detail?id=162042
17// TODO(bryeung): delete this file.
18binding.registerCustomHook(function(api) {
19  var apiFunctions = api.apiFunctions;
20  var permissions = api.compiledApi;
21
22  function maybeConvertToObject(str) {
23    var parts = $String.split(str, '|');
24    if (parts.length != 2)
25      return str;
26
27    var ret = {};
28    ret[parts[0]] = JSON.parse(parts[1]);
29    return ret;
30  }
31
32  function convertObjectPermissionsToStrings() {
33    if (arguments.length < 1)
34      return arguments;
35
36    var args = arguments[0].permissions;
37    if (!args)
38      return arguments;
39
40    for (var i = 0; i < args.length; i += 1) {
41      if (typeof(args[i]) == 'object') {
42        var a = args[i];
43        var keys = $Object.keys(a);
44        if (keys.length != 1) {
45          throw new Error("Too many keys in object-style permission.");
46        }
47        arguments[0].permissions[i] = keys[0] + '|' +
48            JSON.stringify(a[keys[0]]);
49      }
50    }
51
52    return arguments;
53  }
54
55  // Convert complex permissions to strings so they validate against the schema
56  apiFunctions.setUpdateArgumentsPreValidate(
57      'contains', convertObjectPermissionsToStrings);
58  apiFunctions.setUpdateArgumentsPreValidate(
59      'remove', convertObjectPermissionsToStrings);
60  apiFunctions.setUpdateArgumentsPreValidate(
61      'request', convertObjectPermissionsToStrings);
62
63  // Convert complex permissions back to objects
64  apiFunctions.setCustomCallback('getAll',
65      function(name, request, response) {
66        for (var i = 0; i < response.permissions.length; i += 1) {
67          response.permissions[i] =
68              maybeConvertToObject(response.permissions[i]);
69        }
70
71        // Since the schema says Permissions.permissions contains strings and
72        // not objects, validation will fail after the for-loop above.  This
73        // skips validation and calls the callback directly, then clears it so
74        // that handleResponse doesn't call it again.
75        try {
76          if (request.callback)
77            $Function.apply(request.callback, request, [response]);
78        } finally {
79          delete request.callback;
80        }
81      });
82
83  // Also convert complex permissions back to objects for events.  The
84  // dispatchToListener call happens after argument validation, which works
85  // around the problem that Permissions.permissions is supposed to be a list
86  // of strings.
87  permissions.onAdded.dispatchToListener = function(callback, args) {
88    for (var i = 0; i < args[0].permissions.length; i += 1) {
89      args[0].permissions[i] = maybeConvertToObject(args[0].permissions[i]);
90    }
91    $Function.call(Event.prototype.dispatchToListener, this, callback, args);
92  };
93  permissions.onRemoved.dispatchToListener =
94      permissions.onAdded.dispatchToListener;
95});
96
97exports.binding = binding.generate();
98