/*
 * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "web/ContextMenuClientImpl.h"

#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/CSSPropertyNames.h"
#include "core/HTMLNames.h"
#include "core/InputTypeNames.h"
#include "core/css/CSSStyleDeclaration.h"
#include "core/dom/Document.h"
#include "core/editing/Editor.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/html/MediaError.h"
#include "core/input/EventHandler.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutPart.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/HistoryItem.h"
#include "core/page/ContextMenuController.h"
#include "core/page/Page.h"
#include "platform/ContextMenu.h"
#include "platform/Widget.h"
#include "platform/exported/WrappedResourceResponse.h"
#include "platform/text/TextBreakIterator.h"
#include "platform/weborigin/KURL.h"
#include "public/platform/WebPoint.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLResponse.h"
#include "public/platform/WebVector.h"
#include "public/web/WebContextMenuData.h"
#include "public/web/WebFormElement.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebMenuItemInfo.h"
#include "public/web/WebPlugin.h"
#include "public/web/WebSearchableFormData.h"
#include "public/web/WebSpellCheckClient.h"
#include "public/web/WebViewClient.h"
#include "web/ContextMenuAllowedScope.h"
#include "web/WebDataSourceImpl.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WebPluginContainerImpl.h"
#include "web/WebViewImpl.h"
#include "wtf/text/WTFString.h"

namespace blink {

// Figure out the URL of a page or subframe. Returns |page_type| as the type,
// which indicates page or subframe, or ContextNodeType::kNone if the URL could
// not be determined for some reason.
static WebURL urlFromFrame(LocalFrame* frame) {
  if (frame) {
    DocumentLoader* dl = frame->loader().documentLoader();
    if (dl) {
      WebDataSource* ds = WebDataSourceImpl::fromDocumentLoader(dl);
      if (ds)
        return ds->hasUnreachableURL() ? ds->unreachableURL()
                                       : ds->request().url();
    }
  }
  return WebURL();
}

static bool IsWhiteSpaceOrPunctuation(UChar c) {
  return isSpaceOrNewline(c) || WTF::Unicode::isPunct(c);
}

static String selectMisspellingAsync(LocalFrame* selectedFrame,
                                     String& description,
                                     uint32_t& hash) {
  VisibleSelection selection = selectedFrame->selection().selection();
  if (selection.isNone())
    return String();

  // Caret and range selections always return valid normalized ranges.
  Range* selectionRange = createRange(selection.toNormalizedEphemeralRange());
  DocumentMarkerVector markers =
      selectedFrame->document()->markers().markersInRange(
          EphemeralRange(selectionRange), DocumentMarker::MisspellingMarkers());
  if (markers.size() != 1)
    return String();
  description = markers[0]->description();
  hash = markers[0]->hash();

  // Cloning a range fails only for invalid ranges.
  Range* markerRange = selectionRange->cloneRange();
  markerRange->setStart(markerRange->startContainer(),
                        markers[0]->startOffset());
  markerRange->setEnd(markerRange->endContainer(), markers[0]->endOffset());

  if (markerRange->text().stripWhiteSpace(&IsWhiteSpaceOrPunctuation) !=
      selectionRange->text().stripWhiteSpace(&IsWhiteSpaceOrPunctuation))
    return String();

  return markerRange->text();
}

bool ContextMenuClientImpl::shouldShowContextMenuFromTouch(
    const WebContextMenuData& data) {
  return m_webView->page()->settings().alwaysShowContextMenuOnTouch() ||
         !data.linkURL.isEmpty() ||
         data.mediaType == WebContextMenuData::MediaTypeImage ||
         data.mediaType == WebContextMenuData::MediaTypeVideo ||
         data.isEditable;
}

bool ContextMenuClientImpl::showContextMenu(const ContextMenu* defaultMenu,
                                            bool fromTouch) {
  // Displaying the context menu in this function is a big hack as we don't
  // have context, i.e. whether this is being invoked via a script or in
  // response to user input (Mouse event WM_RBUTTONDOWN,
  // Keyboard events KeyVK_APPS, Shift+F10). Check if this is being invoked
  // in response to the above input events before popping up the context menu.
  if (!ContextMenuAllowedScope::isContextMenuAllowed())
    return false;

  HitTestResult r = m_webView->page()->contextMenuController().hitTestResult();

  r.setToShadowHostIfInUserAgentShadowRoot();

  LocalFrame* selectedFrame = r.innerNodeFrame();

  WebContextMenuData data;
  data.mousePosition = selectedFrame->view()->contentsToViewport(
      r.roundedPointInInnerNodeFrame());

  // Compute edit flags.
  data.editFlags = WebContextMenuData::CanDoNone;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canUndo())
    data.editFlags |= WebContextMenuData::CanUndo;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canRedo())
    data.editFlags |= WebContextMenuData::CanRedo;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canCut())
    data.editFlags |= WebContextMenuData::CanCut;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canCopy())
    data.editFlags |= WebContextMenuData::CanCopy;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canPaste())
    data.editFlags |= WebContextMenuData::CanPaste;
  if (toLocalFrame(m_webView->focusedCoreFrame())->editor().canDelete())
    data.editFlags |= WebContextMenuData::CanDelete;
  // We can always select all...
  data.editFlags |= WebContextMenuData::CanSelectAll;
  data.editFlags |= WebContextMenuData::CanTranslate;

  // Links, Images, Media tags, and Image/Media-Links take preference over
  // all else.
  data.linkURL = r.absoluteLinkURL();

  if (r.innerNode()->isHTMLElement()) {
    HTMLElement* htmlElement = toHTMLElement(r.innerNode());
    if (!htmlElement->title().isEmpty()) {
      data.titleText = htmlElement->title();
    } else {
      data.titleText = htmlElement->altText();
    }
  }

  if (isHTMLCanvasElement(r.innerNode())) {
    data.mediaType = WebContextMenuData::MediaTypeCanvas;
    data.hasImageContents = true;
  } else if (!r.absoluteImageURL().isEmpty()) {
    data.srcURL = r.absoluteImageURL();
    data.mediaType = WebContextMenuData::MediaTypeImage;
    data.mediaFlags |= WebContextMenuData::MediaCanPrint;

    // An image can be null for many reasons, like being blocked, no image
    // data received from server yet.
    data.hasImageContents = r.image() && !r.image()->isNull();
    if (data.hasImageContents &&
        isHTMLImageElement(r.innerNodeOrImageMapImage())) {
      HTMLImageElement* imageElement =
          toHTMLImageElement(r.innerNodeOrImageMapImage());
      if (imageElement && imageElement->cachedImage())
        data.imageResponse =
            WrappedResourceResponse(imageElement->cachedImage()->response());
    }
  } else if (!r.absoluteMediaURL().isEmpty()) {
    data.srcURL = r.absoluteMediaURL();

    // We know that if absoluteMediaURL() is not empty, then this
    // is a media element.
    HTMLMediaElement* mediaElement = toHTMLMediaElement(r.innerNode());
    if (isHTMLVideoElement(*mediaElement))
      data.mediaType = WebContextMenuData::MediaTypeVideo;
    else if (isHTMLAudioElement(*mediaElement))
      data.mediaType = WebContextMenuData::MediaTypeAudio;

    if (mediaElement->error())
      data.mediaFlags |= WebContextMenuData::MediaInError;
    if (mediaElement->paused())
      data.mediaFlags |= WebContextMenuData::MediaPaused;
    if (mediaElement->muted())
      data.mediaFlags |= WebContextMenuData::MediaMuted;
    if (mediaElement->loop())
      data.mediaFlags |= WebContextMenuData::MediaLoop;
    if (mediaElement->supportsSave())
      data.mediaFlags |= WebContextMenuData::MediaCanSave;
    if (mediaElement->hasAudio())
      data.mediaFlags |= WebContextMenuData::MediaHasAudio;
    // Media controls can be toggled only for video player. If we toggle
    // controls for audio then the player disappears, and there is no way to
    // return it back. Don't set this bit for fullscreen video, since
    // toggling is ignored in that case.
    if (mediaElement->isHTMLVideoElement() && mediaElement->hasVideo() &&
        !mediaElement->isFullscreen())
      data.mediaFlags |= WebContextMenuData::MediaCanToggleControls;
    if (mediaElement->shouldShowControls())
      data.mediaFlags |= WebContextMenuData::MediaControls;
  } else if (isHTMLObjectElement(*r.innerNode()) ||
             isHTMLEmbedElement(*r.innerNode())) {
    LayoutObject* object = r.innerNode()->layoutObject();
    if (object && object->isLayoutPart()) {
      Widget* widget = toLayoutPart(object)->widget();
      if (widget && widget->isPluginContainer()) {
        data.mediaType = WebContextMenuData::MediaTypePlugin;
        WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget);
        WebString text = plugin->plugin()->selectionAsText();
        if (!text.isEmpty()) {
          data.selectedText = text;
          data.editFlags |= WebContextMenuData::CanCopy;
        }
        data.editFlags &= ~WebContextMenuData::CanTranslate;
        data.linkURL = plugin->plugin()->linkAtPosition(data.mousePosition);
        if (plugin->plugin()->supportsPaginatedPrint())
          data.mediaFlags |= WebContextMenuData::MediaCanPrint;

        HTMLPlugInElement* pluginElement = toHTMLPlugInElement(r.innerNode());
        data.srcURL =
            pluginElement->document().completeURL(pluginElement->url());
        data.mediaFlags |= WebContextMenuData::MediaCanSave;

        // Add context menu commands that are supported by the plugin.
        if (plugin->plugin()->canRotateView())
          data.mediaFlags |= WebContextMenuData::MediaCanRotate;
      }
    }
  }

  // If it's not a link, an image, a media element, or an image/media link,
  // show a selection menu or a more generic page menu.
  if (selectedFrame->document()->loader())
    data.frameEncoding = selectedFrame->document()->encodingName();

  // Send the frame and page URLs in any case.
  if (!m_webView->page()->mainFrame()->isLocalFrame()) {
    // TODO(kenrb): This works around the problem of URLs not being
    // available for top-level frames that are in a different process.
    // It mostly works to convert the security origin to a URL, but
    // extensions accessing that property will not get the correct value
    // in that case. See https://crbug.com/534561
    WebSecurityOrigin origin = m_webView->mainFrame()->getSecurityOrigin();
    if (!origin.isNull())
      data.pageURL = KURL(ParsedURLString, origin.toString());
  } else {
    data.pageURL = urlFromFrame(toLocalFrame(m_webView->page()->mainFrame()));
  }

  if (selectedFrame != m_webView->page()->mainFrame()) {
    data.frameURL = urlFromFrame(selectedFrame);
    HistoryItem* historyItem = selectedFrame->loader().currentItem();
    if (historyItem)
      data.frameHistoryItem = WebHistoryItem(historyItem);
  }

  if (r.isSelected()) {
    if (!isHTMLInputElement(*r.innerNode()) ||
        toHTMLInputElement(r.innerNode())->type() != InputTypeNames::password)
      data.selectedText = selectedFrame->selectedText().stripWhiteSpace();
  }

  if (r.isContentEditable()) {
    data.isEditable = true;

    // Spellchecker adds spelling markers to misspelled words and attaches
    // suggestions to these markers in the background. Therefore, when a
    // user right-clicks a mouse on a word, Chrome just needs to find a
    // spelling marker on the word instead of spellchecking it.
    String description;
    uint32_t hash = 0;
    data.misspelledWord =
        selectMisspellingAsync(selectedFrame, description, hash);
    data.misspellingHash = hash;
    if (description.length()) {
      Vector<String> suggestions;
      description.split('\n', suggestions);
      data.dictionarySuggestions = suggestions;
    } else if (m_webView->spellCheckClient()) {
      int misspelledOffset, misspelledLength;
      m_webView->spellCheckClient()->spellCheck(
          data.misspelledWord, misspelledOffset, misspelledLength,
          &data.dictionarySuggestions);
    }

    HTMLFormElement* form = selectedFrame->selection().currentForm();
    if (form && isHTMLInputElement(*r.innerNode())) {
      HTMLInputElement& selectedElement = toHTMLInputElement(*r.innerNode());
      WebSearchableFormData ws = WebSearchableFormData(
          WebFormElement(form), WebInputElement(&selectedElement));
      if (ws.url().isValid())
        data.keywordURL = ws.url();
    }
  }

  if (selectedFrame->editor().selectionHasStyle(CSSPropertyDirection, "ltr") !=
      FalseTriState)
    data.writingDirectionLeftToRight |=
        WebContextMenuData::CheckableMenuItemChecked;
  if (selectedFrame->editor().selectionHasStyle(CSSPropertyDirection, "rtl") !=
      FalseTriState)
    data.writingDirectionRightToLeft |=
        WebContextMenuData::CheckableMenuItemChecked;

  data.referrerPolicy = static_cast<WebReferrerPolicy>(
      selectedFrame->document()->getReferrerPolicy());

  // Filter out custom menu elements and add them into the data.
  populateCustomMenuItems(defaultMenu, &data);

  if (isHTMLAnchorElement(r.URLElement())) {
    HTMLAnchorElement* anchor = toHTMLAnchorElement(r.URLElement());

    // Extract suggested filename for saving file.
    data.suggestedFilename = anchor->fastGetAttribute(HTMLNames::downloadAttr);

    // If the anchor wants to suppress the referrer, update the referrerPolicy
    // accordingly.
    if (anchor->hasRel(RelationNoReferrer))
      data.referrerPolicy = WebReferrerPolicyNever;

    data.linkText = anchor->innerText();
  }

  // Find the input field type.
  if (isHTMLInputElement(r.innerNode())) {
    HTMLInputElement* element = toHTMLInputElement(r.innerNode());
    if (element->type() == InputTypeNames::password)
      data.inputFieldType = WebContextMenuData::InputFieldTypePassword;
    else if (element->isTextField())
      data.inputFieldType = WebContextMenuData::InputFieldTypePlainText;
    else
      data.inputFieldType = WebContextMenuData::InputFieldTypeOther;
  } else {
    data.inputFieldType = WebContextMenuData::InputFieldTypeNone;
  }

  if (fromTouch && !shouldShowContextMenuFromTouch(data))
    return false;

  WebLocalFrameImpl* selectedWebFrame =
      WebLocalFrameImpl::fromFrame(selectedFrame);
  selectedWebFrame->setContextMenuNode(r.innerNodeOrImageMapImage());
  if (!selectedWebFrame->client())
    return false;

  selectedWebFrame->client()->showContextMenu(data);
  return true;
}

void ContextMenuClientImpl::clearContextMenu() {
  HitTestResult r = m_webView->page()->contextMenuController().hitTestResult();
  LocalFrame* selectedFrame = r.innerNodeFrame();
  if (!selectedFrame)
    return;

  WebLocalFrameImpl* selectedWebFrame =
      WebLocalFrameImpl::fromFrame(selectedFrame);
  selectedWebFrame->clearContextMenuNode();
}

static void populateSubMenuItems(const Vector<ContextMenuItem>& inputMenu,
                                 WebVector<WebMenuItemInfo>& subMenuItems) {
  Vector<WebMenuItemInfo> subItems;
  for (size_t i = 0; i < inputMenu.size(); ++i) {
    const ContextMenuItem* inputItem = &inputMenu.at(i);
    if (inputItem->action() < ContextMenuItemBaseCustomTag ||
        inputItem->action() > ContextMenuItemLastCustomTag)
      continue;

    WebMenuItemInfo outputItem;
    outputItem.label = inputItem->title();
    outputItem.icon = inputItem->icon();
    outputItem.enabled = inputItem->enabled();
    outputItem.checked = inputItem->checked();
    outputItem.action = static_cast<unsigned>(inputItem->action() -
                                              ContextMenuItemBaseCustomTag);
    switch (inputItem->type()) {
      case ActionType:
        outputItem.type = WebMenuItemInfo::Option;
        break;
      case CheckableActionType:
        outputItem.type = WebMenuItemInfo::CheckableOption;
        break;
      case SeparatorType:
        outputItem.type = WebMenuItemInfo::Separator;
        break;
      case SubmenuType:
        outputItem.type = WebMenuItemInfo::SubMenu;
        populateSubMenuItems(inputItem->subMenuItems(),
                             outputItem.subMenuItems);
        break;
    }
    subItems.append(outputItem);
  }

  WebVector<WebMenuItemInfo> outputItems(subItems.size());
  for (size_t i = 0; i < subItems.size(); ++i)
    outputItems[i] = subItems[i];
  subMenuItems.swap(outputItems);
}

void ContextMenuClientImpl::populateCustomMenuItems(
    const ContextMenu* defaultMenu,
    WebContextMenuData* data) {
  populateSubMenuItems(defaultMenu->items(), data->customItems);
}

}  // namespace blink
