| 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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 // Setup Functions. | 344 // Setup Functions. |
| 345 if (apiDef.functions) { | 345 if (apiDef.functions) { |
| 346 apiDef.functions.forEach(function(functionDef) { | 346 apiDef.functions.forEach(function(functionDef) { |
| 347 // Module functions may have been defined earlier by hand. Don't | 347 // Module functions may have been defined earlier by hand. Don't |
| 348 // clobber them. | 348 // clobber them. |
| 349 if (module[functionDef.name]) | 349 if (module[functionDef.name]) |
| 350 return; | 350 return; |
| 351 | 351 |
| 352 var apiFunction = {}; | 352 var apiFunction = {}; |
| 353 apiFunction.definition = functionDef; | 353 apiFunction.definition = functionDef; |
| 354 apiFunction.name = apiDef.namespace + "." + functionDef.name;; | 354 apiFunction.name = apiDef.namespace + "." + functionDef.name; |
| 355 apiFunctions[apiFunction.name] = apiFunction; | 355 apiFunctions[apiFunction.name] = apiFunction; |
| 356 | 356 |
| 357 module[functionDef.name] = bind(apiFunction, function() { | 357 module[functionDef.name] = bind(apiFunction, function() { |
| 358 chromeHidden.validate(arguments, this.definition.parameters); | 358 var args = arguments; |
| 359 if (this.updateArguments) { |
| 360 // Functions whose signature has changed can define an |
| 361 // |updateArguments| function to transform old argument lists |
| 362 // into the new form, preserving compatibility. |
| 363 // TODO(skerner): Once optional args can be omitted (crbug/29215), |
| 364 // this mechanism will become unnecessary. Consider removing it |
| 365 // when crbug/29215 is fixed. |
| 366 args = this.updateArguments.apply(this, args); |
| 367 } |
| 368 chromeHidden.validate(args, this.definition.parameters); |
| 359 | 369 |
| 360 var retval; | 370 var retval; |
| 361 if (this.handleRequest) { | 371 if (this.handleRequest) { |
| 362 retval = this.handleRequest.apply(this, arguments); | 372 retval = this.handleRequest.apply(this, args); |
| 363 } else { | 373 } else { |
| 364 retval = sendRequest(this.name, arguments, | 374 retval = sendRequest(this.name, args, |
| 365 this.definition.parameters, | 375 this.definition.parameters, |
| 366 this.customCallback); | 376 this.customCallback); |
| 367 } | 377 } |
| 368 | 378 |
| 369 // Validate return value if defined - only in debug. | 379 // Validate return value if defined - only in debug. |
| 370 if (chromeHidden.validateCallbacks && | 380 if (chromeHidden.validateCallbacks && |
| 371 chromeHidden.validate && | 381 chromeHidden.validate && |
| 372 this.definition.returns) { | 382 this.definition.returns) { |
| 373 chromeHidden.validate([retval], [this.definition.returns]); | 383 chromeHidden.validate([retval], [this.definition.returns]); |
| 374 } | 384 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 398 }); | 408 }); |
| 399 | 409 |
| 400 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { | 410 apiFunctions["tabs.connect"].handleRequest = function(tabId, connectInfo) { |
| 401 var name = ""; | 411 var name = ""; |
| 402 if (connectInfo) { | 412 if (connectInfo) { |
| 403 name = connectInfo.name || name; | 413 name = connectInfo.name || name; |
| 404 } | 414 } |
| 405 var portId = OpenChannelToTab( | 415 var portId = OpenChannelToTab( |
| 406 tabId, chromeHidden.extensionId, name); | 416 tabId, chromeHidden.extensionId, name); |
| 407 return chromeHidden.Port.createPort(portId, name); | 417 return chromeHidden.Port.createPort(portId, name); |
| 408 } | 418 }; |
| 409 | 419 |
| 410 apiFunctions["tabs.sendRequest"].handleRequest = | 420 apiFunctions["tabs.sendRequest"].handleRequest = |
| 411 function(tabId, request, responseCallback) { | 421 function(tabId, request, responseCallback) { |
| 412 var port = chrome.tabs.connect(tabId, | 422 var port = chrome.tabs.connect(tabId, |
| 413 {name: chromeHidden.kRequestChannel}); | 423 {name: chromeHidden.kRequestChannel}); |
| 414 port.postMessage(request); | 424 port.postMessage(request); |
| 415 port.onMessage.addListener(function(response) { | 425 port.onMessage.addListener(function(response) { |
| 416 if (responseCallback) | 426 if (responseCallback) |
| 417 responseCallback(response); | 427 responseCallback(response); |
| 418 port.disconnect(); | 428 port.disconnect(); |
| 419 }); | 429 }); |
| 420 } | 430 }; |
| 421 | 431 |
| 422 apiFunctions["extension.getViews"].handleRequest = function(properties) { | 432 apiFunctions["extension.getViews"].handleRequest = function(properties) { |
| 423 var windowId = -1; | 433 var windowId = -1; |
| 424 var type = "ALL"; | 434 var type = "ALL"; |
| 425 if (typeof(properties) != "undefined") { | 435 if (typeof(properties) != "undefined") { |
| 426 if (typeof(properties.type) != "undefined") { | 436 if (typeof(properties.type) != "undefined") { |
| 427 type = properties.type; | 437 type = properties.type; |
| 428 } | 438 } |
| 429 if (typeof(properties.windowId) != "undefined") { | 439 if (typeof(properties.windowId) != "undefined") { |
| 430 windowId = properties.windowId; | 440 windowId = properties.windowId; |
| 431 } | 441 } |
| 432 } | 442 } |
| 433 return GetExtensionViews(windowId, type) || null; | 443 return GetExtensionViews(windowId, type) || null; |
| 434 } | 444 }; |
| 435 | 445 |
| 436 apiFunctions["extension.getBackgroundPage"].handleRequest = function() { | 446 apiFunctions["extension.getBackgroundPage"].handleRequest = function() { |
| 437 return GetExtensionViews(-1, "BACKGROUND")[0] || null; | 447 return GetExtensionViews(-1, "BACKGROUND")[0] || null; |
| 438 } | 448 }; |
| 439 | 449 |
| 440 apiFunctions["extension.getToolstrips"].handleRequest = | 450 apiFunctions["extension.getToolstrips"].handleRequest = |
| 441 function(windowId) { | 451 function(windowId) { |
| 442 if (typeof(windowId) == "undefined") | 452 if (typeof(windowId) == "undefined") |
| 443 windowId = -1; | 453 windowId = -1; |
| 444 return GetExtensionViews(windowId, "TOOLSTRIP"); | 454 return GetExtensionViews(windowId, "TOOLSTRIP"); |
| 445 } | 455 }; |
| 446 | 456 |
| 447 apiFunctions["extension.getExtensionTabs"].handleRequest = | 457 apiFunctions["extension.getExtensionTabs"].handleRequest = |
| 448 function(windowId) { | 458 function(windowId) { |
| 449 if (typeof(windowId) == "undefined") | 459 if (typeof(windowId) == "undefined") |
| 450 windowId = -1; | 460 windowId = -1; |
| 451 return GetExtensionViews(windowId, "TAB"); | 461 return GetExtensionViews(windowId, "TAB"); |
| 452 } | 462 }; |
| 453 | 463 |
| 454 apiFunctions["devtools.getTabEvents"].handleRequest = function(tabId) { | 464 apiFunctions["devtools.getTabEvents"].handleRequest = function(tabId) { |
| 455 var tabIdProxy = {}; | 465 var tabIdProxy = {}; |
| 456 var functions = ["onPageEvent", "onTabClose"]; | 466 var functions = ["onPageEvent", "onTabClose"]; |
| 457 functions.forEach(function(name) { | 467 functions.forEach(function(name) { |
| 458 // Event disambiguation is handled by name munging. See | 468 // Event disambiguation is handled by name munging. See |
| 459 // chrome/browser/extensions/extension_devtools_events.h for the C++ | 469 // chrome/browser/extensions/extension_devtools_events.h for the C++ |
| 460 // equivalent of this logic. | 470 // equivalent of this logic. |
| 461 tabIdProxy[name] = new chrome.Event("devtools." + tabId + "." + name); | 471 tabIdProxy[name] = new chrome.Event("devtools." + tabId + "." + name); |
| 462 }); | 472 }); |
| 463 return tabIdProxy; | 473 return tabIdProxy; |
| 464 } | 474 }; |
| 465 | 475 |
| 466 apiFunctions["experimental.popup.show"].handleRequest = | 476 apiFunctions["experimental.popup.show"].handleRequest = |
| 467 function(url, showDetails, callback) { | 477 function(url, showDetails, callback) { |
| 468 // Second argument is a transform from HTMLElement to Rect. | 478 // Second argument is a transform from HTMLElement to Rect. |
| 469 var internalSchema = [ | 479 var internalSchema = [ |
| 470 this.definition.parameters[0], | 480 this.definition.parameters[0], |
| 471 { | 481 { |
| 472 type: "object", | 482 type: "object", |
| 473 name: "showDetails", | 483 name: "showDetails", |
| 474 properties: { | 484 properties: { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 496 ]; | 506 ]; |
| 497 return sendRequest(this.name, | 507 return sendRequest(this.name, |
| 498 [url, | 508 [url, |
| 499 { | 509 { |
| 500 domAnchor: getAbsoluteRect(showDetails.relativeTo), | 510 domAnchor: getAbsoluteRect(showDetails.relativeTo), |
| 501 giveFocus: showDetails.giveFocus, | 511 giveFocus: showDetails.giveFocus, |
| 502 borderStyle: showDetails.borderStyle | 512 borderStyle: showDetails.borderStyle |
| 503 }, | 513 }, |
| 504 callback], | 514 callback], |
| 505 internalSchema); | 515 internalSchema); |
| 506 } | 516 }; |
| 507 | 517 |
| 508 apiFunctions["experimental.extension.getPopupView"].handleRequest = | 518 apiFunctions["experimental.extension.getPopupView"].handleRequest = |
| 509 function() { | 519 function() { |
| 510 return GetPopupView(); | 520 return GetPopupView(); |
| 511 } | 521 }; |
| 512 | 522 |
| 513 apiFunctions["experimental.popup.getParentWindow"].handleRequest = | 523 apiFunctions["experimental.popup.getParentWindow"].handleRequest = |
| 514 function() { | 524 function() { |
| 515 return GetPopupParentWindow(); | 525 return GetPopupParentWindow(); |
| 516 } | 526 }; |
| 517 | 527 |
| 518 var canvas; | 528 var canvas; |
| 519 function setIconCommon(details, name, parameters, actionType) { | 529 function setIconCommon(details, name, parameters, actionType) { |
| 520 var EXTENSION_ACTION_ICON_SIZE = 19; | 530 var EXTENSION_ACTION_ICON_SIZE = 19; |
| 521 | 531 |
| 522 if ("iconIndex" in details) { | 532 if ("iconIndex" in details) { |
| 523 sendRequest(name, [details], parameters); | 533 sendRequest(name, [details], parameters); |
| 524 } else if ("imageData" in details) { | 534 } else if ("imageData" in details) { |
| 525 // Verify that this at least looks like an ImageData element. | 535 // Verify that this at least looks like an ImageData element. |
| 526 // Unfortunately, we cannot use instanceof because the ImageData | 536 // Unfortunately, we cannot use instanceof because the ImageData |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 } | 604 } |
| 595 }; | 605 }; |
| 596 | 606 |
| 597 apiFunctions["experimental.contextMenu.remove"].customCallback = | 607 apiFunctions["experimental.contextMenu.remove"].customCallback = |
| 598 function(name, request, response) { | 608 function(name, request, response) { |
| 599 // Remove any onclick handler we had registered for this menu item. | 609 // Remove any onclick handler we had registered for this menu item. |
| 600 if (request.args.length > 0) { | 610 if (request.args.length > 0) { |
| 601 var menuItemId = request.args[0]; | 611 var menuItemId = request.args[0]; |
| 602 delete chromeHidden.contextMenuHandlers[menuItemId]; | 612 delete chromeHidden.contextMenuHandlers[menuItemId]; |
| 603 } | 613 } |
| 604 } | 614 }; |
| 615 |
| 616 apiFunctions["tabs.captureVisibleTab"].updateArguments = function() { |
| 617 // Old signature: |
| 618 // captureVisibleTab(int windowId, function callback); |
| 619 // New signature: |
| 620 // captureVisibleTab(int windowId, object details, function callback); |
| 621 // |
| 622 // TODO(skerner): The next step to omitting optional arguments is the |
| 623 // replacement of this code with code that matches arguments by type. |
| 624 // Once this is working for captureVisibleTab() it can be enabled for |
| 625 // the rest of the API. See crbug/29215 . |
| 626 if (arguments.length == 2 && typeof(arguments[1]) == "function") { |
| 627 // If the old signature is used, add a null details object. |
| 628 newArgs = [arguments[0], null, arguments[1]]; |
| 629 } else { |
| 630 newArgs = arguments; |
| 631 } |
| 632 return newArgs; |
| 633 }; |
| 605 | 634 |
| 606 if (chrome.test) { | 635 if (chrome.test) { |
| 607 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; | 636 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; |
| 608 } | 637 } |
| 609 | 638 |
| 610 setupBrowserActionEvent(extensionId); | 639 setupBrowserActionEvent(extensionId); |
| 611 setupPageActionEvents(extensionId); | 640 setupPageActionEvents(extensionId); |
| 612 setupToolstripEvents(GetRenderViewId()); | 641 setupToolstripEvents(GetRenderViewId()); |
| 613 setupPopupEvents(GetRenderViewId()); | 642 setupPopupEvents(GetRenderViewId()); |
| 614 setupHiddenContextMenuEvent(extensionId); | 643 setupHiddenContextMenuEvent(extensionId); |
| 615 }); | 644 }); |
| 616 | 645 |
| 617 if (!chrome.experimental) | 646 if (!chrome.experimental) |
| 618 chrome.experimental = {}; | 647 chrome.experimental = {}; |
| 619 | 648 |
| 620 if (!chrome.experimental.accessibility) | 649 if (!chrome.experimental.accessibility) |
| 621 chrome.experimental.accessibility = {}; | 650 chrome.experimental.accessibility = {}; |
| 622 })(); | 651 })(); |
| OLD | NEW |