Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| index 5616cd588a3214c952bbb64b39f2df862759b054..b8d267b0aa247d6017a11cea357ee1fefe0d2bbf 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js |
| @@ -77,24 +77,6 @@ Components.Linkifier = class { |
| } |
| /** |
| - * @param {?Components.Linkifier.LinkHandler} handler |
| - */ |
| - static setLinkHandler(handler) { |
| - Components.Linkifier._linkHandler = handler; |
| - } |
| - |
| - /** |
| - * @param {string} url |
| - * @param {number=} lineNumber |
| - * @return {boolean} |
| - */ |
| - static handleLink(url, lineNumber) { |
| - if (!Components.Linkifier._linkHandler) |
| - return false; |
| - return Components.Linkifier._linkHandler.handleLink(url, lineNumber); |
| - } |
| - |
| - /** |
| * @param {!Element} anchor |
| * @param {!Workspace.UILocation} uiLocation |
| */ |
| @@ -127,27 +109,6 @@ Components.Linkifier = class { |
| } |
| /** |
| - * @param {!SDK.Target} target |
| - * @param {string} scriptId |
| - * @param {number} lineNumber |
| - * @param {number=} columnNumber |
| - * @return {string} |
| - */ |
| - static liveLocationText(target, scriptId, lineNumber, columnNumber) { |
| - var debuggerModel = SDK.DebuggerModel.fromTarget(target); |
| - if (!debuggerModel) |
| - return ''; |
| - var script = debuggerModel.scriptForId(scriptId); |
| - if (!script) |
| - return ''; |
| - var location = /** @type {!SDK.DebuggerModel.Location} */ ( |
| - debuggerModel.createRawLocation(script, lineNumber, columnNumber || 0)); |
| - var uiLocation = |
| - /** @type {!Workspace.UILocation} */ (Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location)); |
| - return uiLocation.linkText(); |
| - } |
| - |
| - /** |
| * @override |
| * @param {!SDK.Target} target |
| */ |
| @@ -466,12 +427,6 @@ Components.Linkifier = class { |
| if (link.preventFollow || UI.isBeingEdited(/** @type {!Node} */ (event.target))) |
| return; |
| var info = Components.Linkifier._linkInfo(link); |
| - if (info.uiLocation && |
| - Components.openAnchorLocationRegistry.dispatch( |
| - {url: info.uiLocation.uiSourceCode.url(), lineNumber: info.uiLocation.lineNumber})) |
| - return; |
| - if (info.url && Components.openAnchorLocationRegistry.dispatch({url: info.url, lineNumber: info.lineNumber})) |
| - return; |
| if (info.revealable) { |
|
lushnikov
2016/11/21 20:51:09
this changes the order: revealable now prevails ov
dgozman
2016/11/21 23:34:50
Fixed.
|
| Common.Revealer.reveal(info.revealable); |
| return; |
| @@ -482,6 +437,33 @@ Components.Linkifier = class { |
| } |
| /** |
| + * @return {!Common.Setting} |
| + */ |
| + static _linkHandlerSetting() { |
| + if (!Components.Linkifier._linkHandlerSettingInstance) { |
| + Components.Linkifier._linkHandlerSettingInstance = |
| + Common.settings.createSetting('openLinkHandler', Common.UIString('auto')); |
| + } |
| + return Components.Linkifier._linkHandlerSettingInstance; |
| + } |
| + |
| + /** |
| + * @param {!{title: string, handler: !Components.Linkifier.LinkHandler}} entry |
| + */ |
| + static registerLinkHandler(entry) { |
| + Components.Linkifier._linkHandlers.push(entry); |
| + self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._update(); |
| + } |
| + |
| + /** |
| + * @param {string} title |
| + */ |
| + static unregisterLinkHandler(title) { |
| + Components.Linkifier._linkHandlers = Components.Linkifier._linkHandlers.filter(entry => entry.title !== title); |
|
caseq
2016/11/21 20:13:09
if we remove by title, this could as well be a map
dgozman
2016/11/21 23:34:50
Done.
|
| + self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._update(); |
| + } |
| + |
| + /** |
| * @param {?Element} link |
| * @return {!Array<{title: string, handler: function()}>} |
| */ |
| @@ -489,11 +471,14 @@ Components.Linkifier = class { |
| var info = Components.Linkifier._linkInfo(link); |
| if (info && info.revealable) |
| return []; |
| + |
| var url = ''; |
| var uiLocation = null; |
| + var lineNumber = info.lineNumber || 0; |
|
lushnikov
2016/11/21 20:51:09
let's inline this to the use-site
uiLocation ? uiL
dgozman
2016/11/21 23:34:50
Done.
|
| if (info && info.uiLocation) { |
| uiLocation = info.uiLocation; |
| url = uiLocation.uiSourceCode.contentURL(); |
| + lineNumber = uiLocation.lineNumber; |
| } else if (info && info.url) { |
| url = info.url; |
| var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); |
| @@ -503,30 +488,44 @@ Components.Linkifier = class { |
| } |
| var result = []; |
| - if (uiLocation) |
| - result.push({title: Common.UIString('Open'), handler: () => Common.Revealer.reveal(uiLocation)}); |
| - |
| var resource = Bindings.resourceForURL(url); |
| + var request = SDK.NetworkLog.requestForURL(url); |
| + var contentProvider = uiLocation ? uiLocation.uiSourceCode : resource; |
| + |
| + if (contentProvider) { |
|
lushnikov
2016/11/21 20:51:09
let's move this to the end.
dgozman
2016/11/21 23:34:50
Done.
|
| + for (var entry of Components.Linkifier._linkHandlers) { |
| + var action = { |
| + title: Common.UIString.capitalize('Open using %s', entry.title), |
| + handler: entry.handler.bind(null, contentProvider, lineNumber) |
| + }; |
| + if (entry.title === Components.Linkifier._linkHandlerSetting().get()) |
| + result.unshift(action); |
| + else |
| + result.push(action); |
| + } |
| + } |
| + if (uiLocation) { |
| + result.push({ |
| + title: Common.UIString.capitalize('Open in Sources ^panel'), |
| + handler: () => Common.Revealer.reveal(uiLocation) |
| + }); |
| + } |
| if (resource) { |
| result.push({ |
| - title: Common.UIString.capitalize('Open ^link in Application ^panel'), |
| + title: Common.UIString.capitalize('Open in Application ^panel'), |
| handler: () => Common.Revealer.reveal(resource) |
| }); |
| } |
| - |
| - var request = SDK.NetworkLog.requestForURL(url); |
| if (request) { |
| result.push({ |
| - title: Common.UIString.capitalize('Open ^request in Network ^panel'), |
| + title: Common.UIString.capitalize('Open in Network ^panel'), |
| handler: () => Common.Revealer.reveal(request) |
| }); |
| } |
| - |
| if (resource || info.url) { |
| result.push({title: UI.openLinkExternallyLabel(), handler: () => InspectorFrontendHost.openInNewTab(url)}); |
| result.push({title: UI.copyLinkAddressLabel(), handler: () => InspectorFrontendHost.copyText(url)}); |
| } |
| - |
| return result; |
| } |
| }; |
| @@ -569,18 +568,12 @@ Components.Linkifier.MaxLengthForDisplayedURLs = 150; |
| Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000; |
| /** |
| - * @interface |
| + * @typedef {function(!Common.ContentProvider, number)} |
| */ |
| -Components.Linkifier.LinkHandler = function() {}; |
| +Components.Linkifier.LinkHandler; |
| -Components.Linkifier.LinkHandler.prototype = { |
| - /** |
| - * @param {string} url |
| - * @param {number=} lineNumber |
| - * @return {boolean} |
| - */ |
| - handleLink(url, lineNumber) {} |
| -}; |
| +/** @type {!Array<{title: string, handler: !Components.Linkifier.LinkHandler}>} */ |
| +Components.Linkifier._linkHandlers = []; |
| /** |
| * @extends {Common.EventTarget} |
| @@ -680,3 +673,111 @@ Components.Linkifier.LinkContextMenuProvider = class { |
| contextMenu.appendItem(action.title, action.handler); |
| } |
| }; |
| + |
| +/** |
| + * @implements {UI.SettingUI} |
| + * @unrestricted |
| + */ |
| +Components.Linkifier.LinkHandlerSettingUI = class { |
|
caseq
2016/11/21 20:13:09
Does it really belong to Linkifier?
|
| + constructor() { |
| + this._element = createElementWithClass('select', 'chrome-select'); |
| + this._element.addEventListener('change', this._onChange.bind(this), false); |
| + this._update(); |
| + } |
| + |
| + _update() { |
| + this._element.removeChildren(); |
| + var names = Components.Linkifier._linkHandlers.map(entry => entry.title); |
| + names.unshift(Common.UIString('auto')); |
| + for (var name of names) { |
| + var option = createElement('option'); |
| + option.textContent = name; |
| + option.selected = name === Components.Linkifier._linkHandlerSetting().get(); |
| + this._element.appendChild(option); |
| + } |
| + this._element.disabled = names.length <= 1; |
| + } |
| + |
| + /** |
| + * @param {!Event} event |
| + */ |
| + _onChange(event) { |
| + var value = event.target.value; |
| + Components.Linkifier._linkHandlerSetting().set(value); |
| + } |
| + |
| + /** |
| + * @override |
| + * @return {?Element} |
| + */ |
| + settingElement() { |
| + return UI.SettingsUI.createCustomSetting(Common.UIString('Link handling:'), this._element); |
| + } |
| +}; |
| + |
| +/** |
| + * @implements {UI.ContextMenu.Provider} |
| + * @unrestricted |
| + */ |
| +Components.Linkifier.ContentProviderContextMenuProvider = class { |
| + /** |
| + * @override |
| + * @param {!Event} event |
| + * @param {!UI.ContextMenu} contextMenu |
| + * @param {!Object} target |
| + */ |
| + appendApplicableItems(event, contextMenu, target) { |
| + var contentProvider = /** @type {!Common.ContentProvider} */ (target); |
| + if (!contentProvider.contentURL()) |
| + return; |
| + |
| + contextMenu.appendItem( |
| + UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(contentProvider.contentURL())); |
| + for (var entry of Components.Linkifier._linkHandlers) { |
| + contextMenu.appendItem( |
| + Common.UIString.capitalize('Open using %s', entry.title), entry.handler.bind(null, contentProvider, 0)); |
| + } |
| + if (contentProvider instanceof SDK.NetworkRequest) |
| + return; |
| + |
| + contextMenu.appendItem( |
| + UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(contentProvider.contentURL())); |
| + if (!contentProvider.contentType().isDocumentOrScriptOrStyleSheet()) |
| + return; |
| + |
| + /** |
| + * @param {boolean} forceSaveAs |
| + * @param {?string} content |
| + */ |
| + function doSave(forceSaveAs, content) { |
| + var url = contentProvider.contentURL(); |
| + Workspace.fileManager.save(url, /** @type {string} */ (content), forceSaveAs); |
| + Workspace.fileManager.close(url); |
| + } |
| + |
| + /** |
| + * @param {boolean} forceSaveAs |
| + */ |
| + function save(forceSaveAs) { |
| + if (contentProvider instanceof Workspace.UISourceCode) { |
| + var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider); |
| + if (forceSaveAs) |
| + uiSourceCode.saveAs(); |
| + else |
| + uiSourceCode.commitWorkingCopy(); |
| + return; |
| + } |
| + contentProvider.requestContent().then(doSave.bind(null, forceSaveAs)); |
| + } |
| + |
| + contextMenu.appendSeparator(); |
| + contextMenu.appendItem(Common.UIString('Save'), save.bind(null, false)); |
| + |
| + if (contentProvider instanceof Workspace.UISourceCode) { |
| + var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider); |
| + if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem && |
| + uiSourceCode.project().type() !== Workspace.projectTypes.Snippets) |
| + contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.bind(null, true)); |
| + } |
| + } |
| +}; |