void V8Clipboard::setDragImageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args) { Clipboard* clipboard = V8Clipboard::toNative(args.Holder()); if (!clipboard->isForDragAndDrop()) return; if (args.Length() != 3) { throwError(v8SyntaxError, "setDragImage: Invalid number of arguments", args.GetIsolate()); return; } int x = toInt32(args[1]); int y = toInt32(args[2]); Node* node = 0; if (V8Node::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) node = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); if (!node || !node->isElementNode()) { throwTypeError("setDragImageFromElement: Invalid first argument", args.GetIsolate()); return; } if (toElement(node)->hasTagName(HTMLNames::imgTag) && !node->inDocument()) clipboard->setDragImage(toHTMLImageElement(node)->cachedImage(), IntPoint(x, y)); else clipboard->setDragImageElement(node, IntPoint(x, y)); }
static void appendServerMapMousePosition(StringBuilder& url, Event* event) { if (!event->isMouseEvent()) return; ASSERT(event->target()); Node* target = event->target()->toNode(); ASSERT(target); if (!isHTMLImageElement(target)) return; HTMLImageElement* imageElement = toHTMLImageElement(target); if (!imageElement || !imageElement->isServerMap()) return; if (!imageElement->renderer() || !imageElement->renderer()->isRenderImage()) return; RenderImage* renderer = toRenderImage(imageElement->renderer()); // FIXME: This should probably pass true for useTransforms. FloatPoint absolutePosition = renderer->absoluteToLocal(FloatPoint(toMouseEvent(event)->pageX(), toMouseEvent(event)->pageY())); int x = absolutePosition.x(); int y = absolutePosition.y(); url.append('?'); url.appendNumber(x); url.append(','); url.appendNumber(y); }
void PageSerializer::serializeFrame(Frame* frame) { Document* document = frame->document(); URL url = document->url(); if (!url.isValid() || url.isBlankURL()) { // For blank frames we generate a fake URL so they can be referenced by their containing frame. url = urlForBlankFrame(frame); } if (m_resourceURLs.contains(url)) { // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now // different content. So we should serialize both and somehow rename the frame src in the containing // frame. Arg! return; } Vector<Node*> nodes; SerializerMarkupAccumulator accumulator(*this, *document, &nodes); TextEncoding textEncoding(document->charset()); CString data; if (!textEncoding.isValid()) { // FIXME: iframes used as images trigger this. We should deal with them correctly. return; } String text = accumulator.serializeNodes(*document->documentElement(), 0, IncludeNode); CString frameHTML = textEncoding.encode(text, EntitiesForUnencodables); m_resources->append(Resource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length()))); m_resourceURLs.add(url); for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) { Node* node = *iter; if (!node->isElementNode()) continue; Element* element = toElement(node); // We have to process in-line style as it might contain some resources (typically background images). if (element->isStyledElement()) retrieveResourcesForProperties(toStyledElement(element)->inlineStyle(), document); if (isHTMLImageElement(element)) { HTMLImageElement* imageElement = toHTMLImageElement(element); URL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr)); CachedImage* cachedImage = imageElement->cachedImage(); addImageToResources(cachedImage, imageElement->renderer(), url); } else if (element->hasTagName(HTMLNames::linkTag)) { HTMLLinkElement* linkElement = toHTMLLinkElement(element); if (CSSStyleSheet* sheet = linkElement->sheet()) { URL url = document->completeURL(linkElement->getAttribute(HTMLNames::hrefAttr)); serializeCSSStyleSheet(sheet, url); ASSERT(m_resourceURLs.contains(url)); } } else if (isHTMLStyleElement(element)) { if (CSSStyleSheet* sheet = toHTMLStyleElement(element)->sheet()) serializeCSSStyleSheet(sheet, URL()); } } for (Frame* childFrame = frame->tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) serializeFrame(childFrame); }
Node* V8GCController::opaqueRootForGC(v8::Isolate*, Node* node) { ASSERT(node); // FIXME: Remove the special handling for image elements. // Maybe should image elements be active DOM nodes? // See https://code.google.com/p/chromium/issues/detail?id=164882 if (node->inDocument() || (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity())) { Document& document = node->document(); if (HTMLImportsController* controller = document.importsController()) return controller->master(); return &document; } if (node->isAttributeNode()) { Node* ownerElement = toAttr(node)->ownerElement(); if (!ownerElement) return node; node = ownerElement; } while (Node* parent = node->parentOrShadowHostOrTemplateHostNode()) node = parent; return node; }
void DataTransfer::setDragImage(Element* element, int x, int y) { if (!canSetDragImage()) return; CachedImage* image; if (element && isHTMLImageElement(element) && !element->inDocument()) image = toHTMLImageElement(element)->cachedImage(); else image = 0; m_dragLocation = IntPoint(x, y); if (m_dragImageLoader && m_dragImage) m_dragImageLoader->stopLoading(m_dragImage); m_dragImage = image; if (m_dragImage) { if (!m_dragImageLoader) m_dragImageLoader = std::make_unique<DragImageLoader>(this); m_dragImageLoader->startLoading(m_dragImage); } m_dragImageElement = image ? 0 : element; updateDragImage(); }
void DataTransfer::setDragImage(Element* image, int x, int y) { ASSERT(image); if (!isForDragAndDrop()) return; IntPoint location(x, y); if (isHTMLImageElement(*image) && !image->isConnected()) setDragImageResource(toHTMLImageElement(*image).cachedImage(), location); else setDragImageElement(image, location); }
static void configureRequest(FetchRequest& request, ImageLoader::BypassMainWorldBehavior bypassBehavior, Element& element, const ClientHintsPreferences& clientHintsPreferences) { if (bypassBehavior == ImageLoader::BypassMainWorldCSP) request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); AtomicString crossOriginMode = element.fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) request.setCrossOriginAccessControl(element.document().securityOrigin(), crossOriginMode); if (clientHintsPreferences.shouldSendResourceWidth() && isHTMLImageElement(element)) request.setResourceWidth(toHTMLImageElement(element).resourceWidth()); }
void DataTransfer::setDragImage(Element* image, int x, int y, ExceptionState& exceptionState) { if (!isForDragAndDrop()) return; if (!image) { exceptionState.throwTypeError("setDragImage: Invalid first argument"); return; } IntPoint location(x, y); if (isHTMLImageElement(*image) && !image->inDocument()) setDragImageResource(toHTMLImageElement(*image).cachedImage(), location); else setDragImageElement(image, location); }
virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override { // A minor DOM GC can collect only Nodes. if (classId != WrapperTypeInfo::NodeClassId) return; // To make minor GC cycle time bounded, we limit the number of wrappers handled // by each minor GC cycle to 10000. This value was selected so that the minor // GC cycle time is bounded to 20 ms in a case where the new space size // is 16 MB and it is full of wrappers (which is almost the worst case). // Practically speaking, as far as I crawled real web applications, // the number of wrappers handled by each minor GC cycle is at most 3000. // So this limit is mainly for pathological micro benchmarks. const unsigned wrappersHandledByEachMinorGC = 10000; if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC) return; // Casting to a Handle is safe here, since the Persistent doesn't get GCd // during the GC prologue. ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = V8Node::toImpl(*wrapper); // A minor DOM GC can handle only node wrappers in the main world. // Note that node->wrapper().IsEmpty() returns true for nodes that // do not have wrappers in the main world. if (node->containsWrapper()) { const WrapperTypeInfo* type = toWrapperTypeInfo(*wrapper); ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); if (activeDOMObject && activeDOMObject->hasPendingActivity()) return; // FIXME: Remove the special handling for image elements. // The same special handling is in V8GCController::opaqueRootForGC(). // Maybe should image elements be active DOM nodes? // See https://code.google.com/p/chromium/issues/detail?id=164882 if (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity()) return; // FIXME: Remove the special handling for SVG elements. // We currently can't collect SVG Elements from minor gc, as we have // strong references from SVG property tear-offs keeping context SVG element alive. if (node->isSVGElement()) return; m_nodesInNewSpace.append(node); node->markV8CollectableDuringMinorGC(); } }
HTMLImageElement* HTMLMapElement::imageElement() { RefPtrWillBeRawPtr<HTMLCollection> images = document().images(); for (unsigned i = 0; Element* curr = images->item(i); ++i) { ASSERT(isHTMLImageElement(curr)); // The HTMLImageElement's useMap() value includes the '#' symbol at the beginning, // which has to be stripped off. HTMLImageElement& imageElement = toHTMLImageElement(*curr); String useMapName = imageElement.getAttribute(usemapAttr).string().substring(1); if (equalIgnoringCase(useMapName, m_name)) return &imageElement; } return nullptr; }
void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override { if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId) { return; } // MinorGC does not collect objects because it may be expensive to // update references during minorGC if (classId == WrapperTypeInfo::ObjectClassId) { v8::Persistent<v8::Object>::Cast(*value).MarkActive(); return; } v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value)); ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper)); const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) { v8::Persistent<v8::Object>::Cast(*value).MarkActive(); return; } if (classId == WrapperTypeInfo::NodeClassId) { ASSERT(V8Node::hasInstance(wrapper, m_isolate)); Node* node = V8Node::toImpl(wrapper); if (node->hasEventListeners()) { v8::Persistent<v8::Object>::Cast(*value).MarkActive(); return; } // FIXME: Remove the special handling for image elements. // The same special handling is in V8GCController::opaqueRootForGC(). // Maybe should image elements be active DOM nodes? // See https://code.google.com/p/chromium/issues/detail?id=164882 if (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity()) { v8::Persistent<v8::Object>::Cast(*value).MarkActive(); return; } // FIXME: Remove the special handling for SVG elements. // We currently can't collect SVG Elements from minor gc, as we have // strong references from SVG property tear-offs keeping context SVG element alive. if (node->isSVGElement()) { v8::Persistent<v8::Object>::Cast(*value).MarkActive(); return; } } }
// FIXME: This doesn't take into account the animation timeline so animations will not // restart on page load, nor will two animations in different pages have different timelines. Image* ImageResource::svgImageForLayoutObject(const LayoutObject* layoutObject) { if (!layoutObject) return Image::nullImage(); ImageForContainerMap::iterator it = m_imageForContainerMap->find(layoutObject); if (it == m_imageForContainerMap->end()) return Image::nullImage(); RefPtr<SVGImageForContainer> imageForContainer = it->value; ASSERT(!imageForContainer->size().isEmpty()); Node* node = layoutObject->node(); if (node && isHTMLImageElement(node)) { const AtomicString& urlString = toHTMLImageElement(node)->imageSourceURL(); KURL url = node->document().completeURL(urlString); imageForContainer->setURL(url); } return imageForContainer.get(); }
QVariant QtPixmapRuntime::toQt(JSContextRef context, JSObjectRef obj, QMetaType::Type hint, JSValueRef* exception) { if (!obj) return emptyVariantForHint(hint); if (JSValueIsObjectOfClass(context, obj, QtPixmapRuntime::getClassRef())) { QVariant* originalVariant = static_cast<QVariant*>(JSObjectGetPrivate(obj)); if (hint == qMetaTypeId<QPixmap>()) return QVariant::fromValue<QPixmap>(toPixmap(*originalVariant)); if (hint == qMetaTypeId<QImage>()) return QVariant::fromValue<QImage>(toImage(*originalVariant)); } JSObject* jsObject = ::toJS(obj); if (!jsObject->inherits(&JSHTMLImageElement::s_info)) return emptyVariantForHint(hint); JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(jsObject); HTMLImageElement* imageElement = toHTMLImageElement(elementJSWrapper->impl()); if (!imageElement) return emptyVariantForHint(hint); CachedImage* cachedImage = imageElement->cachedImage(); if (!cachedImage) return emptyVariantForHint(hint); Image* image = cachedImage->imageForRenderer(imageElement->renderer()); if (!image) return emptyVariantForHint(hint); QPixmap* pixmap = image->nativeImageForCurrentFrame(); if (!pixmap) return emptyVariantForHint(hint); return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>())) ? QVariant::fromValue<QPixmap>(*pixmap) : QVariant::fromValue<QImage>(pixmap->toImage()); }
static JSValueRef assignToHTMLImageElement(JSContextRef context, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { if (!argumentCount) return JSValueMakeUndefined(context); JSObjectRef objectArg = JSValueToObject(context, arguments[0], exception); if (!objectArg) return JSValueMakeUndefined(context); JSObject* jsObject = ::toJS(objectArg); if (!jsObject->inherits(&JSHTMLImageElement::s_info)) return JSValueMakeUndefined(context); QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object)); // We now know that we have a valid <img> element as the argument, we can attach the pixmap to it. RefPtr<StillImage> stillImage = WebCore::StillImage::create(toPixmap(data)); HTMLImageElement* imageElement = toHTMLImageElement(static_cast<JSHTMLImageElement*>(jsObject)->impl()); imageElement->setCachedImage(new CachedImage(stillImage.get())); return JSValueMakeUndefined(context); }
void ImagePainter::paintIntoRect(GraphicsContext* context, const LayoutRect& rect) { IntRect alignedRect = pixelSnappedIntRect(rect); if (!m_renderImage.imageResource()->hasImage() || m_renderImage.imageResource()->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0) return; RefPtr<Image> img = m_renderImage.imageResource()->image(alignedRect.width(), alignedRect.height()); if (!img || img->isNull()) return; HTMLImageElement* imageElt = isHTMLImageElement(m_renderImage.node()) ? toHTMLImageElement(m_renderImage.node()) : 0; CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; Image* image = img.get(); InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(m_renderImage, context, image, image, alignedRect.size()); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(m_renderImage)); // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::willPaintImage(&m_renderImage); InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); context->setImageInterpolationQuality(interpolationQuality); context->drawImage(image, alignedRect, compositeOperator, m_renderImage.shouldRespectImageOrientation()); context->setImageInterpolationQuality(previousInterpolationQuality); InspectorInstrumentation::didPaintImage(&m_renderImage); }