Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // This script contains privileged chrome extension related javascript APIs. | 5 // This script contains privileged chrome extension related javascript APIs. |
| 6 // It is loaded by pages whose URL has the chrome-extension protocol. | 6 // It is loaded by pages whose URL has the chrome-extension protocol. |
| 7 | 7 |
| 8 var chrome = chrome || {}; | 8 var chrome = chrome || {}; |
| 9 (function() { | 9 (function() { |
| 10 native function GetExtensionAPIDefinition(); | 10 native function GetExtensionAPIDefinition(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 } else { | 73 } else { |
| 74 if (!error) { | 74 if (!error) { |
| 75 error = "Unknown error." | 75 error = "Unknown error." |
| 76 } | 76 } |
| 77 console.error("Error during " + name + ": " + error); | 77 console.error("Error during " + name + ": " + error); |
| 78 chrome.extension.lastError = { | 78 chrome.extension.lastError = { |
| 79 "message": error | 79 "message": error |
| 80 }; | 80 }; |
| 81 } | 81 } |
| 82 | 82 |
| 83 if (request.customCallback) | |
|
rafaelw
2010/03/22 22:27:21
need curly braces
| |
| 84 request.customCallback(name, request, response); | |
| 85 | |
| 83 if (request.callback) { | 86 if (request.callback) { |
| 84 // Callbacks currently only support one callback argument. | 87 // Callbacks currently only support one callback argument. |
| 85 var callbackArgs = response ? [JSON.parse(response)] : []; | 88 var callbackArgs = response ? [JSON.parse(response)] : []; |
| 86 | 89 |
| 87 // Validate callback in debug only -- and only when the | 90 // Validate callback in debug only -- and only when the |
| 88 // caller has provided a callback. Implementations of api | 91 // caller has provided a callback. Implementations of api |
| 89 // calls my not return data if they observe the caller | 92 // calls my not return data if they observe the caller |
| 90 // has not provided a callback. | 93 // has not provided a callback. |
| 91 if (chromeHidden.validateCallbacks && !error) { | 94 if (chromeHidden.validateCallbacks && !error) { |
| 92 try { | 95 try { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 request.args = []; | 161 request.args = []; |
| 159 for (var k = 0; k < argCount; k++) { | 162 for (var k = 0; k < argCount; k++) { |
| 160 request.args[k] = args[k]; | 163 request.args[k] = args[k]; |
| 161 } | 164 } |
| 162 } | 165 } |
| 163 | 166 |
| 164 return request; | 167 return request; |
| 165 } | 168 } |
| 166 | 169 |
| 167 // Send an API request and optionally register a callback. | 170 // Send an API request and optionally register a callback. |
| 168 function sendRequest(functionName, args, argSchemas) { | 171 function sendRequest(functionName, args, argSchemas, customCallback) { |
| 169 var request = prepareRequest(args, argSchemas); | 172 var request = prepareRequest(args, argSchemas); |
| 173 if (customCallback) { | |
| 174 request.customCallback = customCallback; | |
| 175 } | |
| 170 // JSON.stringify doesn't support a root object which is undefined. | 176 // JSON.stringify doesn't support a root object which is undefined. |
| 171 if (request.args === undefined) | 177 if (request.args === undefined) |
| 172 request.args = null; | 178 request.args = null; |
| 173 | 179 |
| 174 // Some javascript libraries (e.g. prototype.js version <= 1.6) add a toJSON | 180 // Some javascript libraries (e.g. prototype.js version <= 1.6) add a toJSON |
| 175 // serializer function on Array.prototype that is incompatible with our | 181 // serializer function on Array.prototype that is incompatible with our |
| 176 // native JSON library, causing incorrect deserialization in the C++ side of | 182 // native JSON library, causing incorrect deserialization in the C++ side of |
| 177 // StartRequest. We work around that here by temporarily removing the toJSON | 183 // StartRequest. We work around that here by temporarily removing the toJSON |
| 178 // function. | 184 // function. |
| 179 var arrayToJsonTmp; | 185 var arrayToJsonTmp; |
| 180 if (Array.prototype.toJSON) { | 186 if (Array.prototype.toJSON) { |
| 181 arrayToJsonTmp = Array.prototype.toJSON; | 187 arrayToJsonTmp = Array.prototype.toJSON; |
| 182 Array.prototype.toJSON = null; | 188 Array.prototype.toJSON = null; |
| 183 } | 189 } |
| 184 var sargs = JSON.stringify(request.args); | 190 var sargs = JSON.stringify(request.args); |
| 185 if (arrayToJsonTmp) { | 191 if (arrayToJsonTmp) { |
| 186 Array.prototype.toJSON = arrayToJsonTmp; | 192 Array.prototype.toJSON = arrayToJsonTmp; |
| 187 } | 193 } |
| 188 var requestId = GetNextRequestId(); | 194 var requestId = GetNextRequestId(); |
| 189 requests[requestId] = request; | 195 requests[requestId] = request; |
| 190 return StartRequest(functionName, sargs, requestId, | 196 var hasCallback = (request.callback || customCallback) ? true : false; |
| 191 request.callback ? true : false); | 197 return StartRequest(functionName, sargs, requestId, hasCallback); |
| 192 } | 198 } |
| 193 | 199 |
| 194 // Send a special API request that is not JSON stringifiable, and optionally | 200 // Send a special API request that is not JSON stringifiable, and optionally |
| 195 // register a callback. | 201 // register a callback. |
| 196 function sendCustomRequest(nativeFunction, functionName, args, argSchemas) { | 202 function sendCustomRequest(nativeFunction, functionName, args, argSchemas) { |
| 197 var request = prepareRequest(args, argSchemas); | 203 var request = prepareRequest(args, argSchemas); |
| 198 var requestId = GetNextRequestId(); | 204 var requestId = GetNextRequestId(); |
| 199 requests[requestId] = request; | 205 requests[requestId] = request; |
| 200 return nativeFunction(functionName, request.args, requestId, | 206 return nativeFunction(functionName, request.args, requestId, |
| 201 request.callback ? true : false); | 207 request.callback ? true : false); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 chrome.toolstrip.onCollapsed = | 288 chrome.toolstrip.onCollapsed = |
| 283 new chrome.Event("toolstrip.onCollapsed." + renderViewId); | 289 new chrome.Event("toolstrip.onCollapsed." + renderViewId); |
| 284 } | 290 } |
| 285 | 291 |
| 286 function setupPopupEvents(renderViewId) { | 292 function setupPopupEvents(renderViewId) { |
| 287 chrome.experimental.popup = chrome.experimental.popup || {}; | 293 chrome.experimental.popup = chrome.experimental.popup || {}; |
| 288 chrome.experimental.popup.onClosed = | 294 chrome.experimental.popup.onClosed = |
| 289 new chrome.Event("experimental.popup.onClosed." + renderViewId); | 295 new chrome.Event("experimental.popup.onClosed." + renderViewId); |
| 290 } | 296 } |
| 291 | 297 |
| 298 function setupHiddenContextMenuEvent(extensionId) { | |
| 299 var eventName = "contextMenu/" + extensionId; | |
| 300 chromeHidden.contextMenuEvent = new chrome.Event(eventName); | |
| 301 chromeHidden.contextMenuHandlers = {}; | |
| 302 chromeHidden.contextMenuEvent.addListener(function() { | |
| 303 var menuItemId = arguments[0].menuItemId; | |
| 304 var onclick = chromeHidden.contextMenuHandlers[menuItemId]; | |
| 305 if (onclick) | |
|
rafaelw
2010/03/22 22:27:21
need curly braces
| |
| 306 onclick.apply(onclick, arguments); | |
| 307 | |
| 308 var parentMenuItemId = arguments[0].parentMenuItemId; | |
| 309 var parentOnclick = chromeHidden.contextMenuHandlers[parentMenuItemId]; | |
| 310 if (parentOnclick) | |
|
rafaelw
2010/03/22 22:27:21
need curly braces
| |
| 311 parentOnclick.apply(parentOnclick, arguments); | |
| 312 }); | |
| 313 } | |
| 314 | |
| 292 chromeHidden.onLoad.addListener(function (extensionId) { | 315 chromeHidden.onLoad.addListener(function (extensionId) { |
| 293 chrome.initExtension(extensionId, false); | 316 chrome.initExtension(extensionId, false); |
| 294 | 317 |
| 295 // |apiFunctions| is a hash of name -> object that stores the | 318 // |apiFunctions| is a hash of name -> object that stores the |
| 296 // name & definition of the apiFunction. Custom handling of api functions | 319 // name & definition of the apiFunction. Custom handling of api functions |
| 297 // is implemented by adding a "handleRequest" function to the object. | 320 // is implemented by adding a "handleRequest" function to the object. |
| 298 var apiFunctions = {}; | 321 var apiFunctions = {}; |
| 299 | 322 |
| 300 // Read api definitions and setup api functions in the chrome namespace. | 323 // Read api definitions and setup api functions in the chrome namespace. |
| 301 // TODO(rafaelw): Consider defining a json schema for an api definition | 324 // TODO(rafaelw): Consider defining a json schema for an api definition |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 apiFunctions[apiFunction.name] = apiFunction; | 357 apiFunctions[apiFunction.name] = apiFunction; |
| 335 | 358 |
| 336 module[functionDef.name] = bind(apiFunction, function() { | 359 module[functionDef.name] = bind(apiFunction, function() { |
| 337 chromeHidden.validate(arguments, this.definition.parameters); | 360 chromeHidden.validate(arguments, this.definition.parameters); |
| 338 | 361 |
| 339 var retval; | 362 var retval; |
| 340 if (this.handleRequest) { | 363 if (this.handleRequest) { |
| 341 retval = this.handleRequest.apply(this, arguments); | 364 retval = this.handleRequest.apply(this, arguments); |
| 342 } else { | 365 } else { |
| 343 retval = sendRequest(this.name, arguments, | 366 retval = sendRequest(this.name, arguments, |
| 344 this.definition.parameters); | 367 this.definition.parameters, |
| 368 this.customCallback); | |
| 345 } | 369 } |
| 346 | 370 |
| 347 // Validate return value if defined - only in debug. | 371 // Validate return value if defined - only in debug. |
| 348 if (chromeHidden.validateCallbacks && | 372 if (chromeHidden.validateCallbacks && |
| 349 chromeHidden.validate && | 373 chromeHidden.validate && |
| 350 this.definition.returns) { | 374 this.definition.returns) { |
| 351 chromeHidden.validate([retval], [this.definition.returns]); | 375 chromeHidden.validate([retval], [this.definition.returns]); |
| 352 } | 376 } |
| 353 return retval; | 377 return retval; |
| 354 }); | 378 }); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 apiFunctions["browserAction.setIcon"].handleRequest = function(details) { | 566 apiFunctions["browserAction.setIcon"].handleRequest = function(details) { |
| 543 setIconCommon( | 567 setIconCommon( |
| 544 details, this.name, this.definition.parameters, "browser action"); | 568 details, this.name, this.definition.parameters, "browser action"); |
| 545 }; | 569 }; |
| 546 | 570 |
| 547 apiFunctions["pageAction.setIcon"].handleRequest = function(details) { | 571 apiFunctions["pageAction.setIcon"].handleRequest = function(details) { |
| 548 setIconCommon( | 572 setIconCommon( |
| 549 details, this.name, this.definition.parameters, "page action"); | 573 details, this.name, this.definition.parameters, "page action"); |
| 550 }; | 574 }; |
| 551 | 575 |
| 576 apiFunctions["experimental.contextMenu.create"].customCallback = | |
| 577 function(name, request, response) { | |
| 578 if (chrome.extension.lastError || !response) | |
|
rafaelw
2010/03/22 22:27:21
need curly braces
| |
| 579 return; | |
| 580 | |
| 581 // Set up the onclick handler if we were passed one in the request. | |
| 582 if (request.args.onclick) { | |
| 583 var menuItemId = JSON.parse(response); | |
| 584 chromeHidden.contextMenuHandlers[menuItemId] = request.args.onclick; | |
| 585 } | |
| 586 }; | |
| 587 | |
| 588 apiFunctions["experimental.contextMenu.remove"].customCallback = | |
| 589 function(name, request, response) { | |
| 590 // Remove any onclick handler we had registered for this menu item. | |
| 591 if (request.args.length > 0) { | |
| 592 var menuItemId = request.args[0]; | |
| 593 if (chromeHidden.contextMenuHandlers[menuItemId]) | |
|
rafaelw
2010/03/22 22:27:21
don't need the test here. you can just delete. (ot
| |
| 594 delete chromeHidden.contextMenuHandlers[menuItemId]; | |
| 595 } | |
| 596 } | |
| 597 | |
| 552 if (chrome.test) { | 598 if (chrome.test) { |
| 553 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; | 599 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; |
| 554 } | 600 } |
| 555 | 601 |
| 556 setupBrowserActionEvent(extensionId); | 602 setupBrowserActionEvent(extensionId); |
| 557 setupPageActionEvents(extensionId); | 603 setupPageActionEvents(extensionId); |
| 558 setupToolstripEvents(GetRenderViewId()); | 604 setupToolstripEvents(GetRenderViewId()); |
| 559 setupPopupEvents(GetRenderViewId()); | 605 setupPopupEvents(GetRenderViewId()); |
| 606 setupHiddenContextMenuEvent(extensionId); | |
| 560 }); | 607 }); |
| 561 | 608 |
| 562 if (!chrome.experimental) | 609 if (!chrome.experimental) |
| 563 chrome.experimental = {}; | 610 chrome.experimental = {}; |
| 564 | 611 |
| 565 if (!chrome.experimental.accessibility) | 612 if (!chrome.experimental.accessibility) |
| 566 chrome.experimental.accessibility = {}; | 613 chrome.experimental.accessibility = {}; |
| 567 | 614 |
| 568 if (!chrome.experimental.history) | 615 if (!chrome.experimental.history) |
| 569 chrome.experimental.history = {}; | 616 chrome.experimental.history = {}; |
| 570 | 617 |
| 571 chrome.experimental.history.transitionType = { | 618 chrome.experimental.history.transitionType = { |
| 572 LINK: 0, | 619 LINK: 0, |
| 573 TYPED: 1, | 620 TYPED: 1, |
| 574 AUTO_BOOKMARK: 2, | 621 AUTO_BOOKMARK: 2, |
| 575 AUTO_SUBFRAME: 3, | 622 AUTO_SUBFRAME: 3, |
| 576 MANUAL_SUBFRAME: 4, | 623 MANUAL_SUBFRAME: 4, |
| 577 GENERATED: 5, | 624 GENERATED: 5, |
| 578 START_PAGE: 6, | 625 START_PAGE: 6, |
| 579 FORM_SUBMIT: 7, | 626 FORM_SUBMIT: 7, |
| 580 RELOAD: 8, | 627 RELOAD: 8, |
| 581 KEYWORD: 9, | 628 KEYWORD: 9, |
| 582 KEYWORD_GENERATED: 10 | 629 KEYWORD_GENERATED: 10 |
| 583 }; | 630 }; |
| 584 })(); | 631 })(); |
| OLD | NEW |