static void mediaAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { HTMLSourceElement* imp = V8HTMLSourceElement::toNative(info.Holder()); V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, v, value); imp->setMedia(v); return; }
// http://picture.responsiveimages.org/#update-source-set ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent() { ASSERT(isMainThread()); Node* parent = parentNode(); if (!parent || !isHTMLPictureElement(*parent)) return ImageCandidate(); for (Node* child = parent->firstChild(); child; child = child->nextSibling()) { if (child == this) return ImageCandidate(); if (!isHTMLSourceElement(*child)) continue; HTMLSourceElement* source = toHTMLSourceElement(child); if (!source->fastGetAttribute(srcAttr).isNull()) UseCounter::countDeprecation(document(), UseCounter::PictureSourceSrc); String srcset = source->fastGetAttribute(srcsetAttr); if (srcset.isEmpty()) continue; String type = source->fastGetAttribute(typeAttr); if (!type.isEmpty() && !supportedImageType(type)) continue; if (!source->mediaQueryMatches()) continue; ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), sourceSize(*source), source->fastGetAttribute(srcsetAttr), &document()); if (candidate.isEmpty()) continue; return candidate; } return ImageCandidate(); }
static void mediaAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLSourceElement.media._set"); HTMLSourceElement* imp = V8HTMLSourceElement::toNative(info.Holder()); V8Parameter<> v = value; imp->setMedia(v); return; }
bool HTMLImageElement::SourceElementMatches(nsIContent* aSourceNode) { MOZ_ASSERT(aSourceNode->IsHTMLElement(nsGkAtoms::source)); DebugOnly<Element *> parent(nsINode::GetParentElement()); MOZ_ASSERT(parent && parent->IsHTMLElement(nsGkAtoms::picture)); MOZ_ASSERT(IsPreviousSibling(aSourceNode, this)); // Check media and type HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode); if (!src->MatchesCurrentMedia()) { return false; } nsAutoString type; if (aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) && !SupportedPictureSourceType(type)) { return false; } return true; }
void MediaDocumentParser::createDocumentStructure() { RefPtr<Element> rootElement = document()->createElement(htmlTag, false); document()->appendChild(rootElement, IGNORE_EXCEPTION); document()->setCSSTarget(rootElement.get()); static_cast<HTMLHtmlElement*>(rootElement.get())->insertedByParser(); if (document()->frame()) document()->frame()->loader()->dispatchDocumentElementAvailable(); RefPtr<Element> body = document()->createElement(bodyTag, false); rootElement->appendChild(body, IGNORE_EXCEPTION); RefPtr<Element> mediaElement = document()->createElement(videoTag, false); m_mediaElement = static_cast<HTMLVideoElement*>(mediaElement.get()); m_mediaElement->setAttribute(controlsAttr, ""); m_mediaElement->setAttribute(autoplayAttr, ""); m_mediaElement->setAttribute(nameAttr, "media"); RefPtr<Element> sourceElement = document()->createElement(sourceTag, false); HTMLSourceElement* source = static_cast<HTMLSourceElement*>(sourceElement.get()); source->setSrc(document()->url()); if (DocumentLoader* loader = document()->loader()) source->setType(loader->responseMIMEType()); m_mediaElement->appendChild(sourceElement, IGNORE_EXCEPTION); body->appendChild(mediaElement, IGNORE_EXCEPTION); Frame* frame = document()->frame(); if (!frame) return; frame->loader()->activeDocumentLoader()->setMainResourceDataBufferingPolicy(DoNotBufferData); }
// http://picture.responsiveimages.org/#update-source-set ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent() { ASSERT(isMainThread()); Node* parent = parentNode(); if (!parent || !isHTMLPictureElement(*parent)) return ImageCandidate(); for (Node* child = parent->firstChild(); child; child = child->nextSibling()) { if (child == this) return ImageCandidate(); if (!isHTMLSourceElement(*child)) continue; HTMLSourceElement* source = toHTMLSourceElement(child); String srcset = source->fastGetAttribute(srcsetAttr); if (srcset.isEmpty()) continue; String type = source->fastGetAttribute(typeAttr); if (!type.isEmpty() && !supportedImageType(type)) continue; String media = source->fastGetAttribute(mediaAttr); if (!media.isEmpty()) { RefPtrWillBeRawPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media); if (!document().mediaQueryMatcher().evaluate(mediaQueries.get())) continue; } unsigned effectiveSize = SizesAttributeParser::findEffectiveSize(source->fastGetAttribute(sizesAttr), MediaValuesCached::create(document())); ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), effectiveSize, source->fastGetAttribute(srcsetAttr)); if (candidate.isEmpty()) continue; return candidate; } return ImageCandidate(); }
void JSHTMLSourceElement::putValueProperty(ExecState* exec, int token, JSValue* value) { switch (token) { case SrcAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); imp->setSrc(value->toString(exec)); break; } case TypeAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); imp->setType(value->toString(exec)); break; } case MediaAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); imp->setMedia(value->toString(exec)); break; } } }
JSValue* JSHTMLSourceElement::getValueProperty(ExecState* exec, int token) const { switch (token) { case SrcAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); return jsString(exec, imp->src()); } case TypeAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); return jsString(exec, imp->type()); } case MediaAttrNum: { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(impl()); return jsString(exec, imp->media()); } case ConstructorAttrNum: return getConstructor(exec); } return 0; }
String HTMLMediaElement::pickMedia() { // 3.14.9.2. Location of the media resource String mediaSrc = getAttribute(srcAttr); if (mediaSrc.isEmpty()) { for (Node* n = firstChild(); n; n = n->nextSibling()) { if (n->hasTagName(sourceTag)) { HTMLSourceElement* source = static_cast<HTMLSourceElement*>(n); if (!source->hasAttribute(srcAttr)) continue; if (source->hasAttribute(mediaAttr)) { MediaQueryEvaluator screenEval("screen", document()->frame(), renderer() ? renderer()->style() : 0); RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(source->media()); if (!screenEval.eval(media.get())) continue; } if (source->hasAttribute(typeAttr)) { String type = source->type().stripWhiteSpace(); // "type" can have parameters after a semi-colon, strip them before checking with the type registry int semi = type.find(';'); if (semi != -1) type = type.left(semi).stripWhiteSpace(); if (!MIMETypeRegistry::isSupportedMediaMIMEType(type)) continue; } mediaSrc = source->src().string(); break; } } } if (!mediaSrc.isEmpty()) mediaSrc = document()->completeURL(mediaSrc).string(); return mediaSrc; }
void setJSHTMLSourceElementMedia(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLSourceElement* castedThisObj = static_cast<JSHTMLSourceElement*>(thisObject); HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(castedThisObj->impl()); imp->setMedia(value.toString(exec)); }
static v8::Handle<v8::Value> mediaAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLSourceElement* imp = V8HTMLSourceElement::toNative(info.Holder()); return v8String(imp->media(), info.GetIsolate()); }
static v8::Handle<v8::Value> srcAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLSourceElement* imp = V8HTMLSourceElement::toNative(info.Holder()); return v8String(imp->getURLAttribute(WebCore::HTMLNames::srcAttr), info.GetIsolate()); }
static v8::Handle<v8::Value> mediaAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLSourceElement.media._get"); HTMLSourceElement* imp = V8HTMLSourceElement::toNative(info.Holder()); return v8String(imp->media()); }
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; }
bool HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode, const nsAString *aSrcset, const nsAString *aSizes) { if (!IsSrcsetEnabled()) { return false; } bool pictureEnabled = HTMLPictureElement::IsPictureEnabled(); // Skip if this is not a <source> with matching media query bool isSourceTag = aSourceNode->Tag() == nsGkAtoms::source; if (isSourceTag) { DebugOnly<nsINode *> parent(nsINode::GetParentNode()); MOZ_ASSERT(parent && parent->Tag() == nsGkAtoms::picture); MOZ_ASSERT(IsPreviousSibling(aSourceNode, this)); MOZ_ASSERT(pictureEnabled); // Check media and type HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode); if (!src->MatchesCurrentMedia()) { return false; } nsAutoString type; if (aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) && !imgLoader::SupportImageWithMimeType( NS_ConvertUTF16toUTF8(type).get(), AcceptedMimeTypes::IMAGES_AND_DOCUMENTS) ) { return false; } } else if (aSourceNode->Tag() == nsGkAtoms::img) { // Otherwise this is the <img> tag itself MOZ_ASSERT(aSourceNode == this); } // Skip if has no srcset or an empty srcset nsString srcset; if (aSrcset) { srcset = *aSrcset; } else if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset)) { return false; } if (srcset.IsEmpty()) { return false; } // Try to parse nsRefPtr<ResponsiveImageSelector> sel = new ResponsiveImageSelector(aSourceNode); if (!sel->SetCandidatesFromSourceSet(srcset)) { // No possible candidates, don't need to bother parsing sizes return false; } if (pictureEnabled && aSizes) { sel->SetSizesFromDescriptor(*aSizes); } else if (pictureEnabled) { nsAutoString sizes; aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes); sel->SetSizesFromDescriptor(sizes); } // If this is the <img> tag, also pull in src as the default source if (!isSourceTag) { MOZ_ASSERT(aSourceNode == this); nsAutoString src; if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && !src.IsEmpty()) { sel->SetDefaultSource(src); } } mResponsiveSelector = sel; return true; }
void setJSHTMLSourceElementType(ExecState* exec, JSObject* thisObject, JSValue value) { HTMLSourceElement* imp = static_cast<HTMLSourceElement*>(static_cast<JSHTMLSourceElement*>(thisObject)->impl()); imp->setType(value.toString(exec)); }