| OLD | NEW | 
|---|
|  | (Empty) | 
| 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 runtime API. |  | 
| 6 |  | 
| 7 var binding = require('binding').Binding.create('runtime'); |  | 
| 8 |  | 
| 9 var messaging = require('messaging'); |  | 
| 10 var runtimeNatives = requireNative('runtime'); |  | 
| 11 var unloadEvent = require('unload_event'); |  | 
| 12 var process = requireNative('process'); |  | 
| 13 var forEach = require('utils').forEach; |  | 
| 14 |  | 
| 15 var backgroundPage = window; |  | 
| 16 var backgroundRequire = require; |  | 
| 17 var contextType = process.GetContextType(); |  | 
| 18 if (contextType == 'BLESSED_EXTENSION' || |  | 
| 19     contextType == 'UNBLESSED_EXTENSION') { |  | 
| 20   var manifest = runtimeNatives.GetManifest(); |  | 
| 21   if (manifest.app && manifest.app.background) { |  | 
| 22     // Get the background page if one exists. Otherwise, default to the current |  | 
| 23     // window. |  | 
| 24     backgroundPage = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0]; |  | 
| 25     if (backgroundPage) { |  | 
| 26       var GetModuleSystem = requireNative('v8_context').GetModuleSystem; |  | 
| 27       backgroundRequire = GetModuleSystem(backgroundPage).require; |  | 
| 28     } else { |  | 
| 29       backgroundPage = window; |  | 
| 30     } |  | 
| 31   } |  | 
| 32 } |  | 
| 33 |  | 
| 34 // For packaged apps, all windows use the bindFileEntryCallback from the |  | 
| 35 // background page so their FileEntry objects have the background page's context |  | 
| 36 // as their own.  This allows them to be used from other windows (including the |  | 
| 37 // background page) after the original window is closed. |  | 
| 38 if (window == backgroundPage) { |  | 
| 39   var lastError = require('lastError'); |  | 
| 40   var fileSystemNatives = requireNative('file_system_natives'); |  | 
| 41   var GetIsolatedFileSystem = fileSystemNatives.GetIsolatedFileSystem; |  | 
| 42   var bindDirectoryEntryCallback = function(functionName, apiFunctions) { |  | 
| 43     apiFunctions.setCustomCallback(functionName, |  | 
| 44         function(name, request, response) { |  | 
| 45       if (request.callback && response) { |  | 
| 46         var callback = request.callback; |  | 
| 47         request.callback = null; |  | 
| 48 |  | 
| 49         var fileSystemId = response.fileSystemId; |  | 
| 50         var baseName = response.baseName; |  | 
| 51         var fs = GetIsolatedFileSystem(fileSystemId); |  | 
| 52 |  | 
| 53         try { |  | 
| 54           fs.root.getDirectory(baseName, {}, callback, function(fileError) { |  | 
| 55             lastError.run('runtime.' + functionName, |  | 
| 56                           'Error getting Entry, code: ' + fileError.code, |  | 
| 57                           request.stack, |  | 
| 58                           callback); |  | 
| 59           }); |  | 
| 60         } catch (e) { |  | 
| 61           lastError.run('runtime.' + functionName, |  | 
| 62                         'Error: ' + e.stack, |  | 
| 63                         request.stack, |  | 
| 64                         callback); |  | 
| 65         } |  | 
| 66       } |  | 
| 67     }); |  | 
| 68   }; |  | 
| 69 } else { |  | 
| 70   // Force the runtime API to be loaded in the background page. Using |  | 
| 71   // backgroundPageModuleSystem.require('runtime') is insufficient as |  | 
| 72   // requireNative is only allowed while lazily loading an API. |  | 
| 73   backgroundPage.chrome.runtime; |  | 
| 74   var bindDirectoryEntryCallback = backgroundRequire( |  | 
| 75       'runtime').bindDirectoryEntryCallback; |  | 
| 76 } |  | 
| 77 |  | 
| 78 binding.registerCustomHook(function(binding, id, contextType) { |  | 
| 79   var apiFunctions = binding.apiFunctions; |  | 
| 80   var runtime = binding.compiledApi; |  | 
| 81 |  | 
| 82   // |  | 
| 83   // Unprivileged APIs. |  | 
| 84   // |  | 
| 85 |  | 
| 86   runtime.id = id; |  | 
| 87 |  | 
| 88   apiFunctions.setHandleRequest('getManifest', function() { |  | 
| 89     return runtimeNatives.GetManifest(); |  | 
| 90   }); |  | 
| 91 |  | 
| 92   apiFunctions.setHandleRequest('getURL', function(path) { |  | 
| 93     path = String(path); |  | 
| 94     if (!path.length || path[0] != '/') |  | 
| 95       path = '/' + path; |  | 
| 96     return 'chrome-extension://' + id + path; |  | 
| 97   }); |  | 
| 98 |  | 
| 99   var sendMessageUpdateArguments = messaging.sendMessageUpdateArguments; |  | 
| 100   apiFunctions.setUpdateArgumentsPreValidate('sendMessage', |  | 
| 101       $Function.bind(sendMessageUpdateArguments, null, 'sendMessage', |  | 
| 102                      true /* hasOptionsArgument */)); |  | 
| 103   apiFunctions.setUpdateArgumentsPreValidate('sendNativeMessage', |  | 
| 104       $Function.bind(sendMessageUpdateArguments, null, 'sendNativeMessage', |  | 
| 105                      false /* hasOptionsArgument */)); |  | 
| 106 |  | 
| 107   apiFunctions.setHandleRequest('sendMessage', |  | 
| 108       function(targetId, message, options, responseCallback) { |  | 
| 109     var connectOptions = {name: messaging.kMessageChannel}; |  | 
| 110     forEach(options, function(k, v) { |  | 
| 111       connectOptions[k] = v; |  | 
| 112     }); |  | 
| 113     var port = runtime.connect(targetId || runtime.id, connectOptions); |  | 
| 114     messaging.sendMessageImpl(port, message, responseCallback); |  | 
| 115   }); |  | 
| 116 |  | 
| 117   apiFunctions.setHandleRequest('sendNativeMessage', |  | 
| 118                                 function(targetId, message, responseCallback) { |  | 
| 119     var port = runtime.connectNative(targetId); |  | 
| 120     messaging.sendMessageImpl(port, message, responseCallback); |  | 
| 121   }); |  | 
| 122 |  | 
| 123   apiFunctions.setUpdateArgumentsPreValidate('connect', function() { |  | 
| 124     // Align missing (optional) function arguments with the arguments that |  | 
| 125     // schema validation is expecting, e.g. |  | 
| 126     //   runtime.connect()   -> runtime.connect(null, null) |  | 
| 127     //   runtime.connect({}) -> runtime.connect(null, {}) |  | 
| 128     var nextArg = 0; |  | 
| 129 |  | 
| 130     // targetId (first argument) is optional. |  | 
| 131     var targetId = null; |  | 
| 132     if (typeof(arguments[nextArg]) == 'string') |  | 
| 133       targetId = arguments[nextArg++]; |  | 
| 134 |  | 
| 135     // connectInfo (second argument) is optional. |  | 
| 136     var connectInfo = null; |  | 
| 137     if (typeof(arguments[nextArg]) == 'object') |  | 
| 138       connectInfo = arguments[nextArg++]; |  | 
| 139 |  | 
| 140     if (nextArg != arguments.length) |  | 
| 141       throw new Error('Invalid arguments to connect.'); |  | 
| 142     return [targetId, connectInfo]; |  | 
| 143   }); |  | 
| 144 |  | 
| 145   apiFunctions.setUpdateArgumentsPreValidate('connectNative', |  | 
| 146                                              function(appName) { |  | 
| 147     if (typeof(appName) !== 'string') { |  | 
| 148       throw new Error('Invalid arguments to connectNative.'); |  | 
| 149     } |  | 
| 150     return [appName]; |  | 
| 151   }); |  | 
| 152 |  | 
| 153   apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) { |  | 
| 154     // Don't let orphaned content scripts communicate with their extension. |  | 
| 155     // http://crbug.com/168263 |  | 
| 156     if (unloadEvent.wasDispatched) |  | 
| 157       throw new Error('Error connecting to extension ' + targetId); |  | 
| 158 |  | 
| 159     if (!targetId) |  | 
| 160       targetId = runtime.id; |  | 
| 161 |  | 
| 162     var name = ''; |  | 
| 163     if (connectInfo && connectInfo.name) |  | 
| 164       name = connectInfo.name; |  | 
| 165 |  | 
| 166     var includeTlsChannelId = |  | 
| 167       !!(connectInfo && connectInfo.includeTlsChannelId); |  | 
| 168 |  | 
| 169     var portId = runtimeNatives.OpenChannelToExtension(targetId, name, |  | 
| 170                                                        includeTlsChannelId); |  | 
| 171     if (portId >= 0) |  | 
| 172       return messaging.createPort(portId, name); |  | 
| 173   }); |  | 
| 174 |  | 
| 175   // |  | 
| 176   // Privileged APIs. |  | 
| 177   // |  | 
| 178   if (contextType != 'BLESSED_EXTENSION') |  | 
| 179     return; |  | 
| 180 |  | 
| 181   apiFunctions.setHandleRequest('connectNative', |  | 
| 182                                 function(nativeAppName) { |  | 
| 183     if (!unloadEvent.wasDispatched) { |  | 
| 184       var portId = runtimeNatives.OpenChannelToNativeApp(runtime.id, |  | 
| 185                                                          nativeAppName); |  | 
| 186       if (portId >= 0) |  | 
| 187         return messaging.createPort(portId, ''); |  | 
| 188     } |  | 
| 189     throw new Error('Error connecting to native app: ' + nativeAppName); |  | 
| 190   }); |  | 
| 191 |  | 
| 192   apiFunctions.setCustomCallback('getBackgroundPage', |  | 
| 193                                  function(name, request, response) { |  | 
| 194     if (request.callback) { |  | 
| 195       var bg = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0] || null; |  | 
| 196       request.callback(bg); |  | 
| 197     } |  | 
| 198     request.callback = null; |  | 
| 199   }); |  | 
| 200 |  | 
| 201   bindDirectoryEntryCallback('getPackageDirectoryEntry', apiFunctions); |  | 
| 202 }); |  | 
| 203 |  | 
| 204 exports.bindDirectoryEntryCallback = bindDirectoryEntryCallback; |  | 
| 205 exports.binding = binding.generate(); |  | 
| OLD | NEW | 
|---|