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