ssize_t DaemonSocketPDU::Receive(int aFd) { struct iovec iv; memset(&iv, 0, sizeof(iv)); iv.iov_base = GetData(0); iv.iov_len = GetAvailableSpace(); uint8_t cmsgbuf[CMSG_SPACE(sizeof(int)* MAX_NFDS)]; struct msghdr msg; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); ssize_t res = TEMP_FAILURE_RETRY(recvmsg(aFd, &msg, MSG_NOSIGNAL)); if (res < 0) { MOZ_ASSERT(errno != EBADF); /* internal error */ OnError("recvmsg", errno); return -1; } if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { return -1; } SetRange(0, res); struct cmsghdr* chdr = CMSG_FIRSTHDR(&msg); for (; chdr; chdr = CMSG_NXTHDR(&msg, chdr)) { if (NS_WARN_IF(!CMSGHDR_CONTAINS_FD(chdr))) { continue; } // Retrieve sent file descriptors. size_t fdCount = (chdr->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) / sizeof(int); for (size_t i = 0; i < fdCount; i++) { int* receivedFd = static_cast<int*>(CMSG_DATA(chdr)) + i; mReceivedFds.AppendElement(*receivedFd); } } return res; }
ssize_t DaemonSocketPDU::Receive(int aFd) { struct iovec iv; memset(&iv, 0, sizeof(iv)); iv.iov_base = GetData(0); iv.iov_len = GetAvailableSpace(); uint8_t cmsgbuf[CMSG_SPACE(sizeof(int))]; struct msghdr msg; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); ssize_t res = TEMP_FAILURE_RETRY(recvmsg(aFd, &msg, MSG_NOSIGNAL)); if (res < 0) { MOZ_ASSERT(errno != EBADF); /* internal error */ OnError("recvmsg", errno); return -1; } if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { return -1; } SetRange(0, res); struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); for (; chdr; chdr = CMSG_NXTHDR(&msg, chdr)) { if (NS_WARN_IF(!CMSGHDR_CONTAINS_FD(chdr))) { continue; } // Retrieve sent file descriptor. If multiple file descriptors // have been sent, we close all but the final one. mReceivedFd = *(static_cast<int*>(CMSG_DATA(chdr))); } return res; }
PRBool nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, PRBool* aIsLeftFloat, nsReflowStatus& aReflowStatus, PRBool aForceFit) { aReflowStatus = NS_FRAME_COMPLETE; // Save away the Y coordinate before placing the float. We will // restore mY at the end after placing the float. This is // necessary because any adjustments to mY during the float // placement are for the float only, not for any non-floating // content. nscoord saveY = mY; nsPlaceholderFrame* placeholder = aFloatCache->mPlaceholder; nsIFrame* floatFrame = placeholder->GetOutOfFlowFrame(); // Grab the float's display information const nsStyleDisplay* floatDisplay = floatFrame->GetStyleDisplay(); // The float's old region, so we can propagate damage. nsRect oldRegion = aFloatCache->mRegion; // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't // ``above'' another float that preceded it in the flow. mY = NS_MAX(mSpaceManager->GetLowestRegionTop() + BorderPadding().top, mY); // See if the float should clear any preceding floats... // XXX We need to mark this float somehow so that it gets reflowed // when floats are inserted before it. if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) { // XXXldb Does this handle vertical margins correctly? mY = ClearFloats(mY, floatDisplay->mBreakType); } // Get the band of available space GetAvailableSpace(mY, aForceFit); NS_ASSERTION(floatFrame->GetParent() == mBlock, "Float frame has wrong parent"); // Reflow the float nsMargin floatMargin; mBlock->ReflowFloat(*this, placeholder, floatMargin, aReflowStatus); #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsRect region = floatFrame->GetRect(); nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); printf("flowed float: "); nsFrame::ListTag(stdout, floatFrame); printf(" (%d,%d,%d,%d)\n", region.x, region.y, region.width, region.height); } #endif nsSize floatSize = floatFrame->GetSize() + nsSize(floatMargin.LeftRight(), floatMargin.TopBottom()); // Find a place to place the float. The CSS2 spec doesn't want // floats overlapping each other or sticking out of the containing // block if possible (CSS2 spec section 9.5.1, see the rule list). NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) || (NS_STYLE_FLOAT_RIGHT == floatDisplay->mFloats), "invalid float type"); // Can the float fit here? PRBool keepFloatOnSameLine = PR_FALSE; while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, aForceFit)) { if (mAvailSpaceRect.height <= 0) { // No space, nowhere to put anything. mY = saveY; return PR_FALSE; } // Nope. try to advance to the next band. if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay || eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) { mY += mAvailSpaceRect.height; GetAvailableSpace(mY, aForceFit); } else { // This quirk matches the one in nsBlockFrame::ReflowFloat // IE handles float tables in a very special way // see if the previous float is also a table and has "align" nsFloatCache* fc = mCurrentLineFloats.Head(); nsIFrame* prevFrame = nsnull; while (fc) { if (fc->mPlaceholder->GetOutOfFlowFrame() == floatFrame) { break; } prevFrame = fc->mPlaceholder->GetOutOfFlowFrame(); fc = fc->Next(); } if(prevFrame) { //get the frame type if (nsGkAtoms::tableOuterFrame == prevFrame->GetType()) { //see if it has "align=" // IE makes a difference between align and he float property nsIContent* content = prevFrame->GetContent(); if (content) { // we're interested only if previous frame is align=left // IE messes things up when "right" (overlapping frames) if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::align, NS_LITERAL_STRING("left"), eIgnoreCase)) { keepFloatOnSameLine = PR_TRUE; // don't advance to next line (IE quirkie behaviour) // it breaks rule CSS2/9.5.1/1, but what the hell // since we cannot evangelize the world break; } } } } // the table does not fit anymore in this line so advance to next band mY += mAvailSpaceRect.height; GetAvailableSpace(mY, aForceFit); // reflow the float again now since we have more space // XXXldb We really don't need to Reflow in a loop, we just need // to ComputeSize in a loop (once ComputeSize depends on // availableWidth, which should make this work again). mBlock->ReflowFloat(*this, placeholder, floatMargin, aReflowStatus); // Get the floats bounding box and margin information floatSize = floatFrame->GetSize() + nsSize(floatMargin.LeftRight(), floatMargin.TopBottom()); } } // If the float is continued, it will get the same absolute x value as its prev-in-flow // We don't worry about the geometry of the prev in flow, let the continuation // place and size itself as required. // Assign an x and y coordinate to the float. Note that the x,y // coordinates are computed <b>relative to the translation in the // spacemanager</b> which means that the impacted region will be // <b>inside</b> the border/padding area. PRBool isLeftFloat; nscoord floatX, floatY; if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) { isLeftFloat = PR_TRUE; floatX = mAvailSpaceRect.x; } else { isLeftFloat = PR_FALSE; if (!keepFloatOnSameLine) { floatX = mAvailSpaceRect.XMost() - floatSize.width; } else { // this is the IE quirk (see few lines above) // the table is kept in the same line: don't let it overlap the // previous float floatX = mAvailSpaceRect.x; } } *aIsLeftFloat = isLeftFloat; const nsMargin& borderPadding = BorderPadding(); floatY = mY - borderPadding.top; if (floatY < 0) { // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not // be higher than the top of its containing block." (Since the // containing block is the content edge of the block box, this // means the margin edge of the float can't be higher than the // content edge of the block that contains it.) floatY = 0; } // Place the float in the space manager // if the float split, then take up all of the vertical height if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) && (NS_UNCONSTRAINEDSIZE != mContentArea.height)) { floatSize.height = PR_MAX(floatSize.height, mContentArea.height - floatY); } nsRect region(floatX, floatY, floatSize.width, floatSize.height); // Don't send rectangles with negative margin-box width or height to // the space manager; it can't deal with them. if (region.width < 0) { // Preserve the right margin-edge for left floats and the left // margin-edge for right floats if (isLeftFloat) { region.x = region.XMost(); } region.width = 0; } if (region.height < 0) { region.height = 0; } #ifdef DEBUG nsresult rv = #endif mSpaceManager->AddRectRegion(floatFrame, region); NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement"); // Save away the floats region in the spacemanager, after making // it relative to the containing block's frame instead of relative // to the spacemanager translation (which is inset by the // border+padding). // XXX Maybe RecoverFloats should calc/add in the borderPadding itself? // It's kind of confusing to have the spacemanager translation be different // depending on what stage of reflow we're in. aFloatCache->mRegion = region + nsPoint(borderPadding.left, borderPadding.top); // If the float's dimensions have changed, note the damage in the // space manager. if (aFloatCache->mRegion != oldRegion) { // XXXwaterson conservative: we could probably get away with noting // less damage; e.g., if only height has changed, then only note the // area into which the float has grown or from which the float has // shrunk. nscoord top = NS_MIN(region.y, oldRegion.y); nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost()); mSpaceManager->IncludeInDamage(top, bottom); } #ifdef NOISY_SPACEMANAGER nscoord tx, ty; mSpaceManager->GetTranslation(tx, ty); nsFrame::ListTag(stdout, mBlock); printf(": FlowAndPlaceFloat: AddRectRegion: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n", tx, ty, mSpaceManagerX, mSpaceManagerY, aFloatCache->mRegion.x, aFloatCache->mRegion.y, aFloatCache->mRegion.width, aFloatCache->mRegion.height); #endif // Calculate the actual origin of the float frame's border rect // relative to the parent block; floatX/Y must be converted from space-manager // coordinates to parent coordinates, and the margin must be added in // to get the border rect nsPoint origin(borderPadding.left + floatMargin.left + floatX, borderPadding.top + floatMargin.top + floatY); // If float is relatively positioned, factor that in as well origin += floatFrame->GetRelativeOffset(floatDisplay); // Position the float and make sure and views are properly // positioned. We need to explicitly position its child views as // well, since we're moving the float after flowing it. floatFrame->SetPosition(origin); nsContainerFrame::PositionFrameView(floatFrame); nsContainerFrame::PositionChildViews(floatFrame); // Update the float combined area state nsRect combinedArea = floatFrame->GetOverflowRect() + origin; // XXX Floats should really just get invalidated here if necessary mFloatCombinedArea.UnionRect(combinedArea, mFloatCombinedArea); // Now restore mY mY = saveY; #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsRect r = floatFrame->GetRect(); nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); printf("placed float: "); nsFrame::ListTag(stdout, floatFrame); printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height); } #endif return PR_TRUE; }
PRBool nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, PRBool aForceFit) { // If the current Y coordinate is not impacted by any floats // then by definition the float fits. PRBool result = PR_TRUE; if (0 != mBand.GetFloatCount()) { // XXX We should allow overflow by up to half a pixel here (bug 21193). if (mAvailSpaceRect.width < aFloatSize.width) { // The available width is too narrow (and its been impacted by a // prior float) result = PR_FALSE; } } if (!result) return result; // At this point we know that there is enough horizontal space for // the float (somewhere). Lets see if there is enough vertical // space. if (NSCoordGreaterThan(aFloatSize.height, mAvailSpaceRect.height)) { // The available height is too short. However, its possible that // there is enough open space below which is not impacted by a // float. // // Compute the X coordinate for the float based on its float // type, assuming its placed on the current line. This is // where the float will be placed horizontally if it can go // here. nscoord xa; if (NS_STYLE_FLOAT_LEFT == aFloats) { xa = mAvailSpaceRect.x; } else { xa = mAvailSpaceRect.XMost() - aFloatSize.width; // In case the float is too big, don't go past the left edge // XXXldb This seems wrong, but we might want to fix bug 6976 // first. if (xa < mAvailSpaceRect.x) { xa = mAvailSpaceRect.x; } } nscoord xb = xa + aFloatSize.width; // Calculate the top and bottom y coordinates, again assuming // that the float is placed on the current line. const nsMargin& borderPadding = BorderPadding(); nscoord ya = mY - borderPadding.top; if (ya < 0) { // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not // be higher than the top of its containing block." (Since the // containing block is the content edge of the block box, this // means the margin edge of the float can't be higher than the // content edge of the block that contains it.) ya = 0; } nscoord yb = ya + aFloatSize.height; nscoord saveY = mY; for (;;) { // Get the available space at the new Y coordinate if (mAvailSpaceRect.height <= 0) { // there is no more available space. We lose. result = PR_FALSE; break; } mY += mAvailSpaceRect.height; GetAvailableSpace(mY, aForceFit); if (0 != mBand.GetFloatCount()) { if ((xa < mAvailSpaceRect.x) || (xb > mAvailSpaceRect.XMost())) { // The float can't go here. result = PR_FALSE; break; } } // See if there is now enough height for the float. if (yb <= mY + mAvailSpaceRect.height) { // Winner. The bottom Y coordinate of the float is in // this band. break; } } // Restore Y coordinate and available space information // regardless of the outcome. mY = saveY; GetAvailableSpace(mY, aForceFit); } return result; }
nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, nsPresContext* aPresContext, nsBlockFrame* aFrame, const nsHTMLReflowMetrics& aMetrics, PRBool aTopMarginRoot, PRBool aBottomMarginRoot, PRBool aBlockNeedsSpaceManager) : mBlock(aFrame), mPresContext(aPresContext), mReflowState(aReflowState), mOverflowTracker(aPresContext, aFrame, PR_FALSE), mPrevBottomMargin(), mLineNumber(0), mFlags(0), mFloatBreakType(NS_STYLE_CLEAR_NONE) { SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nsnull); SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame)); const nsMargin& borderPadding = BorderPadding(); if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) { SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE); } if (aBottomMarginRoot || 0 != aReflowState.mComputedBorderPadding.bottom) { SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE); } if (GetFlag(BRS_ISTOPMARGINROOT)) { SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE); } if (aBlockNeedsSpaceManager) { SetFlag(BRS_SPACE_MGR, PR_TRUE); } mSpaceManager = aReflowState.mSpaceManager; NS_ASSERTION(mSpaceManager, "SpaceManager should be set in nsBlockReflowState" ); if (mSpaceManager) { // Translate into our content area and then save the // coordinate system origin for later. mSpaceManager->Translate(borderPadding.left, borderPadding.top); mSpaceManager->GetTranslation(mSpaceManagerX, mSpaceManagerY); } mReflowStatus = NS_FRAME_COMPLETE; mPresContext = aPresContext; mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow()); NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(), "no unconstrained widths should be present anymore"); mContentArea.width = aReflowState.ComputedWidth(); // Compute content area height. Unlike the width, if we have a // specified style height we ignore it since extra content is // managed by the "overflow" property. When we don't have a // specified style height then we may end up limiting our height if // the availableHeight is constrained (this situation occurs when we // are paginated). if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) { // We are in a paginated situation. The bottom edge is just inside // the bottom border and padding. The content area height doesn't // include either border or padding edge. mBottomEdge = aReflowState.availableHeight - borderPadding.bottom; mContentArea.height = PR_MAX(0, mBottomEdge - borderPadding.top); } else { // When we are not in a paginated situation then we always use // an constrained height. SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE); mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE; } mY = borderPadding.top; mBand.Init(mSpaceManager, mContentArea); mPrevChild = nsnull; mCurrentLine = aFrame->end_lines(); mMinLineHeight = nsHTMLReflowState::CalcLineHeight(aReflowState.rendContext, aReflowState.frame); // Calculate mOutsideBulletX GetAvailableSpace(); // FIXME (bug 25888): need to check the entire region that the first // line overlaps, not just the top pixel. mOutsideBulletX = mReflowState.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR ? mAvailSpaceRect.x : PR_MIN(mReflowState.ComputedWidth(), mAvailSpaceRect.XMost()) + mReflowState.mComputedBorderPadding.LeftRight(); }
// XXXldb This behavior doesn't quite fit with CSS1 and CSS2 -- // technically we're supposed let the current line flow around the // float as well unless it won't fit next to what we already have. // But nobody else implements it that way... PRBool nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout, nsPlaceholderFrame* aPlaceholder, PRBool aInitialReflow, nsReflowStatus& aReflowStatus) { NS_PRECONDITION(mBlock->end_lines() != mCurrentLine, "null ptr"); aReflowStatus = NS_FRAME_COMPLETE; // Allocate a nsFloatCache for the float nsFloatCache* fc = mFloatCacheFreeList.Alloc(); fc->mPlaceholder = aPlaceholder; PRBool placed; // Now place the float immediately if possible. Otherwise stash it // away in mPendingFloats and place it later. if (aLineLayout.CanPlaceFloatNow()) { // Because we are in the middle of reflowing a placeholder frame // within a line (and possibly nested in an inline frame or two // that's a child of our block) we need to restore the space // manager's translation to the space that the block resides in // before placing the float. nscoord ox, oy; mSpaceManager->GetTranslation(ox, oy); nscoord dx = ox - mSpaceManagerX; nscoord dy = oy - mSpaceManagerY; mSpaceManager->Translate(-dx, -dy); // And then place it PRBool isLeftFloat; // force it to fit if we're at the top of the block and we can't // break before this PRBool forceFit = IsAdjacentWithTop() && !aLineLayout.LineIsBreakable(); placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus, forceFit); NS_ASSERTION(placed || !forceFit, "If we asked for force-fit, it should have been placed"); if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) { // Pass on updated available space to the current inline reflow engine GetAvailableSpace(mY, forceFit); aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY, mAvailSpaceRect.width, mAvailSpaceRect.height, isLeftFloat, aPlaceholder->GetOutOfFlowFrame()); // Record this float in the current-line list mCurrentLineFloats.Append(fc); // If we can't break here, hide the fact that it's truncated // XXX We can probably do this more cleanly aReflowStatus &= ~NS_FRAME_TRUNCATED; } else { if (IsAdjacentWithTop()) { // Pushing the line to the next page won't give us any more space; // therefore, we break. NS_ASSERTION(aLineLayout.LineIsBreakable(), "We can't get here unless forceFit is false"); aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE(); } else { // Make sure we propagate the truncated status; this signals the // block to push the line to the next page. aReflowStatus |= NS_FRAME_TRUNCATED; } delete fc; } // Restore coordinate system mSpaceManager->Translate(dx, dy); } else { // Always claim to be placed; we don't know whether we fit yet, so we // deal with this in PlaceBelowCurrentLineFloats placed = PR_TRUE; // This float will be placed after the line is done (it is a // below-current-line float). mBelowCurrentLineFloats.Append(fc); if (aPlaceholder->GetNextInFlow()) { // If the float might not be complete, mark it incomplete now to // prevent its next-in-flow placeholders being torn down. We will destroy any // placeholders later if PlaceBelowCurrentLineFloats finds the // float is complete. // Note that we could have unconstrained height and yet have // a next-in-flow placeholder --- for example columns can switch // from constrained height to unconstrained height. if (aPlaceholder->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE) { aReflowStatus = NS_FRAME_NOT_COMPLETE; } } } return placed; }
nscoord nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType, nsIFrame *aReplacedBlock) { #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); printf("clear floats: in: aY=%d(%d)\n", aY, aY - BorderPadding().top); } #endif #ifdef NOISY_FLOAT_CLEARING printf("nsBlockReflowState::ClearFloats: aY=%d breakType=%d\n", aY, aBreakType); mSpaceManager->List(stdout); #endif const nsMargin& bp = BorderPadding(); nscoord newY = aY; if (aBreakType != NS_STYLE_CLEAR_NONE) { newY = bp.top + mSpaceManager->ClearFloats(newY - bp.top, aBreakType); } if (aReplacedBlock) { for (;;) { GetAvailableSpace(newY, PR_FALSE); nsBlockFrame::ReplacedElementWidthToClear replacedWidth = nsBlockFrame::WidthToClearPastFloats(*this, aReplacedBlock); if (mBand.GetFloatCount() == 0 || PR_MAX(mAvailSpaceRect.x, replacedWidth.marginLeft) + replacedWidth.borderBoxWidth + PR_MAX(mContentArea.width - PR_MIN(mContentArea.width, mAvailSpaceRect.XMost()), replacedWidth.marginRight) <= mContentArea.width) { break; } // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames if (mAvailSpaceRect.height > 0) { // See if there's room in the next band. newY += mAvailSpaceRect.height; } else { if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { // Stop trying to clear here; we'll just get pushed to the // next column or page and try again there. break; } NS_NOTREACHED("avail space rect with zero height!"); newY += 1; } } // Restore mBand and mAvailSpaceRect to the way they were. This may // well not be needed, and we should probably come up with // well-defined rules about when these members are valid so that // it's clearly not needed. GetAvailableSpace(); } #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top); } #endif return newY; }