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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 // if there is one. | 278 // if there is one. |
279 var id = arguments[0].menuItemId; | 279 var id = arguments[0].menuItemId; |
280 var onclick = chromeHidden.contextMenus.handlers[id]; | 280 var onclick = chromeHidden.contextMenus.handlers[id]; |
281 if (onclick) { | 281 if (onclick) { |
282 onclick.apply(null, arguments); | 282 onclick.apply(null, arguments); |
283 } | 283 } |
284 }); | 284 }); |
285 }; | 285 }; |
286 } | 286 } |
287 | 287 |
| 288 // Parses the xml syntax supported by omnibox suggestion results. Returns an |
| 289 // object with two properties: 'description', which is just the text content, |
| 290 // and 'descriptionStyles', which is an array of style objects in a format |
| 291 // understood by the C++ backend. |
| 292 function parseOmniboxDescription(input) { |
| 293 var domParser = new DOMParser(); |
| 294 |
| 295 // The XML parser requires a single top-level element, but we want to |
| 296 // support things like 'hello, <match>world</match>!'. So we wrap the |
| 297 // provided text in generated root level element. |
| 298 var root = domParser.parseFromString( |
| 299 '<fragment>' + input + '</fragment>', 'text/xml'); |
| 300 |
| 301 // DOMParser has a terrible error reporting facility. Errors come out nested |
| 302 // inside the returned document. |
| 303 var error = root.querySelector('parsererror div'); |
| 304 if (error) { |
| 305 throw new Error(error.textContent); |
| 306 } |
| 307 |
| 308 // Otherwise, it's valid, so build up the result. |
| 309 var result = { |
| 310 description: '', |
| 311 descriptionStyles: [] |
| 312 }; |
| 313 |
| 314 // Recursively walk the tree. |
| 315 (function(node) { |
| 316 for (var i = 0, child; child = node.childNodes[i]; i++) { |
| 317 // Append text nodes to our description. |
| 318 if (child.nodeType == Node.TEXT_NODE) { |
| 319 result.description += child.nodeValue; |
| 320 continue; |
| 321 } |
| 322 |
| 323 // Process and descend into a subset of recognized tags. |
| 324 if (child.nodeType == Node.ELEMENT_NODE && |
| 325 (child.nodeName == 'dim' || child.nodeName == 'match' || |
| 326 child.nodeName == 'url')) { |
| 327 var style = { |
| 328 'type': child.nodeName, |
| 329 'offset': result.description.length |
| 330 }; |
| 331 result.descriptionStyles.push(style); |
| 332 arguments.callee(child); |
| 333 style.length = result.description.length - style.offset; |
| 334 continue; |
| 335 } |
| 336 |
| 337 // Descend into all other nodes, even if they are unrecognized, for |
| 338 // forward compat. |
| 339 arguments.callee(child); |
| 340 } |
| 341 })(root); |
| 342 |
| 343 return result; |
| 344 } |
| 345 |
288 function setupOmniboxEvents(extensionId) { | 346 function setupOmniboxEvents(extensionId) { |
289 chrome.omnibox.onInputChanged.dispatch = | 347 chrome.omnibox.onInputChanged.dispatch = |
290 function(text, requestId) { | 348 function(text, requestId) { |
291 var suggestCallback = function(suggestions) { | 349 var suggestCallback = function(suggestions) { |
292 chrome.omnibox.sendSuggestions(requestId, suggestions); | 350 chrome.omnibox.sendSuggestions(requestId, suggestions); |
293 }; | 351 }; |
294 chrome.Event.prototype.dispatch.apply(this, [text, suggestCallback]); | 352 chrome.Event.prototype.dispatch.apply(this, [text, suggestCallback]); |
295 }; | 353 }; |
296 } | 354 } |
297 | 355 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 if (module[functionDef.name]) | 395 if (module[functionDef.name]) |
338 return; | 396 return; |
339 | 397 |
340 var apiFunction = {}; | 398 var apiFunction = {}; |
341 apiFunction.definition = functionDef; | 399 apiFunction.definition = functionDef; |
342 apiFunction.name = apiDef.namespace + "." + functionDef.name; | 400 apiFunction.name = apiDef.namespace + "." + functionDef.name; |
343 apiFunctions[apiFunction.name] = apiFunction; | 401 apiFunctions[apiFunction.name] = apiFunction; |
344 | 402 |
345 module[functionDef.name] = (function() { | 403 module[functionDef.name] = (function() { |
346 var args = arguments; | 404 var args = arguments; |
347 if (this.updateArguments) { | 405 if (this.updateArgumentsPreValidate) |
348 // Functions whose signature has changed can define an | 406 args = this.updateArgumentsPreValidate.apply(this, args); |
349 // |updateArguments| function to transform old argument lists | |
350 // into the new form, preserving compatibility. | |
351 // TODO(skerner): Once optional args can be omitted (crbug/29215), | |
352 // this mechanism will become unnecessary. Consider removing it | |
353 // when crbug/29215 is fixed. | |
354 args = this.updateArguments.apply(this, args); | |
355 } | |
356 chromeHidden.validate(args, this.definition.parameters); | 407 chromeHidden.validate(args, this.definition.parameters); |
| 408 if (this.updateArgumentsPostValidate) |
| 409 args = this.updateArgumentsPostValidate.apply(this, args); |
357 | 410 |
358 var retval; | 411 var retval; |
359 if (this.handleRequest) { | 412 if (this.handleRequest) { |
360 retval = this.handleRequest.apply(this, args); | 413 retval = this.handleRequest.apply(this, args); |
361 } else { | 414 } else { |
362 retval = sendRequest(this.name, args, | 415 retval = sendRequest(this.name, args, |
363 this.definition.parameters, | 416 this.definition.parameters, |
364 this.customCallback); | 417 this.customCallback); |
365 } | 418 } |
366 | 419 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 apiFunctions["contextMenus.create"].handleRequest = | 686 apiFunctions["contextMenus.create"].handleRequest = |
634 function() { | 687 function() { |
635 var args = arguments; | 688 var args = arguments; |
636 var id = chromeHidden.contextMenus.nextId++; | 689 var id = chromeHidden.contextMenus.nextId++; |
637 args[0].generatedId = id; | 690 args[0].generatedId = id; |
638 sendRequest(this.name, args, this.definition.parameters, | 691 sendRequest(this.name, args, this.definition.parameters, |
639 this.customCallback); | 692 this.customCallback); |
640 return id; | 693 return id; |
641 }; | 694 }; |
642 | 695 |
| 696 apiFunctions["omnibox.setDefaultSuggestion"].handleRequest = |
| 697 function(details) { |
| 698 var parseResult = parseOmniboxDescription(details.description); |
| 699 sendRequest(this.name, [parseResult], this.definition.parameters); |
| 700 }; |
| 701 |
643 apiFunctions["contextMenus.create"].customCallback = | 702 apiFunctions["contextMenus.create"].customCallback = |
644 function(name, request, response) { | 703 function(name, request, response) { |
645 if (chrome.extension.lastError) { | 704 if (chrome.extension.lastError) { |
646 return; | 705 return; |
647 } | 706 } |
648 | 707 |
649 var id = request.args[0].generatedId; | 708 var id = request.args[0].generatedId; |
650 | 709 |
651 // Set up the onclick handler if we were passed one in the request. | 710 // Set up the onclick handler if we were passed one in the request. |
652 var onclick = request.args.length ? request.args[0].onclick : null; | 711 var onclick = request.args.length ? request.args[0].onclick : null; |
(...skipping 24 matching lines...) Expand all Loading... |
677 }; | 736 }; |
678 | 737 |
679 apiFunctions["contextMenus.removeAll"].customCallback = | 738 apiFunctions["contextMenus.removeAll"].customCallback = |
680 function(name, request, response) { | 739 function(name, request, response) { |
681 if (chrome.extension.lastError) { | 740 if (chrome.extension.lastError) { |
682 return; | 741 return; |
683 } | 742 } |
684 chromeHidden.contextMenus.handlers = {}; | 743 chromeHidden.contextMenus.handlers = {}; |
685 }; | 744 }; |
686 | 745 |
687 apiFunctions["tabs.captureVisibleTab"].updateArguments = function() { | 746 apiFunctions["tabs.captureVisibleTab"].updateArgumentsPreValidate = |
| 747 function() { |
688 // Old signature: | 748 // Old signature: |
689 // captureVisibleTab(int windowId, function callback); | 749 // captureVisibleTab(int windowId, function callback); |
690 // New signature: | 750 // New signature: |
691 // captureVisibleTab(int windowId, object details, function callback); | 751 // captureVisibleTab(int windowId, object details, function callback); |
692 // | 752 // |
693 // TODO(skerner): The next step to omitting optional arguments is the | 753 // TODO(skerner): The next step to omitting optional arguments is the |
694 // replacement of this code with code that matches arguments by type. | 754 // replacement of this code with code that matches arguments by type. |
695 // Once this is working for captureVisibleTab() it can be enabled for | 755 // Once this is working for captureVisibleTab() it can be enabled for |
696 // the rest of the API. See crbug/29215 . | 756 // the rest of the API. See crbug/29215 . |
697 if (arguments.length == 2 && typeof(arguments[1]) == "function") { | 757 if (arguments.length == 2 && typeof(arguments[1]) == "function") { |
698 // If the old signature is used, add a null details object. | 758 // If the old signature is used, add a null details object. |
699 newArgs = [arguments[0], null, arguments[1]]; | 759 newArgs = [arguments[0], null, arguments[1]]; |
700 } else { | 760 } else { |
701 newArgs = arguments; | 761 newArgs = arguments; |
702 } | 762 } |
703 return newArgs; | 763 return newArgs; |
704 }; | 764 }; |
705 | 765 |
706 apiFunctions["omnibox.styleUrl"].handleRequest = function(offset, length) { | 766 apiFunctions["omnibox.sendSuggestions"].updateArgumentsPostValidate = |
707 return {type: "url", offset: offset, length: length}; | 767 function(requestId, userSuggestions) { |
708 }; | 768 var suggestions = []; |
709 apiFunctions["omnibox.styleMatch"].handleRequest = | 769 for (var i = 0; i < userSuggestions.length; i++) { |
710 function(offset, length) { | 770 var parseResult = parseOmniboxDescription( |
711 return {type: "match", offset: offset, length: length}; | 771 userSuggestions[i].description); |
712 }; | 772 parseResult.content = userSuggestions[i].content; |
713 apiFunctions["omnibox.styleDim"].handleRequest = function(offset, length) { | 773 suggestions.push(parseResult); |
714 return {type: "dim", offset: offset, length: length}; | 774 } |
| 775 return [requestId, suggestions]; |
715 }; | 776 }; |
716 | 777 |
717 if (chrome.test) { | 778 if (chrome.test) { |
718 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; | 779 chrome.test.getApiDefinitions = GetExtensionAPIDefinition; |
719 } | 780 } |
720 | 781 |
721 setupPageActionEvents(extensionId); | 782 setupPageActionEvents(extensionId); |
722 setupToolstripEvents(GetRenderViewId()); | 783 setupToolstripEvents(GetRenderViewId()); |
723 setupPopupEvents(GetRenderViewId()); | 784 setupPopupEvents(GetRenderViewId()); |
724 setupHiddenContextMenuEvent(extensionId); | 785 setupHiddenContextMenuEvent(extensionId); |
725 setupOmniboxEvents(extensionId); | 786 setupOmniboxEvents(extensionId); |
726 }); | 787 }); |
727 | 788 |
728 if (!chrome.experimental) | 789 if (!chrome.experimental) |
729 chrome.experimental = {}; | 790 chrome.experimental = {}; |
730 | 791 |
731 if (!chrome.experimental.accessibility) | 792 if (!chrome.experimental.accessibility) |
732 chrome.experimental.accessibility = {}; | 793 chrome.experimental.accessibility = {}; |
733 | 794 |
734 if (!chrome.experimental.tts) | 795 if (!chrome.experimental.tts) |
735 chrome.experimental.tts = {}; | 796 chrome.experimental.tts = {}; |
736 })(); | 797 })(); |
OLD | NEW |