/*
 * Copyright (C) 2014 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.
 */
const _loadedScripts = {};

(function() {
const baseUrl = self.location ? self.location.origin + self.location.pathname : '';
self._importScriptPathPrefix = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);
})();

const REMOTE_MODULE_FALLBACK_REVISION = '@010ddcfda246975d194964ccf20038ebbdec6084';

/**
 * @unrestricted
 */
class Runtime {
  /**
   * @param {!Array.<!ModuleDescriptor>} descriptors
   */
  constructor(descriptors) {
    /** @type {!Array<!Runtime.Module>} */
    this._modules = [];
    /** @type {!Object<string, !Runtime.Module>} */
    this._modulesMap = {};
    /** @type {!Array<!Extension>} */
    this._extensions = [];
    /** @type {!Object<string, !function(new:Object)>} */
    this._cachedTypeClasses = {};
    /** @type {!Object<string, !ModuleDescriptor>} */
    this._descriptorsMap = {};

    for (let i = 0; i < descriptors.length; ++i) {
      this._registerModule(descriptors[i]);
    }
  }

  /**
   * @private
   * @param {string} url
   * @param {boolean} asBinary
   * @template T
   * @return {!Promise.<T>}
   */
  static _loadResourcePromise(url, asBinary) {
    return new Promise(load);

    /**
     * @param {function(?)} fulfill
     * @param {function(*)} reject
     */
    function load(fulfill, reject) {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      if (asBinary) {
        xhr.responseType = 'arraybuffer';
      }
      xhr.onreadystatechange = onreadystatechange;

      /**
       * @param {Event} e
       */
      function onreadystatechange(e) {
        if (xhr.readyState !== XMLHttpRequest.DONE) {
          return;
        }

        const {response} = e.target;

        const text = asBinary ? new TextDecoder().decode(response) : response;

        // DevTools Proxy server can mask 404s as 200s, check the body to be sure
        const status = /^HTTP\/1.1 404/.test(text) ? 404 : xhr.status;

        if ([0, 200, 304].indexOf(status) === -1)  // Testing harness file:/// results in 0.
        {
          reject(new Error('While loading from url ' + url + ' server responded with a status of ' + status));
        } else {
          fulfill(cleanJson(response));
        }
      }
      xhr.send(null);
    }

    function cleanJson(response) {
      if (!asBinary && url.endsWith('.json')) {
        // Matches commented-out lines.
        let commented_line_re = /\s*\/\/.*/g;
        // Matches trailing commas before closing of arrays/objects.
        let trailing_comma_re = /,(?=\s*[\]}])/g
        return response
            .replace(commented_line_re, '')
            .replace(trailing_comma_re, '');
      }
      return response;
    }
  }

  /**
   * @param {string} url
   * @return {!Promise.<string>}
   */
  static loadResourcePromise(url) {
    return Runtime._loadResourcePromise(url, false);
  }

  /**
   * @param {string} url
   * @return {!Promise.<!ArrayBuffer>}
   */
  static loadBinaryResourcePromise(url) {
    return Runtime._loadResourcePromise(url, true);
  }

  /**
   * @param {string} url
   * @return {!Promise.<string>}
   */
  static loadResourcePromiseWithFallback(url) {
    return Runtime.loadResourcePromise(url).catch(err => {
      const urlWithFallbackVersion = url.replace(/@[0-9a-f]{40}/, REMOTE_MODULE_FALLBACK_REVISION);
      // TODO(phulce): mark fallbacks in module.json and modify build script instead
      if (urlWithFallbackVersion === url || !url.includes('audits_worker_module')) {
        throw err;
      }
      return Runtime.loadResourcePromise(urlWithFallbackVersion);
    });
  }

  /**
   * http://tools.ietf.org/html/rfc3986#section-5.2.4
   * @param {string} path
   * @return {string}
   */
  static normalizePath(path) {
    if (path.indexOf('..') === -1 && path.indexOf('.') === -1) {
      return path;
    }

    const normalizedSegments = [];
    const segments = path.split('/');
    for (let i = 0; i < segments.length; i++) {
      const segment = segments[i];
      if (segment === '.') {
        continue;
      } else if (segment === '..') {
        normalizedSegments.pop();
      } else if (segment) {
        normalizedSegments.push(segment);
      }
    }
    let normalizedPath = normalizedSegments.join('/');
    if (normalizedPath[normalizedPath.length - 1] === '/') {
      return normalizedPath;
    }
    if (path[0] === '/' && normalizedPath) {
      normalizedPath = '/' + normalizedPath;
    }
    if ((path[path.length - 1] === '/') || (segments[segments.length - 1] === '.') ||
        (segments[segments.length - 1] === '..')) {
      normalizedPath = normalizedPath + '/';
    }

    return normalizedPath;
  }

  /**
   * @param {string} scriptName
   * @param {string=} base
   * @return {string}
   */
  static getResourceURL(scriptName, base) {
    const sourceURL = (base || self._importScriptPathPrefix) + scriptName;
    const schemaIndex = sourceURL.indexOf('://') + 3;
    let pathIndex = sourceURL.indexOf('/', schemaIndex);
    if (pathIndex === -1) {
      pathIndex = sourceURL.length;
    }
    return sourceURL.substring(0, pathIndex) + Runtime.normalizePath(sourceURL.substring(pathIndex));
  }

  /**
   * @param {!Array.<string>} scriptNames
   * @param {string=} base
   * @return {!Promise.<undefined>}
   */
  static _loadScriptsPromise(scriptNames, base) {
    /** @type {!Array<!Promise<undefined>>} */
    const promises = [];
    /** @type {!Array<string>} */
    const urls = [];
    const sources = new Array(scriptNames.length);
    let scriptToEval = 0;
    for (let i = 0; i < scriptNames.length; ++i) {
      const scriptName = scriptNames[i];
      const sourceURL = Runtime.getResourceURL(scriptName, base);

      if (_loadedScripts[sourceURL]) {
        continue;
      }
      urls.push(sourceURL);
      const loadResourcePromise =
          base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
      promises.push(
          loadResourcePromise.then(scriptSourceLoaded.bind(null, i), scriptSourceLoaded.bind(null, i, undefined)));
    }
    return Promise.all(promises).then(undefined);

    /**
     * @param {number} scriptNumber
     * @param {string=} scriptSource
     */
    function scriptSourceLoaded(scriptNumber, scriptSource) {
      sources[scriptNumber] = scriptSource || '';
      // Eval scripts as fast as possible.
      while (typeof sources[scriptToEval] !== 'undefined') {
        evaluateScript(urls[scriptToEval], sources[scriptToEval]);
        ++scriptToEval;
      }
    }

    /**
     * @param {string} sourceURL
     * @param {string=} scriptSource
     */
    function evaluateScript(sourceURL, scriptSource) {
      _loadedScripts[sourceURL] = true;
      if (!scriptSource) {
        // Do not reject, as this is normal in the hosted mode.
        console.error('Empty response arrived for script \'' + sourceURL + '\'');
        return;
      }
      self.eval(scriptSource + '\n//# sourceURL=' + sourceURL);
    }
  }

  /**
   * @param {string} url
   * @param {boolean} appendSourceURL
   * @return {!Promise<undefined>}
   */
  static _loadResourceIntoCache(url, appendSourceURL) {
    return Runtime.loadResourcePromise(url).then(
        cacheResource.bind(this, url), cacheResource.bind(this, url, undefined));

    /**
     * @param {string} path
     * @param {string=} content
     */
    function cacheResource(path, content) {
      if (!content) {
        console.error('Failed to load resource: ' + path);
        return;
      }
      const sourceURL = appendSourceURL ? Runtime.resolveSourceURL(path) : '';
      Runtime.cachedResources[path] = content + sourceURL;
    }
  }

  /**
   * @return {!Promise}
   */
  static async appStarted() {
    return Runtime._appStartedPromise;
  }

  /**
   * @param {string} appName
   * @return {!Promise.<undefined>}
   */
  static async startApplication(appName) {
    console.timeStamp('Root.Runtime.startApplication');

    const allDescriptorsByName = {};
    for (let i = 0; i < Root.allDescriptors.length; ++i) {
      const d = Root.allDescriptors[i];
      allDescriptorsByName[d['name']] = d;
    }

    if (!Root.applicationDescriptor) {
      let data = await Runtime.loadResourcePromise(appName + '.json');
      Root.applicationDescriptor = JSON.parse(data);
      let descriptor = Root.applicationDescriptor;
      while (descriptor.extends) {
        data = await Runtime.loadResourcePromise(descriptor.extends + '.json');
        descriptor = JSON.parse(data);
        Root.applicationDescriptor.modules = descriptor.modules.concat(Root.applicationDescriptor.modules);
      }
    }

    const configuration = Root.applicationDescriptor.modules;
    const moduleJSONPromises = [];
    const coreModuleNames = [];
    for (let i = 0; i < configuration.length; ++i) {
      const descriptor = configuration[i];
      const name = descriptor['name'];
      const moduleJSON = allDescriptorsByName[name];
      if (moduleJSON) {
        moduleJSONPromises.push(Promise.resolve(moduleJSON));
      } else {
        moduleJSONPromises.push(Runtime.loadResourcePromise(name + '/module.json').then(JSON.parse.bind(JSON)));
      }
      if (descriptor['type'] === 'autostart') {
        coreModuleNames.push(name);
      }
    }

    const moduleDescriptors = await Promise.all(moduleJSONPromises);

    for (let i = 0; i < moduleDescriptors.length; ++i) {
      moduleDescriptors[i].name = configuration[i]['name'];
      moduleDescriptors[i].condition = configuration[i]['condition'];
      moduleDescriptors[i].remote = configuration[i]['type'] === 'remote';
    }
    self.runtime = new Runtime(moduleDescriptors);
    if (coreModuleNames) {
      await self.runtime._loadAutoStartModules(coreModuleNames);
    }
    Runtime._appStartedPromiseCallback();
  }

  /**
   * @param {string} appName
   * @return {!Promise.<undefined>}
   */
  static startWorker(appName) {
    return Root.Runtime.startApplication(appName).then(sendWorkerReady);

    function sendWorkerReady() {
      self.postMessage('workerReady');
    }
  }

  /**
   * @param {string} name
   * @return {?string}
   */
  static queryParam(name) {
    return Runtime._queryParamsObject.get(name);
  }

  /**
   * @return {string}
   */
  static queryParamsString() {
    return location.search;
  }

  /**
   * @return {!Object}
   */
  static _experimentsSetting() {
    try {
      return /** @type {!Object} */ (
          JSON.parse(self.localStorage && self.localStorage['experiments'] ? self.localStorage['experiments'] : '{}'));
    } catch (e) {
      console.error('Failed to parse localStorage[\'experiments\']');
      return {};
    }
  }

  static _assert(value, message) {
    if (value) {
      return;
    }
    Runtime._originalAssert.call(Runtime._console, value, message + ' ' + new Error().stack);
  }

  /**
   * @param {string} platform
   */
  static setPlatform(platform) {
    Runtime._platform = platform;
  }

  /**
   * @param {!Object} descriptor
   * @return {boolean}
   */
  static _isDescriptorEnabled(descriptor) {
    const activatorExperiment = descriptor['experiment'];
    if (activatorExperiment === '*') {
      return Runtime.experiments.supportEnabled();
    }
    if (activatorExperiment && activatorExperiment.startsWith('!') &&
        Runtime.experiments.isEnabled(activatorExperiment.substring(1))) {
      return false;
    }
    if (activatorExperiment && !activatorExperiment.startsWith('!') &&
        !Runtime.experiments.isEnabled(activatorExperiment)) {
      return false;
    }
    const condition = descriptor['condition'];
    if (condition && !condition.startsWith('!') && !Runtime.queryParam(condition)) {
      return false;
    }
    if (condition && condition.startsWith('!') && Runtime.queryParam(condition.substring(1))) {
      return false;
    }
    return true;
  }

  /**
   * @param {string} path
   * @return {string}
   */
  static resolveSourceURL(path) {
    let sourceURL = self.location.href;
    if (self.location.search) {
      sourceURL = sourceURL.replace(self.location.search, '');
    }
    sourceURL = sourceURL.substring(0, sourceURL.lastIndexOf('/') + 1) + path;
    return '\n/*# sourceURL=' + sourceURL + ' */';
  }

  /**
   * @param {function(string):string} localizationFunction
   */
  static setL10nCallback(localizationFunction) {
    Runtime._l10nCallback = localizationFunction;
  }

  useTestBase() {
    Runtime._remoteBase = 'http://localhost:8000/inspector-sources/';
    if (Runtime.queryParam('debugFrontend')) {
      Runtime._remoteBase += 'debug/';
    }
  }

  /**
   * @param {string} moduleName
   * @return {!Runtime.Module}
   */
  module(moduleName) {
    return this._modulesMap[moduleName];
  }

  /**
   * @param {!ModuleDescriptor} descriptor
   */
  _registerModule(descriptor) {
    const module = new Runtime.Module(this, descriptor);
    this._modules.push(module);
    this._modulesMap[descriptor['name']] = module;
  }

  /**
   * @param {string} moduleName
   * @return {!Promise.<undefined>}
   */
  loadModulePromise(moduleName) {
    return this._modulesMap[moduleName]._loadPromise();
  }

  /**
   * @param {!Array.<string>} moduleNames
   * @return {!Promise.<!Array.<*>>}
   */
  _loadAutoStartModules(moduleNames) {
    const promises = [];
    for (let i = 0; i < moduleNames.length; ++i) {
      promises.push(this.loadModulePromise(moduleNames[i]));
    }
    return Promise.all(promises);
  }

  /**
   * @param {!Extension} extension
   * @param {?function(function(new:Object)):boolean} predicate
   * @return {boolean}
   */
  _checkExtensionApplicability(extension, predicate) {
    if (!predicate) {
      return false;
    }
    const contextTypes = extension.descriptor().contextTypes;
    if (!contextTypes) {
      return true;
    }
    for (let i = 0; i < contextTypes.length; ++i) {
      const contextType = this._resolve(contextTypes[i]);
      const isMatching = !!contextType && predicate(contextType);
      if (isMatching) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param {!Extension} extension
   * @param {?Object} context
   * @return {boolean}
   */
  isExtensionApplicableToContext(extension, context) {
    if (!context) {
      return true;
    }
    return this._checkExtensionApplicability(extension, isInstanceOf);

    /**
     * @param {!Function} targetType
     * @return {boolean}
     */
    function isInstanceOf(targetType) {
      return context instanceof targetType;
    }
  }

  /**
   * @param {!Extension} extension
   * @param {!Set.<!Function>=} currentContextTypes
   * @return {boolean}
   */
  isExtensionApplicableToContextTypes(extension, currentContextTypes) {
    if (!extension.descriptor().contextTypes) {
      return true;
    }

    return this._checkExtensionApplicability(extension, currentContextTypes ? isContextTypeKnown : null);

    /**
     * @param {!Function} targetType
     * @return {boolean}
     */
    function isContextTypeKnown(targetType) {
      return currentContextTypes.has(targetType);
    }
  }

  /**
   * @param {*} type
   * @param {?Object=} context
   * @param {boolean=} sortByTitle
   * @return {!Array.<!Extension>}
   */
  extensions(type, context, sortByTitle) {
    return this._extensions.filter(filter).sort(sortByTitle ? titleComparator : orderComparator);

    /**
     * @param {!Extension} extension
     * @return {boolean}
     */
    function filter(extension) {
      if (extension._type !== type && extension._typeClass() !== type) {
        return false;
      }
      if (!extension.enabled()) {
        return false;
      }
      return !context || extension.isApplicable(context);
    }

    /**
     * @param {!Extension} extension1
     * @param {!Extension} extension2
     * @return {number}
     */
    function orderComparator(extension1, extension2) {
      const order1 = extension1.descriptor()['order'] || 0;
      const order2 = extension2.descriptor()['order'] || 0;
      return order1 - order2;
    }

    /**
     * @param {!Extension} extension1
     * @param {!Extension} extension2
     * @return {number}
     */
    function titleComparator(extension1, extension2) {
      const title1 = extension1.title() || '';
      const title2 = extension2.title() || '';
      return title1.localeCompare(title2);
    }
  }

  /**
   * @param {*} type
   * @param {?Object=} context
   * @return {?Extension}
   */
  extension(type, context) {
    return this.extensions(type, context)[0] || null;
  }

  /**
   * @param {*} type
   * @param {?Object=} context
   * @return {!Promise.<!Array.<!Object>>}
   */
  allInstances(type, context) {
    return Promise.all(this.extensions(type, context).map(extension => extension.instance()));
  }

  /**
   * @return {?function(new:Object)}
   */
  _resolve(typeName) {
    if (!this._cachedTypeClasses[typeName]) {
      const path = typeName.split('.');
      let object = self;
      for (let i = 0; object && (i < path.length); ++i) {
        object = object[path[i]];
      }
      if (object) {
        this._cachedTypeClasses[typeName] = /** @type function(new:Object) */ (object);
      }
    }
    return this._cachedTypeClasses[typeName] || null;
  }

  /**
   * @param {function(new:T)} constructorFunction
   * @return {!T}
   * @template T
   */
  sharedInstance(constructorFunction) {
    if (Runtime._instanceSymbol in constructorFunction &&
        Object.getOwnPropertySymbols(constructorFunction).includes(Runtime._instanceSymbol)) {
      return constructorFunction[Runtime._instanceSymbol];
    }

    const instance = new constructorFunction();
    constructorFunction[Runtime._instanceSymbol] = instance;
    return instance;
  }
}

/** @type {!URLSearchParams} */
Runtime._queryParamsObject = new URLSearchParams(Runtime.queryParamsString());

Runtime._instanceSymbol = Symbol('instance');

/**
 * @type {!Object.<string, string>}
 */
Runtime.cachedResources = {
  __proto__: null
};


Runtime._console = console;
Runtime._originalAssert = console.assert;


Runtime._platform = '';


/**
 * @unrestricted
 */
class ModuleDescriptor {
  constructor() {
    /**
     * @type {string}
     */
    this.name;

    /**
     * @type {!Array.<!RuntimeExtensionDescriptor>}
     */
    this.extensions;

    /**
     * @type {!Array.<string>|undefined}
     */
    this.dependencies;

    /**
     * @type {!Array.<string>}
     */
    this.scripts;

    /**
     * @type {!Array.<string>}
     */
    this.modules;

    /**
     * @type {string|undefined}
     */
    this.condition;

    /**
     * @type {boolean|undefined}
     */
    this.remote;
  }
}

// This class is named like this, because we already have an "ExtensionDescriptor" in the externs
// These two do not share the same structure
/**
 * @unrestricted
 */
class RuntimeExtensionDescriptor {
  constructor() {
    /**
     * @type {string}
     */
    this.type;

    /**
     * @type {string|undefined}
     */
    this.className;

    /**
     * @type {string|undefined}
     */
    this.factoryName;

    /**
     * @type {!Array.<string>|undefined}
     */
    this.contextTypes;
  }
}

// Module namespaces.
// NOTE: Update scripts/build/special_case_namespaces.json if you add a special cased namespace.
const specialCases = {
  'sdk': 'SDK',
  'js_sdk': 'JSSDK',
  'browser_sdk': 'BrowserSDK',
  'ui': 'UI',
  'object_ui': 'ObjectUI',
  'javascript_metadata': 'JavaScriptMetadata',
  'perf_ui': 'PerfUI',
  'har_importer': 'HARImporter',
  'sdk_test_runner': 'SDKTestRunner',
  'cpu_profiler_test_runner': 'CPUProfilerTestRunner'
};

/**
 * @unrestricted
 */
class Module {
  /**
   * @param {!Runtime} manager
   * @param {!ModuleDescriptor} descriptor
   */
  constructor(manager, descriptor) {
    this._manager = manager;
    this._descriptor = descriptor;
    this._name = descriptor.name;
    /** @type {!Array<!Extension>} */
    this._extensions = [];

    /** @type {!Map<string, !Array<!Extension>>} */
    this._extensionsByClassName = new Map();
    const extensions = /** @type {?Array.<!RuntimeExtensionDescriptor>} */ (descriptor.extensions);
    for (let i = 0; extensions && i < extensions.length; ++i) {
      const extension = new Extension(this, extensions[i]);
      this._manager._extensions.push(extension);
      this._extensions.push(extension);
    }
    this._loadedForTest = false;
  }

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

  /**
   * @return {boolean}
   */
  enabled() {
    return Runtime._isDescriptorEnabled(this._descriptor);
  }

  /**
   * @param {string} name
   * @return {string}
   */
  resource(name) {
    const fullName = this._name + '/' + name;
    const content = Runtime.cachedResources[fullName];
    if (!content) {
      throw new Error(fullName + ' not preloaded. Check module.json');
    }
    return content;
  }

  /**
   * @return {!Promise.<undefined>}
   */
  _loadPromise() {
    if (!this.enabled()) {
      return Promise.reject(new Error('Module ' + this._name + ' is not enabled'));
    }

    if (this._pendingLoadPromise) {
      return this._pendingLoadPromise;
    }

    const dependencies = this._descriptor.dependencies;
    const dependencyPromises = [];
    for (let i = 0; dependencies && i < dependencies.length; ++i) {
      dependencyPromises.push(this._manager._modulesMap[dependencies[i]]._loadPromise());
    }

    this._pendingLoadPromise = Promise.all(dependencyPromises)
                                   .then(this._loadResources.bind(this))
                                   .then(this._loadModules.bind(this))
                                   .then(this._loadScripts.bind(this))
                                   .then(() => this._loadedForTest = true);

    return this._pendingLoadPromise;
  }

  /**
   * @return {!Promise.<undefined>}
   * @this {Runtime.Module}
   */
  _loadResources() {
    const resources = this._descriptor['resources'];
    if (!resources || !resources.length) {
      return Promise.resolve();
    }
    const promises = [];
    for (let i = 0; i < resources.length; ++i) {
      const url = this._modularizeURL(resources[i]);
      const isHtml = url.endsWith('.html');
      promises.push(Runtime._loadResourceIntoCache(url, !isHtml /* appendSourceURL */));
    }
    return Promise.all(promises).then(undefined);
  }

  _loadModules() {
    if (!this._descriptor.modules || !this._descriptor.modules.length) {
      return Promise.resolve();
    }

    const namespace = this._computeNamespace();
    self[namespace] = self[namespace] || {};

    // TODO(crbug.com/680046): We are in a worker and we dont support modules yet
    if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
      return Promise.resolve();
    }

    const legacyFileName = `${this._name}-legacy.js`;
    const fileName = this._descriptor.modules.includes(legacyFileName) ? legacyFileName : `${this._name}.js`;

    // TODO(crbug.com/1011811): Remove eval when we use TypeScript which does support dynamic imports
    return eval(`import('./${this._name}/${fileName}')`);
  }

  /**
   * @return {!Promise.<undefined>}
   */
  _loadScripts() {
    if (!this._descriptor.scripts || !this._descriptor.scripts.length) {
      return Promise.resolve();
    }

    const namespace = this._computeNamespace();
    self[namespace] = self[namespace] || {};
    return Runtime._loadScriptsPromise(this._descriptor.scripts.map(this._modularizeURL, this), this._remoteBase());
  }

  /**
   * @return {string}
   */
  _computeNamespace() {
    return specialCases[this._name] ||
        this._name.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substring(1)).join('');
  }

  /**
   * @param {string} resourceName
   */
  _modularizeURL(resourceName) {
    return Runtime.normalizePath(this._name + '/' + resourceName);
  }

  /**
   * @return {string|undefined}
   */
  _remoteBase() {
    return !Runtime.queryParam('debugFrontend') && this._descriptor.remote && Runtime._remoteBase || undefined;
  }

  /**
   * @param {string} resourceName
   * @return {!Promise.<string>}
   */
  fetchResource(resourceName) {
    const base = this._remoteBase();
    const sourceURL = Runtime.getResourceURL(this._modularizeURL(resourceName), base);
    return base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
  }

  /**
   * @param {string} value
   * @return {string}
   */
  substituteURL(value) {
    const base = this._remoteBase() || '';
    return value.replace(/@url\(([^\)]*?)\)/g, convertURL.bind(this));

    function convertURL(match, url) {
      return base + this._modularizeURL(url);
    }
  }
}


/**
 * @unrestricted
 */
class Extension { /**
   * @param {!Runtime.Module} module
   * @param {!RuntimeExtensionDescriptor} descriptor
   */
  constructor(module, descriptor) {
    this._module = module;
    this._descriptor = descriptor;

    this._type = descriptor.type;
    this._hasTypeClass = this._type.charAt(0) === '@';

    /**
     * @type {?string}
     */
    this._className = descriptor.className || null;
    this._factoryName = descriptor.factoryName || null;
  }

  /**
   * @return {!Object}
   */
  descriptor() {
    return this._descriptor;
  }

  /**
   * @return {!Runtime.Module}
   */
  module() {
    return this._module;
  }

  /**
   * @return {boolean}
   */
  enabled() {
    return this._module.enabled() && Runtime._isDescriptorEnabled(this.descriptor());
  }

  /**
   * @return {?function(new:Object)}
   */
  _typeClass() {
    if (!this._hasTypeClass) {
      return null;
    }
    return this._module._manager._resolve(this._type.substring(1));
  }

  /**
   * @param {?Object} context
   * @return {boolean}
   */
  isApplicable(context) {
    return this._module._manager.isExtensionApplicableToContext(this, context);
  }

  /**
   * @return {!Promise.<!Object>}
   */
  instance() {
    return this._module._loadPromise().then(this._createInstance.bind(this));
  }

  /**
   * @return {boolean}
   */
  canInstantiate() {
    return !!(this._className || this._factoryName);
  }

  /**
   * @return {!Object}
   */
  _createInstance() {
    const className = this._className || this._factoryName;
    if (!className) {
      throw new Error('Could not instantiate extension with no class');
    }
    const constructorFunction = self.eval(/** @type {string} */ (className));
    if (!(constructorFunction instanceof Function)) {
      throw new Error('Could not instantiate: ' + className);
    }
    if (this._className) {
      return this._module._manager.sharedInstance(constructorFunction);
    }
    return new constructorFunction(this);
  }

  /**
   * @return {string}
   */
  title() {
    const title = this._descriptor['title-' + Runtime._platform] || this._descriptor['title'];
    if (title && Runtime._l10nCallback) {
      return Runtime._l10nCallback(title);
    }
    return title;
  }

  /**
   * @param {function(new:Object)} contextType
   * @return {boolean}
   */
  hasContextType(contextType) {
    const contextTypes = this.descriptor().contextTypes;
    if (!contextTypes) {
      return false;
    }
    for (let i = 0; i < contextTypes.length; ++i) {
      if (contextType === this._module._manager._resolve(contextTypes[i])) {
        return true;
      }
    }
    return false;
  }
}

/**
 * @unrestricted
 */
class ExperimentsSupport {
  constructor() {
    this._supportEnabled = Runtime.queryParam('experiments') !== null;
    this._experiments = [];
    this._experimentNames = {};
    this._enabledTransiently = {};
    /** @type {!Set<string>} */
    this._serverEnabled = new Set();
  }

  /**
   * @return {!Array.<!Runtime.Experiment>}
   */
  allConfigurableExperiments() {
    const result = [];
    for (let i = 0; i < this._experiments.length; i++) {
      const experiment = this._experiments[i];
      if (!this._enabledTransiently[experiment.name]) {
        result.push(experiment);
      }
    }
    return result;
  }

  /**
   * @return {boolean}
   */
  supportEnabled() {
    return this._supportEnabled;
  }

  /**
   * @param {!Object} value
   */
  _setExperimentsSetting(value) {
    if (!self.localStorage) {
      return;
    }
    self.localStorage['experiments'] = JSON.stringify(value);
  }

  /**
   * @param {string} experimentName
   * @param {string} experimentTitle
   * @param {boolean=} hidden
   */
  register(experimentName, experimentTitle, hidden) {
    Runtime._assert(!this._experimentNames[experimentName], 'Duplicate registration of experiment ' + experimentName);
    this._experimentNames[experimentName] = true;
    this._experiments.push(new Runtime.Experiment(this, experimentName, experimentTitle, !!hidden));
  }

  /**
   * @param {string} experimentName
   * @return {boolean}
   */
  isEnabled(experimentName) {
    this._checkExperiment(experimentName);
    // Check for explicitly disabled experiments first - the code could call setEnable(false) on the experiment enabled
    // by default and we should respect that.
    if (Runtime._experimentsSetting()[experimentName] === false) {
      return false;
    }
    if (this._enabledTransiently[experimentName]) {
      return true;
    }
    if (this._serverEnabled.has(experimentName)) {
      return true;
    }
    if (!this.supportEnabled()) {
      return false;
    }

    return !!Runtime._experimentsSetting()[experimentName];
  }

  /**
   * @param {string} experimentName
   * @param {boolean} enabled
   */
  setEnabled(experimentName, enabled) {
    this._checkExperiment(experimentName);
    const experimentsSetting = Runtime._experimentsSetting();
    experimentsSetting[experimentName] = enabled;
    this._setExperimentsSetting(experimentsSetting);
  }

  /**
   * @param {!Array.<string>} experimentNames
   */
  setDefaultExperiments(experimentNames) {
    for (let i = 0; i < experimentNames.length; ++i) {
      this._checkExperiment(experimentNames[i]);
      this._enabledTransiently[experimentNames[i]] = true;
    }
  }

  /**
   * @param {!Array.<string>} experimentNames
   */
  setServerEnabledExperiments(experimentNames) {
    for (const experiment of experimentNames) {
      this._checkExperiment(experiment);
      this._serverEnabled.add(experiment);
    }
  }

  /**
   * @param {string} experimentName
   */
  enableForTest(experimentName) {
    this._checkExperiment(experimentName);
    this._enabledTransiently[experimentName] = true;
  }

  clearForTest() {
    this._experiments = [];
    this._experimentNames = {};
    this._enabledTransiently = {};
    this._serverEnabled.clear();
  }

  cleanUpStaleExperiments() {
    const experimentsSetting = Runtime._experimentsSetting();
    const cleanedUpExperimentSetting = {};
    for (let i = 0; i < this._experiments.length; ++i) {
      const experimentName = this._experiments[i].name;
      if (experimentsSetting[experimentName]) {
        cleanedUpExperimentSetting[experimentName] = true;
      }
    }
    this._setExperimentsSetting(cleanedUpExperimentSetting);
  }

  /**
   * @param {string} experimentName
   */
  _checkExperiment(experimentName) {
    Runtime._assert(this._experimentNames[experimentName], 'Unknown experiment ' + experimentName);
  }
}

/**
 * @unrestricted
 */
class Experiment {
  /**
   * @param {!Runtime.ExperimentsSupport} experiments
   * @param {string} name
   * @param {string} title
   * @param {boolean} hidden
   */
  constructor(experiments, name, title, hidden) {
    this.name = name;
    this.title = title;
    this.hidden = hidden;
    this._experiments = experiments;
  }

  /**
   * @return {boolean}
   */
  isEnabled() {
    return this._experiments.isEnabled(this.name);
  }

  /**
   * @param {boolean} enabled
   */
  setEnabled(enabled) {
    this._experiments.setEnabled(this.name, enabled);
  }
}

// This must be constructed after the query parameters have been parsed.
Runtime.experiments = new ExperimentsSupport();

/** @type {Function} */
Runtime._appStartedPromiseCallback;
Runtime._appStartedPromise = new Promise(fulfil => Runtime._appStartedPromiseCallback = fulfil);

/** @type {function(string):string} */
Runtime._l10nCallback;

/**
 * @type {?string}
 */
Runtime._remoteBase;
(function validateRemoteBase() {
  if (location.href.startsWith('devtools://devtools/bundled/') && Runtime.queryParam('remoteBase')) {
    const versionMatch = /\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(Runtime.queryParam('remoteBase'));
    if (versionMatch) {
      Runtime._remoteBase = `${location.origin}/remote/serve_file/${versionMatch[1]}/`;
    }
  }
})();

self.Root = self.Root || {};
Root = Root || {};

// This gets all concatenated module descriptors in the release mode.
Root.allDescriptors = [];

Root.applicationDescriptor = undefined;

/** @constructor */
Root.Runtime = Runtime;

/** @type {!Runtime} */
Root.runtime;

/** @constructor */
Root.Runtime.ModuleDescriptor = ModuleDescriptor;

/** @constructor */
Root.Runtime.ExtensionDescriptor = RuntimeExtensionDescriptor;

/** @constructor */
Root.Runtime.Extension = Extension;

/** @constructor */
Root.Runtime.Module = Module;

/** @constructor */
Root.Runtime.ExperimentsSupport = ExperimentsSupport;

/** @constructor */
Root.Runtime.Experiment = Experiment;
