/*
 * 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 {?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 (this._executionLocation && 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._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 (!Root.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();
  }

  _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(
            ls`Add logpoint\u2026`,
            this._editBreakpointCondition.bind(this, editorLineNumber, null, null, true /* preferLogpoint */));
        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) {
      const dialog = new Sources.AddSourceMapURLDialog(addSourceMapURLDialogCallback.bind(null, scriptFile));
      dialog.show();
    }

    /**
     * @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._scriptFileForDebuggerModel.size) {
      return;
    }

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

  /**
   * @param {!Common.Event} event
   */
  _workingCopyCommitted(event) {
    this._scriptsPanel.updateLastModificationTime();
    if (!this._scriptFileForDebuggerModel.size) {
      this._restoreBreakpointsAfterEditing();
    }
  }

  _didMergeToVM() {
    this._restoreBreakpointsIfConsistentScripts();
  }

  _didDivergeFromVM() {
    this._muteBreakpointsWhileEditing();
  }

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

  _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;

    const selectedCallFrame =
        /** @type {!SDK.DebuggerModel.CallFrame} */ (UI.context.flavor(SDK.DebuggerModel.CallFrame));
    if (!selectedCallFrame) {
      return null;
    }

    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;
        }
        if (tokenBefore.type === 'js-meta') {
          break;
        }
        if (tokenBefore.type === 'js-string-2') {
          // If we hit a template literal, find the opening ` in this line.
          // TODO(bmeurer): We should eventually replace this tokenization
          // approach with a proper soluation based on parsing, maybe reusing
          // the Parser and AST inside V8 for this (or potentially relying on
          // acorn to do the job).
          if (tokenBefore.endColumn < 2) {
            return null;
          }
          startHighlight = line.lastIndexOf('`', tokenBefore.endColumn - 2);
          if (startHighlight < 0) {
            return null;
          }
          break;
        }
        startHighlight = tokenBefore.startColumn;
      }
    }

    // The eager evaluation on works sort of reliably within the top-most scope of
    // the selected call frame, so don't even try outside the top-most scope.
    const [scope] = selectedCallFrame.scopeChain();
    const scopeStartLocation = scope && scope.startLocation();
    const scopeEndLocation = scope && scope.endLocation();

    if (scopeStartLocation && scopeEndLocation) {
      let {lineNumber: scopeStartLineNumber, columnNumber: scopeStartColNumber} = scopeStartLocation;
      let {lineNumber: scopeEndLineNumber, columnNumber: scopeEndColNumber} = scopeEndLocation;

      const scopeUIStartLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(scopeStartLocation);
      const scopeUIEndLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(scopeEndLocation);

      if (scopeUIStartLocation && scopeUIEndLocation) {
        ({lineNumber: scopeStartLineNumber, columnNumber: scopeStartColNumber} = scopeUIStartLocation);
        ({lineNumber: scopeEndLineNumber, columnNumber: scopeEndColNumber} = scopeUIEndLocation);
      }

      if (editorLineNumber < scopeStartLineNumber) {
        return null;
      }
      if (editorLineNumber === scopeStartLineNumber && startHighlight < scopeStartColNumber) {
        return null;
      }
      if (editorLineNumber > scopeEndLineNumber) {
        return null;
      }
      if (editorLineNumber === scopeEndLineNumber && endHighlight > scopeEndColNumber) {
        return null;
      }
    }

    let objectPopoverHelper;
    let highlightDescriptor;

    return {
      box: anchorBox,
      show: async popover => {
        const evaluationText = this._textEditor.line(editorLineNumber).substring(startHighlight, endHighlight + 1);
        const resolvedText = await Sources.SourceMapNamesResolver.resolveExpression(
            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 || (result.object.type === 'object' && result.object.subtype === 'error')) {
          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.shortcutRegistry.eventMatchesAction(event, 'debugger.breakpoint-input-window')) {
      const selection = this._textEditor.selection();
      if (!selection) {
        return;
      }
      const breakpoints = this._lineBreakpointDecorations(selection.startLine)
                              .map(decoration => decoration.breakpoint)
                              .filter(breakpoint => !!breakpoint);
      let breakpoint;
      if (breakpoints.length) {
        breakpoint = breakpoints[0];
      }
      const isLogpoint =
          breakpoint ? breakpoint.condition().includes(Sources.BreakpointEditDialog.LogpointPrefix) : false;
      this._editBreakpointCondition(selection.startLine, breakpoint, null, isLogpoint);
      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
   * @param {boolean=} preferLogpoint
   */
  async _editBreakpointCondition(editorLineNumber, breakpoint, location, preferLogpoint) {
    const oldCondition = breakpoint ? breakpoint.condition() : '';
    const decorationElement = createElement('div');
    const dialog = new Sources.BreakpointEditDialog(editorLineNumber, oldCondition, !!preferLogpoint, result => {
      dialog.detach();
      this._textEditor.removeDecoration(decorationElement, editorLineNumber);
      if (!result.committed) {
        return;
      }
      if (breakpoint) {
        breakpoint.setCondition(result.condition);
      } else if (location) {
        this._setBreakpoint(location.lineNumber, location.columnNumber, result.condition, true);
      } else {
        this._createNewBreakpoint(editorLineNumber, result.condition, true);
      }
    });
    this._textEditor.addDecoration(decorationElement, editorLineNumber);
    dialog.markAsExternallyManaged();
    dialog.show(decorationElement);
  }

  /**
   * @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)
          .then(this._prepareScopeVariables.bind(this, callFrame));
    }
  }

  _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 {!SDK.GetPropertiesResult} allProperties
   */
  _prepareScopeVariables(callFrame, allProperties) {
    const properties = allProperties.properties;
    this._clearValueWidgets();
    if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing()) {
      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) {
      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];
    const toLine = executionEditorLocation[0];
    if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount) {
      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;
      if (this._clearValueWidgetsTimer) {
        clearTimeout(this._clearValueWidgetsTimer);
        this._clearValueWidgetsTimer = 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(
          ls`Add logpoint\u2026`,
          this._editBreakpointCondition.bind(
              this, editorLocation.lineNumber, null, editorLocation, true /* preferLogpoint */));
      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._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';
    toolbar.element.tabIndex = -1;
    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);
    if (eventData.gutterType !== SourceFrame.SourcesTextEditor.lineNumbersGutterType) {
      return;
    }
    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');
