| 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..8fbab4778c6a4e468c84facae144515cea2d3486 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,19 @@ 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.RegisterLanguageService, this._onRegisterLanguageService.bind(this));
|
| + this._registerHandler(commands.NewMimeType, this._onNewMimeType.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 +85,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 +187,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 +275,171 @@ 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(function(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(function(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);
|
| + },
|
| +
|
| + _onNewMimeType: function(message)
|
| + {
|
| + if (typeof message.mime !== "string") {
|
| + return this._status.E_BADARGTYPE("mime", typeof message.mime, "string");
|
| + }
|
| + if (typeof message.extensionOrName !== "string") {
|
| + return this._status.E_BADARGTYPE("match", typeof message.match, "string");
|
| + }
|
| + WebInspector.ResourceType.newMimeType(message.extensionOrName, message.mime, message.byName);
|
| + },
|
| +
|
| + _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(new WebInspector.SearchResult(item.line, item.lineContent || ''));
|
| + return accum;
|
| + }, []);
|
| + WebInspector.Revealer.reveal(new WebInspector.SearchResultsCollection(results.highlight || '', groupedResults));
|
| + },
|
| +
|
| + /**
|
| + * @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.uiSourceCodeForURLForAnyTarget(url) || WebInspector.workspace.uiSourceCodeForFilePath(url);
|
| + if (!uiSourceCode)
|
| + return this._status.E_NOTFOUND(url);
|
| + WebInspector.Revealer.reveal(new WebInspector.UISourceCodeMessages(uiSourceCode, messages.map(function(m) {
|
| + return new WebInspector.UISourceCodeMessage(m.text, m.kind, m.location);
|
| + })))
|
| + this._dispatchCallback(message.requestId, port, this._status.OK());
|
| + },
|
| +
|
| + /**
|
| + * @param {*} message
|
| * @suppressGlobalPropertiesCheck
|
| */
|
| _onApplyStyleSheet: function(message)
|
| @@ -367,7 +560,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);
|
| if (uiSourceCode) {
|
| WebInspector.Revealer.reveal(uiSourceCode.uiLocation(message.lineNumber, 0));
|
| return this._status.OK();
|
| @@ -489,6 +682,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 +728,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.uiSourceCodeForURLForAnyTarget(url) || WebInspector.workspace.uiSourceCodeForFilePath(url);
|
| if (!contentProvider)
|
| return this._status.E_NOTFOUND(url);
|
| this._getResourceContent(contentProvider, message, port);
|
| @@ -671,6 +865,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 +900,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 +921,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 +1089,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 +1314,22 @@ WebInspector.ExtensionStatus.Record;
|
|
|
| WebInspector.extensionAPI = {};
|
| defineCommonExtensionSymbols(WebInspector.extensionAPI);
|
| +
|
| +/**
|
| + * @typedef {Array<{line: number, lineContent: string}>}
|
| + * @property {string} source
|
| + */
|
| +var SearchResultArray;
|
| +
|
| +/**
|
| + * @interface
|
| + */
|
| +WebInspector.ExtensionServer.UIDelegate = function() {}
|
| +WebInspector.ExtensionServer.UIDelegate.prototype = {
|
| +
|
| + /**
|
| + * @param {!Array<string>} mimes
|
| + * @param {?} mode
|
| + */
|
| + addSimpleCodeMirrorMode: function(mimes, mode){}
|
| +}
|
|
|