/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
export default class ExtensionServer extends Common.Object {
  /**
   * @suppressGlobalPropertiesCheck
   */
  constructor() {
    super();
    this._clientObjects = {};
    this._handlers = {};
    this._subscribers = {};
    this._subscriptionStartHandlers = {};
    this._subscriptionStopHandlers = {};
    this._extraHeaders = {};
    this._requests = {};
    this._lastRequestId = 0;
    this._registeredExtensions = {};
    this._status = new ExtensionStatus();
    /** @type {!Array<!Extensions.ExtensionSidebarPane>} */
    this._sidebarPanes = [];
    /** @type {!Array<!Extensions.ExtensionTraceProvider>} */
    this._traceProviders = [];
    /** @type {!Map<string, !Extensions.TracingSession>} */
    this._traceSessions = new Map();

    const commands = Extensions.extensionAPI.Commands;

    this._registerHandler(commands.AddRequestHeaders, this._onAddRequestHeaders.bind(this));
    this._registerHandler(commands.AddTraceProvider, this._onAddTraceProvider.bind(this));
    this._registerHandler(commands.ApplyStyleSheet, this._onApplyStyleSheet.bind(this));
    this._registerHandler(commands.CompleteTraceSession, this._onCompleteTraceSession.bind(this));
    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.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.Reload, this._onReload.bind(this));
    this._registerHandler(commands.SetOpenResourceHandler, this._onSetOpenResourceHandler.bind(this));
    this._registerHandler(commands.SetResourceContent, this._onSetResourceContent.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));
    this._registerHandler(commands.ShowPanel, this._onShowPanel.bind(this));
    this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this));
    this._registerHandler(commands.OpenResource, this._onOpenResource.bind(this));
    this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this));
    this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this));
    window.addEventListener('message', this._onWindowMessage.bind(this), false);  // Only for main window.

    /** @suppress {checkTypes} */
    const existingTabId =
        window.DevToolsAPI && window.DevToolsAPI.getInspectedTabId && window.DevToolsAPI.getInspectedTabId();

    if (existingTabId) {
      this._setInspectedTabId({data: existingTabId});
    }
    Host.InspectorFrontendHost.events.addEventListener(
        Host.InspectorFrontendHostAPI.Events.SetInspectedTabId, this._setInspectedTabId, this);

    this._initExtensions();
  }

  initializeExtensions() {
    Host.InspectorFrontendHost.setAddExtensionCallback(this._addExtension.bind(this));
  }

  /**
   * @return {boolean}
   */
  hasExtensions() {
    return !!Object.keys(this._registeredExtensions).length;
  }

  /**
   * @param {string} panelId
   * @param {string} action
   * @param {string=} searchString
   */
  notifySearchAction(panelId, action, searchString) {
    this._postNotification(Extensions.extensionAPI.Events.PanelSearch + panelId, action, searchString);
  }

  /**
   * @param {string} identifier
   * @param {number=} frameIndex
   */
  notifyViewShown(identifier, frameIndex) {
    this._postNotification(Extensions.extensionAPI.Events.ViewShown + identifier, frameIndex);
  }

  /**
   * @param {string} identifier
   */
  notifyViewHidden(identifier) {
    this._postNotification(Extensions.extensionAPI.Events.ViewHidden + identifier);
  }

  /**
   * @param {string} identifier
   */
  notifyButtonClicked(identifier) {
    this._postNotification(Extensions.extensionAPI.Events.ButtonClicked + identifier);
  }

  _inspectedURLChanged(event) {
    if (event.data !== SDK.targetManager.mainTarget()) {
      return;
    }
    this._requests = {};
    const url = event.data.inspectedURL();
    this._postNotification(Extensions.extensionAPI.Events.InspectedURLChanged, url);
  }

  /**
   * @param {string} providerId
   * @param {string} sessionId
   * @param {!Extensions.TracingSession} session
   */
  startTraceRecording(providerId, sessionId, session) {
    this._traceSessions.set(sessionId, session);
    this._postNotification('trace-recording-started-' + providerId, sessionId);
  }

  /**
   * @param {string} providerId
   */
  stopTraceRecording(providerId) {
    this._postNotification('trace-recording-stopped-' + providerId);
  }

  /**
   * @param {string} type
   * @return {boolean}
   */
  hasSubscribers(type) {
    return !!this._subscribers[type];
  }

  /**
   * @param {string} type
   * @param {...*} vararg
   */
  _postNotification(type, vararg) {
    const subscribers = this._subscribers[type];
    if (!subscribers) {
      return;
    }
    const message = {command: 'notify-' + type, arguments: Array.prototype.slice.call(arguments, 1)};
    for (let i = 0; i < subscribers.length; ++i) {
      subscribers[i].postMessage(message);
    }
  }

  _onSubscribe(message, port) {
    const subscribers = this._subscribers[message.type];
    if (subscribers) {
      subscribers.push(port);
    } else {
      this._subscribers[message.type] = [port];
      if (this._subscriptionStartHandlers[message.type]) {
        this._subscriptionStartHandlers[message.type]();
      }
    }
  }

  _onUnsubscribe(message, port) {
    const subscribers = this._subscribers[message.type];
    if (!subscribers) {
      return;
    }
    subscribers.remove(port);
    if (!subscribers.length) {
      delete this._subscribers[message.type];
      if (this._subscriptionStopHandlers[message.type]) {
        this._subscriptionStopHandlers[message.type]();
      }
    }
  }

  _onAddRequestHeaders(message) {
    const id = message.extensionId;
    if (typeof id !== 'string') {
      return this._status.E_BADARGTYPE('extensionId', typeof id, 'string');
    }
    let extensionHeaders = this._extraHeaders[id];
    if (!extensionHeaders) {
      extensionHeaders = {};
      this._extraHeaders[id] = extensionHeaders;
    }
    for (const name in message.headers) {
      extensionHeaders[name] = message.headers[name];
    }
    const allHeaders = /** @type {!Protocol.Network.Headers} */ ({});
    for (const extension in this._extraHeaders) {
      const headers = this._extraHeaders[extension];
      for (const name in headers) {
        if (typeof headers[name] === 'string') {
          allHeaders[name] = headers[name];
        }
      }
    }

    SDK.multitargetNetworkManager.setExtraHTTPHeaders(allHeaders);
  }

  /**
   * @param {*} message
   * @suppressGlobalPropertiesCheck
   */
  _onApplyStyleSheet(message) {
    if (!Root.Runtime.experiments.isEnabled('applyCustomStylesheet')) {
      return;
    }
    const styleSheet = createElement('style');
    styleSheet.textContent = message.styleSheet;
    document.head.appendChild(styleSheet);

    UI.themeSupport.addCustomStylesheet(message.styleSheet);
    // Add to all the shadow roots that have already been created
    for (let node = document.body; node; node = node.traverseNextNode(document.body)) {
      if (node instanceof ShadowRoot) {
        UI.themeSupport.injectCustomStyleSheets(node);
      }
    }
  }

  _onCreatePanel(message, port) {
    const id = message.id;
    // The ids are generated on the client API side and must be unique, so the check below
    // shouldn't be hit unless someone is bypassing the API.
    if (id in this._clientObjects || UI.inspectorView.hasPanel(id)) {
      return this._status.E_EXISTS(id);
    }

    const page = this._expandResourcePath(port._extensionOrigin, message.page);
    let persistentId = port._extensionOrigin + message.title;
    persistentId = persistentId.replace(/\s/g, '');
    const panelView = new ExtensionServerPanelView(
        persistentId, message.title, new Extensions.ExtensionPanel(this, persistentId, id, page));
    this._clientObjects[id] = panelView;
    UI.inspectorView.addPanel(panelView);
    return this._status.OK();
  }

  _onShowPanel(message) {
    let panelViewId = message.id;
    const panelView = this._clientObjects[message.id];
    if (panelView && panelView instanceof ExtensionServerPanelView) {
      panelViewId = panelView.viewId();
    }
    UI.inspectorView.showPanel(panelViewId);
  }

  _onCreateToolbarButton(message, port) {
    const panelView = this._clientObjects[message.panel];
    if (!panelView || !(panelView instanceof ExtensionServerPanelView)) {
      return this._status.E_NOTFOUND(message.panel);
    }
    const button = new Extensions.ExtensionButton(
        this, message.id, this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip,
        message.disabled);
    this._clientObjects[message.id] = button;

    panelView.widget().then(appendButton);

    /**
     * @param {!UI.Widget} panel
     */
    function appendButton(panel) {
      /** @type {!Extensions.ExtensionPanel} panel*/ (panel).addToolbarItem(button.toolbarButton());
    }

    return this._status.OK();
  }

  _onUpdateButton(message, port) {
    const button = this._clientObjects[message.id];
    if (!button || !(button instanceof Extensions.ExtensionButton)) {
      return this._status.E_NOTFOUND(message.id);
    }
    button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled);
    return this._status.OK();
  }

  /**
   * @param {!Object} message
   */
  _onCompleteTraceSession(message) {
    const session = this._traceSessions.get(message.id);
    if (!session) {
      return this._status.E_NOTFOUND(message.id);
    }
    this._traceSessions.delete(message.id);
    session.complete(message.url, message.timeOffset);
  }

  _onCreateSidebarPane(message) {
    if (message.panel !== 'elements' && message.panel !== 'sources') {
      return this._status.E_NOTFOUND(message.panel);
    }
    const id = message.id;
    const sidebar = new Extensions.ExtensionSidebarPane(this, message.panel, message.title, id);
    this._sidebarPanes.push(sidebar);
    this._clientObjects[id] = sidebar;
    this.dispatchEventToListeners(Events.SidebarPaneAdded, sidebar);

    return this._status.OK();
  }

  /**
   * @return {!Array.<!Extensions.ExtensionSidebarPane>}
   */
  sidebarPanes() {
    return this._sidebarPanes;
  }

  _onSetSidebarHeight(message) {
    const sidebar = this._clientObjects[message.id];
    if (!sidebar) {
      return this._status.E_NOTFOUND(message.id);
    }
    sidebar.setHeight(message.height);
    return this._status.OK();
  }

  _onSetSidebarContent(message, port) {
    const sidebar = this._clientObjects[message.id];
    if (!sidebar) {
      return this._status.E_NOTFOUND(message.id);
    }

    /**
     * @this {ExtensionServer}
     */
    function callback(error) {
      const result = error ? this._status.E_FAILED(error) : this._status.OK();
      this._dispatchCallback(message.requestId, port, result);
    }
    if (message.evaluateOnPage) {
      return sidebar.setExpression(
          message.expression, message.rootTitle, message.evaluateOptions, port._extensionOrigin, callback.bind(this));
    }
    sidebar.setObject(message.expression, message.rootTitle, callback.bind(this));
  }

  _onSetSidebarPage(message, port) {
    const sidebar = this._clientObjects[message.id];
    if (!sidebar) {
      return this._status.E_NOTFOUND(message.id);
    }
    sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page));
  }

  _onOpenResource(message) {
    const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(message.url);
    if (uiSourceCode) {
      Common.Revealer.reveal(uiSourceCode.uiLocation(message.lineNumber, 0));
      return this._status.OK();
    }

    const resource = Bindings.resourceForURL(message.url);
    if (resource) {
      Common.Revealer.reveal(resource);
      return this._status.OK();
    }

    const request = SDK.networkLog.requestForURL(message.url);
    if (request) {
      Common.Revealer.reveal(request);
      return this._status.OK();
    }

    return this._status.E_NOTFOUND(message.url);
  }

  _onSetOpenResourceHandler(message, port) {
    const name = this._registeredExtensions[port._extensionOrigin].name || ('Extension ' + port._extensionOrigin);
    if (message.handlerPresent) {
      Components.Linkifier.registerLinkHandler(name, this._handleOpenURL.bind(this, port));
    } else {
      Components.Linkifier.unregisterLinkHandler(name);
    }
  }

  _handleOpenURL(port, contentProvider, lineNumber) {
    port.postMessage(
        {command: 'open-resource', resource: this._makeResource(contentProvider), lineNumber: lineNumber + 1});
  }

  _onReload(message) {
    const options = /** @type {!ExtensionReloadOptions} */ (message.options || {});

    SDK.multitargetNetworkManager.setUserAgentOverride(typeof options.userAgent === 'string' ? options.userAgent : '');
    let injectedScript;
    if (options.injectedScript) {
      injectedScript = '(function(){' + options.injectedScript + '})()';
    }
    SDK.ResourceTreeModel.reloadAllPages(!!options.ignoreCache, injectedScript);
    return this._status.OK();
  }

  _onEvaluateOnInspectedPage(message, port) {
    /**
     * @param {?Protocol.Error} error
     * @param {?SDK.RemoteObject} object
     * @param {boolean} wasThrown
     * @this {ExtensionServer}
     */
    function callback(error, object, wasThrown) {
      let result;
      if (error || !object) {
        result = this._status.E_PROTOCOLERROR(error.toString());
      } else if (wasThrown) {
        result = {isException: true, value: object.description};
      } else {
        result = {value: object.value};
      }

      this._dispatchCallback(message.requestId, port, result);
    }
    return this.evaluate(
        message.expression, true, true, message.evaluateOptions, port._extensionOrigin, callback.bind(this));
  }

  async _onGetHAR() {
    const requests = SDK.networkLog.requests();
    const harLog = await SDK.HARLog.build(requests);
    for (let i = 0; i < harLog.entries.length; ++i) {
      harLog.entries[i]._requestId = this._requestId(requests[i]);
    }
    return harLog;
  }

  /**
   * @param {!Common.ContentProvider} contentProvider
   */
  _makeResource(contentProvider) {
    return {url: contentProvider.contentURL(), type: contentProvider.contentType().name()};
  }

  /**
   * @return {!Array<!Common.ContentProvider>}
   */
  _onGetPageResources() {
    /** @type {!Map<string, !Common.ContentProvider>} */
    const resources = new Map();

    /**
     * @this {ExtensionServer}
     */
    function pushResourceData(contentProvider) {
      if (!resources.has(contentProvider.contentURL())) {
        resources.set(contentProvider.contentURL(), this._makeResource(contentProvider));
      }
    }
    let uiSourceCodes = Workspace.workspace.uiSourceCodesForProjectType(Workspace.projectTypes.Network);
    uiSourceCodes =
        uiSourceCodes.concat(Workspace.workspace.uiSourceCodesForProjectType(Workspace.projectTypes.ContentScripts));
    uiSourceCodes.forEach(pushResourceData.bind(this));
    for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
      resourceTreeModel.forAllResources(pushResourceData.bind(this));
    }
    return resources.valuesArray();
  }

  /**
   * @param {!Common.ContentProvider} contentProvider
   * @param {!Object} message
   * @param {!MessagePort} port
   */
  async _getResourceContent(contentProvider, message, port) {
    const {content} = await contentProvider.requestContent();
    const encoded = await contentProvider.contentEncoded();
    this._dispatchCallback(message.requestId, port, {encoding: encoded ? 'base64' : '', content: content});
  }

  _onGetRequestContent(message, port) {
    const request = this._requestById(message.id);
    if (!request) {
      return this._status.E_NOTFOUND(message.id);
    }
    this._getResourceContent(request, message, port);
  }

  _onGetResourceContent(message, port) {
    const url = /** @type {string} */ (message.url);
    const contentProvider = Workspace.workspace.uiSourceCodeForURL(url) || Bindings.resourceForURL(url);
    if (!contentProvider) {
      return this._status.E_NOTFOUND(url);
    }
    this._getResourceContent(contentProvider, message, port);
  }

  _onSetResourceContent(message, port) {
    /**
     * @param {?Protocol.Error} error
     * @this {ExtensionServer}
     */
    function callbackWrapper(error) {
      const response = error ? this._status.E_FAILED(error) : this._status.OK();
      this._dispatchCallback(message.requestId, port, response);
    }

    const url = /** @type {string} */ (message.url);
    const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
    if (!uiSourceCode || !uiSourceCode.contentType().isDocumentOrScriptOrStyleSheet()) {
      const resource = SDK.ResourceTreeModel.resourceForURL(url);
      if (!resource) {
        return this._status.E_NOTFOUND(url);
      }
      return this._status.E_NOTSUPPORTED('Resource is not editable');
    }
    uiSourceCode.setWorkingCopy(message.content);
    if (message.commit) {
      uiSourceCode.commitWorkingCopy();
    }
    callbackWrapper.call(this, null);
  }

  _requestId(request) {
    if (!request._extensionRequestId) {
      request._extensionRequestId = ++this._lastRequestId;
      this._requests[request._extensionRequestId] = request;
    }
    return request._extensionRequestId;
  }

  _requestById(id) {
    return this._requests[id];
  }

  /**
   * @param {!Object} message
   * @param {!MessagePort} port
   */
  _onAddTraceProvider(message, port) {
    const provider = new Extensions.ExtensionTraceProvider(
        port._extensionOrigin, message.id, message.categoryName, message.categoryTooltip);
    this._clientObjects[message.id] = provider;
    this._traceProviders.push(provider);
    this.dispatchEventToListeners(Events.TraceProviderAdded, provider);
  }

  /**
   * @return {!Array<!Extensions.ExtensionTraceProvider>}
   */
  traceProviders() {
    return this._traceProviders;
  }

  _onForwardKeyboardEvent(message) {
    message.entries.forEach(handleEventEntry);

    /**
     * @param {*} entry
     * @suppressGlobalPropertiesCheck
     */
    function handleEventEntry(entry) {
      // Fool around closure compiler -- it has its own notion of both KeyboardEvent constructor
      // and initKeyboardEvent methods and overriding these in externs.js does not have effect.
      const event = new window.KeyboardEvent(entry.eventType, {
        key: entry.key,
        code: entry.code,
        keyCode: entry.keyCode,
        location: entry.location,
        ctrlKey: entry.ctrlKey,
        altKey: entry.altKey,
        shiftKey: entry.shiftKey,
        metaKey: entry.metaKey
      });
      event.__keyCode = keyCodeForEntry(entry);
      document.dispatchEvent(event);
    }

    function keyCodeForEntry(entry) {
      let keyCode = entry.keyCode;
      if (!keyCode) {
        // This is required only for synthetic events (e.g. dispatched in tests).
        if (entry.key === 'Escape') {
          keyCode = 27;
        }
      }
      return keyCode || 0;
    }
  }

  _dispatchCallback(requestId, port, result) {
    if (requestId) {
      port.postMessage({command: 'callback', requestId: requestId, result: result});
    }
  }

  _initExtensions() {
    this._registerAutosubscriptionHandler(
        Extensions.extensionAPI.Events.ResourceAdded, Workspace.workspace, Workspace.Workspace.Events.UISourceCodeAdded,
        this._notifyResourceAdded);
    this._registerAutosubscriptionTargetManagerHandler(
        Extensions.extensionAPI.Events.NetworkRequestFinished, SDK.NetworkManager,
        SDK.NetworkManager.Events.RequestFinished, this._notifyRequestFinished);

    /**
     * @this {ExtensionServer}
     */
    function onElementsSubscriptionStarted() {
      UI.context.addFlavorChangeListener(SDK.DOMNode, this._notifyElementsSelectionChanged, this);
    }

    /**
     * @this {ExtensionServer}
     */
    function onElementsSubscriptionStopped() {
      UI.context.removeFlavorChangeListener(SDK.DOMNode, this._notifyElementsSelectionChanged, this);
    }

    this._registerSubscriptionHandler(
        Extensions.extensionAPI.Events.PanelObjectSelected + 'elements', onElementsSubscriptionStarted.bind(this),
        onElementsSubscriptionStopped.bind(this));
    this._registerResourceContentCommittedHandler(this._notifyUISourceCodeContentCommitted);

    SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this);
  }

  _notifyResourceAdded(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
    this._postNotification(Extensions.extensionAPI.Events.ResourceAdded, this._makeResource(uiSourceCode));
  }

  _notifyUISourceCodeContentCommitted(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
    const content = /** @type {string} */ (event.data.content);
    this._postNotification(
        Extensions.extensionAPI.Events.ResourceContentCommitted, this._makeResource(uiSourceCode), content);
  }

  async _notifyRequestFinished(event) {
    const request = /** @type {!SDK.NetworkRequest} */ (event.data);
    const entry = await SDK.HARLog.Entry.build(request);
    this._postNotification(Extensions.extensionAPI.Events.NetworkRequestFinished, this._requestId(request), entry);
  }

  _notifyElementsSelectionChanged() {
    this._postNotification(Extensions.extensionAPI.Events.PanelObjectSelected + 'elements');
  }

  /**
   * @param {string} url
   * @param {!TextUtils.TextRange} range
   */
  sourceSelectionChanged(url, range) {
    this._postNotification(Extensions.extensionAPI.Events.PanelObjectSelected + 'sources', {
      startLine: range.startLine,
      startColumn: range.startColumn,
      endLine: range.endLine,
      endColumn: range.endColumn,
      url: url,
    });
  }

  /**
   * @param {!Common.Event} event
   */
  _setInspectedTabId(event) {
    this._inspectedTabId = /** @type {string} */ (event.data);
  }

  /**
   * @param {!ExtensionDescriptor} extensionInfo
   * @suppressGlobalPropertiesCheck
   */
  _addExtension(extensionInfo) {
    const urlOriginRegExp = new RegExp('([^:]+:\/\/[^/]*)\/');  // Can't use regexp literal here, MinJS chokes on it.
    const startPage = extensionInfo.startPage;
    const name = extensionInfo.name;

    try {
      const originMatch = urlOriginRegExp.exec(startPage);
      if (!originMatch) {
        console.error('Skipping extension with invalid URL: ' + startPage);
        return false;
      }
      const extensionOrigin = originMatch[1];
      if (!this._registeredExtensions[extensionOrigin]) {
        // See ExtensionAPI.js for details.
        const injectedAPI = self.buildExtensionAPIInjectedScript(
            extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(), UI.shortcutRegistry.globalShortcutKeys(),
            Extensions.extensionServer['_extensionAPITestHook']);
        Host.InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI);
        this._registeredExtensions[extensionOrigin] = {name: name};
      }
      const iframe = createElement('iframe');
      iframe.src = startPage;
      iframe.style.display = 'none';
      document.body.appendChild(iframe);  // Only for main window.
    } catch (e) {
      console.error('Failed to initialize extension ' + startPage + ':' + e);
      return false;
    }
    return true;
  }

  _registerExtension(origin, port) {
    if (!this._registeredExtensions.hasOwnProperty(origin)) {
      if (origin !== window.location.origin)  // Just ignore inspector frames.
      {
        console.error('Ignoring unauthorized client request from ' + origin);
      }
      return;
    }
    port._extensionOrigin = origin;
    port.addEventListener('message', this._onmessage.bind(this), false);
    port.start();
  }

  _onWindowMessage(event) {
    if (event.data === 'registerExtension') {
      this._registerExtension(event.origin, event.ports[0]);
    }
  }

  async _onmessage(event) {
    const message = event.data;
    let result;

    if (message.command in this._handlers) {
      result = await this._handlers[message.command](message, event.target);
    } else {
      result = this._status.E_NOTSUPPORTED(message.command);
    }

    if (result && message.requestId) {
      this._dispatchCallback(message.requestId, event.target, result);
    }
  }

  _registerHandler(command, callback) {
    console.assert(command);
    this._handlers[command] = callback;
  }

  _registerSubscriptionHandler(eventTopic, onSubscribeFirst, onUnsubscribeLast) {
    this._subscriptionStartHandlers[eventTopic] = onSubscribeFirst;
    this._subscriptionStopHandlers[eventTopic] = onUnsubscribeLast;
  }

  /**
   * @param {string} eventTopic
   * @param {!Object} eventTarget
   * @param {symbol} frontendEventType
   * @param {function(!Common.Event)} handler
   */
  _registerAutosubscriptionHandler(eventTopic, eventTarget, frontendEventType, handler) {
    this._registerSubscriptionHandler(
        eventTopic, eventTarget.addEventListener.bind(eventTarget, frontendEventType, handler, this),
        eventTarget.removeEventListener.bind(eventTarget, frontendEventType, handler, this));
  }

  /**
   * @param {string} eventTopic
   * @param {!Function} modelClass
   * @param {symbol} frontendEventType
   * @param {function(!Common.Event)} handler
   */
  _registerAutosubscriptionTargetManagerHandler(eventTopic, modelClass, frontendEventType, handler) {
    this._registerSubscriptionHandler(
        eventTopic,
        SDK.targetManager.addModelListener.bind(SDK.targetManager, modelClass, frontendEventType, handler, this),
        SDK.targetManager.removeModelListener.bind(SDK.targetManager, modelClass, frontendEventType, handler, this));
  }

  _registerResourceContentCommittedHandler(handler) {
    /**
     * @this {ExtensionServer}
     */
    function addFirstEventListener() {
      Workspace.workspace.addEventListener(Workspace.Workspace.Events.WorkingCopyCommittedByUser, handler, this);
      Workspace.workspace.setHasResourceContentTrackingExtensions(true);
    }

    /**
     * @this {ExtensionServer}
     */
    function removeLastEventListener() {
      Workspace.workspace.setHasResourceContentTrackingExtensions(false);
      Workspace.workspace.removeEventListener(Workspace.Workspace.Events.WorkingCopyCommittedByUser, handler, this);
    }

    this._registerSubscriptionHandler(
        Extensions.extensionAPI.Events.ResourceContentCommitted, addFirstEventListener.bind(this),
        removeLastEventListener.bind(this));
  }

  _expandResourcePath(extensionPath, resourcePath) {
    if (!resourcePath) {
      return;
    }
    return extensionPath + this._normalizePath(resourcePath);
  }

  _normalizePath(path) {
    const source = path.split('/');
    const result = [];

    for (let i = 0; i < source.length; ++i) {
      if (source[i] === '.') {
        continue;
      }
      // Ignore empty path components resulting from //, as well as a leading and traling slashes.
      if (source[i] === '') {
        continue;
      }
      if (source[i] === '..') {
        result.pop();
      } else {
        result.push(source[i]);
      }
    }
    return '/' + result.join('/');
  }

  /**
   * @param {string} expression
   * @param {boolean} exposeCommandLineAPI
   * @param {boolean} returnByValue
   * @param {?Object} options
   * @param {string} securityOrigin
   * @param {function(?string, ?SDK.RemoteObject, boolean)} callback
   * @return {!Extensions.ExtensionStatus.Record|undefined}
   */
  evaluate(expression, exposeCommandLineAPI, returnByValue, options, securityOrigin, callback) {
    let context;

    /**
     * @param {string} url
     * @return {boolean}
     */
    function resolveURLToFrame(url) {
      let found;
      function hasMatchingURL(frame) {
        found = (frame.url === url) ? frame : null;
        return found;
      }
      SDK.ResourceTreeModel.frames().some(hasMatchingURL);
      return found;
    }

    options = options || {};
    let frame;
    if (options.frameURL) {
      frame = resolveURLToFrame(options.frameURL);
    } else {
      const target = SDK.targetManager.mainTarget();
      const resourceTreeModel = target && target.model(SDK.ResourceTreeModel);
      frame = resourceTreeModel && resourceTreeModel.mainFrame;
    }
    if (!frame) {
      if (options.frameURL) {
        console.warn('evaluate: there is no frame with URL ' + options.frameURL);
      } else {
        console.warn('evaluate: the main frame is not yet available');
      }
      return this._status.E_NOTFOUND(options.frameURL || '<top>');
    }

    let contextSecurityOrigin;
    if (options.useContentScriptContext) {
      contextSecurityOrigin = securityOrigin;
    } else if (options.scriptExecutionContext) {
      contextSecurityOrigin = options.scriptExecutionContext;
    }

    const runtimeModel = frame.resourceTreeModel().target().model(SDK.RuntimeModel);
    const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
    if (contextSecurityOrigin) {
      for (let i = 0; i < executionContexts.length; ++i) {
        const executionContext = executionContexts[i];
        if (executionContext.frameId === frame.id && executionContext.origin === contextSecurityOrigin &&
            !executionContext.isDefault) {
          context = executionContext;
        }
      }
      if (!context) {
        console.warn('The JavaScript context ' + contextSecurityOrigin + ' was not found in the frame ' + frame.url);
        return this._status.E_NOTFOUND(contextSecurityOrigin);
      }
    } else {
      for (let i = 0; i < executionContexts.length; ++i) {
        const executionContext = executionContexts[i];
        if (executionContext.frameId === frame.id && executionContext.isDefault) {
          context = executionContext;
        }
      }
      if (!context) {
        return this._status.E_FAILED(frame.url + ' has no execution context');
      }
    }

    context
        .evaluate(
            {
              expression: expression,
              objectGroup: 'extension',
              includeCommandLineAPI: exposeCommandLineAPI,
              silent: true,
              returnByValue: returnByValue,
              generatePreview: false
            },
            /* userGesture */ false, /* awaitPromise */ false)
        .then(onEvaluate);

    /**
     * @param {!SDK.RuntimeModel.EvaluationResult} result
     */
    function onEvaluate(result) {
      if (result.error) {
        callback(result.error, null, false);
        return;
      }
      callback(null, result.object || null, !!result.exceptionDetails);
    }
  }
}

/** @enum {symbol} */
export const Events = {
  SidebarPaneAdded: Symbol('SidebarPaneAdded'),
  TraceProviderAdded: Symbol('TraceProviderAdded')
};

/**
 * @unrestricted
 */
class ExtensionServerPanelView extends UI.SimpleView {
  /**
   * @param {string} name
   * @param {string} title
   * @param {!UI.Panel} panel
   */
  constructor(name, title, panel) {
    super(title);
    this._name = name;
    this._panel = panel;
  }

  /**
   * @override
   * @return {string}
   */
  viewId() {
    return this._name;
  }

  /**
   * @override
   * @return {!Promise.<!UI.Widget>}
   */
  widget() {
    return /** @type {!Promise.<!UI.Widget>} */ (Promise.resolve(this._panel));
  }
}

/**
 * @unrestricted
 */
export class ExtensionStatus {
  constructor() {
    /**
     * @param {string} code
     * @param {string} description
     * @return {!Extensions.ExtensionStatus.Record}
     */
    function makeStatus(code, description) {
      const details = Array.prototype.slice.call(arguments, 2);
      const status = {code: code, description: description, details: details};
      if (code !== 'OK') {
        status.isError = true;
        console.error('Extension server error: ' + String.vsprintf(description, details));
      }
      return status;
    }

    this.OK = makeStatus.bind(null, 'OK', 'OK');
    this.E_EXISTS = makeStatus.bind(null, 'E_EXISTS', 'Object already exists: %s');
    this.E_BADARG = makeStatus.bind(null, 'E_BADARG', 'Invalid argument %s: %s');
    this.E_BADARGTYPE = makeStatus.bind(null, 'E_BADARGTYPE', 'Invalid type for argument %s: got %s, expected %s');
    this.E_NOTFOUND = makeStatus.bind(null, 'E_NOTFOUND', 'Object not found: %s');
    this.E_NOTSUPPORTED = makeStatus.bind(null, 'E_NOTSUPPORTED', 'Object does not support requested operation: %s');
    this.E_PROTOCOLERROR = makeStatus.bind(null, 'E_PROTOCOLERROR', 'Inspector protocol error: %s');
    this.E_FAILED = makeStatus.bind(null, 'E_FAILED', 'Operation failed: %s');
  }
}

/* Legacy exported object */
self.Extensions = self.Extensions || {};

/* Legacy exported object */
Extensions = Extensions || {};

/** @constructor */
Extensions.ExtensionServer = ExtensionServer;

/** @enum {symbol} */
Extensions.ExtensionServer.Events = Events;

/** @constructor */
Extensions.ExtensionStatus = ExtensionStatus;

/**
 * @typedef {{code: string, description: string, details: !Array.<*>}}
 */
Extensions.ExtensionStatus.Record;

/** @type {!ExtensionServer} */
Extensions.extensionServer;
