static void searchAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, v, value); imp->setSearch(v); return; }
void CreateLinkCommand::doApply(EditingState* editingState) { if (endingSelection().isNone()) return; HTMLAnchorElement* anchorElement = HTMLAnchorElement::create(document()); anchorElement->setHref(AtomicString(m_url)); if (endingSelection().isRange()) { applyStyledElement(anchorElement, editingState); if (editingState->isAborted()) return; } else { insertNodeAt(anchorElement, endingSelection().start(), editingState); if (editingState->isAborted()) return; Text* textNode = Text::create(document(), m_url); appendNode(textNode, anchorElement, editingState); if (editingState->isAborted()) return; document().updateStyleAndLayoutIgnorePendingStylesheets(); setEndingSelection(createVisibleSelection( Position::inParentBeforeNode(*anchorElement), Position::inParentAfterNode(*anchorElement), TextAffinity::Downstream, endingSelection().isDirectional())); } }
static void searchAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLAnchorElement.search._set"); HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); V8Parameter<WithNullCheck> v = value; imp->setSearch(v); return; }
JSValue jsHTMLAnchorElementText(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLAnchorElement* castedThis = static_cast<JSHTMLAnchorElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLAnchorElement* imp = static_cast<HTMLAnchorElement*>(castedThis->impl()); JSValue result = jsString(exec, imp->text()); return result; }
JSValue jsHTMLAnchorElementShape(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLAnchorElement* castedThis = static_cast<JSHTMLAnchorElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLAnchorElement* imp = static_cast<HTMLAnchorElement*>(castedThis->impl()); JSValue result = jsString(exec, imp->getAttribute(HTMLNames::shapeAttr)); return result; }
JSValue JSC_HOST_CALL jsHTMLAnchorElementPrototypeFunctionToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UNUSED_PARAM(args); if (!thisValue.inherits(&JSHTMLAnchorElement::s_info)) return throwError(exec, TypeError); JSHTMLAnchorElement* castedThisObj = static_cast<JSHTMLAnchorElement*>(asObject(thisValue)); HTMLAnchorElement* imp = static_cast<HTMLAnchorElement*>(castedThisObj->impl()); JSC::JSValue result = jsString(exec, imp->toString()); return result; }
Element* TreeScope::findAnchor(const String& name) { if (name.isEmpty()) return 0; if (Element* element = getElementById(name)) return element; for (Element* element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::next(element)) { if (element->hasTagName(aTag)) { HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element); if (rootNode()->document()->inQuirksMode()) { // Quirks mode, case insensitive comparison of names. if (equalIgnoringCase(anchor->name(), name)) return anchor; } else { // Strict mode, names need to match exactly. if (anchor->name() == name) return anchor; } } } return 0; }
static v8::Handle<v8::Value> hrefAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLAnchorElement.href._get"); HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); return v8String(imp->getURLAttribute(HTMLNames::hrefAttr)); }
static v8::Handle<v8::Value> toStringCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAnchorElement.toString"); HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(args.Holder()); return v8String(imp->toString()); }
static v8::Handle<v8::Value> textAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLAnchorElement.text._get"); HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); return v8String(imp->text()); }
static v8::Handle<v8::Value> hrefAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); return v8String(imp->getURLAttribute(WebCore::HTMLNames::hrefAttr), info.GetIsolate()); }
static v8::Handle<v8::Value> toStringCallback(const v8::Arguments& args) { HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(args.Holder()); return v8String(imp->toString(), args.GetIsolate()); }
static v8::Handle<v8::Value> textAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLAnchorElement* imp = V8HTMLAnchorElement::toNative(info.Holder()); return v8String(imp->text(), info.GetIsolate()); }
void ContextMenuClientImpl::showContextMenu(const WebCore::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; HitTestResult r = m_webView->page()->contextMenuController().hitTestResult(); LocalFrame* selectedFrame = r.innerNodeFrame(); WebContextMenuData data; IntPoint mousePoint = selectedFrame->view()->contentsToWindow(r.roundedPointInInnerNodeFrame()); // FIXME(bokan): crbug.com/371902 - We shouldn't be making these scale // related coordinate transformatios in an ad hoc way. PinchViewport& pinchViewport = selectedFrame->host()->pinchViewport(); mousePoint -= flooredIntSize(pinchViewport.visibleRect().location()); mousePoint.scale(m_webView->pageScaleFactor(), m_webView->pageScaleFactor()); data.mousePosition = mousePoint; // Compute edit flags. data.editFlags = WebContextMenuData::CanDoNone; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canUndo()) data.editFlags |= WebContextMenuData::CanUndo; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canRedo()) data.editFlags |= WebContextMenuData::CanRedo; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canCut()) data.editFlags |= WebContextMenuData::CanCut; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canCopy()) data.editFlags |= WebContextMenuData::CanCopy; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canPaste()) data.editFlags |= WebContextMenuData::CanPaste; if (toLocalFrame(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 (isHTMLCanvasElement(r.innerNonSharedNode())) { data.mediaType = WebContextMenuData::MediaTypeCanvas; } else if (!r.absoluteImageURL().isEmpty()) { data.srcURL = r.absoluteImageURL(); data.mediaType = WebContextMenuData::MediaTypeImage; data.mediaFlags |= WebContextMenuData::MediaCanPrint; } 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.innerNonSharedNode()); 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->hasVideo() && !mediaElement->isFullscreen()) data.mediaFlags |= WebContextMenuData::MediaCanToggleControls; if (mediaElement->controls()) data.mediaFlags |= WebContextMenuData::MediaControls; } else if (isHTMLObjectElement(*r.innerNonSharedNode()) || isHTMLEmbedElement(*r.innerNonSharedNode())) { RenderObject* object = r.innerNonSharedNode()->renderer(); if (object && object->isWidget()) { Widget* widget = toRenderWidget(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.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; } } } // An image can to be null for many reasons, like being blocked, no image // data received from server yet. data.hasImageContents = (data.mediaType == WebContextMenuData::MediaTypeImage) && r.image() && !(r.image()->isNull()); // 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. data.pageURL = urlFromFrame(m_webView->mainFrameImpl()->frame()); if (selectedFrame != m_webView->mainFrameImpl()->frame()) { data.frameURL = urlFromFrame(selectedFrame); RefPtr<HistoryItem> historyItem = selectedFrame->loader().currentItem(); if (historyItem) data.frameHistoryItem = WebHistoryItem(historyItem); } if (r.isSelected()) { if (!isHTMLInputElement(*r.innerNonSharedNode()) || !toHTMLInputElement(r.innerNonSharedNode())->isPasswordField()) data.selectedText = selectedFrame->selectedText().stripWhiteSpace(); } if (r.isContentEditable()) { data.isEditable = true; // 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 instead of spellchecking it. if (selectedFrame->settings() && selectedFrame->settings()->asynchronousSpellCheckingEnabled()) { DocumentMarker marker; data.misspelledWord = selectMisspellingAsync(selectedFrame, marker); data.misspellingHash = marker.hash(); if (marker.description().length()) { Vector<String> suggestions; marker.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); } } else { data.isSpellCheckingEnabled = toLocalFrame(m_webView->focusedWebCoreFrame())->spellChecker().isContinuousSpellCheckingEnabled(); // Spellchecking might be enabled for the field, but could be disabled on the node. if (toLocalFrame(m_webView->focusedWebCoreFrame())->spellChecker().isSpellCheckingEnabledInFocusedNode()) { data.misspelledWord = selectMisspelledWord(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 && isHTMLInputElement(*r.innerNonSharedNode())) { HTMLInputElement& selectedElement = toHTMLInputElement(*r.innerNonSharedNode()); 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; // 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); // Extract suggested filename for saving file. if (isHTMLAnchorElement(r.URLElement())) { HTMLAnchorElement* anchor = toHTMLAnchorElement(r.URLElement()); data.suggestedFilename = anchor->fastGetAttribute(HTMLNames::downloadAttr); } data.node = r.innerNonSharedNode(); WebLocalFrameImpl* selectedWebFrame = WebLocalFrameImpl::fromFrame(selectedFrame); if (selectedWebFrame->client()) selectedWebFrame->client()->showContextMenu(data); }
void setJSHTMLAnchorElementSearch(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLAnchorElement* castedThisObj = static_cast<JSHTMLAnchorElement*>(thisObject); HTMLAnchorElement* imp = static_cast<HTMLAnchorElement*>(castedThisObj->impl()); imp->setSearch(valueToStringWithNullCheck(exec, value)); }
void setJSHTMLAnchorElementType(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLAnchorElement* castedThisObj = static_cast<JSHTMLAnchorElement*>(thisObject); HTMLAnchorElement* imp = static_cast<HTMLAnchorElement*>(castedThisObj->impl()); imp->setAttribute(HTMLNames::typeAttr, valueToStringWithNullCheck(exec, value)); }
void MediaDocumentParser::createDocumentStructure() { DCHECK(document()); HTMLHtmlElement* rootElement = HTMLHtmlElement::create(*document()); document()->appendChild(rootElement); rootElement->insertedByParser(); if (isDetached()) return; // runScriptsAtDocumentElementAvailable can detach the frame. HTMLHeadElement* head = HTMLHeadElement::create(*document()); HTMLMetaElement* meta = HTMLMetaElement::create(*document()); meta->setAttribute(nameAttr, "viewport"); meta->setAttribute(contentAttr, "width=device-width"); head->appendChild(meta); HTMLVideoElement* media = HTMLVideoElement::create(*document()); media->setAttribute(controlsAttr, ""); media->setAttribute(autoplayAttr, ""); media->setAttribute(nameAttr, "media"); HTMLSourceElement* source = HTMLSourceElement::create(*document()); source->setSrc(document()->url()); if (DocumentLoader* loader = document()->loader()) source->setType(loader->responseMIMEType()); media->appendChild(source); HTMLBodyElement* body = HTMLBodyElement::create(*document()); body->setAttribute(styleAttr, "margin: 0px;"); document()->willInsertBody(); HTMLDivElement* div = HTMLDivElement::create(*document()); // Style sheets for media controls are lazily loaded until a media element is // encountered. As a result, elements encountered before the media element // will not get the right style at first if we put the styles in // mediacontrols.css. To solve this issue, set the styles inline so that they // will be applied when the page loads. See w3c example on how to centering // an element: https://www.w3.org/Style/Examples/007/center.en.html div->setAttribute(styleAttr, "display: flex;" "flex-direction: column;" "justify-content: center;" "align-items: center;" "min-height: min-content;" "height: 100%;"); HTMLContentElement* content = HTMLContentElement::create(*document()); div->appendChild(content); if (RuntimeEnabledFeatures::mediaDocumentDownloadButtonEnabled()) { HTMLAnchorElement* anchor = HTMLAnchorElement::create(*document()); anchor->setAttribute(downloadAttr, ""); anchor->setURL(document()->url()); anchor->setTextContent( document() ->getCachedLocale(document()->contentLanguage()) .queryString(WebLocalizedString::DownloadButtonLabel) .upper()); // Using CSS style according to Android material design. anchor->setAttribute( styleAttr, "display: inline-block;" "margin-top: 32px;" "padding: 0 16px 0 16px;" "height: 36px;" "background: #000000;" "-webkit-tap-highlight-color: rgba(255, 255, 255, 0.12);" "font-family: Roboto;" "font-size: 14px;" "border-radius: 5px;" "color: white;" "font-weight: 500;" "text-decoration: none;" "line-height: 36px;"); EventListener* listener = MediaDownloadEventListener::create(); anchor->addEventListener(EventTypeNames::click, listener, false); HTMLDivElement* buttonContainer = HTMLDivElement::create(*document()); buttonContainer->setAttribute(styleAttr, "text-align: center;" "height: 0;" "flex: none"); buttonContainer->appendChild(anchor); div->appendChild(buttonContainer); recordDownloadMetric(MediaDocumentDownloadButtonShown); } // According to // https://html.spec.whatwg.org/multipage/browsers.html#read-media, // MediaDocument should have a single child which is the video element. Use // shadow root to hide all the elements we added here. ShadowRoot& shadowRoot = body->ensureUserAgentShadowRoot(); shadowRoot.appendChild(div); body->appendChild(media); rootElement->appendChild(head); rootElement->appendChild(body); m_didBuildDocumentStructure = true; }