예제 #1
0
bool SubframeLoader::pluginIsLoadable(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType)
{
    if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
        if (!m_frame.settings().isJavaEnabled())
            return false;
        if (document() && document()->securityOrigin()->isLocal() && !m_frame.settings().isJavaEnabledForLocalFiles())
            return false;
    }

    if (document()) {
        if (document()->isSandboxed(SandboxPlugins))
            return false;

        if (!document()->securityOrigin()->canDisplay(url)) {
            FrameLoader::reportLocalLoadFailed(&m_frame, url.string());
            return false;
        }

        String declaredMimeType = document()->isPluginDocument() && document()->ownerElement() ?
            document()->ownerElement()->fastGetAttribute(HTMLNames::typeAttr) :
            pluginElement.fastGetAttribute(HTMLNames::typeAttr);
        if (!document()->contentSecurityPolicy()->allowObjectFromSource(url)
            || !document()->contentSecurityPolicy()->allowPluginType(mimeType, declaredMimeType, url)) {
            RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject();
            renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy);
            return false;
        }

        if (!m_frame.loader().mixedContentChecker().canRunInsecureContent(document()->securityOrigin(), url))
            return false;
    }

    return true;
}
예제 #2
0
bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
{
    RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject();

    // FIXME: This code should not depend on renderer!
    if (!renderer || useFallback)
        return false;

    pluginElement.subframeLoaderWillCreatePlugIn(url);

    IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight()));
    bool loadManually = document()->isPluginDocument() && !m_containsPlugins && toPluginDocument(document())->shouldLoadPluginManually();
    RefPtr<Widget> widget = m_frame.loader().client().createPlugin(contentSize, &pluginElement, url, paramNames, paramValues, mimeType, loadManually);

    if (!widget) {
        if (!renderer->isPluginUnavailable())
            renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
        return false;
    }

    pluginElement.subframeLoaderDidCreatePlugIn(widget.get());
    renderer->setWidget(widget);
    m_containsPlugins = true;
 
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
    pluginElement->setNeedsStyleRecalc(SyntheticStyleChange);
#endif
    return true;
}
예제 #3
0
bool SubframeLoader::loadPlugin(HTMLPlugInImageElement& pluginElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
{
    RenderEmbeddedObject* renderer = pluginElement.renderEmbeddedObject();

    // FIXME: This code should not depend on renderer!
    if (!renderer || useFallback)
        return false;

    pluginElement.subframeLoaderWillCreatePlugIn(url);

    IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight()));
    bool loadManually = is<PluginDocument>(*document()) && !m_containsPlugins && downcast<PluginDocument>(*document()).shouldLoadPluginManually();

#if PLATFORM(IOS)
    // On iOS, we only tell the plugin to be in full page mode if the containing plugin document is the top level document.
    if (document()->ownerElement())
        loadManually = false;
#endif

    RefPtr<Widget> widget = m_frame.loader().client().createPlugin(contentSize, &pluginElement, url, paramNames, paramValues, mimeType, loadManually);

    if (!widget) {
        if (!renderer->isPluginUnavailable())
            renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
        return false;
    }

    pluginElement.subframeLoaderDidCreatePlugIn(*widget);
    renderer->setWidget(widget);
    m_containsPlugins = true;
    return true;
}
예제 #4
0
void WebChromeClient::missingPluginButtonClicked(Element* element) const
{
    ASSERT(element->hasTagName(objectTag) || element->hasTagName(embedTag));

    HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);

    m_page->send(Messages::WebPageProxy::MissingPluginButtonClicked(pluginElement->serviceType(), pluginElement->url(), pluginElement->getAttribute(pluginspageAttr)));
}
예제 #5
0
bool SubframeLoader::requestPlugin(HTMLPlugInImageElement& ownerElement, const URL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
{
    // Application plug-ins are plug-ins implemented by the user agent, for example Qt plug-ins,
    // as opposed to third-party code such as Flash. The user agent decides whether or not they are
    // permitted, rather than WebKit.
    if ((!allowPlugins(AboutToInstantiatePlugin) && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)))
        return false;

    if (!pluginIsLoadable(ownerElement, url, mimeType))
        return false;

    ASSERT(ownerElement.hasTagName(objectTag) || ownerElement.hasTagName(embedTag));
    return loadPlugin(ownerElement, url, mimeType, paramNames, paramValues, useFallback);
}
예제 #6
0
void WebChromeClient::unavailablePluginButtonClicked(Element* element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
{
    ASSERT(element->hasTagName(objectTag) || element->hasTagName(embedTag) || element->hasTagName(appletTag));
    ASSERT(pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing || pluginUnavailabilityReason == RenderEmbeddedObject::InsecurePluginVersion || pluginUnavailabilityReason == RenderEmbeddedObject::PluginInactive);

    HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);

    String frameURLString = pluginElement->document()->frame()->loader()->documentLoader()->responseURL().string();
    String pageURLString = m_page->mainFrame()->loader()->documentLoader()->responseURL().string();
    KURL pluginspageAttributeURL = element->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(pluginElement->getAttribute(pluginspageAttr)));
    if (!pluginspageAttributeURL.protocolIsInHTTPFamily())
        pluginspageAttributeURL = KURL();
    m_page->send(Messages::WebPageProxy::UnavailablePluginButtonClicked(pluginUnavailabilityReason, pluginElement->serviceType(), pluginElement->url(), pluginspageAttributeURL.string(), frameURLString, pageURLString));
}
예제 #7
0
static void addPlugInsFromNodeListMatchingPlugInOrigin(HTMLPlugInImageElementList& plugInList, PassRefPtr<NodeList> collection, const String& plugInOrigin, const String& mimeType)
{
    for (unsigned i = 0, length = collection->length(); i < length; i++) {
        Node* node = collection->item(i);
        if (node->isPluginElement()) {
            HTMLPlugInElement* plugInElement = toHTMLPlugInElement(node);
            if (plugInElement->isPlugInImageElement()) {
                HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(node);
                const KURL& loadedURL = plugInImageElement->loadedUrl();
                String otherMimeType = plugInImageElement->loadedMimeType();
                if (plugInOrigin == loadedURL.host() && mimeType == otherMimeType)
                    plugInList.append(plugInImageElement);
            }
        }
    }
}
예제 #8
0
KURL HitTestResult::absolutePDFURL() const
{
    if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
        return KURL();

    if (!m_innerNonSharedNode->hasTagName(embedTag) && !m_innerNonSharedNode->hasTagName(objectTag))
        return KURL();

    HTMLPlugInImageElement* element = static_cast<HTMLPlugInImageElement*>(m_innerNonSharedNode.get());
    KURL url = m_innerNonSharedNode->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(element->url()));
    if (!url.isValid())
        return KURL();

    if (element->serviceType() == "application/pdf" || (element->serviceType().isEmpty() && url.path().lower().endsWith(".pdf")))
        return url;
    return KURL();
}
예제 #9
0
void WebChromeClient::unavailablePluginButtonClicked(Element* element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
{
    ASSERT(element->hasTagName(objectTag) || element->hasTagName(embedTag));
    ASSERT(pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing || pluginUnavailabilityReason == RenderEmbeddedObject::InsecurePluginVersion);

    HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);

    m_page->send(Messages::WebPageProxy::UnavailablePluginButtonClicked(pluginUnavailabilityReason, pluginElement->serviceType(), pluginElement->url(), pluginElement->getAttribute(pluginspageAttr)));
}
예제 #10
0
void HTMLPlugInImageElement::restartSimilarPlugIns()
{
    // Restart any other snapshotted plugins in the page with the same origin. Note that they
    // may be in different frames, so traverse from the top of the document.

    String plugInOrigin = m_loadedUrl.host();
    String mimeType = loadedMimeType();
    HTMLPlugInImageElementList similarPlugins;

    if (!document()->page())
        return;

    for (Frame* frame = document()->page()->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
        if (!frame->loader()->subframeLoader()->containsPlugins())
            continue;
        
        if (!frame->document())
            continue;

        RefPtr<NodeList> plugIns = frame->document()->getElementsByTagName(embedTag.localName());
        if (plugIns)
            addPlugInsFromNodeListMatchingPlugInOrigin(similarPlugins, plugIns, plugInOrigin, mimeType);

        plugIns = frame->document()->getElementsByTagName(objectTag.localName());
        if (plugIns)
            addPlugInsFromNodeListMatchingPlugInOrigin(similarPlugins, plugIns, plugInOrigin, mimeType);
    }

    for (size_t i = 0, length = similarPlugins.size(); i < length; ++i) {
        HTMLPlugInImageElement* plugInToRestart = similarPlugins[i].get();
        if (plugInToRestart->displayState() <= HTMLPlugInElement::DisplayingSnapshot) {
            LOG(Plugins, "%p Plug-in looks similar to a restarted plug-in. Restart.", plugInToRestart);
            plugInToRestart->setDisplayState(Playing);
            plugInToRestart->restartSnapshottedPlugIn();
        }
        plugInToRestart->m_snapshotDecision = NeverSnapshot;
    }
}
예제 #11
0
bool SubframeLoader::requestObject(HTMLPlugInImageElement& ownerElement, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
{
    if (url.isEmpty() && mimeType.isEmpty())
        return false;

    URL completedURL;
    if (!url.isEmpty())
        completedURL = completeURL(url);

    bool hasFallbackContent = isHTMLObjectElement(ownerElement) && toHTMLObjectElement(ownerElement).hasFallbackContent();

    bool useFallback;
    if (shouldUsePlugin(completedURL, mimeType, ownerElement.shouldPreferPlugInsForImages(), hasFallbackContent, useFallback)) {
        bool success = requestPlugin(ownerElement, completedURL, mimeType, paramNames, paramValues, useFallback);
        logPluginRequest(document()->page(), mimeType, completedURL, success);
        return success;
    }

    // If the plug-in element already contains a subframe, loadOrRedirectSubframe will re-use it. Otherwise,
    // it will create a new frame and set it as the RenderWidget's Widget, causing what was previously 
    // in the widget to be torn down.
    return loadOrRedirectSubframe(ownerElement, completedURL, frameName, true, true);
}
예제 #12
0
void RenderEmbeddedObject::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    ASSERT(needsLayout());

    LayoutSize oldSize = contentBoxRect().size();

    updateLogicalWidth();
    updateLogicalHeight();

    RenderPart::layout();

    m_overflow.clear();
    addVisualEffectOverflow();

    updateLayerTransform();

    bool wasMissingWidget = false;
    if (!widget() && frameView() && canHaveWidget()) {
        wasMissingWidget = true;
        frameView()->addWidgetToUpdate(this);
    }

    setNeedsLayout(false);

    LayoutSize newSize = contentBoxRect().size();

    if (!wasMissingWidget && newSize.width() >= oldSize.width() && newSize.height() >= oldSize.height()) {
        Element* element = toElement(node());
        if (element && element->isPluginElement() && toHTMLPlugInElement(element)->isPlugInImageElement()) {
            HTMLPlugInImageElement* plugInImageElement = toHTMLPlugInImageElement(element);
            if (plugInImageElement->displayState() > HTMLPlugInElement::DisplayingSnapshot && plugInImageElement->snapshotDecision() == HTMLPlugInImageElement::MaySnapshotWhenResized && document()->view()) {
                plugInImageElement->setNeedsCheckForSizeChange();
                document()->view()->addWidgetToUpdate(this);
            }
        }
    }

    if (!canHaveChildren())
        return;

    // This code copied from RenderMedia::layout().
    RenderObject* child = m_children.firstChild();

    if (!child)
        return;

    RenderBox* childBox = toRenderBox(child);

    if (!childBox)
        return;

    if (newSize == oldSize && !childBox->needsLayout())
        return;
    
    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
    // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
    // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
    
    childBox->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
    childBox->style()->setHeight(Length(newSize.height(), Fixed));
    childBox->style()->setWidth(Length(newSize.width(), Fixed));
    childBox->setNeedsLayout(true, MarkOnlyThis);
    childBox->layout();
    setChildNeedsLayout(false);
    
    statePusher.pop();
}
PlatformMenuDescription ContextMenuClientImpl::getCustomMenuFromDefaultItems(
    ContextMenu* defaultMenu)
{
    // 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 (!m_webView->contextMenuAllowed())
        return 0;

    HitTestResult r = m_webView->page()->contextMenuController()->hitTestResult();
    Frame* selectedFrame = r.innerNonSharedNode()->document()->frame();

    WebContextMenuData data;
    data.mousePosition = selectedFrame->view()->contentsToWindow(r.point());

    // Compute edit flags.
    data.editFlags = WebContextMenuData::CanDoNone;
    if (m_webView->focusedWebCoreFrame()->editor()->canUndo())
        data.editFlags |= WebContextMenuData::CanUndo;
    if (m_webView->focusedWebCoreFrame()->editor()->canRedo())
        data.editFlags |= WebContextMenuData::CanRedo;
    if (m_webView->focusedWebCoreFrame()->editor()->canCut())
        data.editFlags |= WebContextMenuData::CanCut;
    if (m_webView->focusedWebCoreFrame()->editor()->canCopy())
        data.editFlags |= WebContextMenuData::CanCopy;
    if (m_webView->focusedWebCoreFrame()->editor()->canPaste())
        data.editFlags |= WebContextMenuData::CanPaste;
    if (m_webView->focusedWebCoreFrame()->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.absoluteImageURL().isEmpty()) {
        data.srcURL = r.absoluteImageURL();
        data.mediaType = WebContextMenuData::MediaTypeImage;
    } 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 =
            static_cast<HTMLMediaElement*>(r.innerNonSharedNode());
        if (mediaElement->hasTagName(HTMLNames::videoTag))
            data.mediaType = WebContextMenuData::MediaTypeVideo;
        else if (mediaElement->hasTagName(HTMLNames::audioTag))
            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;
        if (mediaElement->hasVideo())
            data.mediaFlags |= WebContextMenuData::MediaHasVideo;
        if (mediaElement->controls())
            data.mediaFlags |= WebContextMenuData::MediaControls;
    } else if (r.innerNonSharedNode()->hasTagName(HTMLNames::objectTag)
               || r.innerNonSharedNode()->hasTagName(HTMLNames::embedTag)) {
        RenderObject* object = r.innerNonSharedNode()->renderer();
        if (object && object->isWidget()) {
            Widget* widget = toRenderWidget(object)->widget();
            if (widget && widget->isPluginContainer()) {
                data.mediaType = WebContextMenuData::MediaTypePlugin;
                WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(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;

                HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(r.innerNonSharedNode());
                data.srcURL = pluginElement->document()->completeURL(pluginElement->url());
                data.mediaFlags |= WebContextMenuData::MediaCanSave;
            }
        }
    }

    data.isImageBlocked =
        (data.mediaType == WebContextMenuData::MediaTypeImage) && !r.image();

    // 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.
    data.frameEncoding = selectedFrame->document()->loader()->writer()->encoding();

    // Send the frame and page URLs in any case.
    data.pageURL = urlFromFrame(m_webView->mainFrameImpl()->frame());
    if (selectedFrame != m_webView->mainFrameImpl()->frame()) {
        data.frameURL = urlFromFrame(selectedFrame);
        RefPtr<HistoryItem> historyItem = selectedFrame->loader()->history()->currentItem();
        if (historyItem)
            data.frameHistoryItem = WebHistoryItem(historyItem);
    }

    if (r.isSelected())
        data.selectedText = selectedFrame->editor()->selectedText().stripWhiteSpace();

    if (r.isContentEditable()) {
        data.isEditable = true;
        if (m_webView->focusedWebCoreFrame()->editor()->isContinuousSpellCheckingEnabled()) {
            data.isSpellCheckingEnabled = true;
            // Spellchecking might be enabled for the field, but could be disabled on the node.
            if (m_webView->focusedWebCoreFrame()->editor()->isSpellCheckingEnabledInFocusedNode())
                data.misspelledWord = selectMisspelledWord(defaultMenu, selectedFrame);
        }
    }

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

    // Now retrieve the security info.
    DocumentLoader* dl = selectedFrame->loader()->documentLoader();
    WebDataSource* ds = WebDataSourceImpl::fromDocumentLoader(dl);
    if (ds)
        data.securityInfo = ds->response().securityInfo();

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

    data.node = r.innerNonSharedNode();

    WebFrame* selected_web_frame = WebFrameImpl::fromFrame(selectedFrame);
    if (m_webView->client())
        m_webView->client()->showContextMenu(selected_web_frame, data);

    return 0;
}
예제 #14
0
PlatformMenuDescription ContextMenuClientImpl::getCustomMenuFromDefaultItems(
    ContextMenu* defaultMenu)
{
    // 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 (!m_webView->contextMenuAllowed())
        return 0;

    HitTestResult r = m_webView->page()->contextMenuController()->hitTestResult();
    Frame* selectedFrame = r.innerNonSharedNode()->document()->frame();

    WebContextMenuData data;
    data.mousePosition = selectedFrame->view()->contentsToWindow(r.roundedPoint());

    // Compute edit flags.
    data.editFlags = WebContextMenuData::CanDoNone;
    if (m_webView->focusedWebCoreFrame()->editor()->canUndo())
        data.editFlags |= WebContextMenuData::CanUndo;
    if (m_webView->focusedWebCoreFrame()->editor()->canRedo())
        data.editFlags |= WebContextMenuData::CanRedo;
    if (m_webView->focusedWebCoreFrame()->editor()->canCut())
        data.editFlags |= WebContextMenuData::CanCut;
    if (m_webView->focusedWebCoreFrame()->editor()->canCopy())
        data.editFlags |= WebContextMenuData::CanCopy;
    if (m_webView->focusedWebCoreFrame()->editor()->canPaste())
        data.editFlags |= WebContextMenuData::CanPaste;
    if (m_webView->focusedWebCoreFrame()->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.absoluteImageURL().isEmpty()) {
        data.srcURL = r.absoluteImageURL();
        data.mediaType = WebContextMenuData::MediaTypeImage;
    } 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 =
            static_cast<HTMLMediaElement*>(r.innerNonSharedNode());
        if (mediaElement->hasTagName(HTMLNames::videoTag))
            data.mediaType = WebContextMenuData::MediaTypeVideo;
        else if (mediaElement->hasTagName(HTMLNames::audioTag))
            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;
        if (mediaElement->hasVideo())
            data.mediaFlags |= WebContextMenuData::MediaHasVideo;
        if (mediaElement->controls())
            data.mediaFlags |= WebContextMenuData::MediaControlRootElement;
    } else if (r.innerNonSharedNode()->hasTagName(HTMLNames::objectTag)
               || r.innerNonSharedNode()->hasTagName(HTMLNames::embedTag)) {
        RenderObject* object = r.innerNonSharedNode()->renderer();
        if (object && object->isWidget()) {
            Widget* widget = toRenderWidget(object)->widget();
            if (widget && widget->isPluginContainer()) {
                data.mediaType = WebContextMenuData::MediaTypePlugin;
                WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(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;

                HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(r.innerNonSharedNode());
                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;
            }
        }
    }

    data.isImageBlocked =
        (data.mediaType == WebContextMenuData::MediaTypeImage) && !r.image();

    // 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()->encoding();

    // Send the frame and page URLs in any case.
    data.pageURL = urlFromFrame(m_webView->mainFrameImpl()->frame());
    if (selectedFrame != m_webView->mainFrameImpl()->frame()) {
        data.frameURL = urlFromFrame(selectedFrame);
        RefPtr<HistoryItem> historyItem = selectedFrame->loader()->history()->currentItem();
        if (historyItem)
            data.frameHistoryItem = WebHistoryItem(historyItem);
    }

    if (r.isSelected()) {
        if (!r.innerNonSharedNode()->hasTagName(HTMLNames::inputTag) || !static_cast<HTMLInputElement*>(r.innerNonSharedNode())->isPasswordField())
            data.selectedText = selectedFrame->editor()->selectedText().stripWhiteSpace();
    }

    if (r.isContentEditable()) {
        data.isEditable = true;
#if ENABLE(INPUT_SPEECH)
        if (r.innerNonSharedNode()->hasTagName(HTMLNames::inputTag)) {
            data.isSpeechInputEnabled = 
                static_cast<HTMLInputElement*>(r.innerNonSharedNode())->isSpeechEnabled();
        }  
#endif
        // When Chrome enables asynchronous spellchecking, its 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 instread of spellchecking it.
        if (selectedFrame->settings() && selectedFrame->settings()->asynchronousSpellCheckingEnabled()) {
            VisibleSelection selection = selectedFrame->selection()->selection();
            if (selection.isCaret()) {
                selection.expandUsingGranularity(WordGranularity);
                RefPtr<Range> range = selection.toNormalizedRange();
                Vector<DocumentMarker*> markers = selectedFrame->document()->markers()->markersInRange(range.get(), DocumentMarker::Spelling | DocumentMarker::Grammar);
                if (markers.size() == 1) {
                    range->setStart(range->startContainer(), markers[0]->startOffset());
                    range->setEnd(range->endContainer(), markers[0]->endOffset());
                    data.misspelledWord = range->text();
                    if (markers[0]->description().length()) {
                        Vector<String> suggestions;
                        markers[0]->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);
                    }
                    selection = VisibleSelection(range.get());
                    if (selectedFrame->selection()->shouldChangeSelection(selection))
                        selectedFrame->selection()->setSelection(selection, WordGranularity);
                }
            }
        } else if (m_webView->focusedWebCoreFrame()->editor()->isContinuousSpellCheckingEnabled()) {
            data.isSpellCheckingEnabled = true;
            // Spellchecking might be enabled for the field, but could be disabled on the node.
            if (m_webView->focusedWebCoreFrame()->editor()->isSpellCheckingEnabledInFocusedNode()) {
                data.misspelledWord = selectMisspelledWord(defaultMenu, selectedFrame);
                if (m_webView->spellCheckClient()) {
                    int misspelledOffset, misspelledLength;
                    m_webView->spellCheckClient()->spellCheck(
                        data.misspelledWord, misspelledOffset, misspelledLength,
                        &data.dictionarySuggestions);
                    if (!misspelledLength)
                        data.misspelledWord.reset();
                }
            }
        }
        HTMLFormElement* form = selectedFrame->selection()->currentForm();
        if (form && form->checkValidity() && r.innerNonSharedNode()->hasTagName(HTMLNames::inputTag)) {
            HTMLInputElement* selectedElement = static_cast<HTMLInputElement*>(r.innerNonSharedNode());
            if (selectedElement) {
                WebSearchableFormData ws = WebSearchableFormData(WebFormElement(form), WebInputElement(selectedElement));
                if (ws.url().isValid())
                    data.keywordURL = ws.url();
            }
        }
    }

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

    // Now retrieve the security info.
    DocumentLoader* dl = selectedFrame->loader()->documentLoader();
    WebDataSource* ds = WebDataSourceImpl::fromDocumentLoader(dl);
    if (ds)
        data.securityInfo = ds->response().securityInfo();

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

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

    data.node = r.innerNonSharedNode();

    WebFrame* selected_web_frame = WebFrameImpl::fromFrame(selectedFrame);
    if (m_webView->client())
        m_webView->client()->showContextMenu(selected_web_frame, data);

    return 0;
}