Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Custom binding for the runtime API. | 5 // Custom binding for the runtime API. |
| 6 | 6 |
| 7 var binding = require('binding').Binding.create('runtime'); | 7 var binding = require('binding').Binding.create('runtime'); |
| 8 | 8 |
| 9 var messaging = require('messaging'); | 9 var messaging = require('messaging'); |
| 10 var runtimeNatives = requireNative('runtime'); | 10 var runtimeNatives = requireNative('runtime'); |
| 11 var process = requireNative('process'); | 11 var process = requireNative('process'); |
| 12 var forEach = require('utils').forEach; | 12 var utils = require('utils'); |
| 13 | 13 |
| 14 var backgroundPage = window; | 14 var backgroundPage = window; |
| 15 var backgroundRequire = require; | 15 var backgroundRequire = require; |
| 16 var contextType = process.GetContextType(); | 16 var contextType = process.GetContextType(); |
| 17 | |
| 17 if (contextType == 'BLESSED_EXTENSION' || | 18 if (contextType == 'BLESSED_EXTENSION' || |
| 18 contextType == 'UNBLESSED_EXTENSION') { | 19 contextType == 'UNBLESSED_EXTENSION') { |
| 19 var manifest = runtimeNatives.GetManifest(); | 20 var manifest = runtimeNatives.GetManifest(); |
| 20 if (manifest.app && manifest.app.background) { | 21 if (manifest.app && manifest.app.background) { |
| 21 // Get the background page if one exists. Otherwise, default to the current | 22 // Get the background page if one exists. Otherwise, default to the current |
| 22 // window. | 23 // window. |
| 23 backgroundPage = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0]; | 24 backgroundPage = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0]; |
| 24 if (backgroundPage) { | 25 if (backgroundPage) { |
| 25 var GetModuleSystem = requireNative('v8_context').GetModuleSystem; | 26 var GetModuleSystem = requireNative('v8_context').GetModuleSystem; |
| 26 backgroundRequire = GetModuleSystem(backgroundPage).require; | 27 backgroundRequire = GetModuleSystem(backgroundPage).require; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 callback); | 65 callback); |
| 65 } | 66 } |
| 66 } | 67 } |
| 67 }); | 68 }); |
| 68 }; | 69 }; |
| 69 } else { | 70 } else { |
| 70 // Force the runtime API to be loaded in the background page. Using | 71 // Force the runtime API to be loaded in the background page. Using |
| 71 // backgroundPageModuleSystem.require('runtime') is insufficient as | 72 // backgroundPageModuleSystem.require('runtime') is insufficient as |
| 72 // requireNative is only allowed while lazily loading an API. | 73 // requireNative is only allowed while lazily loading an API. |
| 73 backgroundPage.chrome.runtime; | 74 backgroundPage.chrome.runtime; |
| 74 var bindDirectoryEntryCallback = backgroundRequire( | 75 var bindDirectoryEntryCallback = |
| 75 'runtime').bindDirectoryEntryCallback; | 76 backgroundRequire('runtime').bindDirectoryEntryCallback; |
| 76 } | 77 } |
| 77 | 78 |
| 78 binding.registerCustomHook(function(binding, id, contextType) { | 79 binding.registerCustomHook(function(binding, id, contextType) { |
| 79 var apiFunctions = binding.apiFunctions; | 80 var apiFunctions = binding.apiFunctions; |
| 80 var runtime = binding.compiledApi; | 81 var runtime = binding.compiledApi; |
| 81 | 82 |
| 82 // | 83 // |
| 83 // Unprivileged APIs. | 84 // Unprivileged APIs. |
| 84 // | 85 // |
| 85 | 86 |
| 86 if (id != '') | 87 if (id != '') |
| 87 runtime.id = id; | 88 utils.defineProperty(runtime, 'id', id); |
| 88 | 89 |
| 89 apiFunctions.setHandleRequest('getManifest', function() { | 90 apiFunctions.setHandleRequest('getManifest', function() { |
| 90 return runtimeNatives.GetManifest(); | 91 return runtimeNatives.GetManifest(); |
| 91 }); | 92 }); |
| 92 | 93 |
| 93 apiFunctions.setHandleRequest('getURL', function(path) { | 94 apiFunctions.setHandleRequest('getURL', function(path) { |
| 94 path = String(path); | 95 path = $String.self(path); |
| 95 if (!path.length || path[0] != '/') | 96 if (!path.length || path[0] != '/') |
| 96 path = '/' + path; | 97 path = '/' + path; |
| 97 return 'chrome-extension://' + id + path; | 98 return 'chrome-extension://' + id + path; |
| 98 }); | 99 }); |
| 99 | 100 |
| 100 var sendMessageUpdateArguments = messaging.sendMessageUpdateArguments; | 101 var sendMessageUpdateArguments = messaging.sendMessageUpdateArguments; |
| 101 apiFunctions.setUpdateArgumentsPreValidate('sendMessage', | 102 apiFunctions.setUpdateArgumentsPreValidate( |
| 103 'sendMessage', | |
| 102 $Function.bind(sendMessageUpdateArguments, null, 'sendMessage', | 104 $Function.bind(sendMessageUpdateArguments, null, 'sendMessage', |
| 103 true /* hasOptionsArgument */)); | 105 true /* hasOptionsArgument */)); |
| 104 apiFunctions.setUpdateArgumentsPreValidate('sendNativeMessage', | 106 apiFunctions.setUpdateArgumentsPreValidate( |
| 107 'sendNativeMessage', | |
| 105 $Function.bind(sendMessageUpdateArguments, null, 'sendNativeMessage', | 108 $Function.bind(sendMessageUpdateArguments, null, 'sendNativeMessage', |
| 106 false /* hasOptionsArgument */)); | 109 false /* hasOptionsArgument */)); |
| 107 | 110 |
| 108 apiFunctions.setHandleRequest('sendMessage', | 111 apiFunctions.setHandleRequest( |
| 112 'sendMessage', | |
| 109 function(targetId, message, options, responseCallback) { | 113 function(targetId, message, options, responseCallback) { |
| 110 var connectOptions = {name: messaging.kMessageChannel}; | 114 var connectOptions = $Object.assign({ |
| 111 forEach(options, function(k, v) { | 115 __proto__: null, |
| 112 connectOptions[k] = v; | 116 name: messaging.kMessageChannel, |
| 113 }); | 117 }, options); |
| 114 var port = runtime.connect(targetId || runtime.id, connectOptions); | 118 var port = runtime.connect(targetId, connectOptions); |
| 115 messaging.sendMessageImpl(port, message, responseCallback); | 119 messaging.sendMessageImpl(port, message, responseCallback); |
| 116 }); | 120 }); |
| 117 | 121 |
| 118 apiFunctions.setHandleRequest('sendNativeMessage', | 122 apiFunctions.setHandleRequest('sendNativeMessage', |
| 119 function(targetId, message, responseCallback) { | 123 function(targetId, message, responseCallback) { |
| 120 var port = runtime.connectNative(targetId); | 124 var port = runtime.connectNative(targetId); |
| 121 messaging.sendMessageImpl(port, message, responseCallback); | 125 messaging.sendMessageImpl(port, message, responseCallback); |
| 122 }); | 126 }); |
| 123 | 127 |
| 124 apiFunctions.setUpdateArgumentsPreValidate('connect', function() { | |
| 125 // Align missing (optional) function arguments with the arguments that | |
| 126 // schema validation is expecting, e.g. | |
| 127 // runtime.connect() -> runtime.connect(null, null) | |
| 128 // runtime.connect({}) -> runtime.connect(null, {}) | |
| 129 var nextArg = 0; | |
| 130 | |
| 131 // targetId (first argument) is optional. | |
| 132 var targetId = null; | |
| 133 if (typeof(arguments[nextArg]) == 'string') | |
| 134 targetId = arguments[nextArg++]; | |
| 135 | |
| 136 // connectInfo (second argument) is optional. | |
| 137 var connectInfo = null; | |
| 138 if (typeof(arguments[nextArg]) == 'object') | |
| 139 connectInfo = arguments[nextArg++]; | |
| 140 | |
| 141 if (nextArg != arguments.length) | |
| 142 throw new Error('Invalid arguments to connect.'); | |
| 143 return [targetId, connectInfo]; | |
| 144 }); | |
| 145 | |
| 146 apiFunctions.setUpdateArgumentsPreValidate('connectNative', | |
| 147 function(appName) { | |
| 148 if (typeof(appName) !== 'string') { | |
| 149 throw new Error('Invalid arguments to connectNative.'); | |
| 150 } | |
| 151 return [appName]; | |
| 152 }); | |
|
robwu
2016/05/08 18:06:50
Nice. Removing this unnecessary logic improves the
| |
| 153 | |
| 154 apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) { | 128 apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) { |
| 155 if (!targetId) { | 129 if (!targetId) { |
| 156 // runtime.id is only defined inside extensions. If we're in a webpage, | 130 // id is only defined inside extensions. If we're in a webpage, the best |
| 157 // the best we can do at this point is to fail. | 131 // we can do at this point is to fail. |
| 158 if (!runtime.id) { | 132 if (!id) { |
| 159 throw new Error('chrome.runtime.connect() called from a webpage must ' + | 133 throw new Error('chrome.runtime.connect() called from a webpage must ' + |
| 160 'specify an Extension ID (string) for its first ' + | 134 'specify an Extension ID (string) for its first ' + |
| 161 'argument'); | 135 'argument'); |
| 162 } | 136 } |
| 163 targetId = runtime.id; | 137 targetId = id; |
| 164 } | 138 } |
| 165 | 139 |
| 166 var name = ''; | 140 var name = ''; |
| 167 if (connectInfo && connectInfo.name) | 141 if (connectInfo && connectInfo.name) |
| 168 name = connectInfo.name; | 142 name = connectInfo.name; |
| 169 | 143 |
| 170 var includeTlsChannelId = | 144 var includeTlsChannelId = |
| 171 !!(connectInfo && connectInfo.includeTlsChannelId); | 145 !!(connectInfo && connectInfo.includeTlsChannelId); |
| 172 | 146 |
| 173 var portId = runtimeNatives.OpenChannelToExtension(targetId, name, | 147 var portId = runtimeNatives.OpenChannelToExtension(targetId, name, |
| 174 includeTlsChannelId); | 148 includeTlsChannelId); |
| 175 if (portId >= 0) | 149 if (portId >= 0) |
| 176 return messaging.createPort(portId, name); | 150 return messaging.createPort(portId, name); |
| 177 }); | 151 }); |
| 178 | 152 |
| 179 // | 153 // |
| 180 // Privileged APIs. | 154 // Privileged APIs. |
| 181 // | 155 // |
| 182 if (contextType != 'BLESSED_EXTENSION') | 156 if (contextType != 'BLESSED_EXTENSION') |
| 183 return; | 157 return; |
| 184 | 158 |
| 185 apiFunctions.setHandleRequest('connectNative', | 159 apiFunctions.setHandleRequest('connectNative', |
| 186 function(nativeAppName) { | 160 function(nativeAppName) { |
| 187 var portId = runtimeNatives.OpenChannelToNativeApp(runtime.id, | 161 var portId = runtimeNatives.OpenChannelToNativeApp(nativeAppName); |
| 188 nativeAppName); | |
| 189 if (portId >= 0) | 162 if (portId >= 0) |
| 190 return messaging.createPort(portId, ''); | 163 return messaging.createPort(portId, ''); |
| 191 throw new Error('Error connecting to native app: ' + nativeAppName); | 164 throw new Error('Error connecting to native app: ' + nativeAppName); |
| 192 }); | 165 }); |
| 193 | 166 |
| 194 apiFunctions.setCustomCallback('getBackgroundPage', | 167 apiFunctions.setCustomCallback('getBackgroundPage', |
| 195 function(name, request, callback, response) { | 168 function(name, request, callback, response) { |
| 196 if (callback) { | 169 if (callback) { |
| 197 var bg = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0] || null; | 170 var bg = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0] || null; |
| 198 callback(bg); | 171 callback(bg); |
| 199 } | 172 } |
| 200 }); | 173 }); |
| 201 | 174 |
| 202 bindDirectoryEntryCallback('getPackageDirectoryEntry', apiFunctions); | 175 bindDirectoryEntryCallback('getPackageDirectoryEntry', apiFunctions); |
| 203 }); | 176 }); |
| 204 | 177 |
| 205 exports.$set('bindDirectoryEntryCallback', bindDirectoryEntryCallback); | 178 exports.$set('bindDirectoryEntryCallback', bindDirectoryEntryCallback); |
| 206 exports.$set('binding', binding.generate()); | 179 exports.$set('binding', binding.generate()); |
| OLD | NEW |