void HTMLLabelElement::defaultEventHandler(Event* evt) { if (evt->type() == EventTypeNames::click && !m_processingClick) { RefPtrWillBeRawPtr<HTMLElement> element = control(); // If we can't find a control or if the control received the click // event, then there's no need for us to do anything. if (!element || (evt->target() && element->containsIncludingShadowDOM(evt->target()->toNode()))) return; if (evt->target() && isInInteractiveContent(evt->target()->toNode())) return; // Behaviour of label element is as follows: // - If there is double click, two clicks will be passed to control // element. Control element will *not* be focused. // - If there is selection of label element by dragging, no click // event is passed. Also, no focus on control element. // - If there is already a selection on label element and then label // is clicked, then click event is passed to control element and // control element is focused. bool isLabelTextSelected = false; // If the click is not simulated and the text of the label element // is selected by dragging over it, then return without passing the // click event to control element. // Note: check if it is a MouseEvent because a click event may // not be an instance of a MouseEvent if created by document.createEvent(). if (evt->isMouseEvent() && toMouseEvent(evt)->hasPosition()) { if (LocalFrame* frame = document().frame()) { // Check if there is a selection and click is not on the // selection. if (layoutObject() && layoutObject()->isSelectable() && frame->selection().isRange() && !frame->eventHandler().selectionController().mouseDownWasSingleClickInSelection()) isLabelTextSelected = true; // If selection is there and is single click i.e. text is // selected by dragging over label text, then return. // Click count >=2, meaning double click or triple click, // should pass click event to control element. // Only in case of drag, *neither* we pass the click event, // *nor* we focus the control element. if (isLabelTextSelected && frame->eventHandler().clickCount() == 1) return; } } m_processingClick = true; document().updateLayoutIgnorePendingStylesheets(); if (element->isMouseFocusable()) { // If the label is *not* selected, or if the click happened on // selection of label, only then focus the control element. // In case of double click or triple click, selection will be there, // so do not focus the control element. if (!isLabelTextSelected) element->focus(FocusParams(SelectionBehaviorOnFocus::Restore, WebFocusTypeMouse, nullptr)); } // Click the corresponding control. element->dispatchSimulatedClick(evt); m_processingClick = false; evt->setDefaultHandled(); } HTMLElement::defaultEventHandler(evt); }
PassRefPtrWillBeRawPtr<HTMLLabelElement> HTMLLabelElement::create(Document& document, HTMLFormElement* form) { RefPtrWillBeRawPtr<HTMLLabelElement> labelElement = adoptRefWillBeNoop(new HTMLLabelElement(document, form)); return labelElement.release(); }
static PassRefPtrWillBeRawPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> value, v8::Isolate* isolate, bool& succeeded) { succeeded = true; // Create default options. RefPtrWillBeRawPtr<PositionOptions> options = PositionOptions::create(); // Argument is optional (hence undefined is allowed), and null is allowed. if (isUndefinedOrNull(value)) { // Use default options. return options.release(); } // Given the above test, this will always yield an object. v8::Local<v8::Object> object = value->ToObject(); // For all three properties, we apply the following ... // - If the getter or the property's valueOf method throws an exception, we // quit so as not to risk overwriting the exception. // - If the value is absent or undefined, we don't override the default. v8::Local<v8::Value> enableHighAccuracyValue = object->Get(v8AtomicString(isolate, "enableHighAccuracy")); if (enableHighAccuracyValue.IsEmpty()) { succeeded = false; return nullptr; } if (!enableHighAccuracyValue->IsUndefined()) { v8::Local<v8::Boolean> enableHighAccuracyBoolean = enableHighAccuracyValue->ToBoolean(); if (enableHighAccuracyBoolean.IsEmpty()) { succeeded = false; return nullptr; } options->setEnableHighAccuracy(enableHighAccuracyBoolean->Value()); } v8::Local<v8::Value> timeoutValue = object->Get(v8AtomicString(isolate, "timeout")); if (timeoutValue.IsEmpty()) { succeeded = false; return nullptr; } if (!timeoutValue->IsUndefined()) { v8::Local<v8::Number> timeoutNumber = timeoutValue->ToNumber(); if (timeoutNumber.IsEmpty()) { succeeded = false; return nullptr; } double timeoutDouble = timeoutNumber->Value(); // If the value is positive infinity, there's nothing to do. if (!(std::isinf(timeoutDouble) && timeoutDouble > 0)) { v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32(); if (timeoutInt32.IsEmpty()) { succeeded = false; return nullptr; } // Wrap to int32 and force non-negative to match behavior of window.setTimeout. options->setTimeout(max(0, timeoutInt32->Value())); } } v8::Local<v8::Value> maximumAgeValue = object->Get(v8AtomicString(isolate, "maximumAge")); if (maximumAgeValue.IsEmpty()) { succeeded = false; return nullptr; } if (!maximumAgeValue->IsUndefined()) { v8::Local<v8::Number> maximumAgeNumber = maximumAgeValue->ToNumber(); if (maximumAgeNumber.IsEmpty()) { succeeded = false; return nullptr; } double maximumAgeDouble = maximumAgeNumber->Value(); if (std::isinf(maximumAgeDouble) && maximumAgeDouble > 0) { // If the value is positive infinity, clear maximumAge. options->clearMaximumAge(); } else { v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32(); if (maximumAgeInt32.IsEmpty()) { succeeded = false; return nullptr; } // Wrap to int32 and force non-negative to match behavior of window.setTimeout. options->setMaximumAge(max(0, maximumAgeInt32->Value())); } } return options.release(); }
PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) { CSSValuePool& pool = cssValuePool(); RefPtrWillBeRawPtr<CSSBasicShape> basicShapeValue; switch (basicShape->type()) { case BasicShape::BasicShapeRectangleType: { const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create(); rectangleValue->setX(pool.createValue(rectangle->x(), style)); rectangleValue->setY(pool.createValue(rectangle->y(), style)); rectangleValue->setWidth(pool.createValue(rectangle->width(), style)); rectangleValue->setHeight(pool.createValue(rectangle->height(), style)); rectangleValue->setRadiusX(pool.createValue(rectangle->cornerRadiusX(), style)); rectangleValue->setRadiusY(pool.createValue(rectangle->cornerRadiusY(), style)); basicShapeValue = rectangleValue.release(); break; } case BasicShape::DeprecatedBasicShapeCircleType: { const DeprecatedBasicShapeCircle* circle = static_cast<const DeprecatedBasicShapeCircle*>(basicShape); RefPtrWillBeRawPtr<CSSDeprecatedBasicShapeCircle> circleValue = CSSDeprecatedBasicShapeCircle::create(); circleValue->setCenterX(pool.createValue(circle->centerX(), style)); circleValue->setCenterY(pool.createValue(circle->centerY(), style)); circleValue->setRadius(pool.createValue(circle->radius(), style)); basicShapeValue = circleValue.release(); break; } case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); circleValue->setCenterX(valueForCenterCoordinate(pool, style, circle->centerX())); circleValue->setCenterY(valueForCenterCoordinate(pool, style, circle->centerY())); circleValue->setRadius(basicShapeRadiusToCSSValue(pool, style, circle->radius())); basicShapeValue = circleValue.release(); break; } case BasicShape::DeprecatedBasicShapeEllipseType: { const DeprecatedBasicShapeEllipse* ellipse = static_cast<const DeprecatedBasicShapeEllipse*>(basicShape); RefPtrWillBeRawPtr<CSSDeprecatedBasicShapeEllipse> ellipseValue = CSSDeprecatedBasicShapeEllipse::create(); ellipseValue->setCenterX(pool.createValue(ellipse->centerX(), style)); ellipseValue->setCenterY(pool.createValue(ellipse->centerY(), style)); ellipseValue->setRadiusX(pool.createValue(ellipse->radiusX(), style)); ellipseValue->setRadiusY(pool.createValue(ellipse->radiusY(), style)); basicShapeValue = ellipseValue.release(); break; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); ellipseValue->setCenterX(valueForCenterCoordinate(pool, style, ellipse->centerX())); ellipseValue->setCenterY(valueForCenterCoordinate(pool, style, ellipse->centerY())); ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusX())); ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusY())); basicShapeValue = ellipseValue.release(); break; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); polygonValue->setWindRule(polygon->windRule()); const Vector<Length>& values = polygon->values(); for (unsigned i = 0; i < values.size(); i += 2) polygonValue->appendPoint(pool.createValue(values.at(i), style), pool.createValue(values.at(i + 1), style)); basicShapeValue = polygonValue.release(); break; } case BasicShape::BasicShapeInsetRectangleType: { const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create(); rectangleValue->setTop(cssValuePool().createValue(rectangle->top())); rectangleValue->setRight(cssValuePool().createValue(rectangle->right())); rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom())); rectangleValue->setLeft(cssValuePool().createValue(rectangle->left())); rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX())); rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY())); basicShapeValue = rectangleValue.release(); break; } case BasicShape::BasicShapeInsetType: { const BasicShapeInset* inset = static_cast<const BasicShapeInset*>(basicShape); RefPtrWillBeRawPtr<CSSBasicShapeInset> insetValue = CSSBasicShapeInset::create(); insetValue->setTop(CSSPrimitiveValue::create(inset->top())); insetValue->setRight(CSSPrimitiveValue::create(inset->right())); insetValue->setBottom(CSSPrimitiveValue::create(inset->bottom())); insetValue->setLeft(CSSPrimitiveValue::create(inset->left())); insetValue->setTopLeftRadius(CSSPrimitiveValue::create(inset->topLeftRadius())); insetValue->setTopRightRadius(CSSPrimitiveValue::create(inset->topRightRadius())); insetValue->setBottomRightRadius(CSSPrimitiveValue::create(inset->bottomRightRadius())); insetValue->setBottomLeftRadius(CSSPrimitiveValue::create(inset->bottomLeftRadius())); basicShapeValue = insetValue.release(); break; } default: break; } if (basicShape->layoutBox() != BoxMissing) basicShapeValue->setLayoutBox(pool.createValue(basicShape->layoutBox())); return pool.createValue(basicShapeValue.release()); }
TEST(FileInputTypeTest, ignoreDroppedNonNativeFiles) { const RefPtrWillBeRawPtr<Document> document = Document::create(); const RefPtrWillBeRawPtr<HTMLInputElement> input = HTMLInputElement::create(*document, nullptr, false); const RefPtrWillBeRawPtr<InputType> fileInput = FileInputType::create(*input); const RefPtrWillBeRawPtr<DataObject> nativeFileRawDragData = DataObject::create(); const DragData nativeFileDragData(nativeFileRawDragData.get(), IntPoint(), IntPoint(), DragOperationCopy); nativeFileDragData.platformData()->add(File::create("/native/path")); nativeFileDragData.platformData()->setFilesystemId("fileSystemId"); fileInput->receiveDroppedFiles(&nativeFileDragData); EXPECT_EQ("fileSystemId", fileInput->droppedFileSystemId()); ASSERT_EQ(1u, fileInput->files()->length()); EXPECT_EQ(String("/native/path"), fileInput->files()->item(0)->path()); const RefPtrWillBeRawPtr<DataObject> nonNativeFileRawDragData = DataObject::create(); const DragData nonNativeFileDragData(nonNativeFileRawDragData.get(), IntPoint(), IntPoint(), DragOperationCopy); FileMetadata metadata; metadata.length = 1234; const KURL url(ParsedURLStringTag(), "filesystem:http://example.com/isolated/hash/non-native-file"); nonNativeFileDragData.platformData()->add(File::createForFileSystemFile(url, metadata, File::IsUserVisible)); nonNativeFileDragData.platformData()->setFilesystemId("fileSystemId"); fileInput->receiveDroppedFiles(&nonNativeFileDragData); // Dropping non-native files should not change the existing files. EXPECT_EQ("fileSystemId", fileInput->droppedFileSystemId()); ASSERT_EQ(1u, fileInput->files()->length()); EXPECT_EQ(String("/native/path"), fileInput->files()->item(0)->path()); }
bool WebFrame::swap(WebFrame* frame) { using std::swap; RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this); // All child frames must be detached first. oldFrame->detachChildren(); // If the frame has been detached during detaching its children, return // immediately. // FIXME: There is no unit test for this condition, so one needs to be // written. if (!oldFrame->host()) return false; if (m_parent) { if (m_parent->m_firstChild == this) m_parent->m_firstChild = frame; if (m_parent->m_lastChild == this) m_parent->m_lastChild = frame; swap(m_parent, frame->m_parent); } if (m_previousSibling) { m_previousSibling->m_nextSibling = frame; swap(m_previousSibling, frame->m_previousSibling); } if (m_nextSibling) { m_nextSibling->m_previousSibling = frame; swap(m_nextSibling, frame->m_nextSibling); } if (m_opener) { m_opener->m_openedFrameTracker->remove(this); m_opener->m_openedFrameTracker->add(frame); swap(m_opener, frame->m_opener); } if (!m_openedFrameTracker->isEmpty()) { m_openedFrameTracker->updateOpener(frame); frame->m_openedFrameTracker.reset(m_openedFrameTracker.release()); } // Finally, clone the state of the current Frame into one matching // the type of the passed in WebFrame. // FIXME: This is a bit clunky; this results in pointless decrements and // increments of connected subframes. FrameOwner* owner = oldFrame->owner(); oldFrame->disconnectOwnerElement(); if (Frame* newFrame = toCoreFrame(frame)) { ASSERT(owner == newFrame->owner()); if (owner->isLocal()) { HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(owner); ownerElement->setContentFrame(*newFrame); if (newFrame->isLocalFrame()) ownerElement->setWidget(toLocalFrame(newFrame)->view()); } } else if (frame->isWebLocalFrame()) { toWebLocalFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name(), nullAtom); } else { toWebRemoteFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name()); } return true; }
void ImageDocument::createDocumentStructure(bool loadingMultipartContent) { RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*this); appendChild(rootElement); rootElement->insertedByParser(); if (frame()) frame()->loader().dispatchDocumentElementAvailable(); // Normally, ImageDocument creates an HTMLImageElement that doesn't actually load // anything, and the ImageDocument routes the main resource data into the HTMLImageElement's // ImageResource. However, the main resource pipeline doesn't know how to handle multipart content. // For multipart content, we instead stop streaming data through the main resource and re-request // the data directly. if (loadingMultipartContent) loader()->stopLoading(); RefPtrWillBeRawPtr<HTMLHeadElement> head = HTMLHeadElement::create(*this); RefPtrWillBeRawPtr<HTMLMetaElement> meta = HTMLMetaElement::create(*this); meta->setAttribute(nameAttr, "viewport"); meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1"); head->appendChild(meta); RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*this); body->setAttribute(styleAttr, "margin: 0px;"); if (frame()) frame()->loader().client()->dispatchWillInsertBody(); m_imageElement = HTMLImageElement::create(*this); m_imageElement->setAttribute(styleAttr, "-webkit-user-select: none"); // If the image is multipart, we neglect to mention to the HTMLImageElement that it's in an // ImageDocument, so that it requests the image normally. if (!loadingMultipartContent) m_imageElement->setLoadingImageDocument(); m_imageElement->setSrc(url().string()); body->appendChild(m_imageElement.get()); if (shouldShrinkToFit()) { // Add event listeners RefPtrWillBeRawPtr<EventListener> listener = ImageEventListener::create(this); if (LocalDOMWindow* domWindow = this->domWindow()) domWindow->addEventListener("resize", listener, false); if (m_shrinkToFitMode == Desktop) m_imageElement->addEventListener("click", listener.release(), false); } rootElement->appendChild(head); rootElement->appendChild(body); if (loadingMultipartContent) finishedParsing(); }
SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) { SMILTime earliestFireTime = SMILTime::unresolved(); #if ENABLE(ASSERT) // This boolean will catch any attempts to schedule/unschedule scheduledAnimations during this critical section. // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply. m_preventScheduledAnimationsChanges = true; #endif if (m_documentOrderIndexesDirty) updateDocumentOrderIndexes(); WillBeHeapHashSet<ElementAttributePair> invalidKeys; using AnimationsVector = WillBeHeapVector<RefPtrWillBeMember<SVGSMILElement>>; AnimationsVector animationsToApply; for (const auto& entry : m_scheduledAnimations) { if (!entry.key.first || entry.value->isEmpty()) { invalidKeys.add(entry.key); continue; } AnimationsLinkedHashSet* scheduled = entry.value.get(); // Sort according to priority. Elements with later begin time have higher priority. // In case of a tie, document order decides. // FIXME: This should also consider timing relationships between the elements. Dependents // have higher priority. AnimationsVector scheduledAnimations; copyToVector(*scheduled, scheduledAnimations); std::sort(scheduledAnimations.begin(), scheduledAnimations.end(), PriorityCompare(elapsed)); SVGSMILElement* resultElement = nullptr; for (const auto& itAnimation : scheduledAnimations) { SVGSMILElement* animation = itAnimation.get(); ASSERT(animation->timeContainer() == this); ASSERT(animation->targetElement()); ASSERT(animation->hasValidAttributeName()); // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair. // FIXME: we should ensure that resultElement is of an appropriate type. if (!resultElement) { if (!animation->hasValidAttributeType()) continue; resultElement = animation; } // This will calculate the contribution from the animation and add it to the resultsElement. if (!animation->progress(elapsed, resultElement, seekToTime) && resultElement == animation) resultElement = nullptr; SMILTime nextFireTime = animation->nextProgressTime(); if (nextFireTime.isFinite()) earliestFireTime = std::min(nextFireTime, earliestFireTime); } if (resultElement) animationsToApply.append(resultElement); } m_scheduledAnimations.removeAll(invalidKeys); std::sort(animationsToApply.begin(), animationsToApply.end(), PriorityCompare(elapsed)); unsigned animationsToApplySize = animationsToApply.size(); if (!animationsToApplySize) { #if ENABLE(ASSERT) m_preventScheduledAnimationsChanges = false; #endif return earliestFireTime; } // Apply results to target elements. for (unsigned i = 0; i < animationsToApplySize; ++i) animationsToApply[i]->applyResultsToTarget(); #if ENABLE(ASSERT) m_preventScheduledAnimationsChanges = false; #endif for (unsigned i = 0; i < animationsToApplySize; ++i) { if (animationsToApply[i]->inDocument() && animationsToApply[i]->isSVGDiscardElement()) { RefPtrWillBeRawPtr<SVGSMILElement> animDiscard = animationsToApply[i]; RefPtrWillBeRawPtr<SVGElement> targetElement = animDiscard->targetElement(); if (targetElement && targetElement->inDocument()) { targetElement->remove(IGNORE_EXCEPTION); ASSERT(!targetElement->inDocument()); } if (animDiscard->inDocument()) { animDiscard->remove(IGNORE_EXCEPTION); ASSERT(!animDiscard->inDocument()); } } } return earliestFireTime; }
PassRefPtrWillBeRawPtr<Text> GranularityStrategyTest::appendTextNode(const String& data) { RefPtrWillBeRawPtr<Text> text = document().createTextNode(data); document().body()->appendChild(text); return text.release(); }
bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode, double* compilationFinishTime) { ASSERT(m_alreadyStarted); if (sourceCode.isEmpty()) return true; RefPtrWillBeRawPtr<Document> elementDocument(m_element->document()); RefPtrWillBeRawPtr<Document> contextDocument = elementDocument->contextDocument().get(); if (!contextDocument) return true; LocalFrame* frame = contextDocument->frame(); const ContentSecurityPolicy* csp = elementDocument->contentSecurityPolicy(); bool shouldBypassMainWorldCSP = (frame && frame->script().shouldBypassMainWorldCSP()) || csp->allowScriptWithNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)) || csp->allowScriptWithHash(sourceCode.source()); if (!m_isExternalScript && (!shouldBypassMainWorldCSP && !csp->allowInlineScript(elementDocument->url(), m_startLineNumber, sourceCode.source()))) { return false; } if (m_isExternalScript) { ScriptResource* resource = m_resource ? m_resource.get() : sourceCode.resource(); if (resource && !resource->mimeTypeAllowedByNosniff()) { contextDocument->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + resource->url().elidedString() + "' because its MIME type ('" + resource->mimeType() + "') is not executable, and strict MIME type checking is enabled.")); return false; } if (resource && resource->mimeType().lower().startsWith("image/")) { contextDocument->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + resource->url().elidedString() + "' because its MIME type ('" + resource->mimeType() + "') is not executable.")); UseCounter::count(frame, UseCounter::BlockedSniffingImageToScript); return false; } } // FIXME: Can this be moved earlier in the function? // Why are we ever attempting to execute scripts without a frame? if (!frame) return true; AccessControlStatus corsCheck = NotSharableCrossOrigin; if (!m_isExternalScript || (sourceCode.resource() && sourceCode.resource()->passesAccessControlCheck(m_element->document().securityOrigin()))) corsCheck = SharableCrossOrigin; if (m_isExternalScript) { const KURL resourceUrl = sourceCode.resource()->resourceRequest().url(); if (!SubresourceIntegrity::CheckSubresourceIntegrity(*m_element, sourceCode.source(), sourceCode.resource()->url(), *sourceCode.resource())) { return false; } } const bool isImportedScript = contextDocument != elementDocument; // http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block step 2.3 // with additional support for HTML imports. IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_isExternalScript || isImportedScript ? contextDocument.get() : 0); if (isHTMLScriptLoader(m_element)) contextDocument->pushCurrentScript(toHTMLScriptElement(m_element)); // Create a script from the script element node, using the script // block's source and the script block's type. // Note: This is where the script is compiled and actually executed. frame->script().executeScriptInMainWorld(sourceCode, corsCheck, compilationFinishTime); if (isHTMLScriptLoader(m_element)) { ASSERT(contextDocument->currentScript() == m_element); contextDocument->popCurrentScript(); } return true; }
bool MediaControls::initializeControls() { TrackExceptionState exceptionState; if (document().settings() && document().settings()->mediaControlsOverlayPlayButtonEnabled()) { RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = MediaControlOverlayEnclosureElement::create(*this); RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButton = MediaControlOverlayPlayButtonElement::create(*this); m_overlayPlayButton = overlayPlayButton.get(); overlayEnclosure->appendChild(overlayPlayButton.release(), exceptionState); if (exceptionState.hadException()) return false; m_overlayEnclosure = overlayEnclosure.get(); appendChild(overlayEnclosure.release(), exceptionState); if (exceptionState.hadException()) return false; } // Create an enclosing element for the panel so we can visually offset the controls correctly. RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaControlPanelEnclosureElement::create(*this); RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(*this); RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(*this); m_playButton = playButton.get(); panel->appendChild(playButton.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(*this); m_timeline = timeline.get(); panel->appendChild(timeline.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this); m_currentTimeDisplay = currentTimeDisplay.get(); m_currentTimeDisplay->hide(); panel->appendChild(currentTimeDisplay.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this); m_durationDisplay = durationDisplay.get(); panel->appendChild(durationDisplay.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlMuteButtonElement::create(*this); m_muteButton = muteButton.get(); panel->appendChild(muteButton.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVolumeSliderElement::create(*this); m_volumeSlider = slider.get(); panel->appendChild(slider.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this); m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); panel->appendChild(toggleClosedCaptionsButton.release(), exceptionState); if (exceptionState.hadException()) return false; RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = MediaControlFullscreenButtonElement::create(*this); m_fullScreenButton = fullscreenButton.get(); panel->appendChild(fullscreenButton.release(), exceptionState); if (exceptionState.hadException()) return false; m_panel = panel.get(); enclosure->appendChild(panel.release(), exceptionState); if (exceptionState.hadException()) return false; m_enclosure = enclosure.get(); appendChild(enclosure.release(), exceptionState); if (exceptionState.hadException()) return false; return true; }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::createPropertyForAnimation(const String& value) { if (isAnimatingSVGDom()) { // SVG DOM animVal animation code-path. if (m_type == AnimatedTransformList) { // TransformList must be animated via <animateTransform>, // and its {from,by,to} attribute values needs to be parsed w.r.t. its "type" attribute. // Spec: http://www.w3.org/TR/SVG/single-page.html#animate-AnimateTransformElement ASSERT(m_animationElement); SVGTransformType transformType = toSVGAnimateTransformElement(m_animationElement)->transformType(); return SVGTransformList::create(transformType, value); } ASSERT(m_animatedProperty); return m_animatedProperty->currentValueBase()->cloneForAnimation(value); } ASSERT(isAnimatingCSSProperty()); // CSS properties animation code-path. // Create a basic instance of the corresponding SVG property. // The instance will not have full context info. (e.g. SVGLengthMode) switch (m_type) { case AnimatedColor: return SVGColorProperty::create(value.isEmpty() ? StyleColor::currentColor() : CSSParser::colorFromRGBColorString(value)); case AnimatedNumber: { RefPtrWillBeRawPtr<SVGNumber> property = SVGNumber::create(); property->setValueAsString(value, IGNORE_EXCEPTION); return property.release(); } case AnimatedLength: { RefPtrWillBeRawPtr<SVGLength> property = SVGLength::create(LengthModeOther); property->setValueAsString(value, IGNORE_EXCEPTION); return property.release(); } case AnimatedLengthList: { RefPtrWillBeRawPtr<SVGLengthList> property = SVGLengthList::create(LengthModeOther); property->setValueAsString(value, IGNORE_EXCEPTION); return property.release(); } case AnimatedString: { RefPtrWillBeRawPtr<SVGString> property = SVGString::create(); property->setValueAsString(value, IGNORE_EXCEPTION); return property.release(); } // These types don't appear in the table in SVGElement::animatedPropertyTypeForCSSAttribute() and thus don't need support. case AnimatedAngle: case AnimatedBoolean: case AnimatedEnumeration: case AnimatedInteger: case AnimatedIntegerOptionalInteger: case AnimatedNumberList: case AnimatedNumberOptionalNumber: case AnimatedPath: case AnimatedPoint: case AnimatedPoints: case AnimatedPreserveAspectRatio: case AnimatedRect: case AnimatedStringList: case AnimatedTransform: case AnimatedTransformList: ASSERT_NOT_REACHED(); case AnimatedUnknown: ASSERT_NOT_REACHED(); }; ASSERT_NOT_REACHED(); return nullptr; }
PassRefPtrWillBeRawPtr<HTMLSummaryElement> HTMLSummaryElement::create(Document& document) { RefPtrWillBeRawPtr<HTMLSummaryElement> summary = adoptRefWillBeNoop(new HTMLSummaryElement(document)); summary->ensureUserAgentShadowRoot(); return summary.release(); }
TEST_F(AnimationInterpolationEffectTest, MultipleInterpolations) { RefPtrWillBeRawPtr<InterpolationEffect> interpolationEffect = InterpolationEffect::create(); interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(10), InterpolableNumber::create(15)), RefPtr<TimingFunction>(), 1, 2, 1, 3); interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(0), InterpolableNumber::create(1)), LinearTimingFunction::shared(), 0, 1, 0, 1); interpolationEffect->addInterpolation(Interpolation::create(InterpolableNumber::create(1), InterpolableNumber::create(6)), CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease), 0.5, 1.5, 0.5, 1.5); OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > activeInterpolations = nullptr; interpolationEffect->getActiveInterpolations(-0.5, duration, activeInterpolations); EXPECT_EQ(0ul, activeInterpolations->size()); interpolationEffect->getActiveInterpolations(0, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(0, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(0.5, duration, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(0.5f, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(1, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1, duration, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(5.0282884f, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1, duration * 1000, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(5.0120168f, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1.5, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(12.5f, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(2, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0))); }
PassRefPtrWillBeRawPtr<StyleRuleKeyframe> CSSParser::parseKeyframeRule(const CSSParserContext& context, const String& rule) { RefPtrWillBeRawPtr<StyleRuleBase> keyframe = CSSParserImpl::parseRule(rule, context, nullptr, CSSParserImpl::KeyframeRules); return toStyleRuleKeyframe(keyframe.get()); }
// This test checks that Documunt::linkManifest() returns a value conform to the specification. TEST_F(DocumentTest, LinkManifest) { // Test the default result. EXPECT_EQ(0, document().linkManifest()); // Check that we use the first manifest with <link rel=manifest> RefPtrWillBeRawPtr<HTMLLinkElement> link = HTMLLinkElement::create(document(), false); link->setAttribute(blink::HTMLNames::relAttr, "manifest"); link->setAttribute(blink::HTMLNames::hrefAttr, "foo.json"); document().head()->appendChild(link); EXPECT_EQ(link, document().linkManifest()); RefPtrWillBeRawPtr<HTMLLinkElement> link2 = HTMLLinkElement::create(document(), false); link2->setAttribute(blink::HTMLNames::relAttr, "manifest"); link2->setAttribute(blink::HTMLNames::hrefAttr, "bar.json"); document().head()->insertBefore(link2, link.get()); EXPECT_EQ(link2, document().linkManifest()); document().head()->appendChild(link2); EXPECT_EQ(link, document().linkManifest()); // Check that crazy URLs are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, "http:foo.json"); EXPECT_EQ(link, document().linkManifest()); // Check that empty URLs are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, ""); EXPECT_EQ(link, document().linkManifest()); // Check that URLs from different origins are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, "http://example.org/manifest.json"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.example.org/manifest.json"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.bar/manifest.json"); EXPECT_EQ(link, document().linkManifest()); // More than one token in @rel is accepted. link->setAttribute(blink::HTMLNames::relAttr, "foo bar manifest"); EXPECT_EQ(link, document().linkManifest()); // Such as spaces around the token. link->setAttribute(blink::HTMLNames::relAttr, " manifest "); EXPECT_EQ(link, document().linkManifest()); // Check that rel=manifest actually matters. link->setAttribute(blink::HTMLNames::relAttr, ""); EXPECT_EQ(link2, document().linkManifest()); link->setAttribute(blink::HTMLNames::relAttr, "manifest"); // Check that link outside of the <head> are ignored. document().head()->removeChild(link.get(), ASSERT_NO_EXCEPTION); document().head()->removeChild(link2.get(), ASSERT_NO_EXCEPTION); EXPECT_EQ(0, document().linkManifest()); document().body()->appendChild(link); EXPECT_EQ(0, document().linkManifest()); document().head()->appendChild(link); document().head()->appendChild(link2); // Check that some attribute values do not have an effect. link->setAttribute(blink::HTMLNames::crossoriginAttr, "use-credentials"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hreflangAttr, "klingon"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::typeAttr, "image/gif"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::sizesAttr, "16x16"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::mediaAttr, "print"); EXPECT_EQ(link, document().linkManifest()); }
void XMLErrors::insertErrorMessageBlock() { // One or more errors occurred during parsing of the code. Display an error block to the user above // the normal content (the DOM tree is created manually and includes line/col info regarding // where the errors are located) // Create elements for display RefPtrWillBeRawPtr<Element> documentElement = m_document->documentElement(); if (!documentElement) { RefPtrWillBeRawPtr<Element> rootElement = m_document->createElement(htmlTag, true); RefPtrWillBeRawPtr<Element> body = m_document->createElement(bodyTag, true); rootElement->parserAppendChild(body); m_document->parserAppendChild(rootElement); documentElement = body.get(); } else if (documentElement->namespaceURI() == SVGNames::svgNamespaceURI) { RefPtrWillBeRawPtr<Element> rootElement = m_document->createElement(htmlTag, true); RefPtrWillBeRawPtr<Element> head = m_document->createElement(headTag, true); RefPtrWillBeRawPtr<Element> style = m_document->createElement(styleTag, true); head->parserAppendChild(style); style->parserAppendChild(m_document->createTextNode("html, body { height: 100% } parsererror + svg { width: 100%; height: 100% }")); style->finishParsingChildren(); rootElement->parserAppendChild(head); RefPtrWillBeRawPtr<Element> body = m_document->createElement(bodyTag, true); rootElement->parserAppendChild(body); m_document->parserRemoveChild(*documentElement); body->parserAppendChild(documentElement); m_document->parserAppendChild(rootElement); documentElement = body.get(); } String errorMessages = m_errorMessages.toString(); RefPtrWillBeRawPtr<Element> reportElement = createXHTMLParserErrorHeader(m_document, errorMessages); if (DocumentXSLT::hasTransformSourceDocument(*m_document)) { Vector<Attribute> attributes; attributes.append(Attribute(styleAttr, "white-space: normal")); RefPtrWillBeRawPtr<Element> paragraph = m_document->createElement(pTag, true); paragraph->parserSetAttributes(attributes); paragraph->parserAppendChild(m_document->createTextNode("This document was created as the result of an XSL transformation. The line and column numbers given are from the transformed result.")); reportElement->parserAppendChild(paragraph.release()); } Node* firstChild = documentElement->firstChild(); if (firstChild) documentElement->parserInsertBefore(reportElement, *firstChild); else documentElement->parserAppendChild(reportElement); // FIXME: Why do we need to call this manually? m_document->updateRenderTreeIfNeeded(); }
PassRefPtrWillBeRawPtr<HTMLObjectElement> HTMLObjectElement::create(Document& document, HTMLFormElement* form, bool createdByParser) { RefPtrWillBeRawPtr<HTMLObjectElement> element = adoptRefWillBeNoop(new HTMLObjectElement(document, form, createdByParser)); element->ensureUserAgentShadowRoot(); return element.release(); }
void TextFinder::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset) { if (reset) { // This is a brand new search, so we need to reset everything. // Scoping is just about to begin. m_scopingInProgress = true; // Need to keep the current identifier locally in order to finish the // request in case the frame is detached during the process. m_findRequestIdentifier = identifier; // Clear highlighting for this frame. LocalFrame* frame = ownerFrame().frame(); if (frame && frame->page() && frame->editor().markedTextMatchesAreHighlighted()) frame->page()->unmarkAllTextMatches(); // Clear the tickmarks and results cache. clearFindMatchesCache(); // Clear the counters from last operation. m_lastMatchCount = 0; m_nextInvalidateAfter = 0; m_resumeScopingFromRange = nullptr; // The view might be null on detached frames. if (frame && frame->page()) ownerFrame().viewImpl()->mainFrameImpl()->ensureTextFinder().m_framesScopingCount++; // Now, defer scoping until later to allow find operation to finish quickly. scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again. return; } if (!shouldScopeMatches(searchText)) { // Note that we want to defer the final update when resetting even if shouldScopeMatches returns false. // This is done in order to prevent sending a final message based only on the results of the first frame // since m_framesScopingCount would be 0 as other frames have yet to reset. finishCurrentScopingEffort(identifier); return; } WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl(); Position searchStart = firstPositionInNode(ownerFrame().frame()->document()); Position searchEnd = lastPositionInNode(ownerFrame().frame()->document()); ASSERT(searchStart.document() == searchEnd.document()); if (m_resumeScopingFromRange) { // This is a continuation of a scoping operation that timed out and didn't // complete last time around, so we should start from where we left off. ASSERT(m_resumeScopingFromRange->collapsed()); searchStart = m_resumeScopingFromRange->endPosition(); if (searchStart.document() != searchEnd.document()) return; } // This timeout controls how long we scope before releasing control. This // value does not prevent us from running for longer than this, but it is // periodically checked to see if we have exceeded our allocated time. const double maxScopingDuration = 0.1; // seconds int matchCount = 0; bool timedOut = false; double startTime = currentTime(); do { // Find next occurrence of the search string. // FIXME: (http://crbug.com/6818) This WebKit operation may run for longer // than the timeout value, and is not interruptible as it is currently // written. We may need to rewrite it with interruptibility in mind, or // find an alternative. Position resultStart; Position resultEnd; findPlainText(searchStart, searchEnd, searchText, options.matchCase ? 0 : CaseInsensitive, resultStart, resultEnd); if (resultStart == resultEnd) { // Not found. break; } RefPtrWillBeRawPtr<Range> resultRange = Range::create(*resultStart.document(), resultStart, resultEnd); if (resultRange->collapsed()) { // resultRange will be collapsed if the matched text spans over multiple TreeScopes. // FIXME: Show such matches to users. searchStart = resultEnd; continue; } ++matchCount; // Catch a special case where Find found something but doesn't know what // the bounding box for it is. In this case we set the first match we find // as the active rect. IntRect resultBounds = resultRange->boundingBox(); IntRect activeSelectionRect; if (m_locatingActiveRect) { activeSelectionRect = m_activeMatch.get() ? m_activeMatch->boundingBox() : resultBounds; } // If the Find function found a match it will have stored where the // match was found in m_activeSelectionRect on the current frame. If we // find this rect during scoping it means we have found the active // tickmark. bool foundActiveMatch = false; if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) { // We have found the active tickmark frame. mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &ownerFrame(); foundActiveMatch = true; // We also know which tickmark is active now. m_activeMatchIndexInCurrentFrame = matchCount - 1; // To stop looking for the active tickmark, we set this flag. m_locatingActiveRect = false; // Notify browser of new location for the selected rectangle. reportFindInPageSelection( ownerFrame().frameView()->contentsToWindow(resultBounds), m_activeMatchIndexInCurrentFrame + 1, identifier); } addMarker(resultRange.get(), foundActiveMatch); m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount)); // Set the new start for the search range to be the end of the previous // result range. There is no need to use a VisiblePosition here, // since findPlainText will use a TextIterator to go over the visible // text nodes. searchStart = resultEnd; m_resumeScopingFromRange = Range::create(*resultStart.document(), resultEnd, resultEnd); timedOut = (currentTime() - startTime) >= maxScopingDuration; } while (!timedOut); // Remember what we search for last time, so we can skip searching if more // letters are added to the search string (and last outcome was 0). m_lastSearchString = searchText; if (matchCount > 0) { ownerFrame().frame()->editor().setMarkedTextMatchesAreHighlighted(true); m_lastMatchCount += matchCount; // Let the mainframe know how much we found during this pass. mainFrameImpl->increaseMatchCount(matchCount, identifier); } if (timedOut) { // If we found anything during this pass, we should redraw. However, we // don't want to spam too much if the page is extremely long, so if we // reach a certain point we start throttling the redraw requests. if (matchCount > 0) invalidateIfNecessary(); // Scoping effort ran out of time, lets ask for another time-slice. scopeStringMatchesSoon( identifier, searchText, options, false); // don't reset. return; // Done for now, resume work later. } finishCurrentScopingEffort(identifier); }
PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document) { RefPtrWillBeRawPtr<HTMLOptionElement> option = adoptRefWillBeNoop(new HTMLOptionElement(document)); option->ensureUserAgentShadowRoot(); return option.release(); }
PassRefPtrWillBeRawPtr<Text> Text::replaceWholeText(const String& newText) { // Remove all adjacent text nodes, and replace the contents of this one. // Protect startText and endText against mutation event handlers removing the last ref RefPtrWillBeRawPtr<Text> startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this)); RefPtrWillBeRawPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this)); RefPtrWillBeRawPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away RefPtrWillBeRawPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal for (RefPtrWillBeRawPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) { RefPtrWillBeRawPtr<Node> nodeToRemove(n.release()); n = nodeToRemove->nextSibling(); parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); } if (this != endText) { Node* onePastEndText = endText->nextSibling(); for (RefPtrWillBeRawPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTextNode() && n->parentNode() == parent;) { RefPtrWillBeRawPtr<Node> nodeToRemove(n.release()); n = nodeToRemove->nextSibling(); parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); } } if (newText.isEmpty()) { if (parent && parentNode() == parent) parent->removeChild(this, IGNORE_EXCEPTION); return nullptr; } setData(newText); return protectedThis.release(); }