OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 70 } |
71 | 71 |
72 _updateAllAnchorDecorations() { | 72 _updateAllAnchorDecorations() { |
73 for (var anchors of this._anchorsByTarget.values()) { | 73 for (var anchors of this._anchorsByTarget.values()) { |
74 for (var anchor of anchors) | 74 for (var anchor of anchors) |
75 Components.Linkifier._updateLinkDecorations(anchor); | 75 Components.Linkifier._updateLinkDecorations(anchor); |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 /** | 79 /** |
80 * @param {?Components.Linkifier.LinkHandler} handler | |
81 */ | |
82 static setLinkHandler(handler) { | |
83 Components.Linkifier._linkHandler = handler; | |
84 } | |
85 | |
86 /** | |
87 * @param {string} url | |
88 * @param {number=} lineNumber | |
89 * @return {boolean} | |
90 */ | |
91 static handleLink(url, lineNumber) { | |
92 if (!Components.Linkifier._linkHandler) | |
93 return false; | |
94 return Components.Linkifier._linkHandler.handleLink(url, lineNumber); | |
95 } | |
96 | |
97 /** | |
98 * @param {!Element} anchor | 80 * @param {!Element} anchor |
99 * @param {!Workspace.UILocation} uiLocation | 81 * @param {!Workspace.UILocation} uiLocation |
100 */ | 82 */ |
101 static _bindUILocation(anchor, uiLocation) { | 83 static _bindUILocation(anchor, uiLocation) { |
102 Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation; | 84 Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation; |
103 if (!uiLocation) | 85 if (!uiLocation) |
104 return; | 86 return; |
105 var uiSourceCode = uiLocation.uiSourceCode; | 87 var uiSourceCode = uiLocation.uiSourceCode; |
106 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors
]; | 88 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors
]; |
107 if (!sourceCodeAnchors) { | 89 if (!sourceCodeAnchors) { |
(...skipping 12 matching lines...) Expand all Loading... |
120 return; | 102 return; |
121 | 103 |
122 var uiSourceCode = info.uiLocation.uiSourceCode; | 104 var uiSourceCode = info.uiLocation.uiSourceCode; |
123 info.uiLocation = null; | 105 info.uiLocation = null; |
124 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors
]; | 106 var sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors
]; |
125 if (sourceCodeAnchors) | 107 if (sourceCodeAnchors) |
126 sourceCodeAnchors.delete(anchor); | 108 sourceCodeAnchors.delete(anchor); |
127 } | 109 } |
128 | 110 |
129 /** | 111 /** |
130 * @param {!SDK.Target} target | |
131 * @param {string} scriptId | |
132 * @param {number} lineNumber | |
133 * @param {number=} columnNumber | |
134 * @return {string} | |
135 */ | |
136 static liveLocationText(target, scriptId, lineNumber, columnNumber) { | |
137 var debuggerModel = SDK.DebuggerModel.fromTarget(target); | |
138 if (!debuggerModel) | |
139 return ''; | |
140 var script = debuggerModel.scriptForId(scriptId); | |
141 if (!script) | |
142 return ''; | |
143 var location = /** @type {!SDK.DebuggerModel.Location} */ ( | |
144 debuggerModel.createRawLocation(script, lineNumber, columnNumber || 0)); | |
145 var uiLocation = | |
146 /** @type {!Workspace.UILocation} */ (Bindings.debuggerWorkspaceBinding.
rawLocationToUILocation(location)); | |
147 return uiLocation.linkText(); | |
148 } | |
149 | |
150 /** | |
151 * @override | 112 * @override |
152 * @param {!SDK.Target} target | 113 * @param {!SDK.Target} target |
153 */ | 114 */ |
154 targetAdded(target) { | 115 targetAdded(target) { |
155 this._anchorsByTarget.set(target, []); | 116 this._anchorsByTarget.set(target, []); |
156 this._locationPoolByTarget.set(target, new Bindings.LiveLocationPool()); | 117 this._locationPoolByTarget.set(target, new Bindings.LiveLocationPool()); |
157 } | 118 } |
158 | 119 |
159 /** | 120 /** |
160 * @override | 121 * @override |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 } | 416 } |
456 | 417 |
457 /** | 418 /** |
458 * @param {!Event} event | 419 * @param {!Event} event |
459 */ | 420 */ |
460 static _handleClick(event) { | 421 static _handleClick(event) { |
461 var link = /** @type {!Element} */ (event.currentTarget); | 422 var link = /** @type {!Element} */ (event.currentTarget); |
462 event.consume(true); | 423 event.consume(true); |
463 if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.targe
t))) | 424 if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.targe
t))) |
464 return; | 425 return; |
465 var info = Components.Linkifier._linkInfo(link); | |
466 if (info.uiLocation && | |
467 Components.openAnchorLocationRegistry.dispatch( | |
468 {url: info.uiLocation.uiSourceCode.url(), lineNumber: info.uiLocatio
n.lineNumber})) | |
469 return; | |
470 if (info.url && Components.openAnchorLocationRegistry.dispatch({url: info.ur
l, lineNumber: info.lineNumber})) | |
471 return; | |
472 if (info.revealable) { | |
473 Common.Revealer.reveal(info.revealable); | |
474 return; | |
475 } | |
476 var actions = Components.Linkifier._linkActions(link); | 426 var actions = Components.Linkifier._linkActions(link); |
477 if (actions.length) | 427 if (actions.length) |
478 actions[0].handler.call(null); | 428 actions[0].handler.call(null); |
479 } | 429 } |
480 | 430 |
481 /** | 431 /** |
| 432 * @return {!Common.Setting} |
| 433 */ |
| 434 static _linkHandlerSetting() { |
| 435 if (!Components.Linkifier._linkHandlerSettingInstance) { |
| 436 Components.Linkifier._linkHandlerSettingInstance = |
| 437 Common.settings.createSetting('openLinkHandler', Common.UIString('auto
')); |
| 438 } |
| 439 return Components.Linkifier._linkHandlerSettingInstance; |
| 440 } |
| 441 |
| 442 /** |
| 443 * @param {string} title |
| 444 * @param {!Components.Linkifier.LinkHandler} handler |
| 445 */ |
| 446 static registerLinkHandler(title, handler) { |
| 447 Components.Linkifier._linkHandlers.set(title, handler); |
| 448 self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._upda
te(); |
| 449 } |
| 450 |
| 451 /** |
| 452 * @param {string} title |
| 453 */ |
| 454 static unregisterLinkHandler(title) { |
| 455 Components.Linkifier._linkHandlers.delete(title); |
| 456 self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._upda
te(); |
| 457 } |
| 458 |
| 459 /** |
482 * @param {?Element} link | 460 * @param {?Element} link |
483 * @return {!Array<{title: string, handler: function()}>} | 461 * @return {!Array<{title: string, handler: function()}>} |
484 */ | 462 */ |
485 static _linkActions(link) { | 463 static _linkActions(link) { |
486 var info = Components.Linkifier._linkInfo(link); | 464 var info = Components.Linkifier._linkInfo(link); |
487 var result = []; | 465 var result = []; |
488 if (!info) | 466 if (!info) |
489 return result; | 467 return result; |
490 | 468 |
491 var url = ''; | 469 var url = ''; |
492 var uiLocation = null; | 470 var uiLocation = null; |
493 if (info.uiLocation) { | 471 if (info.uiLocation) { |
494 uiLocation = info.uiLocation; | 472 uiLocation = info.uiLocation; |
495 url = uiLocation.uiSourceCode.contentURL(); | 473 url = uiLocation.uiSourceCode.contentURL(); |
496 } else if (info.url) { | 474 } else if (info.url) { |
497 url = info.url; | 475 url = info.url; |
498 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); | 476 var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); |
499 uiLocation = uiSourceCode ? uiSourceCode.uiLocation(info.lineNumber || 0,
info.columnNumber || 0) : null; | 477 uiLocation = uiSourceCode ? uiSourceCode.uiLocation(info.lineNumber || 0,
info.columnNumber || 0) : null; |
500 } | 478 } |
| 479 var resource = url ? Bindings.resourceForURL(url) : null; |
| 480 var request = url ? SDK.NetworkLog.requestForURL(url) : null; |
| 481 var contentProvider = uiLocation ? uiLocation.uiSourceCode : resource; |
501 | 482 |
502 if (info.revealable) | 483 if (info.revealable) |
503 result.push({title: Common.UIString('Reveal'), handler: () => Common.Revea
ler.reveal(info.revealable)}); | 484 result.push({title: Common.UIString('Reveal'), handler: () => Common.Revea
ler.reveal(info.revealable)}); |
504 | 485 if (uiLocation) { |
505 if (uiLocation) | 486 result.push({ |
506 result.push({title: Common.UIString('Open'), handler: () => Common.Reveale
r.reveal(uiLocation)}); | 487 title: Common.UIString.capitalize('Open in Sources ^panel'), |
507 | 488 handler: () => Common.Revealer.reveal(uiLocation) |
508 var resource = url ? Bindings.resourceForURL(url) : null; | 489 }); |
| 490 } |
509 if (resource) { | 491 if (resource) { |
510 result.push({ | 492 result.push({ |
511 title: Common.UIString.capitalize('Open ^link in Application ^panel'), | 493 title: Common.UIString.capitalize('Open in Application ^panel'), |
512 handler: () => Common.Revealer.reveal(resource) | 494 handler: () => Common.Revealer.reveal(resource) |
513 }); | 495 }); |
514 } | 496 } |
515 | |
516 var request = url ? SDK.NetworkLog.requestForURL(url) : null; | |
517 if (request) { | 497 if (request) { |
518 result.push({ | 498 result.push({ |
519 title: Common.UIString.capitalize('Open ^request in Network ^panel'), | 499 title: Common.UIString.capitalize('Open in Network ^panel'), |
520 handler: () => Common.Revealer.reveal(request) | 500 handler: () => Common.Revealer.reveal(request) |
521 }); | 501 }); |
522 } | 502 } |
523 | 503 if (contentProvider) { |
| 504 var lineNumber = uiLocation ? uiLocation.lineNumber : info.lineNumber || 0
; |
| 505 for (var title of Components.Linkifier._linkHandlers.keys()) { |
| 506 var handler = Components.Linkifier._linkHandlers.get(title); |
| 507 var action = { |
| 508 title: Common.UIString.capitalize('Open using %s', title), |
| 509 handler: handler.bind(null, contentProvider, lineNumber) |
| 510 }; |
| 511 if (title === Components.Linkifier._linkHandlerSetting().get()) |
| 512 result.unshift(action); |
| 513 else |
| 514 result.push(action); |
| 515 } |
| 516 } |
524 if (resource || info.url) { | 517 if (resource || info.url) { |
525 result.push({title: UI.openLinkExternallyLabel(), handler: () => Inspector
FrontendHost.openInNewTab(url)}); | 518 result.push({title: UI.openLinkExternallyLabel(), handler: () => Inspector
FrontendHost.openInNewTab(url)}); |
526 result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFro
ntendHost.copyText(url)}); | 519 result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFro
ntendHost.copyText(url)}); |
527 } | 520 } |
528 | |
529 return result; | 521 return result; |
530 } | 522 } |
531 }; | 523 }; |
532 | 524 |
533 /** @type {!Set<!Components.Linkifier>} */ | 525 /** @type {!Set<!Components.Linkifier>} */ |
534 Components.Linkifier._instances = new Set(); | 526 Components.Linkifier._instances = new Set(); |
535 /** @type {?Components.LinkDecorator} */ | 527 /** @type {?Components.LinkDecorator} */ |
536 Components.Linkifier._decorator = null; | 528 Components.Linkifier._decorator = null; |
537 | 529 |
538 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); | 530 Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors'); |
(...skipping 22 matching lines...) Expand all Loading... |
561 Components.Linkifier.MaxLengthForDisplayedURLs = 150; | 553 Components.Linkifier.MaxLengthForDisplayedURLs = 150; |
562 | 554 |
563 /** | 555 /** |
564 * The maximum length before strings are considered too long for finding URLs. | 556 * The maximum length before strings are considered too long for finding URLs. |
565 * @const | 557 * @const |
566 * @type {number} | 558 * @type {number} |
567 */ | 559 */ |
568 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; | 560 Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; |
569 | 561 |
570 /** | 562 /** |
571 * @interface | 563 * @typedef {function(!Common.ContentProvider, number)} |
572 */ | 564 */ |
573 Components.Linkifier.LinkHandler = function() {}; | 565 Components.Linkifier.LinkHandler; |
574 | 566 |
575 Components.Linkifier.LinkHandler.prototype = { | 567 /** @type {!Map<string, !Components.Linkifier.LinkHandler>} */ |
576 /** | 568 Components.Linkifier._linkHandlers = new Map(); |
577 * @param {string} url | |
578 * @param {number=} lineNumber | |
579 * @return {boolean} | |
580 */ | |
581 handleLink(url, lineNumber) {} | |
582 }; | |
583 | 569 |
584 /** | 570 /** |
585 * @extends {Common.EventTarget} | 571 * @extends {Common.EventTarget} |
586 * @interface | 572 * @interface |
587 */ | 573 */ |
588 Components.LinkDecorator = function() {}; | 574 Components.LinkDecorator = function() {}; |
589 | 575 |
590 Components.LinkDecorator.prototype = { | 576 Components.LinkDecorator.prototype = { |
591 /** | 577 /** |
592 * @param {!Workspace.UISourceCode} uiSourceCode | 578 * @param {!Workspace.UISourceCode} uiSourceCode |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 appendApplicableItems(event, contextMenu, target) { | 658 appendApplicableItems(event, contextMenu, target) { |
673 var targetNode = /** @type {!Node} */ (target); | 659 var targetNode = /** @type {!Node} */ (target); |
674 while (targetNode && !targetNode[Components.Linkifier._infoSymbol]) | 660 while (targetNode && !targetNode[Components.Linkifier._infoSymbol]) |
675 targetNode = targetNode.parentNodeOrShadowHost(); | 661 targetNode = targetNode.parentNodeOrShadowHost(); |
676 var link = /** @type {?Element} */ (targetNode); | 662 var link = /** @type {?Element} */ (targetNode); |
677 var actions = Components.Linkifier._linkActions(link); | 663 var actions = Components.Linkifier._linkActions(link); |
678 for (var action of actions) | 664 for (var action of actions) |
679 contextMenu.appendItem(action.title, action.handler); | 665 contextMenu.appendItem(action.title, action.handler); |
680 } | 666 } |
681 }; | 667 }; |
| 668 |
| 669 /** |
| 670 * @implements {UI.SettingUI} |
| 671 * @unrestricted |
| 672 */ |
| 673 Components.Linkifier.LinkHandlerSettingUI = class { |
| 674 constructor() { |
| 675 this._element = createElementWithClass('select', 'chrome-select'); |
| 676 this._element.addEventListener('change', this._onChange.bind(this), false); |
| 677 this._update(); |
| 678 } |
| 679 |
| 680 _update() { |
| 681 this._element.removeChildren(); |
| 682 var names = Components.Linkifier._linkHandlers.keysArray(); |
| 683 names.unshift(Common.UIString('auto')); |
| 684 for (var name of names) { |
| 685 var option = createElement('option'); |
| 686 option.textContent = name; |
| 687 option.selected = name === Components.Linkifier._linkHandlerSetting().get(
); |
| 688 this._element.appendChild(option); |
| 689 } |
| 690 this._element.disabled = names.length <= 1; |
| 691 } |
| 692 |
| 693 /** |
| 694 * @param {!Event} event |
| 695 */ |
| 696 _onChange(event) { |
| 697 var value = event.target.value; |
| 698 Components.Linkifier._linkHandlerSetting().set(value); |
| 699 } |
| 700 |
| 701 /** |
| 702 * @override |
| 703 * @return {?Element} |
| 704 */ |
| 705 settingElement() { |
| 706 return UI.SettingsUI.createCustomSetting(Common.UIString('Link handling:'),
this._element); |
| 707 } |
| 708 }; |
| 709 |
| 710 /** |
| 711 * @implements {UI.ContextMenu.Provider} |
| 712 * @unrestricted |
| 713 */ |
| 714 Components.Linkifier.ContentProviderContextMenuProvider = class { |
| 715 /** |
| 716 * @override |
| 717 * @param {!Event} event |
| 718 * @param {!UI.ContextMenu} contextMenu |
| 719 * @param {!Object} target |
| 720 */ |
| 721 appendApplicableItems(event, contextMenu, target) { |
| 722 var contentProvider = /** @type {!Common.ContentProvider} */ (target); |
| 723 if (!contentProvider.contentURL()) |
| 724 return; |
| 725 |
| 726 contextMenu.appendItem( |
| 727 UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(c
ontentProvider.contentURL())); |
| 728 for (var title of Components.Linkifier._linkHandlers.keys()) { |
| 729 var handler = Components.Linkifier._linkHandlers.get(title); |
| 730 contextMenu.appendItem( |
| 731 Common.UIString.capitalize('Open using %s', title), handler.bind(null,
contentProvider, 0)); |
| 732 } |
| 733 if (contentProvider instanceof SDK.NetworkRequest) |
| 734 return; |
| 735 |
| 736 contextMenu.appendItem( |
| 737 UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(contentP
rovider.contentURL())); |
| 738 if (!contentProvider.contentType().isDocumentOrScriptOrStyleSheet()) |
| 739 return; |
| 740 |
| 741 /** |
| 742 * @param {boolean} forceSaveAs |
| 743 * @param {?string} content |
| 744 */ |
| 745 function doSave(forceSaveAs, content) { |
| 746 var url = contentProvider.contentURL(); |
| 747 Workspace.fileManager.save(url, /** @type {string} */ (content), forceSave
As); |
| 748 Workspace.fileManager.close(url); |
| 749 } |
| 750 |
| 751 /** |
| 752 * @param {boolean} forceSaveAs |
| 753 */ |
| 754 function save(forceSaveAs) { |
| 755 if (contentProvider instanceof Workspace.UISourceCode) { |
| 756 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvid
er); |
| 757 if (forceSaveAs) |
| 758 uiSourceCode.saveAs(); |
| 759 else |
| 760 uiSourceCode.commitWorkingCopy(); |
| 761 return; |
| 762 } |
| 763 contentProvider.requestContent().then(doSave.bind(null, forceSaveAs)); |
| 764 } |
| 765 |
| 766 contextMenu.appendSeparator(); |
| 767 contextMenu.appendItem(Common.UIString('Save'), save.bind(null, false)); |
| 768 |
| 769 if (contentProvider instanceof Workspace.UISourceCode) { |
| 770 var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider
); |
| 771 if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem && |
| 772 uiSourceCode.project().type() !== Workspace.projectTypes.Snippets) |
| 773 contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.b
ind(null, true)); |
| 774 } |
| 775 } |
| 776 }; |
OLD | NEW |