/*
 * Copyright (C) 2012 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.
 */

/* eslint-disable indent */

function defineCommonExtensionSymbols(apiPrivate) {
  if (!apiPrivate.panels)
    apiPrivate.panels = {};
  apiPrivate.panels.SearchAction = {
    CancelSearch: 'cancelSearch',
    PerformSearch: 'performSearch',
    NextSearchResult: 'nextSearchResult',
    PreviousSearchResult: 'previousSearchResult'
  };

  /** @enum {string} */
  apiPrivate.Events = {
    ButtonClicked: 'button-clicked-',
    PanelObjectSelected: 'panel-objectSelected-',
    NetworkRequestFinished: 'network-request-finished',
    OpenResource: 'open-resource',
    PanelSearch: 'panel-search-',
    RecordingStarted: 'trace-recording-started-',
    RecordingStopped: 'trace-recording-stopped-',
    ResourceAdded: 'resource-added',
    ResourceContentCommitted: 'resource-content-committed',
    ViewShown: 'view-shown-',
    ViewHidden: 'view-hidden-'
  };

  /** @enum {string} */
  apiPrivate.Commands = {
    AddRequestHeaders: 'addRequestHeaders',
    AddTraceProvider: 'addTraceProvider',
    ApplyStyleSheet: 'applyStyleSheet',
    CompleteTraceSession: 'completeTraceSession',
    CreatePanel: 'createPanel',
    CreateSidebarPane: 'createSidebarPane',
    CreateToolbarButton: 'createToolbarButton',
    EvaluateOnInspectedPage: 'evaluateOnInspectedPage',
    ForwardKeyboardEvent: '_forwardKeyboardEvent',
    GetHAR: 'getHAR',
    GetPageResources: 'getPageResources',
    GetRequestContent: 'getRequestContent',
    GetResourceContent: 'getResourceContent',
    InspectedURLChanged: 'inspectedURLChanged',
    OpenResource: 'openResource',
    Reload: 'Reload',
    Subscribe: 'subscribe',
    SetOpenResourceHandler: 'setOpenResourceHandler',
    SetResourceContent: 'setResourceContent',
    SetSidebarContent: 'setSidebarContent',
    SetSidebarHeight: 'setSidebarHeight',
    SetSidebarPage: 'setSidebarPage',
    ShowPanel: 'showPanel',
    Unsubscribe: 'unsubscribe',
    UpdateButton: 'updateButton'
  };
}

/**
 * @param {!ExtensionDescriptor} extensionInfo
 * @param {string} inspectedTabId
 * @param {string} themeName
 * @param {number} injectedScriptId
 * @param {function(!Object, !Object)} testHook
 * @suppressGlobalPropertiesCheck
 */
function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook, injectedScriptId) {
  const chrome = window.chrome || {};
  const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
  if (devtools_descriptor)
    return;

  const apiPrivate = {};

  defineCommonExtensionSymbols(apiPrivate);

  const commands = apiPrivate.Commands;
  const events = apiPrivate.Events;
  let userAction = false;

  // Here and below, all constructors are private to API implementation.
  // For a public type Foo, if internal fields are present, these are on
  // a private FooImpl type, an instance of FooImpl is used in a closure
  // by Foo consutrctor to re-bind publicly exported members to an instance
  // of Foo.

  /**
   * @constructor
   */
  function EventSinkImpl(type, customDispatch) {
    this._type = type;
    this._listeners = [];
    this._customDispatch = customDispatch;
  }

  EventSinkImpl.prototype = {
    addListener: function(callback) {
      if (typeof callback !== 'function')
        throw 'addListener: callback is not a function';
      if (this._listeners.length === 0)
        extensionServer.sendRequest({command: commands.Subscribe, type: this._type});
      this._listeners.push(callback);
      extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
    },

    removeListener: function(callback) {
      const listeners = this._listeners;

      for (let i = 0; i < listeners.length; ++i) {
        if (listeners[i] === callback) {
          listeners.splice(i, 1);
          break;
        }
      }
      if (this._listeners.length === 0)
        extensionServer.sendRequest({command: commands.Unsubscribe, type: this._type});
    },

    /**
     * @param {...} vararg
     */
    _fire: function(vararg) {
      const listeners = this._listeners.slice();
      for (let i = 0; i < listeners.length; ++i)
        listeners[i].apply(null, arguments);
    },

    _dispatch: function(request) {
      if (this._customDispatch)
        this._customDispatch.call(this, request);
      else
        this._fire.apply(this, request.arguments);
    }
  };

  /**
   * @constructor
   */
  function InspectorExtensionAPI() {
    this.inspectedWindow = new InspectedWindow();
    this.panels = new Panels();
    this.network = new Network();
    this.timeline = new Timeline();
    defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
  }

  /**
   * @constructor
   */
  function Network() {
    /**
     * @this {EventSinkImpl}
     */
    function dispatchRequestEvent(message) {
      const request = message.arguments[1];
      request.__proto__ = new Request(message.arguments[0]);
      this._fire(request);
    }
    this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent);
    defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
    this.onNavigated = new EventSink(events.InspectedURLChanged);
  }

  Network.prototype = {
    getHAR: function(callback) {
      function callbackWrapper(result) {
        const entries = (result && result.entries) || [];
        for (let i = 0; i < entries.length; ++i) {
          entries[i].__proto__ = new Request(entries[i]._requestId);
          delete entries[i]._requestId;
        }
        callback(result);
      }
      extensionServer.sendRequest({command: commands.GetHAR}, callback && callbackWrapper);
    },

    addRequestHeaders: function(headers) {
      extensionServer.sendRequest(
          {command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
    }
  };

  /**
   * @constructor
   */
  function RequestImpl(id) {
    this._id = id;
  }

  RequestImpl.prototype = {
    getContent: function(callback) {
      function callbackWrapper(response) {
        callback(response.content, response.encoding);
      }
      extensionServer.sendRequest({command: commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
    }
  };

  /**
   * @constructor
   */
  function Panels() {
    const panels = {
      elements: new ElementsPanel(),
      sources: new SourcesPanel(),
    };

    function panelGetter(name) {
      return panels[name];
    }
    for (const panel in panels)
      this.__defineGetter__(panel, panelGetter.bind(null, panel));
    this.applyStyleSheet = function(styleSheet) {
      extensionServer.sendRequest({command: commands.ApplyStyleSheet, styleSheet: styleSheet});
    };
  }

  Panels.prototype = {
    create: function(title, icon, page, callback) {
      const id = 'extension-panel-' + extensionServer.nextObjectId();
      const request = {command: commands.CreatePanel, id: id, title: title, icon: icon, page: page};
      extensionServer.sendRequest(request, callback && callback.bind(this, new ExtensionPanel(id)));
    },

    setOpenResourceHandler: function(callback) {
      const hadHandler = extensionServer.hasHandler(events.OpenResource);

      function callbackWrapper(message) {
        // Allow the panel to show itself when handling the event.
        userAction = true;
        try {
          callback.call(null, new Resource(message.resource), message.lineNumber);
        } finally {
          userAction = false;
        }
      }

      if (!callback)
        extensionServer.unregisterHandler(events.OpenResource);
      else
        extensionServer.registerHandler(events.OpenResource, callbackWrapper);

      // Only send command if we either removed an existing handler or added handler and had none before.
      if (hadHandler === !callback)
        extensionServer.sendRequest({command: commands.SetOpenResourceHandler, 'handlerPresent': !!callback});
    },

    openResource: function(url, lineNumber, callback) {
      extensionServer.sendRequest({command: commands.OpenResource, 'url': url, 'lineNumber': lineNumber}, callback);
    },

    get SearchAction() {
      return apiPrivate.panels.SearchAction;
    }
  };

  /**
   * @constructor
   */
  function ExtensionViewImpl(id) {
    this._id = id;

    /**
     * @this {EventSinkImpl}
     */
    function dispatchShowEvent(message) {
      const frameIndex = message.arguments[0];
      if (typeof frameIndex === 'number')
        this._fire(window.parent.frames[frameIndex]);
      else
        this._fire();
    }

    if (id) {
      this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent);
      this.onHidden = new EventSink(events.ViewHidden + id);
    }
  }

  /**
   * @constructor
   * @extends {ExtensionViewImpl}
   * @param {string} hostPanelName
   */
  function PanelWithSidebarImpl(hostPanelName) {
    ExtensionViewImpl.call(this, null);
    this._hostPanelName = hostPanelName;
    this.onSelectionChanged = new EventSink(events.PanelObjectSelected + hostPanelName);
  }

  PanelWithSidebarImpl.prototype = {
    createSidebarPane: function(title, callback) {
      const id = 'extension-sidebar-' + extensionServer.nextObjectId();
      const request = {command: commands.CreateSidebarPane, panel: this._hostPanelName, id: id, title: title};
      function callbackWrapper() {
        callback(new ExtensionSidebarPane(id));
      }
      extensionServer.sendRequest(request, callback && callbackWrapper);
    },

    __proto__: ExtensionViewImpl.prototype
  };

  function declareInterfaceClass(implConstructor) {
    return function() {
      const impl = {__proto__: implConstructor.prototype};
      implConstructor.apply(impl, arguments);
      populateInterfaceClass(this, impl);
    };
  }

  function defineDeprecatedProperty(object, className, oldName, newName) {
    let warningGiven = false;
    function getter() {
      if (!warningGiven) {
        console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
        warningGiven = true;
      }
      return object[newName];
    }
    object.__defineGetter__(oldName, getter);
  }

  function extractCallbackArgument(args) {
    const lastArgument = args[args.length - 1];
    return typeof lastArgument === 'function' ? lastArgument : undefined;
  }

  const Button = declareInterfaceClass(ButtonImpl);
  const EventSink = declareInterfaceClass(EventSinkImpl);
  const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
  const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
  const PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
  const Request = declareInterfaceClass(RequestImpl);
  const Resource = declareInterfaceClass(ResourceImpl);
  const TraceSession = declareInterfaceClass(TraceSessionImpl);

  /**
   * @constructor
   * @extends {PanelWithSidebar}
   */
  function ElementsPanel() {
    PanelWithSidebar.call(this, 'elements');
  }

  ElementsPanel.prototype = {__proto__: PanelWithSidebar.prototype};

  /**
   * @constructor
   * @extends {PanelWithSidebar}
   */
  function SourcesPanel() {
    PanelWithSidebar.call(this, 'sources');
  }

  SourcesPanel.prototype = {__proto__: PanelWithSidebar.prototype};

  /**
   * @constructor
   * @extends {ExtensionViewImpl}
   */
  function ExtensionPanelImpl(id) {
    ExtensionViewImpl.call(this, id);
    this.onSearch = new EventSink(events.PanelSearch + id);
  }

  ExtensionPanelImpl.prototype = {
    /**
     * @return {!Object}
     */
    createStatusBarButton: function(iconPath, tooltipText, disabled) {
      const id = 'button-' + extensionServer.nextObjectId();
      const request = {
        command: commands.CreateToolbarButton,
        panel: this._id,
        id: id,
        icon: iconPath,
        tooltip: tooltipText,
        disabled: !!disabled
      };
      extensionServer.sendRequest(request);
      return new Button(id);
    },

    show: function() {
      if (!userAction)
        return;

      const request = {command: commands.ShowPanel, id: this._id};
      extensionServer.sendRequest(request);
    },

    __proto__: ExtensionViewImpl.prototype
  };

  /**
   * @constructor
   * @extends {ExtensionViewImpl}
   */
  function ExtensionSidebarPaneImpl(id) {
    ExtensionViewImpl.call(this, id);
  }

  ExtensionSidebarPaneImpl.prototype = {
    setHeight: function(height) {
      extensionServer.sendRequest({command: commands.SetSidebarHeight, id: this._id, height: height});
    },

    setExpression: function(expression, rootTitle, evaluateOptions) {
      const request = {
        command: commands.SetSidebarContent,
        id: this._id,
        expression: expression,
        rootTitle: rootTitle,
        evaluateOnPage: true,
      };
      if (typeof evaluateOptions === 'object')
        request.evaluateOptions = evaluateOptions;
      extensionServer.sendRequest(request, extractCallbackArgument(arguments));
    },

    setObject: function(jsonObject, rootTitle, callback) {
      extensionServer.sendRequest(
          {command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle}, callback);
    },

    setPage: function(page) {
      extensionServer.sendRequest({command: commands.SetSidebarPage, id: this._id, page: page});
    },

    __proto__: ExtensionViewImpl.prototype
  };

  /**
   * @constructor
   */
  function ButtonImpl(id) {
    this._id = id;
    this.onClicked = new EventSink(events.ButtonClicked + id);
  }

  ButtonImpl.prototype = {
    update: function(iconPath, tooltipText, disabled) {
      const request =
          {command: commands.UpdateButton, id: this._id, icon: iconPath, tooltip: tooltipText, disabled: !!disabled};
      extensionServer.sendRequest(request);
    }
  };

  /**
   * @constructor
   */
  function Timeline() {
  }

  Timeline.prototype = {
    /**
     * @param {string} categoryName
     * @param {string} categoryTooltip
     * @return {!TraceProvider}
     */
    addTraceProvider: function(categoryName, categoryTooltip) {
      const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
      extensionServer.sendRequest(
          {command: commands.AddTraceProvider, id: id, categoryName: categoryName, categoryTooltip: categoryTooltip});
      return new TraceProvider(id);
    }
  };

  /**
   * @constructor
   * @param {string} id
   */
  function TraceSessionImpl(id) {
    this._id = id;
  }

  TraceSessionImpl.prototype = {
    /**
     * @param {string=} url
     * @param {number=} timeOffset
     */
    complete: function(url, timeOffset) {
      const request =
          {command: commands.CompleteTraceSession, id: this._id, url: url || '', timeOffset: timeOffset || 0};
      extensionServer.sendRequest(request);
    }
  };

  /**
   * @constructor
   * @param {string} id
   */
  function TraceProvider(id) {
    /**
     * @this {EventSinkImpl}
     */
    function dispatchRecordingStarted(message) {
      const sessionId = message.arguments[0];
      this._fire(new TraceSession(sessionId));
    }

    this.onRecordingStarted = new EventSink(events.RecordingStarted + id, dispatchRecordingStarted);
    this.onRecordingStopped = new EventSink(events.RecordingStopped + id);
  }

  /**
   * @constructor
   */
  function InspectedWindow() {
    /**
     * @this {EventSinkImpl}
     */
    function dispatchResourceEvent(message) {
      this._fire(new Resource(message.arguments[0]));
    }

    /**
     * @this {EventSinkImpl}
     */
    function dispatchResourceContentEvent(message) {
      this._fire(new Resource(message.arguments[0]), message.arguments[1]);
    }

    this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent);
    this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent);
  }

  InspectedWindow.prototype = {
    reload: function(optionsOrUserAgent) {
      let options = null;
      if (typeof optionsOrUserAgent === 'object') {
        options = optionsOrUserAgent;
      } else if (typeof optionsOrUserAgent === 'string') {
        options = {userAgent: optionsOrUserAgent};
        console.warn(
            'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
            'Use inspectedWindow.reload({ userAgent: value}) instead.');
      }
      extensionServer.sendRequest({command: commands.Reload, options: options});
    },

    /**
     * @return {?Object}
     */
    eval: function(expression, evaluateOptions) {
      const callback = extractCallbackArgument(arguments);
      function callbackWrapper(result) {
        if (result.isError || result.isException)
          callback(undefined, result);
        else
          callback(result.value);
      }
      const request = {command: commands.EvaluateOnInspectedPage, expression: expression};
      if (typeof evaluateOptions === 'object')
        request.evaluateOptions = evaluateOptions;
      extensionServer.sendRequest(request, callback && callbackWrapper);
      return null;
    },

    getResources: function(callback) {
      function wrapResource(resourceData) {
        return new Resource(resourceData);
      }
      function callbackWrapper(resources) {
        callback(resources.map(wrapResource));
      }
      extensionServer.sendRequest({command: commands.GetPageResources}, callback && callbackWrapper);
    }
  };

  /**
   * @constructor
   */
  function ResourceImpl(resourceData) {
    this._url = resourceData.url;
    this._type = resourceData.type;
  }

  ResourceImpl.prototype = {
    get url() {
      return this._url;
    },

    get type() {
      return this._type;
    },

    getContent: function(callback) {
      function callbackWrapper(response) {
        callback(response.content, response.encoding);
      }

      extensionServer.sendRequest({command: commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
    },

    setContent: function(content, commit, callback) {
      extensionServer.sendRequest(
          {command: commands.SetResourceContent, url: this._url, content: content, commit: commit}, callback);
    }
  };

  function getTabId() {
    return inspectedTabId;
  }

  let keyboardEventRequestQueue = [];
  let forwardTimer = null;

  function forwardKeyboardEvent(event) {
    // We only care about global hotkeys, not about random text
    if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(event.key) && event.key !== 'Escape')
      return;
    const requestPayload = {
      eventType: event.type,
      ctrlKey: event.ctrlKey,
      altKey: event.altKey,
      metaKey: event.metaKey,
      keyIdentifier: event.keyIdentifier,
      key: event.key,
      code: event.code,
      location: event.location,
      keyCode: event.keyCode
    };
    keyboardEventRequestQueue.push(requestPayload);
    if (!forwardTimer)
      forwardTimer = setTimeout(forwardEventQueue, 0);
  }

  function forwardEventQueue() {
    forwardTimer = null;
    const request = {command: commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue};
    extensionServer.sendRequest(request);
    keyboardEventRequestQueue = [];
  }

  document.addEventListener('keydown', forwardKeyboardEvent, false);
  document.addEventListener('keypress', forwardKeyboardEvent, false);

  /**
   * @constructor
   */
  function ExtensionServerClient() {
    this._callbacks = {};
    this._handlers = {};
    this._lastRequestId = 0;
    this._lastObjectId = 0;

    this.registerHandler('callback', this._onCallback.bind(this));

    const channel = new MessageChannel();
    this._port = channel.port1;
    this._port.addEventListener('message', this._onMessage.bind(this), false);
    this._port.start();

    window.parent.postMessage('registerExtension', '*', [channel.port2]);
  }

  ExtensionServerClient.prototype = {
    /**
     * @param {!Object} message
     * @param {function()=} callback
     */
    sendRequest: function(message, callback) {
      if (typeof callback === 'function')
        message.requestId = this._registerCallback(callback);
      this._port.postMessage(message);
    },

    /**
     * @return {boolean}
     */
    hasHandler: function(command) {
      return !!this._handlers[command];
    },

    registerHandler: function(command, handler) {
      this._handlers[command] = handler;
    },

    unregisterHandler: function(command) {
      delete this._handlers[command];
    },

    /**
     * @return {string}
     */
    nextObjectId: function() {
      return injectedScriptId.toString() + '_' + ++this._lastObjectId;
    },

    _registerCallback: function(callback) {
      const id = ++this._lastRequestId;
      this._callbacks[id] = callback;
      return id;
    },

    _onCallback: function(request) {
      if (request.requestId in this._callbacks) {
        const callback = this._callbacks[request.requestId];
        delete this._callbacks[request.requestId];
        callback(request.result);
      }
    },

    _onMessage: function(event) {
      const request = event.data;
      const handler = this._handlers[request.command];
      if (handler)
        handler.call(this, request);
    }
  };

  function populateInterfaceClass(interfaze, implementation) {
    for (const member in implementation) {
      if (member.charAt(0) === '_')
        continue;
      let descriptor = null;
      // Traverse prototype chain until we find the owner.
      for (let owner = implementation; owner && !descriptor; owner = owner.__proto__)
        descriptor = Object.getOwnPropertyDescriptor(owner, member);
      if (!descriptor)
        continue;
      if (typeof descriptor.value === 'function')
        interfaze[member] = descriptor.value.bind(implementation);
      else if (typeof descriptor.get === 'function')
        interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
      else
        Object.defineProperty(interfaze, member, descriptor);
    }
  }

  const extensionServer = new ExtensionServerClient();
  const coreAPI = new InspectorExtensionAPI();

  Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});

  // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
  chrome.devtools.inspectedWindow = {};
  chrome.devtools.inspectedWindow.__defineGetter__('tabId', getTabId);
  chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
  chrome.devtools.network = coreAPI.network;
  chrome.devtools.panels = coreAPI.panels;
  chrome.devtools.panels.themeName = themeName;

  // default to expose experimental APIs for now.
  if (extensionInfo.exposeExperimentalAPIs !== false) {
    chrome.experimental = chrome.experimental || {};
    chrome.experimental.devtools = chrome.experimental.devtools || {};

    const properties = Object.getOwnPropertyNames(coreAPI);
    for (let i = 0; i < properties.length; ++i) {
      const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
      if (descriptor)
        Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
    }
    chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
  }

  if (extensionInfo.exposeWebInspectorNamespace)
    window.webInspector = coreAPI;
  testHook(extensionServer, coreAPI);
}

/**
 * @param {!ExtensionDescriptor} extensionInfo
 * @param {string} inspectedTabId
 * @param {string} themeName
 * @param {function(!Object, !Object)|undefined} testHook
 * @return {string}
 */
function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeName, testHook) {
  const argumentsJSON = [extensionInfo, inspectedTabId || null, themeName].map(_ => JSON.stringify(_)).join(',');
  if (!testHook)
    testHook = () => {};
  return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString() + ';' +
      '(' + injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
      '})';
}
