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