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 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