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 extension API.
      6 
      7 var binding = require('binding').Binding.create('extension');
      8 
      9 var extensionNatives = requireNative('extension');
     10 var GetExtensionViews = extensionNatives.GetExtensionViews;
     11 var messaging = require('messaging');
     12 var runtimeNatives = requireNative('runtime');
     13 var OpenChannelToExtension = runtimeNatives.OpenChannelToExtension;
     14 var OpenChannelToNativeApp = runtimeNatives.OpenChannelToNativeApp;
     15 var chrome = requireNative('chrome').GetChrome();
     16 
     17 var inIncognitoContext = requireNative('process').InIncognitoContext();
     18 var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled();
     19 var contextType = requireNative('process').GetContextType();
     20 var manifestVersion = requireNative('process').GetManifestVersion();
     21 
     22 // This should match chrome.windows.WINDOW_ID_NONE.
     23 //
     24 // We can't use chrome.windows.WINDOW_ID_NONE directly because the
     25 // chrome.windows API won't exist unless this extension has permission for it;
     26 // which may not be the case.
     27 var WINDOW_ID_NONE = -1;
     28 
     29 binding.registerCustomHook(function(bindingsAPI, extensionId) {
     30   var extension = bindingsAPI.compiledApi;
     31   if (manifestVersion < 2) {
     32     chrome.self = extension;
     33     extension.inIncognitoTab = inIncognitoContext;
     34   }
     35   extension.inIncognitoContext = inIncognitoContext;
     36 
     37   var apiFunctions = bindingsAPI.apiFunctions;
     38 
     39   apiFunctions.setHandleRequest('getViews', function(properties) {
     40     var windowId = WINDOW_ID_NONE;
     41     var type = 'ALL';
     42     if (properties) {
     43       if (properties.type != null) {
     44         type = properties.type;
     45       }
     46       if (properties.windowId != null) {
     47         windowId = properties.windowId;
     48       }
     49     }
     50     return GetExtensionViews(windowId, type);
     51   });
     52 
     53   apiFunctions.setHandleRequest('getBackgroundPage', function() {
     54     return GetExtensionViews(-1, 'BACKGROUND')[0] || null;
     55   });
     56 
     57   apiFunctions.setHandleRequest('getExtensionTabs', function(windowId) {
     58     if (windowId == null)
     59       windowId = WINDOW_ID_NONE;
     60     return GetExtensionViews(windowId, 'TAB');
     61   });
     62 
     63   apiFunctions.setHandleRequest('getURL', function(path) {
     64     path = String(path);
     65     if (!path.length || path[0] != '/')
     66       path = '/' + path;
     67     return 'chrome-extension://' + extensionId + path;
     68   });
     69 
     70   // Alias several messaging deprecated APIs to their runtime counterparts.
     71   var mayNeedAlias = [
     72     // Types
     73     'Port',
     74     // Functions
     75     'connect', 'sendMessage', 'connectNative', 'sendNativeMessage',
     76     // Events
     77     'onConnect', 'onConnectExternal', 'onMessage', 'onMessageExternal'
     78   ];
     79   $Array.forEach(mayNeedAlias, function(alias) {
     80     // Checking existence isn't enough since some functions are disabled via
     81     // getters that throw exceptions. Assume that any getter is such a function.
     82     if (chrome.runtime &&
     83         $Object.hasOwnProperty(chrome.runtime, alias) &&
     84         chrome.runtime.__lookupGetter__(alias) === undefined) {
     85       extension[alias] = chrome.runtime[alias];
     86     }
     87   });
     88 
     89   apiFunctions.setUpdateArgumentsPreValidate('sendRequest',
     90       $Function.bind(messaging.sendMessageUpdateArguments,
     91                      null, 'sendRequest'));
     92 
     93   apiFunctions.setHandleRequest('sendRequest',
     94                                 function(targetId, request, responseCallback) {
     95     if (sendRequestIsDisabled)
     96       throw new Error(sendRequestIsDisabled);
     97     var port = chrome.runtime.connect(targetId || extensionId,
     98                                       {name: messaging.kRequestChannel});
     99     messaging.sendMessageImpl(port, request, responseCallback);
    100   });
    101 
    102   if (sendRequestIsDisabled) {
    103     extension.onRequest.addListener = function() {
    104       throw new Error(sendRequestIsDisabled);
    105     };
    106     if (contextType == 'BLESSED_EXTENSION') {
    107       extension.onRequestExternal.addListener = function() {
    108         throw new Error(sendRequestIsDisabled);
    109       };
    110     }
    111   }
    112 });
    113 
    114 exports.binding = binding.generate();
    115