/*
 * 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.
 */

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 {!Array<number>} keysToForward
 * @param {number} injectedScriptId
 * @param {function(!Object, !Object)} testHook
 * @suppressGlobalPropertiesCheck
 */
self.injectedExtensionAPI = function(
    extensionInfo, inspectedTabId, themeName, keysToForward, testHook, injectedScriptId) {
  const keysToForwardSet = new Set(keysToForward);
  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) {
      Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
    }
    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);
  /**
   * @constructor
   * @param {string} hostPanelName
   */
  const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
  const Request = declareInterfaceClass(RequestImpl);
  const Resource = declareInterfaceClass(ResourceImpl);
  const TraceSession = declareInterfaceClass(TraceSessionImpl);

  class ElementsPanel extends PanelWithSidebarClass {
    constructor() {
      super('elements');
    }
  }

  class SourcesPanel extends PanelWithSidebarClass {
    constructor() {
      super('sources');
    }
  }

  /**
   * @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;

  /**
   * @suppressGlobalPropertiesCheck
   */
  function forwardKeyboardEvent(event) {
    // Check if the event should be forwarded.
    // This is a workaround for crbug.com/923338.
    const focused = document.activeElement;
    if (focused) {
      const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
      if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
        return;
      }
    }

    let modifiers = 0;
    if (event.shiftKey) {
      modifiers |= 1;
    }
    if (event.ctrlKey) {
      modifiers |= 2;
    }
    if (event.altKey) {
      modifiers |= 4;
    }
    if (event.metaKey) {
      modifiers |= 8;
    }
    const num = (event.keyCode & 255) | (modifiers << 8);
    // We only care about global hotkeys, not about random text
    if (!keysToForwardSet.has(num)) {
      return;
    }
    event.preventDefault();
    const requestPayload = {
      eventType: event.type,
      ctrlKey: event.ctrlKey,
      altKey: event.altKey,
      metaKey: event.metaKey,
      shiftKey: event.shiftKey,
      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);

  /**
   * @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 = {};
  Object.defineProperty(chrome.devtools.inspectedWindow, 'tabId', {get: 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 {!Array<number>} keysToForward
 * @param {function(!Object, !Object)|undefined} testHook
 * @return {string}
 */
self.buildExtensionAPIInjectedScript = function(extensionInfo, inspectedTabId, themeName, keysToForward, testHook) {
  const argumentsJSON = [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
  if (!testHook) {
    testHook = () => {};
  }
  return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString() + ';' +
      '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
      '})';
};

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

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

Extensions.extensionAPI = {};
defineCommonExtensionSymbols(Extensions.extensionAPI);
