Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / renderer / resources / runtime_custom_bindings.js
blob2f0cb4940c4476d56ae4fe1969cb2533d2539d28
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.
5 // Custom binding for the runtime API.
7 var binding = require('binding').Binding.create('runtime');
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;
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;
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;
49 var fileSystemId = response.fileSystemId;
50 var baseName = response.baseName;
51 var fs = GetIsolatedFileSystem(fileSystemId);
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);
67 });
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;
78 binding.registerCustomHook(function(binding, id, contextType) {
79 var apiFunctions = binding.apiFunctions;
80 var runtime = binding.compiledApi;
83 // Unprivileged APIs.
86 if (id != '')
87 runtime.id = id;
89 apiFunctions.setHandleRequest('getManifest', function() {
90 return runtimeNatives.GetManifest();
91 });
93 apiFunctions.setHandleRequest('getURL', function(path) {
94 path = String(path);
95 if (!path.length || path[0] != '/')
96 path = '/' + path;
97 return 'chrome-extension://' + id + path;
98 });
100 var sendMessageUpdateArguments = messaging.sendMessageUpdateArguments;
101 apiFunctions.setUpdateArgumentsPreValidate('sendMessage',
102 $Function.bind(sendMessageUpdateArguments, null, 'sendMessage',
103 true /* hasOptionsArgument */));
104 apiFunctions.setUpdateArgumentsPreValidate('sendNativeMessage',
105 $Function.bind(sendMessageUpdateArguments, null, 'sendNativeMessage',
106 false /* hasOptionsArgument */));
108 apiFunctions.setHandleRequest('sendMessage',
109 function(targetId, message, options, responseCallback) {
110 var connectOptions = {name: messaging.kMessageChannel};
111 forEach(options, function(k, v) {
112 connectOptions[k] = v;
114 var port = runtime.connect(targetId || runtime.id, connectOptions);
115 messaging.sendMessageImpl(port, message, responseCallback);
118 apiFunctions.setHandleRequest('sendNativeMessage',
119 function(targetId, message, responseCallback) {
120 var port = runtime.connectNative(targetId);
121 messaging.sendMessageImpl(port, message, responseCallback);
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;
131 // targetId (first argument) is optional.
132 var targetId = null;
133 if (typeof(arguments[nextArg]) == 'string')
134 targetId = arguments[nextArg++];
136 // connectInfo (second argument) is optional.
137 var connectInfo = null;
138 if (typeof(arguments[nextArg]) == 'object')
139 connectInfo = arguments[nextArg++];
141 if (nextArg != arguments.length)
142 throw new Error('Invalid arguments to connect.');
143 return [targetId, connectInfo];
146 apiFunctions.setUpdateArgumentsPreValidate('connectNative',
147 function(appName) {
148 if (typeof(appName) !== 'string') {
149 throw new Error('Invalid arguments to connectNative.');
151 return [appName];
154 apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) {
155 // Don't let orphaned content scripts communicate with their extension.
156 // http://crbug.com/168263
157 if (unloadEvent.wasDispatched)
158 throw new Error('Error connecting to extension ' + targetId);
160 if (!targetId)
161 targetId = runtime.id;
163 var name = '';
164 if (connectInfo && connectInfo.name)
165 name = connectInfo.name;
167 var includeTlsChannelId =
168 !!(connectInfo && connectInfo.includeTlsChannelId);
170 var portId = runtimeNatives.OpenChannelToExtension(targetId, name,
171 includeTlsChannelId);
172 if (portId >= 0)
173 return messaging.createPort(portId, name);
177 // Privileged APIs.
179 if (contextType != 'BLESSED_EXTENSION')
180 return;
182 apiFunctions.setHandleRequest('connectNative',
183 function(nativeAppName) {
184 if (!unloadEvent.wasDispatched) {
185 var portId = runtimeNatives.OpenChannelToNativeApp(runtime.id,
186 nativeAppName);
187 if (portId >= 0)
188 return messaging.createPort(portId, '');
190 throw new Error('Error connecting to native app: ' + nativeAppName);
193 apiFunctions.setCustomCallback('getBackgroundPage',
194 function(name, request, response) {
195 if (request.callback) {
196 var bg = runtimeNatives.GetExtensionViews(-1, 'BACKGROUND')[0] || null;
197 request.callback(bg);
199 request.callback = null;
202 bindDirectoryEntryCallback('getPackageDirectoryEntry', apiFunctions);
205 exports.bindDirectoryEntryCallback = bindDirectoryEntryCallback;
206 exports.binding = binding.generate();