Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: Source/devtools/front_end/extensions/ExtensionServer.js

Issue 1264133002: Devtools: [WIP] Implement enhanced devtools extension language APIs Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Modify override dropdown to apply to console completions & transpile Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/devtools/front_end/extensions/ExtensionServer.js
diff --git a/Source/devtools/front_end/extensions/ExtensionServer.js b/Source/devtools/front_end/extensions/ExtensionServer.js
index 5d8cab22c3660a102f3c0efd86ddfb78d265cc8e..2a675e50a613144960313b1961dda3915ae01502 100644
--- a/Source/devtools/front_end/extensions/ExtensionServer.js
+++ b/Source/devtools/front_end/extensions/ExtensionServer.js
@@ -31,12 +31,15 @@
/**
* @constructor
* @extends {WebInspector.Object}
+ * @param {!WebInspector.ExtensionServer.UIDelegate} delegate
* @suppressGlobalPropertiesCheck
*/
-WebInspector.ExtensionServer = function()
+WebInspector.ExtensionServer = function(delegate)
{
+ this._delegate = delegate;
this._clientObjects = {};
this._handlers = {};
+ this._callbacks = {};
this._subscribers = {};
this._subscriptionStartHandlers = {};
this._subscriptionStopHandlers = {};
@@ -59,15 +62,20 @@ WebInspector.ExtensionServer = function()
this._registerHandler(commands.CreatePanel, this._onCreatePanel.bind(this));
this._registerHandler(commands.CreateSidebarPane, this._onCreateSidebarPane.bind(this));
this._registerHandler(commands.CreateToolbarButton, this._onCreateToolbarButton.bind(this));
+ this._registerHandler(commands.DisplaySearchResults, this._onDisplaySearchResults.bind(this));
this._registerHandler(commands.EvaluateOnInspectedPage, this._onEvaluateOnInspectedPage.bind(this));
this._registerHandler(commands.ForwardKeyboardEvent, this._onForwardKeyboardEvent.bind(this));
this._registerHandler(commands.GetHAR, this._onGetHAR.bind(this));
this._registerHandler(commands.GetPageResources, this._onGetPageResources.bind(this));
this._registerHandler(commands.GetRequestContent, this._onGetRequestContent.bind(this));
this._registerHandler(commands.GetResourceContent, this._onGetResourceContent.bind(this));
+ this._registerHandler(commands.GetResourceLineMessages, this._onGetResourceLineMessages.bind(this));
+ this._registerHandler(commands.RegisterLanguageService, this._onRegisterLanguageService.bind(this));
+ this._registerHandler(commands.RegisterMimeRecognizer, this._onRegisterMimeRecognizer.bind(this));
this._registerHandler(commands.Reload, this._onReload.bind(this));
this._registerHandler(commands.SetOpenResourceHandler, this._onSetOpenResourceHandler.bind(this));
this._registerHandler(commands.SetResourceContent, this._onSetResourceContent.bind(this));
+ this._registerHandler(commands.SetResourceLineMessages, this._onSetResourceLineMessages.bind(this));
this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bind(this));
this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent.bind(this));
this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(this));
@@ -78,6 +86,7 @@ WebInspector.ExtensionServer = function()
this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this));
this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this));
this._registerHandler(commands.UpdateAuditProgress, this._onUpdateAuditProgress.bind(this));
+ this._registerHandler("callback", this._onCallback.bind(this));
window.addEventListener("message", this._onWindowMessage.bind(this), false); // Only for main window.
InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.AddExtensions, this._addExtensions, this);
@@ -179,6 +188,26 @@ WebInspector.ExtensionServer.prototype = {
return !!this._subscribers[type];
},
+ _registerCallback: function(callback) {
+ var cbId = Math.random()*Number.MAX_VALUE;
+ if (this._callbacks[cbId]) {
+ return this._registerCallback(callback);
+ }
+ this._callbacks[cbId] = callback;
+ return cbId;
+ },
+
+ /**
+ * @param {!MessagePort} port
+ * @param {*} message
+ * @param {?Function=} callback
+ */
+ _sendRequest: function(port, message, callback) {
+ if (typeof callback === "function")
+ message.requestId = this._registerCallback(callback);
+ port.postMessage(message);
+ },
+
/**
* @param {string} type
* @param {...*} vararg
@@ -247,6 +276,197 @@ WebInspector.ExtensionServer.prototype = {
/**
* @param {*} message
+ * @param {!MessagePort} port
+ */
+ _onRegisterLanguageService: function(message, port) {
+ if (!(message.mimes && message.name && message.capabilities)) {
+ return;
+ }
+ var _this = this;
+
+ if (message.simplemode) {
+ this._delegate.addSimpleCodeMirrorMode(message.mimes, message.simplemode);
+ }
+
+ var service = new WebInspector.LanguageService.CallbackDelegate(message.name, {});
+
+ if (message.capabilities.indexOf(WebInspector.LanguageService.Capabilities.Transpile) !== -1) {
+ service.appendActionHandler(WebInspector.LanguageService.Capabilities.Transpile, function(input, location, callback) {
+ if (!callback) {
+ callback = location;
+ location = undefined;
+ }
+ _this._sendRequest(port, {
+ command: WebInspector.LanguageService.Capabilities.Transpile+"-"+message.name,
+ input: input,
+ location: location
+ }, function(result) {
+ if ((!result) || typeof result !== "string") {
+ return callback(input);
+ }
+ callback(result);
+ });
+ });
+ }
+ if (message.capabilities.indexOf(WebInspector.LanguageService.Capabilities.PopulateContextMenu) !== -1) {
+ service.appendActionHandler(WebInspector.LanguageService.Capabilities.PopulateContextMenu, function(location, callback) {
+ _this._sendRequest(port, {
+ command: WebInspector.LanguageService.Capabilities.PopulateContextMenu+"-"+message.name,
+ location: location
+ }, function(items) {
+ if (!items || !(items instanceof Array)) {
+ return callback([]);
+ }
+ callback(items.map(function(item) {
+ if (typeof item.text !== "string") return;
+ if (typeof item.id !== "number") return;
+ return {
+ text: item.text,
+ callback: function() {
+ _this._sendRequest(port, {command: "notify-"+WebInspector.extensionAPI.Events.ContextMenuClicked, id: item.id});
+ }
+ };
+ }).filter(i => {return i;}));
+ });
+ });
+ }
+
+ function handleCompletionsResponse(callback) {
+ return function(completions) {
+ if ((!completions) || !(completions instanceof Array)) {
+ return callback([]);
+ }
+ callback(completions.map(function(c){
+ if (typeof c.text !== "string") return;
+ if (!(typeof c.icon === "string" || typeof c.icon === "undefined")) return;
+ if (typeof c.id !== "number") return;
+ return {
+ text: c.text,
+ icon: c.icon,
+ details: function() {
+ return new Promise(function(resolve, reject) {
+ _this._sendRequest(port, {command: "completionDetails-"+message.name, id: c.id}, function(resp) {
+ if (!resp) reject();
+ if (typeof resp.detail !== "string") reject();
+ if (typeof resp.description !== "string") reject();
+ resolve(resp);
+ });
+ });
+ }
+ };
+ }).filter(i => {return i;}));
+ }
+ }
+
+ if (message.capabilities.indexOf(WebInspector.LanguageService.Capabilities.Completions) !== -1) {
+ service.appendActionHandler(WebInspector.LanguageService.Capabilities.Completions, function(location, prefix, callback) {
+ _this._sendRequest(port, {
+ command: WebInspector.LanguageService.Capabilities.Completions+"-"+message.name,
+ location: location,
+ prefix: prefix
+ }, handleCompletionsResponse(callback));
+ });
+ }
+
+ if (message.capabilities.indexOf(WebInspector.LanguageService.Capabilities.DebuggerCompletions) !== -1) {
+ service.appendActionHandler(WebInspector.LanguageService.Capabilities.DebuggerCompletions, function(content, cursor, prefix, context, callback) {
+ _this._sendRequest(port, {
+ command: WebInspector.LanguageService.Capabilities.DebuggerCompletions+"-"+message.name,
+ content: content,
+ cursor: cursor,
+ prefix: prefix,
+ context: context
+ }, handleCompletionsResponse(callback));
+ });
+ }
+
+ WebInspector.languageService.register(message.mimes, service);
+ },
+
+ _onRegisterMimeRecognizer: function(message) {
+ if (typeof message.mime !== "string") {
+ return this._status.E_BADARGTYPE("mime", typeof message.mime, "string");
+ }
+ if (typeof message.match !== "string") {
+ return this._status.E_BADARGTYPE("match", typeof message.match, "string");
+ }
+ WebInspector.ResourceType.registerMimeRecognizer(message.match, message.mime, message.matchName);
+ },
+
+ _onDisplaySearchResults: function(message) {
+ //FIXME: Search result highlighting should allow ranges to be highlighted rather than regexes
+ var results = message.results || [];
+
+ var groupedResults = results.reduce(function(accum, item) { //group by source
+ var elem;
+ for (var index = 0; index < accum.length; index++) {
+ var element = accum[index];
+ if (element.source === item.source) {
+ elem = element;
+ break;
+ }
+ }
+ if (!elem) {
+ elem = [];
+ elem.source = item.source;
+ accum.push(elem);
+ }
+ elem.push({
+ line: item.line,
+ lineContent: item.lineContent || '',
+ startColumn: item.startColumn || 0,
+ endColumn: item.endColumn || 0
+ });
+ return accum;
+ }, []);
+ this._delegate.displaySearchResults(results.highlight || '', groupedResults);
+ },
+
+ /**
+ * @param {*} message
+ * @param {!MessagePort} port
+ */
+ _onGetResourceLineMessages: function(message, port) {
+ var url = /** @type {string} */ (message.url);
+ var uiSourceCode = WebInspector.networkMapping.uiSourceCodeFromURL(url);
+ if (!uiSourceCode)
+ return this._status.E_NOTFOUND(url);
+
+ this._delegate.getResourceLineMessages(uiSourceCode).then(arr => {
+ var result = arr.map(m => {
+ return {
+ text: m.messageText(),
+ kind: m.level(),
+ location: {
+ startLine: m.start().line,
+ startColumn: m.start().column,
+ endLine: m.end().line,
+ endColumn: m.end().column
+ }
+ };
+ });
+ this._dispatchCallback(message.requestId, port, result);
+ });
+ },
+
+ /**
+ * @param {*} message
+ * @param {!MessagePort} port
+ */
+ _onSetResourceLineMessages: function(message, port) {
+ var url = /** @type {string} */ (message.url);
+ var messages = /** @type {?Array.<{kind: string, text: string, location: {startLine: number, startColumn: number, endLine: number, endColumn: number}}>} */ (message.messages);
+ if ((!messages) || typeof messages !== "object")
+ return this._status.E_BADARGTYPE("messages", typeof messages, "Array<LineMessage>");
+ var uiSourceCode = WebInspector.networkMapping.uiSourceCodeFromURL(url);
+ if (!uiSourceCode)
+ return this._status.E_NOTFOUND(url);
+ this._delegate.setResourceLineMessages(uiSourceCode, messages);
+ this._dispatchCallback(message.requestId, port, this._status.OK());
+ },
+
+ /**
+ * @param {*} message
* @suppressGlobalPropertiesCheck
*/
_onApplyStyleSheet: function(message)
@@ -367,7 +587,7 @@ WebInspector.ExtensionServer.prototype = {
_onOpenResource: function(message)
{
- var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForURLForAnyTarget(message.url);
+ var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForURLForAnyTarget(message.url) || WebInspector.workspace.uiSourceCodeForFilePath(message.url);
wes 2015/08/14 01:13:32 Upon review, I see that this line is an alias to t
pfeldman 2015/08/17 21:15:51 Your message has a target, so you should get resou
wes 2015/08/25 18:13:18 The open resource message only has a url and a lin
if (uiSourceCode) {
WebInspector.Revealer.reveal(uiSourceCode.uiLocation(message.lineNumber, 0));
return this._status.OK();
@@ -489,6 +709,7 @@ WebInspector.ExtensionServer.prototype = {
}
var uiSourceCodes = WebInspector.workspace.uiSourceCodesForProjectType(WebInspector.projectTypes.Network);
uiSourceCodes = uiSourceCodes.concat(WebInspector.workspace.uiSourceCodesForProjectType(WebInspector.projectTypes.ContentScripts));
+ uiSourceCodes = uiSourceCodes.concat(WebInspector.workspace.uiSourceCodesForProjectType(WebInspector.projectTypes.FileSystem));
uiSourceCodes.forEach(pushResourceData.bind(this));
for (var target of WebInspector.targetManager.targets())
target.resourceTreeModel.forAllResources(pushResourceData.bind(this));
@@ -534,7 +755,7 @@ WebInspector.ExtensionServer.prototype = {
_onGetResourceContent: function(message, port)
{
var url = /** @type {string} */ (message.url);
- var contentProvider = WebInspector.workspace.uiSourceCodeForOriginURL(url) || WebInspector.resourceForURL(url);
+ var contentProvider = WebInspector.networkMapping.uiSourceCodeFromURL(url);
if (!contentProvider)
return this._status.E_NOTFOUND(url);
this._getResourceContent(contentProvider, message, port);
@@ -671,6 +892,15 @@ WebInspector.ExtensionServer.prototype = {
port.postMessage({ command: "callback", requestId: requestId, result: result });
},
+ _onCallback: function(request, target)
+ {
+ if (request.requestId in this._callbacks) {
+ var callback = this._callbacks[request.requestId];
+ delete this._callbacks[request.requestId];
+ callback(request.result);
+ }
+ },
+
_initExtensions: function()
{
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceAdded,
@@ -697,6 +927,7 @@ WebInspector.ExtensionServer.prototype = {
this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.PanelObjectSelected + "elements",
onElementsSubscriptionStarted.bind(this), onElementsSubscriptionStopped.bind(this));
this._registerResourceContentCommittedHandler(this._notifyUISourceCodeContentCommitted);
+ this._registerResourceContentEditedHandler(this._notifyUISourceCodeContentEdited);
WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.InspectedURLChanged,
this._inspectedURLChanged, this);
@@ -717,6 +948,12 @@ WebInspector.ExtensionServer.prototype = {
this._postNotification(WebInspector.extensionAPI.Events.ResourceContentCommitted, this._makeResource(uiSourceCode), content);
},
+ _notifyUISourceCodeContentEdited: function(event)
+ {
+ var data = /** @type {{uiSourceCode: !WebInspector.UISourceCode, replacement: string, range: !WebInspector.TextRange}} */ (event.data);
+ this._postNotification(WebInspector.extensionAPI.Events.ResourceContentEdited, this._makeResource(data.uiSourceCode), data.range, data.replacement);
+ },
+
_notifyRequestFinished: function(event)
{
var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
@@ -879,6 +1116,29 @@ WebInspector.ExtensionServer.prototype = {
removeLastEventListener.bind(this));
},
+ _registerResourceContentEditedHandler: function(handler)
+ {
+ /**
+ * @this {WebInspector.ExtensionServer}
+ */
+ function addFirstEventListener()
+ {
+ WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeEdited, handler, this);
+ }
+
+ /**
+ * @this {WebInspector.ExtensionServer}
+ */
+ function removeLastEventListener()
+ {
+ WebInspector.workspace.removeEventListener(WebInspector.Workspace.Events.UISourceCodeEdited, handler, this);
+ }
+
+ this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.ResourceContentEdited,
+ addFirstEventListener.bind(this),
+ removeLastEventListener.bind(this));
+ },
+
_expandResourcePath: function(extensionPath, resourcePath)
{
if (!resourcePath)
@@ -1081,3 +1341,44 @@ WebInspector.ExtensionStatus.Record;
WebInspector.extensionAPI = {};
defineCommonExtensionSymbols(WebInspector.extensionAPI);
+
+/**
+ * @typedef {Array<{line: number, lineContent: string}>}
+ * @property {string} source
+ */
+var SearchResultArray;
+
+/**
+ * @typedef {!Array<{messageText: function(): string, level: function(): string, start: function(): {line: number, column: number}, end: function(): {line: number, column: number}}>}
+ */
+var SourceFrameMessageGetter;
+
+/**
+ * @interface
+ */
+WebInspector.ExtensionServer.UIDelegate = function() {}
+WebInspector.ExtensionServer.UIDelegate.prototype = {
+ /**
+ * @param {!WebInspector.UISourceCode} code
+ * @param {!Array<{kind: string, text: string, location: {startLine: number, startColumn: number, endLine: number, endColumn: number}}>} messages
+ */
+ setResourceLineMessages: function(code, messages) {},
+
+ /**
+ * @param {!WebInspector.UISourceCode} code
+ * @return {!Promise<!SourceFrameMessageGetter>}
+ */
+ getResourceLineMessages: function(code) { return Promise.reject(); },
+
+ /**
+ * @param {string} highlightText
+ * @param {!Array<!SearchResultArray>} groupedResults
+ */
+ displaySearchResults: function(highlightText, groupedResults) {},
+
+ /**
+ * @param {!Array<string>} mimes
+ * @param {?} mode
+ */
+ addSimpleCodeMirrorMode: function(mimes, mode){}
+}

Powered by Google App Engine
This is Rietveld 408576698