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

Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
  /**
   * @param {!SourceFrame.SourcesTextEditor} textEditor
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @param {!SourceFrame.Transformer} transformer
   */
  constructor(textEditor, uiSourceCode, transformer) {
    super();
    this._textEditor = textEditor;
    this._uiSourceCode = uiSourceCode;
    this._transformer = transformer;

    /** @type {?Element} */
    this._conditionEditorElement = null;
    /** @type {?Element} */
    this._conditionElement = null;
    /** @type {?Workspace.UILocation} */
    this._executionLocation = null;
    this._controlDown = false;
    this._asyncStepInHoveredLine = 0;
    this._asyncStepInHovered = false;
    /** @type {?number} */
    this._clearValueWidgetsTimer = null;
    /** @type {?UI.Infobar} */
    this._sourceMapInfobar = null;
    /** @type {?number} */
    this._controlTimeout = null;

    this._scriptsPanel = Sources.SourcesPanel.instance();
    this._breakpointManager = Bindings.breakpointManager;
    if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger)
      this._textEditor.element.classList.add('source-frame-debugger-script');

    this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, this._getPopoverRequest.bind(this));
    this._popoverHelper.setDisableOnClick(true);
    this._popoverHelper.setTimeout(250, 250);
    this._popoverHelper.setHasPadding(true);
    this._boundPopoverHelperHide = this._popoverHelper.hidePopover.bind(this._popoverHelper);
    this._scriptsPanel.element.addEventListener('scroll', this._boundPopoverHelperHide, true);

    this._boundKeyDown = /** @type {function(!Event)} */ (this._onKeyDown.bind(this));
    this._textEditor.element.addEventListener('keydown', this._boundKeyDown, true);
    this._boundKeyUp = /** @type {function(!Event)} */ (this._onKeyUp.bind(this));
    this._textEditor.element.addEventListener('keyup', this._boundKeyUp, true);
    this._boundMouseMove = /** @type {function(!Event)} */ (this._onMouseMove.bind(this));
    this._textEditor.element.addEventListener('mousemove', this._boundMouseMove, false);
    this._boundMouseDown = /** @type {function(!Event)} */ (this._onMouseDown.bind(this));
    this._textEditor.element.addEventListener('mousedown', this._boundMouseDown, true);
    this._boundBlur = this._onBlur.bind(this);
    this._textEditor.element.addEventListener('focusout', this._boundBlur, false);
    this._boundWheel = event => {
      if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
        event.preventDefault();
    };
    this._textEditor.element.addEventListener('wheel', this._boundWheel, true);

    this._textEditor.addEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, this._handleGutterClick, this);

    this._breakpointManager.addEventListener(
        Bindings.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
    this._breakpointManager.addEventListener(
        Bindings.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);

    this._uiSourceCode.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
    this._uiSourceCode.addEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);

    /** @type {!Set<!Sources.DebuggerPlugin.BreakpointDecoration>} */
    this._breakpointDecorations = new Set();
    /** @type {!Map<!Bindings.BreakpointManager.Breakpoint, !Sources.DebuggerPlugin.BreakpointDecoration>} */
    this._decorationByBreakpoint = new Map();
    /** @type {!Set<number>} */
    this._possibleBreakpointsRequested = new Set();

    /** @type {!Map.<!SDK.DebuggerModel, !Bindings.ResourceScriptFile>}*/
    this._scriptFileForDebuggerModel = new Map();

    Common.moduleSetting('skipStackFramesPattern').addChangeListener(this._showBlackboxInfobarIfNeeded, this);
    Common.moduleSetting('skipContentScripts').addChangeListener(this._showBlackboxInfobarIfNeeded, this);

    /** @type {!Map.<number, !Element>} */
    this._valueWidgets = new Map();
    /** @type {?Map<!Object, !Function>} */
    this._continueToLocationDecorations = null;

    UI.context.addFlavorChangeListener(SDK.DebuggerModel.CallFrame, this._callFrameChanged, this);
    this._liveLocationPool = new Bindings.LiveLocationPool();
    this._callFrameChanged();

    this._updateScriptFiles();

    if (this._uiSourceCode.isDirty() && !this._supportsEnabledBreakpointsWhileEditing()) {
      this._muted = true;
      this._mutedFromStart = true;
    } else {
      this._muted = false;
      this._mutedFromStart = false;
      this._initializeBreakpoints();
    }

    /** @type {?UI.Infobar} */
    this._blackboxInfobar = null;
    this._showBlackboxInfobarIfNeeded();

    const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
    for (let i = 0; i < scriptFiles.length; ++i)
      scriptFiles[i].checkMapping();

    this._hasLineWithoutMapping = false;
    this._updateLinesWithoutMappingHighlight();
    if (!Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
      /** @type {?UI.Infobar} */
      this._prettyPrintInfobar = null;
      this._detectMinified();
    }
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  static accepts(uiSourceCode) {
    return uiSourceCode.contentType().hasScripts();
  }

  /**
   * @override
   * @return {!Array<!UI.ToolbarItem>}
   */
  rightToolbarItems() {
    const originURL = Bindings.CompilerScriptMapping.uiSourceCodeOrigin(this._uiSourceCode);
    if (originURL) {
      const parsedURL = originURL.asParsedURL();
      if (parsedURL)
        return [new UI.ToolbarText(Common.UIString('(source mapped from %s)', parsedURL.displayName))];
    }

    return [];
  }

  _showBlackboxInfobarIfNeeded() {
    const uiSourceCode = this._uiSourceCode;
    if (!uiSourceCode.contentType().hasScripts())
      return;
    const projectType = uiSourceCode.project().type();
    if (!Bindings.blackboxManager.isBlackboxedUISourceCode(uiSourceCode)) {
      this._hideBlackboxInfobar();
      return;
    }

    if (this._blackboxInfobar)
      this._blackboxInfobar.dispose();

    const infobar = new UI.Infobar(UI.Infobar.Type.Warning, Common.UIString('This script is blackboxed in debugger'));
    this._blackboxInfobar = infobar;

    infobar.createDetailsRowMessage(
        Common.UIString('Debugger will skip stepping through this script, and will not stop on exceptions'));

    const scriptFile = this._scriptFileForDebuggerModel.size ? this._scriptFileForDebuggerModel.valuesArray()[0] : null;
    if (scriptFile && scriptFile.hasSourceMapURL())
      infobar.createDetailsRowMessage(Common.UIString('Source map found, but ignored for blackboxed file.'));
    infobar.createDetailsRowMessage();
    infobar.createDetailsRowMessage(Common.UIString('Possible ways to cancel this behavior are:'));

    infobar.createDetailsRowMessage(' - ').createTextChild(
        Common.UIString('Go to "%s" tab in settings', Common.UIString('Blackboxing')));
    const unblackboxLink = infobar.createDetailsRowMessage(' - ').createChild('span', 'link');
    unblackboxLink.textContent = Common.UIString('Unblackbox this script');
    unblackboxLink.addEventListener('click', unblackbox, false);

    function unblackbox() {
      Bindings.blackboxManager.unblackboxUISourceCode(uiSourceCode);
      if (projectType === Workspace.projectTypes.ContentScripts)
        Bindings.blackboxManager.unblackboxContentScripts();
    }
    this._textEditor.attachInfobar(this._blackboxInfobar);
  }

  _hideBlackboxInfobar() {
    if (!this._blackboxInfobar)
      return;
    this._blackboxInfobar.dispose();
    this._blackboxInfobar = null;
  }

  /**
   * @override
   */
  wasShown() {
    if (this._executionLocation) {
      // We need SourcesTextEditor to be initialized prior to this call. @see crbug.com/499889
      setImmediate(() => {
        this._generateValuesInSource();
      });
    }
  }

  /**
   * @override
   */
  willHide() {
    this._popoverHelper.hidePopover();
  }

  /**
   * @override
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} editorLineNumber
   * @return {!Promise}
   */
  populateLineGutterContextMenu(contextMenu, editorLineNumber) {
    /**
     * @this {Sources.DebuggerPlugin}
     */
    function populate(resolve, reject) {
      const uiLocation = new Workspace.UILocation(this._uiSourceCode, editorLineNumber, 0);
      this._scriptsPanel.appendUILocationItems(contextMenu, uiLocation);
      const breakpoints = this._lineBreakpointDecorations(editorLineNumber)
                              .map(decoration => decoration.breakpoint)
                              .filter(breakpoint => !!breakpoint);
      if (!breakpoints.length) {
        contextMenu.debugSection().appendItem(
            Common.UIString('Add breakpoint'), this._createNewBreakpoint.bind(this, editorLineNumber, '', true));
        contextMenu.debugSection().appendItem(
            Common.UIString('Add conditional breakpoint\u2026'),
            this._editBreakpointCondition.bind(this, editorLineNumber, null, null));
        contextMenu.debugSection().appendItem(
            Common.UIString('Never pause here'), this._createNewBreakpoint.bind(this, editorLineNumber, 'false', true));
      } else {
        const hasOneBreakpoint = breakpoints.length === 1;
        const removeTitle =
            hasOneBreakpoint ? Common.UIString('Remove breakpoint') : Common.UIString('Remove all breakpoints in line');
        contextMenu.debugSection().appendItem(removeTitle, () => breakpoints.map(breakpoint => breakpoint.remove()));
        if (hasOneBreakpoint) {
          contextMenu.debugSection().appendItem(
              Common.UIString('Edit breakpoint\u2026'),
              this._editBreakpointCondition.bind(this, editorLineNumber, breakpoints[0], null));
        }
        const hasEnabled = breakpoints.some(breakpoint => breakpoint.enabled());
        if (hasEnabled) {
          const title = hasOneBreakpoint ? Common.UIString('Disable breakpoint') :
                                           Common.UIString('Disable all breakpoints in line');
          contextMenu.debugSection().appendItem(
              title, () => breakpoints.map(breakpoint => breakpoint.setEnabled(false)));
        }
        const hasDisabled = breakpoints.some(breakpoint => !breakpoint.enabled());
        if (hasDisabled) {
          const title = hasOneBreakpoint ? Common.UIString('Enable breakpoint') :
                                           Common.UIString('Enabled all breakpoints in line');
          contextMenu.debugSection().appendItem(
              title, () => breakpoints.map(breakpoint => breakpoint.setEnabled(true)));
        }
      }
      resolve();
    }
    return new Promise(populate.bind(this));
  }

  /**
   * @override
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} editorLineNumber
   * @param {number} editorColumnNumber
   * @return {!Promise}
   */
  populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber) {
    /**
     * @param {!Bindings.ResourceScriptFile} scriptFile
     */
    function addSourceMapURL(scriptFile) {
      Sources.AddSourceMapURLDialog.show(addSourceMapURLDialogCallback.bind(null, scriptFile));
    }

    /**
     * @param {!Bindings.ResourceScriptFile} scriptFile
     * @param {string} url
     */
    function addSourceMapURLDialogCallback(scriptFile, url) {
      if (!url)
        return;
      scriptFile.addSourceMapURL(url);
    }

    /**
     * @this {Sources.DebuggerPlugin}
     */
    function populateSourceMapMembers() {
      if (this._uiSourceCode.project().type() === Workspace.projectTypes.Network &&
          Common.moduleSetting('jsSourceMapsEnabled').get() &&
          !Bindings.blackboxManager.isBlackboxedUISourceCode(this._uiSourceCode)) {
        if (this._scriptFileForDebuggerModel.size) {
          const scriptFile = this._scriptFileForDebuggerModel.valuesArray()[0];
          const addSourceMapURLLabel = Common.UIString('Add source map\u2026');
          contextMenu.debugSection().appendItem(addSourceMapURLLabel, addSourceMapURL.bind(null, scriptFile));
        }
      }
    }

    return super.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber)
        .then(populateSourceMapMembers.bind(this));
  }

  _workingCopyChanged() {
    if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFileForDebuggerModel.size)
      return;

    if (this._uiSourceCode.isDirty())
      this._muteBreakpointsWhileEditing();
    else
      this._restoreBreakpointsAfterEditing();
  }

  /**
   * @param {!Common.Event} event
   */
  _workingCopyCommitted(event) {
    this._scriptsPanel.updateLastModificationTime();
    if (this._supportsEnabledBreakpointsWhileEditing())
      return;

    if (!this._scriptFileForDebuggerModel.size)
      this._restoreBreakpointsAfterEditing();
  }

  _didMergeToVM() {
    if (this._supportsEnabledBreakpointsWhileEditing())
      return;
    this._restoreBreakpointsIfConsistentScripts();
  }

  _didDivergeFromVM() {
    if (this._supportsEnabledBreakpointsWhileEditing())
      return;
    this._muteBreakpointsWhileEditing();
  }

  _muteBreakpointsWhileEditing() {
    if (this._muted)
      return;
    for (const decoration of this._breakpointDecorations)
      this._updateBreakpointDecoration(decoration);
    this._muted = true;
  }

  _supportsEnabledBreakpointsWhileEditing() {
    return this._uiSourceCode.project().type() === Workspace.projectTypes.Snippets;
  }

  _restoreBreakpointsIfConsistentScripts() {
    const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
    for (let i = 0; i < scriptFiles.length; ++i) {
      if (scriptFiles[i].hasDivergedFromVM() || scriptFiles[i].isMergingToVM())
        return;
    }

    this._restoreBreakpointsAfterEditing();
  }

  _restoreBreakpointsAfterEditing() {
    this._muted = false;
    if (this._mutedFromStart) {
      this._mutedFromStart = false;
      this._initializeBreakpoints();
      return;
    }
    const decorations = Array.from(this._breakpointDecorations);
    this._breakpointDecorations.clear();
    this._textEditor.operation(() => decorations.map(decoration => decoration.hide()));
    for (const decoration of decorations) {
      if (!decoration.breakpoint)
        continue;
      const enabled = decoration.enabled;
      decoration.breakpoint.remove();
      const location = decoration.handle.resolve();
      if (location)
        this._setBreakpoint(location.lineNumber, location.columnNumber, decoration.condition, enabled);
    }
  }

  /**
   * @param {string}  tokenType
   * @return {boolean}
   */
  _isIdentifier(tokenType) {
    return tokenType.startsWith('js-variable') || tokenType.startsWith('js-property') || tokenType === 'js-def';
  }

  /**
   * @param {!MouseEvent} event
   * @return {?UI.PopoverRequest}
   */
  _getPopoverRequest(event) {
    if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
      return null;
    const target = UI.context.flavor(SDK.Target);
    const debuggerModel = target ? target.model(SDK.DebuggerModel) : null;
    if (!debuggerModel || !debuggerModel.isPaused())
      return null;

    const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
    if (!textPosition)
      return null;

    const mouseLine = textPosition.startLine;
    const mouseColumn = textPosition.startColumn;
    const textSelection = this._textEditor.selection().normalize();
    let anchorBox;
    let editorLineNumber;
    let startHighlight;
    let endHighlight;

    if (textSelection && !textSelection.isEmpty()) {
      if (textSelection.startLine !== textSelection.endLine || textSelection.startLine !== mouseLine ||
          mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn)
        return null;

      const leftCorner =
          this._textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn);
      const rightCorner = this._textEditor.cursorPositionToCoordinates(textSelection.endLine, textSelection.endColumn);
      anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);
      editorLineNumber = textSelection.startLine;
      startHighlight = textSelection.startColumn;
      endHighlight = textSelection.endColumn - 1;
    } else {
      const token = this._textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn);
      if (!token || !token.type)
        return null;
      editorLineNumber = textPosition.startLine;
      const line = this._textEditor.line(editorLineNumber);
      const tokenContent = line.substring(token.startColumn, token.endColumn);

      const isIdentifier = this._isIdentifier(token.type);
      if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this'))
        return null;

      const leftCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.startColumn);
      const rightCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.endColumn - 1);
      anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);

      startHighlight = token.startColumn;
      endHighlight = token.endColumn - 1;
      while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') {
        const tokenBefore = this._textEditor.tokenAtTextPosition(editorLineNumber, startHighlight - 2);
        if (!tokenBefore || !tokenBefore.type)
          return null;
        startHighlight = tokenBefore.startColumn;
      }
    }

    let objectPopoverHelper;
    let highlightDescriptor;

    return {
      box: anchorBox,
      show: async popover => {
        const selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
        if (!selectedCallFrame)
          return false;
        const evaluationText = this._textEditor.line(editorLineNumber).substring(startHighlight, endHighlight + 1);
        const resolvedText = await Sources.SourceMapNamesResolver.resolveExpression(
            /** @type {!SDK.DebuggerModel.CallFrame} */ (selectedCallFrame), evaluationText, this._uiSourceCode,
            editorLineNumber, startHighlight, endHighlight);
        const result = await selectedCallFrame.evaluate({
          expression: resolvedText || evaluationText,
          objectGroup: 'popover',
          includeCommandLineAPI: false,
          silent: true,
          returnByValue: false,
          generatePreview: false
        });
        if (!result.object)
          return false;
        objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(result.object, popover);
        const potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
        if (!objectPopoverHelper || selectedCallFrame !== potentiallyUpdatedCallFrame) {
          debuggerModel.runtimeModel().releaseObjectGroup('popover');
          if (objectPopoverHelper)
            objectPopoverHelper.dispose();
          return false;
        }
        const highlightRange =
            new TextUtils.TextRange(editorLineNumber, startHighlight, editorLineNumber, endHighlight);
        highlightDescriptor = this._textEditor.highlightRange(highlightRange, 'source-frame-eval-expression');
        return true;
      },
      hide: () => {
        objectPopoverHelper.dispose();
        debuggerModel.runtimeModel().releaseObjectGroup('popover');
        this._textEditor.removeHighlight(highlightDescriptor);
      }
    };
  }

  /**
   * @param {!KeyboardEvent} event
   */
  _onKeyDown(event) {
    this._clearControlDown();

    if (event.key === 'Escape') {
      if (this._popoverHelper.isPopoverVisible()) {
        this._popoverHelper.hidePopover();
        event.consume();
      }
      return;
    }

    if (UI.shortcutRegistry.eventMatchesAction(event, 'debugger.toggle-breakpoint')) {
      const selection = this._textEditor.selection();
      if (!selection)
        return;
      this._toggleBreakpoint(selection.startLine, false);
      event.consume(true);
      return;
    }
    if (UI.shortcutRegistry.eventMatchesAction(event, 'debugger.toggle-breakpoint-enabled')) {
      const selection = this._textEditor.selection();
      if (!selection)
        return;
      this._toggleBreakpoint(selection.startLine, true);
      event.consume(true);
      return;
    }

    if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event) && this._executionLocation) {
      this._controlDown = true;
      if (event.key === (Host.isMac() ? 'Meta' : 'Control')) {
        this._controlTimeout = setTimeout(() => {
          if (this._executionLocation && this._controlDown)
            this._showContinueToLocations();
        }, 150);
      }
    }
  }

  /**
   * @param {!MouseEvent} event
   */
  _onMouseMove(event) {
    if (this._executionLocation && this._controlDown && UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
      if (!this._continueToLocationDecorations)
        this._showContinueToLocations();
    }
    if (this._continueToLocationDecorations) {
      const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
      const hovering = !!event.target.enclosingNodeOrSelfWithClass('source-frame-async-step-in');
      this._setAsyncStepInHoveredLine(textPosition ? textPosition.startLine : null, hovering);
    }
  }

  /**
   * @param {?number} editorLineNumber
   * @param {boolean} hovered
   */
  _setAsyncStepInHoveredLine(editorLineNumber, hovered) {
    if (this._asyncStepInHoveredLine === editorLineNumber && this._asyncStepInHovered === hovered)
      return;
    if (this._asyncStepInHovered && this._asyncStepInHoveredLine)
      this._textEditor.toggleLineClass(this._asyncStepInHoveredLine, 'source-frame-async-step-in-hovered', false);
    this._asyncStepInHoveredLine = editorLineNumber;
    this._asyncStepInHovered = hovered;
    if (this._asyncStepInHovered && this._asyncStepInHoveredLine)
      this._textEditor.toggleLineClass(this._asyncStepInHoveredLine, 'source-frame-async-step-in-hovered', true);
  }

  /**
   * @param {!MouseEvent} event
   */
  _onMouseDown(event) {
    if (!this._executionLocation || !UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
      return;
    if (!this._continueToLocationDecorations)
      return;
    event.consume();
    const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
    if (!textPosition)
      return;
    for (const decoration of this._continueToLocationDecorations.keys()) {
      const range = decoration.find();
      if (range.from.line !== textPosition.startLine || range.to.line !== textPosition.startLine)
        continue;
      if (range.from.ch <= textPosition.startColumn && textPosition.startColumn <= range.to.ch) {
        this._continueToLocationDecorations.get(decoration)();
        break;
      }
    }
  }

  /**
   * @param {!Event} event
   */
  _onBlur(event) {
    if (this._textEditor.element.isAncestor(/** @type {!Node} */ (event.target)))
      return;
    this._clearControlDown();
  }

  /**
   * @param {!KeyboardEvent} event
   */
  _onKeyUp(event) {
    this._clearControlDown();
  }

  _clearControlDown() {
    this._controlDown = false;
    this._clearContinueToLocations();
    clearTimeout(this._controlTimeout);
  }

  /**
   * @param {number} editorLineNumber
   * @param {?Bindings.BreakpointManager.Breakpoint} breakpoint
   * @param {?{lineNumber: number, columnNumber: number}} location
   */
  _editBreakpointCondition(editorLineNumber, breakpoint, location) {
    this._conditionElement = this._createConditionElement(editorLineNumber);
    this._textEditor.addDecoration(this._conditionElement, editorLineNumber);

    /**
     * @this {Sources.DebuggerPlugin}
     */
    function finishEditing(committed, element, newText) {
      this._textEditor.removeDecoration(/** @type {!Element} */ (this._conditionElement), editorLineNumber);
      this._conditionEditorElement = null;
      this._conditionElement = null;
      if (!committed)
        return;

      if (breakpoint)
        breakpoint.setCondition(newText);
      else if (location)
        this._setBreakpoint(location.lineNumber, location.columnNumber, newText, true);
      else
        this._createNewBreakpoint(editorLineNumber, newText, true);
    }

    const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
    UI.InplaceEditor.startEditing(/** @type {!Element} */ (this._conditionEditorElement), config);
    this._conditionEditorElement.value = breakpoint ? breakpoint.condition() : '';
    this._conditionEditorElement.select();
  }

  /**
   * @param {number} editorLineNumber
   * @return {!Element}
   */
  _createConditionElement(editorLineNumber) {
    const conditionElement = createElementWithClass('div', 'source-frame-breakpoint-condition');

    const labelElement = conditionElement.createChild('label', 'source-frame-breakpoint-message');
    labelElement.htmlFor = 'source-frame-breakpoint-condition';
    labelElement.createTextChild(
        Common.UIString('The breakpoint on line %d will stop only if this expression is true:', editorLineNumber + 1));

    const editorElement = UI.createInput('monospace', 'text');
    conditionElement.appendChild(editorElement);
    editorElement.id = 'source-frame-breakpoint-condition';
    this._conditionEditorElement = editorElement;

    return conditionElement;
  }

  /**
   * @param {!Bindings.LiveLocation} liveLocation
   */
  _executionLineChanged(liveLocation) {
    this._clearExecutionLine();
    const uiLocation = liveLocation.uiLocation();
    if (!uiLocation || uiLocation.uiSourceCode !== this._uiSourceCode) {
      this._executionLocation = null;
      return;
    }

    this._executionLocation = uiLocation;
    const editorLocation = this._transformer.rawToEditorLocation(uiLocation.lineNumber, uiLocation.columnNumber);
    this._textEditor.setExecutionLocation(editorLocation[0], editorLocation[1]);
    if (this._textEditor.isShowing()) {
      // We need SourcesTextEditor to be initialized prior to this call. @see crbug.com/506566
      setImmediate(() => {
        if (this._controlDown)
          this._showContinueToLocations();
        else
          this._generateValuesInSource();
      });
    }
  }

  _generateValuesInSource() {
    if (!Common.moduleSetting('inlineVariableValues').get())
      return;
    const executionContext = UI.context.flavor(SDK.ExecutionContext);
    if (!executionContext)
      return;
    const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
    if (!callFrame)
      return;

    const localScope = callFrame.localScope();
    const functionLocation = callFrame.functionLocation();
    if (localScope && functionLocation) {
      Sources.SourceMapNamesResolver.resolveScopeInObject(localScope)
          .getAllProperties(false, false, this._prepareScopeVariables.bind(this, callFrame));
    }

    if (this._clearValueWidgetsTimer) {
      clearTimeout(this._clearValueWidgetsTimer);
      this._clearValueWidgetsTimer = null;
    }
  }

  _showContinueToLocations() {
    this._popoverHelper.hidePopover();
    const executionContext = UI.context.flavor(SDK.ExecutionContext);
    if (!executionContext)
      return;
    const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
    if (!callFrame)
      return;
    const start = callFrame.functionLocation() || callFrame.location();
    const debuggerModel = callFrame.debuggerModel;
    debuggerModel.getPossibleBreakpoints(start, null, true)
        .then(locations => this._textEditor.operation(renderLocations.bind(this, locations)));

    /**
     * @param {!Array<!SDK.DebuggerModel.BreakLocation>} locations
     * @this {Sources.DebuggerPlugin}
     */
    function renderLocations(locations) {
      this._clearContinueToLocationsNoRestore();
      this._textEditor.hideExecutionLineBackground();
      this._clearValueWidgets();
      this._continueToLocationDecorations = new Map();
      locations = locations.reverse();
      let previousCallLine = -1;
      for (const location of locations) {
        const editorLocation = this._transformer.rawToEditorLocation(location.lineNumber, location.columnNumber);
        let token = this._textEditor.tokenAtTextPosition(editorLocation[0], editorLocation[1]);
        if (!token)
          continue;
        const line = this._textEditor.line(editorLocation[0]);
        let tokenContent = line.substring(token.startColumn, token.endColumn);
        if (!token.type && tokenContent === '.') {
          token = this._textEditor.tokenAtTextPosition(editorLocation[0], token.endColumn + 1);
          tokenContent = line.substring(token.startColumn, token.endColumn);
        }
        if (!token.type)
          continue;
        const validKeyword = token.type === 'js-keyword' &&
            (tokenContent === 'this' || tokenContent === 'return' || tokenContent === 'new' ||
             tokenContent === 'continue' || tokenContent === 'break');
        if (!validKeyword && !this._isIdentifier(token.type))
          continue;
        if (previousCallLine === editorLocation[0] && location.type !== Protocol.Debugger.BreakLocationType.Call)
          continue;

        let highlightRange =
            new TextUtils.TextRange(editorLocation[0], token.startColumn, editorLocation[0], token.endColumn - 1);
        let decoration = this._textEditor.highlightRange(highlightRange, 'source-frame-continue-to-location');
        this._continueToLocationDecorations.set(decoration, location.continueToLocation.bind(location));
        if (location.type === Protocol.Debugger.BreakLocationType.Call)
          previousCallLine = editorLocation[0];

        let isAsyncCall = (line[token.startColumn - 1] === '.' && tokenContent === 'then') ||
            tokenContent === 'setTimeout' || tokenContent === 'setInterval' || tokenContent === 'postMessage';
        if (tokenContent === 'new') {
          token = this._textEditor.tokenAtTextPosition(editorLocation[0], token.endColumn + 1);
          tokenContent = line.substring(token.startColumn, token.endColumn);
          isAsyncCall = tokenContent === 'Worker';
        }
        const isCurrentPosition = this._executionLocation &&
            location.lineNumber === this._executionLocation.lineNumber &&
            location.columnNumber === this._executionLocation.columnNumber;
        if (location.type === Protocol.Debugger.BreakLocationType.Call && isAsyncCall) {
          const asyncStepInRange =
              this._findAsyncStepInRange(this._textEditor, editorLocation[0], line, token.endColumn);
          if (asyncStepInRange) {
            highlightRange = new TextUtils.TextRange(
                editorLocation[0], asyncStepInRange.from, editorLocation[0], asyncStepInRange.to - 1);
            decoration = this._textEditor.highlightRange(highlightRange, 'source-frame-async-step-in');
            this._continueToLocationDecorations.set(
                decoration, this._asyncStepIn.bind(this, location, !!isCurrentPosition));
          }
        }
      }

      this._continueToLocationRenderedForTest();
    }
  }

  _continueToLocationRenderedForTest() {
  }

  /**
   * @param {!SourceFrame.SourcesTextEditor} textEditor
   * @param {number} editorLineNumber
   * @param {string} line
   * @param {number} column
   * @return {?{from: number, to: number}}
   */
  _findAsyncStepInRange(textEditor, editorLineNumber, line, column) {
    let token;
    let tokenText;
    let from = column;
    let to = line.length;

    let position = line.indexOf('(', column);
    const argumentsStart = position;
    if (position === -1)
      return null;
    position++;

    skipWhitespace();
    if (position >= line.length)
      return null;

    nextToken();
    if (!token)
      return null;
    from = token.startColumn;

    if (token.type === 'js-keyword' && tokenText === 'async') {
      skipWhitespace();
      if (position >= line.length)
        return {from: from, to: to};
      nextToken();
      if (!token)
        return {from: from, to: to};
    }

    if (token.type === 'js-keyword' && tokenText === 'function')
      return {from: from, to: to};

    if (token.type === 'js-string')
      return {from: argumentsStart, to: to};

    if (token.type && this._isIdentifier(token.type))
      return {from: from, to: to};

    if (tokenText !== '(')
      return null;
    const closeParen = line.indexOf(')', position);
    if (closeParen === -1 || line.substring(position, closeParen).indexOf('(') !== -1)
      return {from: from, to: to};
    return {from: from, to: closeParen + 1};

    function nextToken() {
      token = textEditor.tokenAtTextPosition(editorLineNumber, position);
      if (token) {
        position = token.endColumn;
        to = token.endColumn;
        tokenText = line.substring(token.startColumn, token.endColumn);
      }
    }

    function skipWhitespace() {
      while (position < line.length) {
        if (line[position] === ' ') {
          position++;
          continue;
        }
        const token = textEditor.tokenAtTextPosition(editorLineNumber, position);
        if (token.type === 'js-comment') {
          position = token.endColumn;
          continue;
        }
        break;
      }
    }
  }

  /**
   * @param {!SDK.DebuggerModel.BreakLocation} location
   * @param {boolean} isCurrentPosition
   */
  _asyncStepIn(location, isCurrentPosition) {
    if (!isCurrentPosition)
      location.continueToLocation(asyncStepIn);
    else
      asyncStepIn();

    function asyncStepIn() {
      location.debuggerModel.scheduleStepIntoAsync();
    }
  }

  /**
   * @param {!SDK.DebuggerModel.CallFrame} callFrame
   * @param {?Array.<!SDK.RemoteObjectProperty>} properties
   * @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
   */
  _prepareScopeVariables(callFrame, properties, internalProperties) {
    if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing()) {
      this._clearValueWidgets();
      return;
    }

    const functionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(
        /** @type {!SDK.DebuggerModel.Location} */ (callFrame.functionLocation()));
    const executionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(callFrame.location());
    if (!functionUILocation || !executionUILocation || functionUILocation.uiSourceCode !== this._uiSourceCode ||
        executionUILocation.uiSourceCode !== this._uiSourceCode) {
      this._clearValueWidgets();
      return;
    }

    const functionEditorLocation =
        this._transformer.rawToEditorLocation(functionUILocation.lineNumber, functionUILocation.columnNumber);
    const executionEditorLocation =
        this._transformer.rawToEditorLocation(executionUILocation.lineNumber, executionUILocation.columnNumber);
    const fromLine = functionEditorLocation[0];
    const fromColumn = functionEditorLocation[1];
    let toLine = executionEditorLocation[0];

    // Make sure we have a chance to update all existing widgets.
    if (this._valueWidgets) {
      for (const line of this._valueWidgets.keys())
        toLine = Math.max(toLine, line + 1);
    }
    if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount) {
      this._clearValueWidgets();
      return;
    }

    const valuesMap = new Map();
    for (const property of properties)
      valuesMap.set(property.name, property.value);

    /** @type {!Map.<number, !Set<string>>} */
    const namesPerLine = new Map();
    let skipObjectProperty = false;
    const tokenizer = new TextEditor.CodeMirrorUtils.TokenizerFactory().createTokenizer('text/javascript');
    tokenizer(this._textEditor.line(fromLine).substring(fromColumn), processToken.bind(this, fromLine));
    for (let i = fromLine + 1; i < toLine; ++i)
      tokenizer(this._textEditor.line(i), processToken.bind(this, i));

    /**
     * @param {number} editorLineNumber
     * @param {string} tokenValue
     * @param {?string} tokenType
     * @param {number} column
     * @param {number} newColumn
     * @this {Sources.DebuggerPlugin}
     */
    function processToken(editorLineNumber, tokenValue, tokenType, column, newColumn) {
      if (!skipObjectProperty && tokenType && this._isIdentifier(tokenType) && valuesMap.get(tokenValue)) {
        let names = namesPerLine.get(editorLineNumber);
        if (!names) {
          names = new Set();
          namesPerLine.set(editorLineNumber, names);
        }
        names.add(tokenValue);
      }
      skipObjectProperty = tokenValue === '.';
    }
    this._textEditor.operation(this._renderDecorations.bind(this, valuesMap, namesPerLine, fromLine, toLine));
  }

  /**
   * @param {!Map.<string,!SDK.RemoteObject>} valuesMap
   * @param {!Map.<number, !Set<string>>} namesPerLine
   * @param {number} fromLine
   * @param {number} toLine
   */
  _renderDecorations(valuesMap, namesPerLine, fromLine, toLine) {
    const formatter = new ObjectUI.RemoteObjectPreviewFormatter();
    for (let i = fromLine; i < toLine; ++i) {
      const names = namesPerLine.get(i);
      const oldWidget = this._valueWidgets.get(i);
      if (!names) {
        if (oldWidget) {
          this._valueWidgets.delete(i);
          this._textEditor.removeDecoration(oldWidget, i);
        }
        continue;
      }

      const widget = createElementWithClass('div', 'text-editor-value-decoration');
      const base = this._textEditor.cursorPositionToCoordinates(i, 0);
      const offset = this._textEditor.cursorPositionToCoordinates(i, this._textEditor.line(i).length);
      const codeMirrorLinesLeftPadding = 4;
      const left = offset.x - base.x + codeMirrorLinesLeftPadding;
      widget.style.left = left + 'px';
      widget.__nameToToken = new Map();

      let renderedNameCount = 0;
      for (const name of names) {
        if (renderedNameCount > 10)
          break;
        if (namesPerLine.get(i - 1) && namesPerLine.get(i - 1).has(name))
          continue;  // Only render name once in the given continuous block.
        if (renderedNameCount)
          widget.createTextChild(', ');
        const nameValuePair = widget.createChild('span');
        widget.__nameToToken.set(name, nameValuePair);
        nameValuePair.createTextChild(name + ' = ');
        const value = valuesMap.get(name);
        const propertyCount = value.preview ? value.preview.properties.length : 0;
        const entryCount = value.preview && value.preview.entries ? value.preview.entries.length : 0;
        if (value.preview && propertyCount + entryCount < 10) {
          formatter.appendObjectPreview(nameValuePair, value.preview, false /* isEntry */);
        } else {
          nameValuePair.appendChild(ObjectUI.ObjectPropertiesSection.createValueElement(
              value, false /* wasThrown */, false /* showPreview */));
        }
        ++renderedNameCount;
      }

      let widgetChanged = true;
      if (oldWidget) {
        widgetChanged = false;
        for (const name of widget.__nameToToken.keys()) {
          const oldText = oldWidget.__nameToToken.get(name) ? oldWidget.__nameToToken.get(name).textContent : '';
          const newText = widget.__nameToToken.get(name) ? widget.__nameToToken.get(name).textContent : '';
          if (newText !== oldText) {
            widgetChanged = true;
            // value has changed, update it.
            UI.runCSSAnimationOnce(
                /** @type {!Element} */ (widget.__nameToToken.get(name)), 'source-frame-value-update-highlight');
          }
        }
        if (widgetChanged) {
          this._valueWidgets.delete(i);
          this._textEditor.removeDecoration(oldWidget, i);
        }
      }
      if (widgetChanged) {
        this._valueWidgets.set(i, widget);
        this._textEditor.addDecoration(widget, i);
      }
    }
  }

  _clearExecutionLine() {
    this._textEditor.operation(() => {
      if (this._executionLocation)
        this._textEditor.clearExecutionLine();
      this._executionLocation = null;
      this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000);
      this._clearContinueToLocationsNoRestore();
    });
  }

  _clearValueWidgets() {
    clearTimeout(this._clearValueWidgetsTimer);
    this._clearValueWidgetsTimer = null;
    this._textEditor.operation(() => {
      for (const line of this._valueWidgets.keys())
        this._textEditor.removeDecoration(this._valueWidgets.get(line), line);
      this._valueWidgets.clear();
    });
  }

  _clearContinueToLocationsNoRestore() {
    if (!this._continueToLocationDecorations)
      return;
    this._textEditor.operation(() => {
      for (const decoration of this._continueToLocationDecorations.keys())
        this._textEditor.removeHighlight(decoration);
      this._continueToLocationDecorations = null;
      this._setAsyncStepInHoveredLine(null, false);
    });
  }

  _clearContinueToLocations() {
    if (!this._continueToLocationDecorations)
      return;
    this._textEditor.operation(() => {
      this._textEditor.showExecutionLineBackground();
      this._generateValuesInSource();
      this._clearContinueToLocationsNoRestore();
    });
  }

  /**
   * @param {number} lineNumber
   * @return {!Array<!Sources.DebuggerPlugin.BreakpointDecoration>}
   */
  _lineBreakpointDecorations(lineNumber) {
    return Array.from(this._breakpointDecorations)
        .filter(decoration => (decoration.handle.resolve() || {}).lineNumber === lineNumber);
  }

  /**
   * @param {number} editorLineNumber
   * @param {number} editorColumnNumber
   * @return {?Sources.DebuggerPlugin.BreakpointDecoration}
   */
  _breakpointDecoration(editorLineNumber, editorColumnNumber) {
    for (const decoration of this._breakpointDecorations) {
      const location = decoration.handle.resolve();
      if (!location)
        continue;
      if (location.lineNumber === editorLineNumber && location.columnNumber === editorColumnNumber)
        return decoration;
    }
    return null;
  }

  /**
   * @param {!Sources.DebuggerPlugin.BreakpointDecoration} decoration
   */
  _updateBreakpointDecoration(decoration) {
    if (!this._scheduledBreakpointDecorationUpdates) {
      /** @type {?Set<!Sources.DebuggerPlugin.BreakpointDecoration>} */
      this._scheduledBreakpointDecorationUpdates = new Set();
      setImmediate(() => this._textEditor.operation(update.bind(this)));
    }
    this._scheduledBreakpointDecorationUpdates.add(decoration);

    /**
     * @this {Sources.DebuggerPlugin}
     */
    function update() {
      if (!this._scheduledBreakpointDecorationUpdates)
        return;
      const editorLineNumbers = new Set();
      for (const decoration of this._scheduledBreakpointDecorationUpdates) {
        const location = decoration.handle.resolve();
        if (!location)
          continue;
        editorLineNumbers.add(location.lineNumber);
      }
      this._scheduledBreakpointDecorationUpdates = null;
      let waitingForInlineDecorations = false;
      for (const lineNumber of editorLineNumbers) {
        const decorations = this._lineBreakpointDecorations(lineNumber);
        updateGutter.call(this, lineNumber, decorations);
        if (this._possibleBreakpointsRequested.has(lineNumber)) {
          waitingForInlineDecorations = true;
          continue;
        }
        updateInlineDecorations.call(this, lineNumber, decorations);
      }
      if (!waitingForInlineDecorations)
        this._breakpointDecorationsUpdatedForTest();
    }

    /**
     * @param {number} editorLineNumber
     * @param {!Array<!Sources.DebuggerPlugin.BreakpointDecoration>} decorations
     * @this {Sources.DebuggerPlugin}
     */
    function updateGutter(editorLineNumber, decorations) {
      this._textEditor.toggleLineClass(editorLineNumber, 'cm-breakpoint', false);
      this._textEditor.toggleLineClass(editorLineNumber, 'cm-breakpoint-disabled', false);
      this._textEditor.toggleLineClass(editorLineNumber, 'cm-breakpoint-conditional', false);

      if (decorations.length) {
        decorations.sort(Sources.DebuggerPlugin.BreakpointDecoration.mostSpecificFirst);
        this._textEditor.toggleLineClass(editorLineNumber, 'cm-breakpoint', true);
        this._textEditor.toggleLineClass(
            editorLineNumber, 'cm-breakpoint-disabled', !decorations[0].enabled || this._muted);
        this._textEditor.toggleLineClass(editorLineNumber, 'cm-breakpoint-conditional', !!decorations[0].condition);
      }
    }

    /**
     * @param {number} editorLineNumber
     * @param {!Array<!Sources.DebuggerPlugin.BreakpointDecoration>} decorations
     * @this {Sources.DebuggerPlugin}
     */
    function updateInlineDecorations(editorLineNumber, decorations) {
      const actualBookmarks =
          new Set(decorations.map(decoration => decoration.bookmark).filter(bookmark => !!bookmark));
      const lineEnd = this._textEditor.line(editorLineNumber).length;
      const bookmarks = this._textEditor.bookmarks(
          new TextUtils.TextRange(editorLineNumber, 0, editorLineNumber, lineEnd),
          Sources.DebuggerPlugin.BreakpointDecoration.bookmarkSymbol);
      for (const bookmark of bookmarks) {
        if (!actualBookmarks.has(bookmark))
          bookmark.clear();
      }
      if (!decorations.length)
        return;
      if (decorations.length > 1) {
        for (const decoration of decorations) {
          decoration.update();
          if (!this._muted)
            decoration.show();
          else
            decoration.hide();
        }
      } else {
        decorations[0].update();
        decorations[0].hide();
      }
    }
  }

  _breakpointDecorationsUpdatedForTest() {
  }

  /**
   * @param {!Sources.DebuggerPlugin.BreakpointDecoration} decoration
   * @param {!Event} event
   */
  _inlineBreakpointClick(decoration, event) {
    event.consume(true);
    if (decoration.breakpoint) {
      if (event.shiftKey)
        decoration.breakpoint.setEnabled(!decoration.breakpoint.enabled());
      else
        decoration.breakpoint.remove();
    } else {
      const editorLocation = decoration.handle.resolve();
      if (!editorLocation)
        return;
      const location = this._transformer.editorToRawLocation(editorLocation.lineNumber, editorLocation.columnNumber);
      this._setBreakpoint(location[0], location[1], decoration.condition, true);
    }
  }

  /**
   * @param {!Sources.DebuggerPlugin.BreakpointDecoration} decoration
   * @param {!Event} event
   */
  _inlineBreakpointContextMenu(decoration, event) {
    event.consume(true);
    const editorLocation = decoration.handle.resolve();
    if (!editorLocation)
      return;
    const location = this._transformer.editorToRawLocation(editorLocation[0], editorLocation[1]);
    const contextMenu = new UI.ContextMenu(event);
    if (decoration.breakpoint) {
      contextMenu.debugSection().appendItem(
          Common.UIString('Edit breakpoint\u2026'),
          this._editBreakpointCondition.bind(this, editorLocation.lineNumber, decoration.breakpoint, null));
    } else {
      contextMenu.debugSection().appendItem(
          Common.UIString('Add conditional breakpoint\u2026'),
          this._editBreakpointCondition.bind(this, editorLocation.lineNumber, null, editorLocation));
      contextMenu.debugSection().appendItem(
          Common.UIString('Never pause here'), this._setBreakpoint.bind(this, location[0], location[1], 'false', true));
    }
    contextMenu.show();
  }

  /**
   * @param {!Common.Event} event
   * @return {boolean}
   */
  _shouldIgnoreExternalBreakpointEvents(event) {
    const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
    if (uiLocation.uiSourceCode !== this._uiSourceCode)
      return true;
    if (this._supportsEnabledBreakpointsWhileEditing())
      return false;
    if (this._muted)
      return true;
    const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
    for (let i = 0; i < scriptFiles.length; ++i) {
      if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM())
        return true;
    }
    return false;
  }

  /**
   * @param {!Common.Event} event
   */
  _breakpointAdded(event) {
    if (this._shouldIgnoreExternalBreakpointEvents(event))
      return;
    const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
    const breakpoint = /** @type {!Bindings.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
    this._addBreakpoint(uiLocation, breakpoint);
  }

  /**
   * @param {!Workspace.UILocation} uiLocation
   * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
   */
  _addBreakpoint(uiLocation, breakpoint) {
    const editorLocation = this._transformer.rawToEditorLocation(uiLocation.lineNumber, uiLocation.columnNumber);
    const lineDecorations = this._lineBreakpointDecorations(uiLocation.lineNumber);
    let decoration = this._breakpointDecoration(editorLocation[0], editorLocation[1]);
    if (decoration) {
      decoration.breakpoint = breakpoint;
      decoration.condition = breakpoint.condition();
      decoration.enabled = breakpoint.enabled();
    } else {
      const handle = this._textEditor.textEditorPositionHandle(editorLocation[0], editorLocation[1]);
      decoration = new Sources.DebuggerPlugin.BreakpointDecoration(
          this._textEditor, handle, breakpoint.condition(), breakpoint.enabled(), breakpoint);
      decoration.element.addEventListener('click', this._inlineBreakpointClick.bind(this, decoration), true);
      decoration.element.addEventListener(
          'contextmenu', this._inlineBreakpointContextMenu.bind(this, decoration), true);
      this._breakpointDecorations.add(decoration);
    }
    this._decorationByBreakpoint.set(breakpoint, decoration);
    this._updateBreakpointDecoration(decoration);
    if (breakpoint.enabled() && !lineDecorations.length) {
      this._possibleBreakpointsRequested.add(editorLocation[0]);
      const start = this._transformer.editorToRawLocation(editorLocation[0], 0);
      const end = this._transformer.editorToRawLocation(editorLocation[0] + 1, 0);
      this._breakpointManager
          .possibleBreakpoints(this._uiSourceCode, new TextUtils.TextRange(start[0], start[1], end[0], end[1]))
          .then(addInlineDecorations.bind(this, editorLocation[0]));
    }

    /**
     * @this {Sources.DebuggerPlugin}
     * @param {number} editorLineNumber
     * @param {!Array<!Workspace.UILocation>} possibleLocations
     */
    function addInlineDecorations(editorLineNumber, possibleLocations) {
      this._possibleBreakpointsRequested.delete(editorLineNumber);
      const decorations = this._lineBreakpointDecorations(editorLineNumber);
      for (const decoration of decorations)
        this._updateBreakpointDecoration(decoration);
      if (!decorations.some(decoration => !!decoration.breakpoint))
        return;
      /** @type {!Set<number>} */
      const columns = new Set();
      for (const decoration of decorations) {
        const editorLocation = decoration.handle.resolve();
        if (!editorLocation)
          continue;
        columns.add(editorLocation.columnNumber);
      }
      for (const location of possibleLocations) {
        const editorLocation = this._transformer.rawToEditorLocation(location.lineNumber, location.columnNumber);
        if (columns.has(editorLocation[1]))
          continue;
        const handle = this._textEditor.textEditorPositionHandle(editorLocation[0], editorLocation[1]);
        const decoration = new Sources.DebuggerPlugin.BreakpointDecoration(this._textEditor, handle, '', false, null);
        decoration.element.addEventListener('click', this._inlineBreakpointClick.bind(this, decoration), true);
        decoration.element.addEventListener(
            'contextmenu', this._inlineBreakpointContextMenu.bind(this, decoration), true);
        this._breakpointDecorations.add(decoration);
        this._updateBreakpointDecoration(decoration);
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _breakpointRemoved(event) {
    if (this._shouldIgnoreExternalBreakpointEvents(event))
      return;
    const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
    const breakpoint = /** @type {!Bindings.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
    const decoration = this._decorationByBreakpoint.get(breakpoint);
    if (!decoration)
      return;
    this._decorationByBreakpoint.delete(breakpoint);

    const editorLocation = this._transformer.rawToEditorLocation(uiLocation.lineNumber, uiLocation.columnNumber);
    decoration.breakpoint = null;
    decoration.enabled = false;

    const lineDecorations = this._lineBreakpointDecorations(editorLocation[0]);
    if (!lineDecorations.some(decoration => !!decoration.breakpoint)) {
      for (const lineDecoration of lineDecorations) {
        this._breakpointDecorations.delete(lineDecoration);
        this._updateBreakpointDecoration(lineDecoration);
      }
    } else {
      this._updateBreakpointDecoration(decoration);
    }
  }

  _initializeBreakpoints() {
    const breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode);
    for (const breakpointLocation of breakpointLocations)
      this._addBreakpoint(breakpointLocation.uiLocation, breakpointLocation.breakpoint);
  }

  _updateLinesWithoutMappingHighlight() {
    const isSourceMapSource = !!Bindings.CompilerScriptMapping.uiSourceCodeOrigin(this._uiSourceCode);
    if (!isSourceMapSource)
      return;
    const linesCount = this._textEditor.linesCount;
    for (let i = 0; i < linesCount; ++i) {
      const lineHasMapping = Bindings.CompilerScriptMapping.uiLineHasMapping(this._uiSourceCode, i);
      if (!lineHasMapping)
        this._hasLineWithoutMapping = true;
      if (this._hasLineWithoutMapping)
        this._textEditor.toggleLineClass(i, 'cm-line-without-source-mapping', !lineHasMapping);
    }
  }

  _updateScriptFiles() {
    for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)) {
      const scriptFile = Bindings.debuggerWorkspaceBinding.scriptFile(this._uiSourceCode, debuggerModel);
      if (scriptFile)
        this._updateScriptFile(debuggerModel);
    }
  }

  /**
   * @param {!SDK.DebuggerModel} debuggerModel
   */
  _updateScriptFile(debuggerModel) {
    const oldScriptFile = this._scriptFileForDebuggerModel.get(debuggerModel);
    const newScriptFile = Bindings.debuggerWorkspaceBinding.scriptFile(this._uiSourceCode, debuggerModel);
    this._scriptFileForDebuggerModel.delete(debuggerModel);
    if (oldScriptFile) {
      oldScriptFile.removeEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
      oldScriptFile.removeEventListener(
          Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
      if (this._muted && !this._uiSourceCode.isDirty())
        this._restoreBreakpointsIfConsistentScripts();
    }
    if (!newScriptFile)
      return;
    this._scriptFileForDebuggerModel.set(debuggerModel, newScriptFile);
    newScriptFile.addEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
    newScriptFile.addEventListener(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
    newScriptFile.checkMapping();
    if (newScriptFile.hasSourceMapURL())
      this._showSourceMapInfobar();
  }

  _showSourceMapInfobar() {
    if (this._sourceMapInfobar)
      return;
    this._sourceMapInfobar = UI.Infobar.create(
        UI.Infobar.Type.Info, Common.UIString('Source Map detected.'),
        Common.settings.createSetting('sourceMapInfobarDisabled', false));
    if (!this._sourceMapInfobar)
      return;
    this._sourceMapInfobar.createDetailsRowMessage(Common.UIString(
        'Associated files should be added to the file tree. You can debug these resolved source files as regular JavaScript files.'));
    this._sourceMapInfobar.createDetailsRowMessage(Common.UIString(
        'Associated files are available via file tree or %s.',
        UI.shortcutRegistry.shortcutTitleForAction('quickOpen.show')));
    this._sourceMapInfobar.setCloseCallback(() => this._sourceMapInfobar = null);
    this._textEditor.attachInfobar(this._sourceMapInfobar);
  }

  _detectMinified() {
    const content = this._uiSourceCode.content();
    if (!content || !TextUtils.isMinified(content))
      return;

    this._prettyPrintInfobar = UI.Infobar.create(
        UI.Infobar.Type.Info, Common.UIString('Pretty-print this minified file?'),
        Common.settings.createSetting('prettyPrintInfobarDisabled', false));
    if (!this._prettyPrintInfobar)
      return;

    this._prettyPrintInfobar.setCloseCallback(() => this._prettyPrintInfobar = null);
    const toolbar = new UI.Toolbar('');
    const button = new UI.ToolbarButton('', 'largeicon-pretty-print');
    toolbar.appendToolbarItem(button);
    toolbar.element.style.display = 'inline-block';
    toolbar.element.style.verticalAlign = 'middle';
    toolbar.element.style.marginBottom = '3px';
    toolbar.element.style.pointerEvents = 'none';
    const element = this._prettyPrintInfobar.createDetailsRowMessage();
    element.appendChild(UI.formatLocalized(
        'You can click the %s button on the bottom status bar, and continue debugging with the new formatted source.',
        [toolbar.element]));
    this._textEditor.attachInfobar(this._prettyPrintInfobar);
  }

  /**
   * @param {!Common.Event} event
   */
  _handleGutterClick(event) {
    if (this._muted)
      return;

    const eventData = /** @type {!SourceFrame.SourcesTextEditor.GutterClickEventData} */ (event.data);
    const editorLineNumber = eventData.lineNumber;
    const eventObject = eventData.event;

    if (eventObject.button !== 0 || eventObject.altKey || eventObject.ctrlKey || eventObject.metaKey)
      return;

    this._toggleBreakpoint(editorLineNumber, eventObject.shiftKey);
    eventObject.consume(true);
  }

  /**
   * @param {number} editorLineNumber
   * @param {boolean} onlyDisable
   */
  _toggleBreakpoint(editorLineNumber, onlyDisable) {
    const decorations = this._lineBreakpointDecorations(editorLineNumber);
    if (!decorations.length) {
      this._createNewBreakpoint(editorLineNumber, '', true);
      return;
    }
    const hasDisabled = this._textEditor.hasLineClass(editorLineNumber, 'cm-breakpoint-disabled');
    const breakpoints = decorations.map(decoration => decoration.breakpoint).filter(breakpoint => !!breakpoint);
    for (const breakpoint of breakpoints) {
      if (onlyDisable)
        breakpoint.setEnabled(hasDisabled);
      else
        breakpoint.remove();
    }
  }

  /**
   * @param {number} editorLineNumber
   * @param {string} condition
   * @param {boolean} enabled
   */
  async _createNewBreakpoint(editorLineNumber, condition, enabled) {
    Host.userMetrics.actionTaken(Host.UserMetrics.Action.ScriptsBreakpointSet);
    if (editorLineNumber < this._textEditor.linesCount) {
      const lineLength = Math.min(this._textEditor.line(editorLineNumber).length, 1024);
      const start = this._transformer.editorToRawLocation(editorLineNumber, 0);
      const end = this._transformer.editorToRawLocation(editorLineNumber, lineLength);
      const locations = await this._breakpointManager.possibleBreakpoints(
          this._uiSourceCode, new TextUtils.TextRange(start[0], start[1], end[0], end[1]));
      if (locations && locations.length) {
        this._setBreakpoint(locations[0].lineNumber, locations[0].columnNumber, condition, enabled);
        return;
      }
    }
    const origin = this._transformer.editorToRawLocation(editorLineNumber, 0);
    await this._setBreakpoint(origin[0], origin[1], condition, enabled);
  }

  /**
   * @param {boolean} onlyDisable
   */
  toggleBreakpointOnCurrentLine(onlyDisable) {
    if (this._muted)
      return;

    const selection = this._textEditor.selection();
    if (!selection)
      return;
    this._toggleBreakpoint(selection.startLine, onlyDisable);
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @param {string} condition
   * @param {boolean} enabled
   */
  _setBreakpoint(lineNumber, columnNumber, condition, enabled) {
    if (!Bindings.CompilerScriptMapping.uiLineHasMapping(this._uiSourceCode, lineNumber))
      return;

    Common.moduleSetting('breakpointsActive').set(true);
    this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, columnNumber, condition, enabled);
    this._breakpointWasSetForTest(lineNumber, columnNumber, condition, enabled);
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @param {string} condition
   * @param {boolean} enabled
   */
  _breakpointWasSetForTest(lineNumber, columnNumber, condition, enabled) {
  }


  _callFrameChanged() {
    this._liveLocationPool.disposeAll();
    const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
    if (!callFrame) {
      this._clearExecutionLine();
      return;
    }
    Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(
        callFrame.location(), this._executionLineChanged.bind(this), this._liveLocationPool);
  }

  /**
   * @override
   */
  dispose() {
    for (const decoration of this._breakpointDecorations)
      decoration.dispose();
    this._breakpointDecorations.clear();
    if (this._scheduledBreakpointDecorationUpdates) {
      for (const decoration of this._scheduledBreakpointDecorationUpdates)
        decoration.dispose();
      this._scheduledBreakpointDecorationUpdates.clear();
    }

    this._hideBlackboxInfobar();
    if (this._sourceMapInfobar)
      this._sourceMapInfobar.dispose();
    if (this._prettyPrintInfobar)
      this._prettyPrintInfobar.dispose();
    this._scriptsPanel.element.removeEventListener('scroll', this._boundPopoverHelperHide, true);
    for (const script of this._scriptFileForDebuggerModel.values()) {
      script.removeEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
      script.removeEventListener(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
    }
    this._scriptFileForDebuggerModel.clear();


    this._textEditor.element.removeEventListener('keydown', this._boundKeyDown, true);
    this._textEditor.element.removeEventListener('keyup', this._boundKeyUp, true);
    this._textEditor.element.removeEventListener('mousemove', this._boundMouseMove, false);
    this._textEditor.element.removeEventListener('mousedown', this._boundMouseDown, true);
    this._textEditor.element.removeEventListener('focusout', this._boundBlur, false);
    this._textEditor.element.removeEventListener('wheel', this._boundWheel, true);

    this._textEditor.removeEventListener(
        SourceFrame.SourcesTextEditor.Events.GutterClick, this._handleGutterClick, this);
    this._popoverHelper.hidePopover();
    this._popoverHelper.dispose();

    this._breakpointManager.removeEventListener(
        Bindings.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
    this._breakpointManager.removeEventListener(
        Bindings.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
    this._uiSourceCode.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
    this._uiSourceCode.removeEventListener(
        Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);

    Common.moduleSetting('skipStackFramesPattern').removeChangeListener(this._showBlackboxInfobarIfNeeded, this);
    Common.moduleSetting('skipContentScripts').removeChangeListener(this._showBlackboxInfobarIfNeeded, this);
    super.dispose();

    this._clearExecutionLine();
    UI.context.removeFlavorChangeListener(SDK.DebuggerModel.CallFrame, this._callFrameChanged, this);
    this._liveLocationPool.disposeAll();
  }
};

/**
 * @unrestricted
 */
Sources.DebuggerPlugin.BreakpointDecoration = class {
  /**
   * @param {!TextEditor.CodeMirrorTextEditor} textEditor
   * @param {!TextEditor.TextEditorPositionHandle} handle
   * @param {string} condition
   * @param {boolean} enabled
   * @param {?Bindings.BreakpointManager.Breakpoint} breakpoint
   */
  constructor(textEditor, handle, condition, enabled, breakpoint) {
    this._textEditor = textEditor;
    this.handle = handle;
    this.condition = condition;
    this.enabled = enabled;
    this.breakpoint = breakpoint;
    this.element = UI.Icon.create('smallicon-inline-breakpoint');
    this.element.classList.toggle('cm-inline-breakpoint', true);

    /** @type {?TextEditor.TextEditorBookMark} */
    this.bookmark = null;
  }

  /**
   * @param {!Sources.DebuggerPlugin.BreakpointDecoration} decoration1
   * @param {!Sources.DebuggerPlugin.BreakpointDecoration} decoration2
   * @return {number}
   */
  static mostSpecificFirst(decoration1, decoration2) {
    if (decoration1.enabled !== decoration2.enabled)
      return decoration1.enabled ? -1 : 1;
    if (!!decoration1.condition !== !!decoration2.condition)
      return !!decoration1.condition ? -1 : 1;
    return 0;
  }

  update() {
    if (!this.condition)
      this.element.setIconType('smallicon-inline-breakpoint');
    else
      this.element.setIconType('smallicon-inline-breakpoint-conditional');
    this.element.classList.toggle('cm-inline-disabled', !this.enabled);
  }

  show() {
    if (this.bookmark)
      return;
    const editorLocation = this.handle.resolve();
    if (!editorLocation)
      return;
    this.bookmark = this._textEditor.addBookmark(
        editorLocation.lineNumber, editorLocation.columnNumber, this.element,
        Sources.DebuggerPlugin.BreakpointDecoration.bookmarkSymbol);
    this.bookmark[Sources.DebuggerPlugin.BreakpointDecoration._elementSymbolForTest] = this.element;
  }

  hide() {
    if (!this.bookmark)
      return;
    this.bookmark.clear();
    this.bookmark = null;
  }

  dispose() {
    const location = this.handle.resolve();
    if (location) {
      this._textEditor.toggleLineClass(location.lineNumber, 'cm-breakpoint', false);
      this._textEditor.toggleLineClass(location.lineNumber, 'cm-breakpoint-disabled', false);
      this._textEditor.toggleLineClass(location.lineNumber, 'cm-breakpoint-conditional', false);
    }
    this.hide();
  }
};

Sources.DebuggerPlugin.BreakpointDecoration.bookmarkSymbol = Symbol('bookmark');
Sources.DebuggerPlugin.BreakpointDecoration._elementSymbolForTest = Symbol('element');

Sources.DebuggerPlugin.continueToLocationDecorationSymbol = Symbol('bookmark');
