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