Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(555)

Unified Diff: chrome/renderer/resources/extensions/extension_process_bindings.js

Issue 8540012: Enable extension APIs for content scripts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/resources/extensions/extension_process_bindings.js
diff --git a/chrome/renderer/resources/extensions/extension_process_bindings.js b/chrome/renderer/resources/extensions/extension_process_bindings.js
deleted file mode 100644
index 96db3680440ac2be55915a2ea65468198c0fe7c2..0000000000000000000000000000000000000000
--- a/chrome/renderer/resources/extensions/extension_process_bindings.js
+++ /dev/null
@@ -1,1058 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This script contains privileged chrome extension related javascript APIs.
-// It is loaded by pages whose URL has the chrome-extension protocol.
-
-var chrome = chrome || {};
-(function() {
- native function GetExtensionAPIDefinition();
- native function StartRequest();
- native function GetChromeHidden();
- native function GetNextRequestId();
- native function Print();
-
- native function GetCurrentPageActions(extensionId);
- native function GetExtensionViews();
- native function GetNextContextMenuId();
- native function GetNextTtsEventId();
- native function OpenChannelToTab();
- native function GetRenderViewId();
- native function SetIconCommon();
- native function GetUniqueSubEventName(eventName);
- native function GetLocalFileSystem(name, path);
- native function DecodeJPEG(jpegImage);
- native function CreateBlob(filePath);
-
- var chromeHidden = GetChromeHidden();
-
- if (!chrome)
- chrome = {};
-
- function forEach(dict, f) {
- for (key in dict) {
- if (dict.hasOwnProperty(key))
- f(key, dict[key]);
- }
- }
-
- // Validate arguments.
- chromeHidden.validationTypes = [];
- chromeHidden.validate = function(args, schemas) {
- if (args.length > schemas.length)
- throw new Error("Too many arguments.");
-
- for (var i = 0; i < schemas.length; i++) {
- if (i in args && args[i] !== null && args[i] !== undefined) {
- var validator = new chromeHidden.JSONSchemaValidator();
- validator.addTypes(chromeHidden.validationTypes);
- validator.validate(args[i], schemas[i]);
- if (validator.errors.length == 0)
- continue;
-
- var message = "Invalid value for argument " + (i + 1) + ". ";
- for (var i = 0, err; err = validator.errors[i]; i++) {
- if (err.path) {
- message += "Property '" + err.path + "': ";
- }
- message += err.message;
- message = message.substring(0, message.length - 1);
- message += ", ";
- }
- message = message.substring(0, message.length - 2);
- message += ".";
-
- throw new Error(message);
- } else if (!schemas[i].optional) {
- throw new Error("Parameter " + (i + 1) + " is required.");
- }
- }
- };
-
- // Callback handling.
- var requests = [];
- chromeHidden.handleResponse = function(requestId, name,
- success, response, error) {
- try {
- var request = requests[requestId];
- if (success) {
- delete chrome.extension.lastError;
- } else {
- if (!error) {
- error = "Unknown error.";
- }
- console.error("Error during " + name + ": " + error);
- chrome.extension.lastError = {
- "message": error
- };
- }
-
- if (request.customCallback) {
- request.customCallback(name, request, response);
- }
-
- if (request.callback) {
- // Callbacks currently only support one callback argument.
- var callbackArgs = response ? [chromeHidden.JSON.parse(response)] : [];
-
- // Validate callback in debug only -- and only when the
- // caller has provided a callback. Implementations of api
- // calls my not return data if they observe the caller
- // has not provided a callback.
- if (chromeHidden.validateCallbacks && !error) {
- try {
- if (!request.callbackSchema.parameters) {
- throw "No callback schemas defined";
- }
-
- if (request.callbackSchema.parameters.length > 1) {
- throw "Callbacks may only define one parameter";
- }
-
- chromeHidden.validate(callbackArgs,
- request.callbackSchema.parameters);
- } catch (exception) {
- return "Callback validation error during " + name + " -- " +
- exception.stack;
- }
- }
-
- if (response) {
- request.callback(callbackArgs[0]);
- } else {
- request.callback();
- }
- }
- } finally {
- delete requests[requestId];
- delete chrome.extension.lastError;
- }
-
- return undefined;
- };
-
- function prepareRequest(args, argSchemas) {
- var request = {};
- var argCount = args.length;
-
- // Look for callback param.
- if (argSchemas.length > 0 &&
- args.length == argSchemas.length &&
- argSchemas[argSchemas.length - 1].type == "function") {
- request.callback = args[argSchemas.length - 1];
- request.callbackSchema = argSchemas[argSchemas.length - 1];
- --argCount;
- }
-
- request.args = [];
- for (var k = 0; k < argCount; k++) {
- request.args[k] = args[k];
- }
-
- return request;
- }
-
- // Send an API request and optionally register a callback.
- // |opt_args| is an object with optional parameters as follows:
- // - noStringify: true if we should not stringify the request arguments.
- // - customCallback: a callback that should be called instead of the standard
- // callback.
- // - nativeFunction: the v8 native function to handle the request, or
- // StartRequest if missing.
- // - forIOThread: true if this function should be handled on the browser IO
- // thread.
- function sendRequest(functionName, args, argSchemas, opt_args) {
- if (!opt_args)
- opt_args = {};
- var request = prepareRequest(args, argSchemas);
- if (opt_args.customCallback) {
- request.customCallback = opt_args.customCallback;
- }
- // JSON.stringify doesn't support a root object which is undefined.
- if (request.args === undefined)
- request.args = null;
-
- var sargs = opt_args.noStringify ?
- request.args : chromeHidden.JSON.stringify(request.args);
- var nativeFunction = opt_args.nativeFunction || StartRequest;
-
- var requestId = GetNextRequestId();
- requests[requestId] = request;
- var hasCallback =
- (request.callback || opt_args.customCallback) ? true : false;
- return nativeFunction(functionName, sargs, requestId, hasCallback,
- opt_args.forIOThread);
- }
-
- // --- Setup additional api's not currently handled in common/extensions/api
-
- // WebRequestEvent object. This is used for special webRequest events with
- // extra parameters. Each invocation of addListener creates a new named
- // sub-event. That sub-event is associated with the extra parameters in the
- // browser process, so that only it is dispatched when the main event occurs
- // matching the extra parameters.
- //
- // Example:
- // chrome.webRequest.onBeforeRequest.addListener(
- // callback, {urls: "http://*.google.com/*"});
- // ^ callback will only be called for onBeforeRequests matching the filter.
- chrome.WebRequestEvent =
- function(eventName, opt_argSchemas, opt_extraArgSchemas) {
- if (typeof eventName != "string")
- throw new Error("chrome.WebRequestEvent requires an event name.");
-
- this.eventName_ = eventName;
- this.argSchemas_ = opt_argSchemas;
- this.extraArgSchemas_ = opt_extraArgSchemas;
- this.subEvents_ = [];
- };
-
- // Test if the given callback is registered for this event.
- chrome.WebRequestEvent.prototype.hasListener = function(cb) {
- return this.findListener_(cb) > -1;
- };
-
- // Test if any callbacks are registered fur thus event.
- chrome.WebRequestEvent.prototype.hasListeners = function(cb) {
- return this.subEvents_.length > 0;
- };
-
- // Registers a callback to be called when this event is dispatched. If
- // opt_filter is specified, then the callback is only called for events that
- // match the given filters. If opt_extraInfo is specified, the given optional
- // info is sent to the callback.
- chrome.WebRequestEvent.prototype.addListener =
- function(cb, opt_filter, opt_extraInfo) {
- var subEventName = GetUniqueSubEventName(this.eventName_);
- // Note: this could fail to validate, in which case we would not add the
- // subEvent listener.
- chromeHidden.validate(Array.prototype.slice.call(arguments, 1),
- this.extraArgSchemas_);
- chrome.experimental.webRequest.addEventListener(
- cb, opt_filter, opt_extraInfo, this.eventName_, subEventName);
-
- var subEvent = new chrome.Event(subEventName, this.argSchemas_);
- var subEventCallback = cb;
- if (opt_extraInfo && opt_extraInfo.indexOf("blocking") >= 0) {
- var eventName = this.eventName_;
- subEventCallback = function() {
- var requestId = arguments[0].requestId;
- try {
- var result = cb.apply(null, arguments);
- chrome.experimental.webRequest.eventHandled(
- eventName, subEventName, requestId, result);
- } catch (e) {
- chrome.experimental.webRequest.eventHandled(
- eventName, subEventName, requestId);
- throw e;
- }
- };
- } else if (opt_extraInfo && opt_extraInfo.indexOf("asyncBlocking") >= 0) {
- var eventName = this.eventName_;
- subEventCallback = function() {
- var details = arguments[0];
- var requestId = details.requestId;
- var handledCallback = function(response) {
- chrome.experimental.webRequest.eventHandled(
- eventName, subEventName, requestId, response);
- };
- cb.apply(null, [details, handledCallback]);
- };
- }
- this.subEvents_.push(
- {subEvent: subEvent, callback: cb, subEventCallback: subEventCallback});
- subEvent.addListener(subEventCallback);
- };
-
- // Unregisters a callback.
- chrome.WebRequestEvent.prototype.removeListener = function(cb) {
- var idx = this.findListener_(cb);
- if (idx < 0) {
- return;
- }
-
- var e = this.subEvents_[idx];
- e.subEvent.removeListener(e.subEventCallback);
- if (e.subEvent.hasListeners()) {
- console.error(
- "Internal error: webRequest subEvent has orphaned listeners.");
- }
- this.subEvents_.splice(idx, 1);
- };
-
- chrome.WebRequestEvent.prototype.findListener_ = function(cb) {
- for (var i in this.subEvents_) {
- var e = this.subEvents_[i];
- if (e.callback === cb) {
- if (e.subEvent.findListener_(e.subEventCallback) > -1)
- return i;
- console.error("Internal error: webRequest subEvent has no callback.");
- }
- }
-
- return -1;
- };
-
- function CustomBindingsObject() {
- }
- CustomBindingsObject.prototype.setSchema = function(schema) {
- // The functions in the schema are in list form, so we move them into a
- // dictionary for easier access.
- var self = this;
- self.parameters = {};
- schema.functions.forEach(function(f) {
- self.parameters[f.name] = f.parameters;
- });
- };
-
- function extendSchema(schema) {
- var extendedSchema = schema.slice();
- extendedSchema.unshift({'type': 'string'});
- return extendedSchema;
- }
-
- var customBindings = {};
-
- function setupChromeSetting() {
- function ChromeSetting(prefKey, valueSchema) {
- this.get = function(details, callback) {
- var getSchema = this.parameters.get;
- chromeHidden.validate([details, callback], getSchema);
- return sendRequest('types.ChromeSetting.get',
- [prefKey, details, callback],
- extendSchema(getSchema));
- };
- this.set = function(details, callback) {
- var setSchema = this.parameters.set.slice();
- setSchema[0].properties.value = valueSchema;
- chromeHidden.validate([details, callback], setSchema);
- return sendRequest('types.ChromeSetting.set',
- [prefKey, details, callback],
- extendSchema(setSchema));
- };
- this.clear = function(details, callback) {
- var clearSchema = this.parameters.clear;
- chromeHidden.validate([details, callback], clearSchema);
- return sendRequest('types.ChromeSetting.clear',
- [prefKey, details, callback],
- extendSchema(clearSchema));
- };
- this.onChange = new chrome.Event('types.ChromeSetting.' + prefKey +
- '.onChange');
- };
- ChromeSetting.prototype = new CustomBindingsObject();
- customBindings['ChromeSetting'] = ChromeSetting;
- }
-
- function setupContentSetting() {
- function ContentSetting(contentType, settingSchema) {
- this.get = function(details, callback) {
- var getSchema = this.parameters.get;
- chromeHidden.validate([details, callback], getSchema);
- return sendRequest('contentSettings.get',
- [contentType, details, callback],
- extendSchema(getSchema));
- };
- this.set = function(details, callback) {
- var setSchema = this.parameters.set.slice();
- setSchema[0].properties.setting = settingSchema;
- chromeHidden.validate([details, callback], setSchema);
- return sendRequest('contentSettings.set',
- [contentType, details, callback],
- extendSchema(setSchema));
- };
- this.clear = function(details, callback) {
- var clearSchema = this.parameters.clear;
- chromeHidden.validate([details, callback], clearSchema);
- return sendRequest('contentSettings.clear',
- [contentType, details, callback],
- extendSchema(clearSchema));
- };
- this.getResourceIdentifiers = function(callback) {
- var schema = this.parameters.getResourceIdentifiers;
- chromeHidden.validate([callback], schema);
- return sendRequest(
- 'contentSettings.getResourceIdentifiers',
- [contentType, callback],
- extendSchema(schema));
- };
- }
- ContentSetting.prototype = new CustomBindingsObject();
- customBindings['ContentSetting'] = ContentSetting;
- }
-
- function setupInputEvents() {
- chrome.experimental.input.onKeyEvent.dispatch =
- function(engineID, keyData) {
- var args = Array.prototype.slice.call(arguments);
- if (this.validate_) {
- var validationErrors = this.validate_(args);
- if (validationErrors) {
- chrome.experimental.input.eventHandled(requestId, false);
- return validationErrors;
- }
- }
- if (this.listeners_.length > 1) {
- console.error("Too many listeners for 'onKeyEvent': " + e.stack);
- chrome.experimental.input.eventHandled(requestId, false);
- return;
- }
- for (var i = 0; i < this.listeners_.length; i++) {
- try {
- var requestId = keyData.requestId;
- var result = this.listeners_[i].apply(null, args);
- chrome.experimental.input.eventHandled(requestId, result);
- } catch (e) {
- console.error("Error in event handler for 'onKeyEvent': " + e.stack);
- chrome.experimental.input.eventHandled(requestId, false);
- }
- }
- };
- }
-
- // Page action events send (pageActionId, {tabId, tabUrl}).
- function setupPageActionEvents(extensionId) {
- var pageActions = GetCurrentPageActions(extensionId);
-
- var oldStyleEventName = "pageActions";
- // TODO(EXTENSIONS_DEPRECATED): only one page action
- for (var i = 0; i < pageActions.length; ++i) {
- // Setup events for each extension_id/page_action_id string we find.
- chrome.pageActions[pageActions[i]] = new chrome.Event(oldStyleEventName);
- }
- }
-
- function setupHiddenContextMenuEvent(extensionId) {
- chromeHidden.contextMenus = {};
- chromeHidden.contextMenus.handlers = {};
- var eventName = "contextMenus";
- chromeHidden.contextMenus.event = new chrome.Event(eventName);
- chromeHidden.contextMenus.ensureListenerSetup = function() {
- if (chromeHidden.contextMenus.listening) {
- return;
- }
- chromeHidden.contextMenus.listening = true;
- chromeHidden.contextMenus.event.addListener(function() {
- // An extension context menu item has been clicked on - fire the onclick
- // if there is one.
- var id = arguments[0].menuItemId;
- var onclick = chromeHidden.contextMenus.handlers[id];
- if (onclick) {
- onclick.apply(null, arguments);
- }
- });
- };
- }
-
- // Remove invalid characters from |text| so that it is suitable to use
- // for |AutocompleteMatch::contents|.
- function sanitizeString(text) {
- // NOTE: This logic mirrors |AutocompleteMatch::SanitizeString()|.
- // 0x2028 = line separator; 0x2029 = paragraph separator.
- var kRemoveChars = /(\r|\n|\t|\u2028|\u2029)/gm;
- return text.trimLeft().replace(kRemoveChars, '');
- }
-
- // Parses the xml syntax supported by omnibox suggestion results. Returns an
- // object with two properties: 'description', which is just the text content,
- // and 'descriptionStyles', which is an array of style objects in a format
- // understood by the C++ backend.
- function parseOmniboxDescription(input) {
- var domParser = new DOMParser();
-
- // The XML parser requires a single top-level element, but we want to
- // support things like 'hello, <match>world</match>!'. So we wrap the
- // provided text in generated root level element.
- var root = domParser.parseFromString(
- '<fragment>' + input + '</fragment>', 'text/xml');
-
- // DOMParser has a terrible error reporting facility. Errors come out nested
- // inside the returned document.
- var error = root.querySelector('parsererror div');
- if (error) {
- throw new Error(error.textContent);
- }
-
- // Otherwise, it's valid, so build up the result.
- var result = {
- description: '',
- descriptionStyles: []
- };
-
- // Recursively walk the tree.
- (function(node) {
- for (var i = 0, child; child = node.childNodes[i]; i++) {
- // Append text nodes to our description.
- if (child.nodeType == Node.TEXT_NODE) {
- result.description += sanitizeString(child.nodeValue);
- continue;
- }
-
- // Process and descend into a subset of recognized tags.
- if (child.nodeType == Node.ELEMENT_NODE &&
- (child.nodeName == 'dim' || child.nodeName == 'match' ||
- child.nodeName == 'url')) {
- var style = {
- 'type': child.nodeName,
- 'offset': result.description.length
- };
- result.descriptionStyles.push(style);
- arguments.callee(child);
- style.length = result.description.length - style.offset;
- continue;
- }
-
- // Descend into all other nodes, even if they are unrecognized, for
- // forward compat.
- arguments.callee(child);
- }
- })(root);
-
- return result;
- }
-
- function setupOmniboxEvents() {
- chrome.omnibox.onInputChanged.dispatch =
- function(text, requestId) {
- var suggestCallback = function(suggestions) {
- chrome.omnibox.sendSuggestions(requestId, suggestions);
- };
- chrome.Event.prototype.dispatch.apply(this, [text, suggestCallback]);
- };
- }
-
- function setupTtsEvents() {
- chromeHidden.tts = {};
- chromeHidden.tts.handlers = {};
- chrome.ttsEngine.onSpeak.dispatch =
- function(text, options, requestId) {
- var sendTtsEvent = function(event) {
- chrome.ttsEngine.sendTtsEvent(requestId, event);
- };
- chrome.Event.prototype.dispatch.apply(
- this, [text, options, sendTtsEvent]);
- };
- try {
- chrome.tts.onEvent.addListener(
- function(event) {
- var eventHandler = chromeHidden.tts.handlers[event.srcId];
- if (eventHandler) {
- eventHandler({
- type: event.type,
- charIndex: event.charIndex,
- errorMessage: event.errorMessage
- });
- if (event.isFinalEvent) {
- delete chromeHidden.tts.handlers[event.srcId];
- }
- }
- });
- } catch (e) {
- // This extension doesn't have permission to access TTS, so we
- // can safely ignore this.
- }
- }
-
- // Get the platform from navigator.appVersion.
- function getPlatform() {
- var platforms = [
- [/CrOS Touch/, "chromeos touch"],
- [/CrOS/, "chromeos"],
- [/Linux/, "linux"],
- [/Mac/, "mac"],
- [/Win/, "win"],
- ];
-
- for (var i = 0; i < platforms.length; i++) {
- if (platforms[i][0].test(navigator.appVersion)) {
- return platforms[i][1];
- }
- }
- return "unknown";
- }
-
- chromeHidden.onLoad.addListener(function(extensionId, isExtensionProcess,
- isIncognitoProcess) {
- if (!isExtensionProcess)
- return;
-
- // Setup the ChromeSetting class so we can use it to construct
- // ChromeSetting objects from the API definition.
- setupChromeSetting();
-
- // Setup the ContentSetting class so we can use it to construct
- // ContentSetting objects from the API definition.
- setupContentSetting();
-
- // |apiFunctions| is a hash of name -> object that stores the
- // name & definition of the apiFunction. Custom handling of api functions
- // is implemented by adding a "handleRequest" function to the object.
- var apiFunctions = {};
-
- // Read api definitions and setup api functions in the chrome namespace.
- // TODO(rafaelw): Consider defining a json schema for an api definition
- // and validating either here, in a unit_test or both.
- // TODO(rafaelw): Handle synchronous functions.
- // TOOD(rafaelw): Consider providing some convenient override points
- // for api functions that wish to insert themselves into the call.
- var apiDefinitions = chromeHidden.JSON.parse(GetExtensionAPIDefinition());
- var platform = getPlatform();
-
- apiDefinitions.forEach(function(apiDef) {
- // Check platform, if apiDef has platforms key.
- if (apiDef.platforms && apiDef.platforms.indexOf(platform) == -1) {
- return;
- }
-
- var module = chrome;
- var namespaces = apiDef.namespace.split('.');
- for (var index = 0, name; name = namespaces[index]; index++) {
- module[name] = module[name] || {};
- module = module[name];
- }
-
- // Add types to global validationTypes
- if (apiDef.types) {
- apiDef.types.forEach(function(t) {
- chromeHidden.validationTypes.push(t);
- if (t.type == 'object' && customBindings[t.id]) {
- customBindings[t.id].prototype.setSchema(t);
- }
- });
- }
-
- // Setup Functions.
- if (apiDef.functions) {
- apiDef.functions.forEach(function(functionDef) {
- // Module functions may have been defined earlier by hand. Don't
- // clobber them.
- if (module[functionDef.name])
- return;
-
- var apiFunction = {};
- apiFunction.definition = functionDef;
- apiFunction.name = apiDef.namespace + "." + functionDef.name;
- apiFunctions[apiFunction.name] = apiFunction;
-
- module[functionDef.name] = (function() {
- var args = arguments;
- if (this.updateArgumentsPreValidate)
- args = this.updateArgumentsPreValidate.apply(this, args);
- chromeHidden.validate(args, this.definition.parameters);
- if (this.updateArgumentsPostValidate)
- args = this.updateArgumentsPostValidate.apply(this, args);
-
- var retval;
- if (this.handleRequest) {
- retval = this.handleRequest.apply(this, args);
- } else {
- retval = sendRequest(this.name, args,
- this.definition.parameters,
- {customCallback: this.customCallback});
- }
-
- // Validate return value if defined - only in debug.
- if (chromeHidden.validateCallbacks &&
- chromeHidden.validate &&
- this.definition.returns) {
- chromeHidden.validate([retval], [this.definition.returns]);
- }
- return retval;
- }).bind(apiFunction);
- });
- }
-
- // Setup Events
- if (apiDef.events) {
- apiDef.events.forEach(function(eventDef) {
- // Module events may have been defined earlier by hand. Don't clobber
- // them.
- if (module[eventDef.name])
- return;
-
- var eventName = apiDef.namespace + "." + eventDef.name;
- if (apiDef.namespace == "experimental.webRequest") {
- module[eventDef.name] = new chrome.WebRequestEvent(eventName,
- eventDef.parameters, eventDef.extraParameters);
- } else {
- module[eventDef.name] = new chrome.Event(eventName,
- eventDef.parameters);
- }
- });
- }
-
- function addProperties(m, def) {
- // Parse any values defined for properties.
- if (def.properties) {
- forEach(def.properties, function(prop, property) {
- var value = property.value;
- if (value) {
- if (property.type === 'integer') {
- value = parseInt(value);
- } else if (property.type === 'boolean') {
- value = value === "true";
- } else if (property["$ref"]) {
- var constructor = customBindings[property["$ref"]];
- var args = value;
- // For an object property, |value| is an array of constructor
- // arguments, but we want to pass the arguments directly
- // (i.e. not as an array), so we have to fake calling |new| on
- // the constructor.
- value = { __proto__: constructor.prototype };
- constructor.apply(value, args);
- } else if (property.type === 'object') {
- // Recursively add properties.
- addProperties(value, property);
- } else if (property.type !== 'string') {
- throw "NOT IMPLEMENTED (extension_api.json error): Cannot " +
- "parse values for type \"" + property.type + "\"";
- }
- }
- if (value) {
- m[prop] = value;
- }
- });
- }
- }
-
- addProperties(module, apiDef);
- });
-
- // getTabContentses is retained for backwards compatibility
- // See http://crbug.com/21433
- chrome.extension.getTabContentses = chrome.extension.getExtensionTabs;
- // TOOD(mihaip): remove this alias once the webstore stops calling
- // beginInstallWithManifest2.
- // See http://crbug.com/100242
- chrome.webstorePrivate.beginInstallWithManifest2 =
- chrome.webstorePrivate.beginInstallWithManifest3;
-
- apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) {
- var name = "";
- if (connectInfo) {
- name = connectInfo.name || name;
- }
- var portId = OpenChannelToTab(tabId, chromeHidden.extensionId, name);
- return chromeHidden.Port.createPort(portId, name);
- };
-
- apiFunctions["tabs.sendRequest"].handleRequest =
- function(tabId, request, responseCallback) {
- var port = chrome.tabs.connect(tabId,
- {name: chromeHidden.kRequestChannel});
- port.postMessage(request);
- port.onDisconnect.addListener(function() {
- // For onDisconnects, we only notify the callback if there was an error.
- if (chrome.extension.lastError && responseCallback)
- responseCallback();
- });
- port.onMessage.addListener(function(response) {
- try {
- if (responseCallback)
- responseCallback(response);
- } finally {
- port.disconnect();
- port = null;
- }
- });
- };
-
- apiFunctions["experimental.savePage.saveAsMHTML"].customCallback =
- function(name, request, response) {
- var params = chromeHidden.JSON.parse(response);
- var path = params.mhtmlFilePath;
- var size = params.mhtmlFileLength;
-
- if (request.callback)
- request.callback(CreateBlob(path, size));
-
- request.callback = null;
- };
-
- apiFunctions["fileBrowserPrivate.requestLocalFileSystem"].customCallback =
- function(name, request, response) {
- var resp = response ? [chromeHidden.JSON.parse(response)] : [];
- var fs = null;
- if (!resp[0].error)
- fs = GetLocalFileSystem(resp[0].name, resp[0].path);
- if (request.callback)
- request.callback(fs);
- request.callback = null;
- };
-
- apiFunctions["chromePrivate.decodeJPEG"].handleRequest =
- function(jpeg_image) {
- return DecodeJPEG(jpeg_image);
- };
-
- apiFunctions["extension.getViews"].handleRequest = function(properties) {
- var windowId = -1;
- var type = "ALL";
- if (typeof(properties) != "undefined") {
- if (typeof(properties.type) != "undefined") {
- type = properties.type;
- }
- if (typeof(properties.windowId) != "undefined") {
- windowId = properties.windowId;
- }
- }
- return GetExtensionViews(windowId, type) || null;
- };
-
- apiFunctions["extension.getBackgroundPage"].handleRequest = function() {
- return GetExtensionViews(-1, "BACKGROUND")[0] || null;
- };
-
- apiFunctions["extension.getExtensionTabs"].handleRequest =
- function(windowId) {
- if (typeof(windowId) == "undefined")
- windowId = -1;
- return GetExtensionViews(windowId, "TAB");
- };
-
- apiFunctions["devtools.getTabEvents"].handleRequest = function(tabId) {
- var tabIdProxy = {};
- var functions = ["onPageEvent", "onTabClose"];
- functions.forEach(function(name) {
- // Event disambiguation is handled by name munging. See
- // chrome/browser/extensions/extension_devtools_events.h for the C++
- // equivalent of this logic.
- tabIdProxy[name] = new chrome.Event("devtools." + tabId + "." + name);
- });
- return tabIdProxy;
- };
-
- var canvas;
- function setIconCommon(details, name, parameters, actionType, iconSize,
- nativeFunction) {
- if ("iconIndex" in details) {
- sendRequest(name, [details], parameters);
- } else if ("imageData" in details) {
- // Verify that this at least looks like an ImageData element.
- // Unfortunately, we cannot use instanceof because the ImageData
- // constructor is not public.
- //
- // We do this manually instead of using JSONSchema to avoid having these
- // properties show up in the doc.
- if (!("width" in details.imageData) ||
- !("height" in details.imageData) ||
- !("data" in details.imageData)) {
- throw new Error(
- "The imageData property must contain an ImageData object.");
- }
-
- if (details.imageData.width > iconSize ||
- details.imageData.height > iconSize) {
- throw new Error(
- "The imageData property must contain an ImageData object that " +
- "is no larger than " + iconSize + " pixels square.");
- }
-
- sendRequest(name, [details], parameters,
- {noStringify: true, nativeFunction: nativeFunction});
- } else if ("path" in details) {
- var img = new Image();
- img.onerror = function() {
- console.error("Could not load " + actionType + " icon '" +
- details.path + "'.");
- };
- img.onload = function() {
- var canvas = document.createElement("canvas");
- canvas.width = img.width > iconSize ? iconSize : img.width;
- canvas.height = img.height > iconSize ? iconSize : img.height;
-
- var canvas_context = canvas.getContext('2d');
- canvas_context.clearRect(0, 0, canvas.width, canvas.height);
- canvas_context.drawImage(img, 0, 0, canvas.width, canvas.height);
- delete details.path;
- details.imageData = canvas_context.getImageData(0, 0, canvas.width,
- canvas.height);
- sendRequest(name, [details], parameters,
- {noStringify: true, nativeFunction: nativeFunction});
- };
- img.src = details.path;
- } else {
- throw new Error(
- "Either the path or imageData property must be specified.");
- }
- }
-
- function setExtensionActionIconCommon(details, name, parameters,
- actionType) {
- var EXTENSION_ACTION_ICON_SIZE = 19;
- setIconCommon(details, name, parameters, actionType,
- EXTENSION_ACTION_ICON_SIZE, SetIconCommon);
- }
-
- apiFunctions["browserAction.setIcon"].handleRequest = function(details) {
- setExtensionActionIconCommon(
- details, this.name, this.definition.parameters, "browser action");
- };
-
- apiFunctions["pageAction.setIcon"].handleRequest = function(details) {
- setExtensionActionIconCommon(
- details, this.name, this.definition.parameters, "page action");
- };
-
- apiFunctions["experimental.sidebar.setIcon"].handleRequest =
- function(details) {
- var SIDEBAR_ICON_SIZE = 16;
- setIconCommon(
- details, this.name, this.definition.parameters, "sidebar",
- SIDEBAR_ICON_SIZE, SetIconCommon);
- };
-
- apiFunctions["contextMenus.create"].handleRequest =
- function() {
- var args = arguments;
- var id = GetNextContextMenuId();
- args[0].generatedId = id;
- sendRequest(this.name, args, this.definition.parameters,
- {customCallback: this.customCallback});
- return id;
- };
-
- apiFunctions["omnibox.setDefaultSuggestion"].handleRequest =
- function(details) {
- var parseResult = parseOmniboxDescription(details.description);
- sendRequest(this.name, [parseResult], this.definition.parameters);
- };
-
- apiFunctions["experimental.webRequest.addEventListener"].handleRequest =
- function() {
- var args = Array.prototype.slice.call(arguments);
- sendRequest(this.name, args, this.definition.parameters,
- {forIOThread: true});
- };
-
- apiFunctions["experimental.webRequest.eventHandled"].handleRequest =
- function() {
- var args = Array.prototype.slice.call(arguments);
- sendRequest(this.name, args, this.definition.parameters,
- {forIOThread: true});
- };
-
- apiFunctions["experimental.webRequest.handlerBehaviorChanged"].
- handleRequest = function() {
- var args = Array.prototype.slice.call(arguments);
- sendRequest(this.name, args, this.definition.parameters,
- {forIOThread: true});
- };
-
- apiFunctions["contextMenus.create"].customCallback =
- function(name, request, response) {
- if (chrome.extension.lastError) {
- return;
- }
-
- var id = request.args[0].generatedId;
-
- // Set up the onclick handler if we were passed one in the request.
- var onclick = request.args.length ? request.args[0].onclick : null;
- if (onclick) {
- chromeHidden.contextMenus.ensureListenerSetup();
- chromeHidden.contextMenus.handlers[id] = onclick;
- }
- };
-
- apiFunctions["contextMenus.remove"].customCallback =
- function(name, request, response) {
- if (chrome.extension.lastError) {
- return;
- }
- var id = request.args[0];
- delete chromeHidden.contextMenus.handlers[id];
- };
-
- apiFunctions["contextMenus.update"].customCallback =
- function(name, request, response) {
- if (chrome.extension.lastError) {
- return;
- }
- var id = request.args[0];
- if (request.args[1].onclick) {
- chromeHidden.contextMenus.handlers[id] = request.args[1].onclick;
- }
- };
-
- apiFunctions["contextMenus.removeAll"].customCallback =
- function(name, request, response) {
- if (chrome.extension.lastError) {
- return;
- }
- chromeHidden.contextMenus.handlers = {};
- };
-
- apiFunctions["tabs.captureVisibleTab"].updateArgumentsPreValidate =
- function() {
- // Old signature:
- // captureVisibleTab(int windowId, function callback);
- // New signature:
- // captureVisibleTab(int windowId, object details, function callback);
- //
- // TODO(skerner): The next step to omitting optional arguments is the
- // replacement of this code with code that matches arguments by type.
- // Once this is working for captureVisibleTab() it can be enabled for
- // the rest of the API. See crbug/29215 .
- if (arguments.length == 2 && typeof(arguments[1]) == "function") {
- // If the old signature is used, add a null details object.
- newArgs = [arguments[0], null, arguments[1]];
- } else {
- newArgs = arguments;
- }
- return newArgs;
- };
-
- apiFunctions["omnibox.sendSuggestions"].updateArgumentsPostValidate =
- function(requestId, userSuggestions) {
- var suggestions = [];
- for (var i = 0; i < userSuggestions.length; i++) {
- var parseResult = parseOmniboxDescription(
- userSuggestions[i].description);
- parseResult.content = userSuggestions[i].content;
- suggestions.push(parseResult);
- }
- return [requestId, suggestions];
- };
-
- apiFunctions["tts.speak"].handleRequest = function() {
- var args = arguments;
- if (args.length > 1 && args[1] && args[1].onEvent) {
- var id = GetNextTtsEventId();
- args[1].srcId = id;
- chromeHidden.tts.handlers[id] = args[1].onEvent;
- }
- sendRequest(this.name, args, this.definition.parameters);
- return id;
- };
-
- if (chrome.test) {
- chrome.test.getApiDefinitions = GetExtensionAPIDefinition;
- }
-
- setupPageActionEvents(extensionId);
- setupHiddenContextMenuEvent(extensionId);
- setupInputEvents();
- setupOmniboxEvents();
- setupTtsEvents();
- });
-
- if (!chrome.experimental)
- chrome.experimental = {};
-
- if (!chrome.experimental.accessibility)
- chrome.experimental.accessibility = {};
-
- if (!chrome.experimental.speechInput)
- chrome.experimental.speechInput = {};
-
- if (!chrome.tts)
- chrome.tts = {};
-
- if (!chrome.ttsEngine)
- chrome.ttsEngine = {};
-
- if (!chrome.experimental.downloads)
- chrome.experimental.downloads = {};
-})();
« no previous file with comments | « chrome/renderer/resources/extensions/event.js ('k') | chrome/renderer/resources/extensions/miscellaneous_bindings.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698