Merge autoland to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2016-09-03 11:17:55 -04:00
Родитель 1c5b9d7220 59f394c4bb
Коммит d6f23d6c08
45 изменённых файлов: 1191 добавлений и 610 удалений

Просмотреть файл

@ -85,7 +85,7 @@ tasks:
# Note: This task is built server side without the context or tooling that
# exist in tree so we must hard code the version
image: 'taskcluster/decision:0.1.5'
image: 'taskcluster/decision:0.1.6'
maxRunTime: 1800

Просмотреть файл

@ -24,9 +24,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 3123796,
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 3245716,
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
"algorithm": "sha512",
"filename": "cargo.tar.xz",
"unpack": true

Просмотреть файл

@ -845,7 +845,7 @@ BrowserGlue.prototype = {
if (samples >= Services.prefs.getIntPref("browser.slowStartup.maxSamples")) {
if (averageTime > Services.prefs.getIntPref("browser.slowStartup.timeThreshold"))
this._showSlowStartupNotification();
this._calculateProfileAgeInDays().then(this._showSlowStartupNotification, null);
averageTime = 0;
samples = 0;
}
@ -854,7 +854,25 @@ BrowserGlue.prototype = {
Services.prefs.setIntPref("browser.slowStartup.samples", samples);
},
_showSlowStartupNotification: function () {
_calculateProfileAgeInDays: Task.async(function* () {
let ProfileAge = Cu.import("resource://gre/modules/ProfileAge.jsm", {}).ProfileAge;
let profileAge = new ProfileAge(null, null);
let creationDate = yield profileAge.created;
let resetDate = yield profileAge.reset;
// if the profile was reset, consider the
// reset date for its age.
let profileDate = resetDate || creationDate;
const ONE_DAY = 24 * 60 * 60 * 1000;
return (Date.now() - profileDate) / ONE_DAY;
}),
_showSlowStartupNotification: function (profileAge) {
if (profileAge < 90) // 3 months
return;
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win)
return;

Просмотреть файл

@ -127,7 +127,20 @@ var gSecurityPane = {
*/
showPasswordExceptions: function ()
{
gSubDialog.open("chrome://passwordmgr/content/passwordManagerExceptions.xul");
var bundlePrefs = document.getElementById("bundlePreferences");
var params = {
blockVisible: true,
sessionVisible: false,
allowVisible: false,
hideStatusColumn: true,
prefilledHost: "",
permissionType: "login-saving",
windowTitle: bundlePrefs.getString("savedLoginsExceptions_title"),
introText: bundlePrefs.getString("savedLoginsExceptions_desc")
};
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
/**

Просмотреть файл

@ -306,7 +306,7 @@ var gPermissionManager = {
this._handleCapabilityChange();
}
else if (aData == "deleted") {
this._removePermissionFromList(permission);
this._removePermissionFromList(permission.principal);
}
}
},

Просмотреть файл

@ -4,8 +4,8 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/permissions.dtd" >
@ -34,7 +34,7 @@
<separator class="thin"/>
<label id="urlLabel" control="url" value="&address.label;" accesskey="&address.accesskey;"/>
<hbox align="start">
<textbox id="url" flex="1"
<textbox id="url" flex="1"
oninput="gPermissionManager.onHostInput(event.target);"
onkeypress="gPermissionManager.onHostKeyPress(event);"/>
</hbox>
@ -69,7 +69,7 @@
oncommand="gPermissionManager.onPermissionDeleted();"/>
<button id="removeAllPermissions"
icon="clear" label="&removeallpermissions.label;"
accesskey="&removeallpermissions.accesskey;"
accesskey="&removeallpermissions.accesskey;"
oncommand="gPermissionManager.onAllPermissionsDeleted();"/>
</hbox>
<spacer flex="1"/>

Просмотреть файл

@ -24,9 +24,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 3123796,
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 3245716,
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
"algorithm": "sha512",
"filename": "cargo.tar.xz",
"unpack": true

Просмотреть файл

@ -24,9 +24,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 3123796,
"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 3245716,
"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
"algorithm": "sha512",
"filename": "cargo.tar.xz",
"unpack": true

Просмотреть файл

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 2571167,
"digest": "b2616459fbf15c75b54628a6bfe8cf89c0841ea08431f5096e72be4fac4c685785dfc7a2f18a03a5f7bd377e78d3c108e5029b12616842cbbd0497ff7363fdaf",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 2715131,
"digest": "f037d2bbbeccb2c95519e083d6d9eecb5cb06a510e849b5721d6933a6c2428203b93ed3d20d3f20329f4d4eee17177d762f051b1ae79fee97d93b84611f3df66",
"algorithm": "sha512",
"filename": "cargo.tar.bz2",
"unpack": true

Просмотреть файл

@ -14,9 +14,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 2298848,
"digest": "d3d1f7b6d195248550f98eb8ce87aa314d36a8a667c110ff2058777fe5a97b7007a41dc1c8a4605c4230e9105972768918222352d5e0fdebbc49639671de38ca",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 2402000,
"digest": "56f12f7ac437742ed717ce0ccfb0b4134160948e45d73016e48d9033567e5b01a171ac95dd7965eb007702c31da73274b5913281655f461f611ddeee37181ecc",
"algorithm": "sha512",
"filename": "cargo.tar.bz2",
"unpack": true

Просмотреть файл

@ -15,9 +15,9 @@
"unpack": true
},
{
"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
"size": 2561498,
"digest": "d300fd06b16efe49bdb1a238d516c8797d2de0edca7efadd55249401e1dd1d775fb84649630e273f95d9e8b956d87d1f75726c0a68294d25fafe078c3b2b9ba9",
"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
"size": 2677831,
"digest": "eada1edd6142dcde907f14f23c08a2a0b86f108a8fb242f62be6573bbbe1d3b2a4a04c05465d561253d6a617e18cdabee3c87d8cef9a1b5bdd20fe835ef25ff1",
"algorithm": "sha512",
"filename": "cargo.tar.bz2",
"unpack": true

3
browser/extensions/e10srollout/bootstrap.js поставляемый
Просмотреть файл

@ -17,7 +17,8 @@ const TEST_THRESHOLD = {
};
const ADDON_ROLLOUT_POLICY = {
"beta" : "2a", // Set 2 + any WebExtension
"beta" : "49a", // 10 tested add-ons + any WebExtension
"release" : "49a", // 10 tested add-ons + any WebExtension
};
const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample";

Просмотреть файл

@ -31,6 +31,8 @@ notificationspermissionstext4=Control which websites are always or never allowed
notificationspermissionstitle=Notification Permissions
invalidURI=Please enter a valid hostname
invalidURITitle=Invalid Hostname Entered
savedLoginsExceptions_title=Exceptions - Saved Logins
savedLoginsExceptions_desc=Logins for the following sites will not be saved:
#### Block List Manager
@ -126,7 +128,7 @@ cookiesFiltered=The following cookies match your search:
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
# If you need to display the number of selected elements in your language,
# you can use #1 in your localization as a placeholder for the number.
# For example this is the English string with numbers:
# For example this is the English string with numbers:
# removeSelectedCookied=Remove #1 Selected;Remove #1 Selected
removeSelectedCookies=Remove Selected;Remove Selected
defaultUserContextLabel=None

Просмотреть файл

@ -147,6 +147,7 @@ skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keybo
[browser_inspector_search-08.js]
[browser_inspector_search-clear.js]
[browser_inspector_search-filter_context-menu.js]
subsuite = clipboard
[browser_inspector_search_keyboard_trap.js]
[browser_inspector_search-label.js]
[browser_inspector_search-reserved.js]

Просмотреть файл

@ -45,6 +45,7 @@ skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_Close.html]
[test_browserElement_oop_CookiesNotThirdParty.html]
[test_browserElement_oop_CopyPaste.html]
subsuite = clipboard
[test_browserElement_oop_DOMRequestError.html]
disabled = Disabling some OOP tests for WebIDL scope changes
[test_browserElement_oop_DataURI.html]

Просмотреть файл

@ -758,6 +758,17 @@ VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource,
if (!mIsPresenting) {
return;
}
if (mRenderTargets.IsEmpty()) {
/**
* XXX - We should resolve fail the promise returned by
* VRDisplay.requestPresent() when the DX11 resources fail allocation
* in VRDisplayOculus::StartPresentation().
* Bailing out here prevents the crash but content should be aware
* that frames are not being presented.
* See Bug 1299309.
**/
return;
}
MOZ_ASSERT(mDevice);
MOZ_ASSERT(mContext);

Просмотреть файл

@ -3589,8 +3589,13 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
basic->BeginTransaction();
basic->SetTarget(context);
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
static_cast<nsDisplaySVGEffects*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
if (basic->InTransaction()) {
basic->AbortTransaction();
}
} else if (aItem->GetType() == nsDisplayItem::TYPE_FILTER){
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
if (basic->InTransaction()) {
basic->AbortTransaction();
}

Просмотреть файл

@ -51,7 +51,8 @@ DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT)
DECLARE_DISPLAY_ITEM_TYPE(SVG_EFFECTS)
DECLARE_DISPLAY_ITEM_TYPE(MASK)
DECLARE_DISPLAY_ITEM_TYPE(FILTER)
DECLARE_DISPLAY_ITEM_TYPE(SVG_GLYPHS)
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)

Просмотреть файл

@ -1009,7 +1009,10 @@ nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
}
nsPresContext* pc = aReferenceFrame->PresContext();
pc->GetDocShell()->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
if (docShell) {
docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
}
mIsInChromePresContext = pc->IsChrome();
}
@ -1025,7 +1028,10 @@ nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame)
if (!mPresShellStates.IsEmpty()) {
nsPresContext* pc = CurrentPresContext();
pc->GetDocShell()->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
if (docShell) {
docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
}
mIsInChromePresContext = pc->IsChrome();
}
}
@ -6677,128 +6683,6 @@ nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect
}
}
void
nsDisplaySVGEffects::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
mFrame, mVisibleRect,
borderArea, aBuilder,
aManager, mOpacityItemCreated);
image::DrawResult result =
nsSVGIntegrationUtils::PaintFramesWithEffects(params);
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
}
LayerState
nsDisplaySVGEffects::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
return LAYER_SVG_EFFECTS;
}
already_AddRefed<Layer>
nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters)
{
const nsIContent* content = mFrame->GetContent();
bool hasSVGLayout = (mFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
if (hasSVGLayout) {
nsISVGChildFrame *svgChildFrame = do_QueryFrame(mFrame);
if (!svgChildFrame || !mFrame->GetContent()->IsSVGElement()) {
NS_ASSERTION(false, "why?");
return nullptr;
}
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
return nullptr; // The SVG spec says not to draw filters for this
}
}
if (mFrame->StyleEffects()->mOpacity == 0.0f &&
!mOpacityItemCreated)
return nullptr;
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
effectProperties.GetClipPathFrame(&isOK);
if (!isOK) {
return nullptr;
}
ContainerLayerParameters newContainerParameters = aContainerParameters;
if (effectProperties.HasValidFilter()) {
newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
}
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
newContainerParameters, nullptr);
return container.forget();
}
nsRect
nsDisplaySVGEffects::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
{
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
if (effectProperties.HasValidFilter()) {
return nsRect();
}
return nsDisplayWrapList::GetComponentAlphaBounds(aBuilder);
}
bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsPoint offset = ToReferenceFrame();
nsRect dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mFrame,
mVisibleRect - offset) +
offset;
// Our children may be made translucent or arbitrarily deformed so we should
// not allow them to subtract area from aVisibleRegion.
nsRegion childrenVisible(dirtyRect);
nsRect r = dirtyRect.Intersect(mList.GetBounds(aBuilder));
mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
return true;
}
bool nsDisplaySVGEffects::TryMerge(nsDisplayItem* aItem)
{
if (aItem->GetType() != TYPE_SVG_EFFECTS)
return false;
// items for the same content element should be merged into a single
// compositing group
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplaySVGEffects
if (aItem->Frame()->GetContent() != mFrame->GetContent())
return false;
if (aItem->GetClip() != GetClip())
return false;
if (aItem->ScrollClip() != ScrollClip())
return false;
nsDisplaySVGEffects* other = static_cast<nsDisplaySVGEffects*>(aItem);
MergeFromTrackingMergedFrames(other);
mEffectsBounds.UnionRect(mEffectsBounds,
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
return true;
}
gfxRect
nsDisplaySVGEffects::BBoxInUserSpace() const
{
@ -6838,9 +6722,130 @@ nsDisplaySVGEffects::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
}
}
bool nsDisplaySVGEffects::ValidateSVGFrame()
{
const nsIContent* content = mFrame->GetContent();
bool hasSVGLayout = (mFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
if (hasSVGLayout) {
nsISVGChildFrame *svgChildFrame = do_QueryFrame(mFrame);
if (!svgChildFrame || !mFrame->GetContent()->IsSVGElement()) {
NS_ASSERTION(false, "why?");
return false;
}
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
return false; // The SVG spec says not to draw filters for this
}
}
return true;
}
nsDisplayMask::nsDisplayMask(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
bool aOpacityItemCreated)
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aOpacityItemCreated)
{
MOZ_COUNT_CTOR(nsDisplayMask);
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplayMask::~nsDisplayMask()
{
MOZ_COUNT_DTOR(nsDisplayMask);
}
#endif
bool nsDisplayMask::TryMerge(nsDisplayItem* aItem)
{
if (aItem->GetType() != TYPE_MASK)
return false;
// items for the same content element should be merged into a single
// compositing group
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplaySVGEffects
if (aItem->Frame()->GetContent() != mFrame->GetContent())
return false;
if (aItem->GetClip() != GetClip())
return false;
if (aItem->ScrollClip() != ScrollClip())
return false;
nsDisplayMask* other = static_cast<nsDisplayMask*>(aItem);
MergeFromTrackingMergedFrames(other);
mEffectsBounds.UnionRect(mEffectsBounds,
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
return true;
}
already_AddRefed<Layer>
nsDisplayMask::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters)
{
if (!ValidateSVGFrame()) {
return nullptr;
}
if (mFrame->StyleEffects()->mOpacity == 0.0f && !mOpacityItemCreated) {
return nullptr;
}
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
effectProperties.GetClipPathFrame(&isOK);
if (!isOK) {
return nullptr;
}
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
aContainerParameters, nullptr);
return container.forget();
}
LayerState
nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
return LAYER_SVG_EFFECTS;
}
bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
// Our children may be made translucent or arbitrarily deformed so we should
// not allow them to subtract area from aVisibleRegion.
nsRegion childrenVisible(mVisibleRect);
nsRect r = mVisibleRect.Intersect(mList.GetBounds(aBuilder));
mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
return true;
}
void
nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
mFrame, mVisibleRect,
borderArea, aBuilder,
aManager, mOpacityItemCreated);
image::DrawResult result =
nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
}
#ifdef MOZ_DUMP_PAINTING
void
nsDisplaySVGEffects::PrintEffects(nsACString& aTo)
nsDisplayMask::PrintEffects(nsACString& aTo)
{
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
@ -6869,13 +6874,7 @@ nsDisplaySVGEffects::PrintEffects(nsACString& aTo)
aTo += "clip(basic-shape)";
first = false;
}
if (effectProperties.HasValidFilter()) {
if (!first) {
aTo += ", ";
}
aTo += "filter";
first = false;
}
if (effectProperties.GetFirstMaskFrame()) {
if (!first) {
aTo += ", ";
@ -6886,3 +6885,140 @@ nsDisplaySVGEffects::PrintEffects(nsACString& aTo)
}
#endif
nsDisplayFilter::nsDisplayFilter(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
bool aOpacityItemCreated)
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aOpacityItemCreated)
{
MOZ_COUNT_CTOR(nsDisplayFilter);
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplayFilter::~nsDisplayFilter()
{
MOZ_COUNT_DTOR(nsDisplayFilter);
}
#endif
already_AddRefed<Layer>
nsDisplayFilter::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters)
{
if (!ValidateSVGFrame()) {
return nullptr;
}
if (mFrame->StyleEffects()->mOpacity == 0.0f && !mOpacityItemCreated) {
return nullptr;
}
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
ContainerLayerParameters newContainerParameters = aContainerParameters;
if (effectProperties.HasValidFilter()) {
newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
}
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
newContainerParameters, nullptr);
return container.forget();
}
bool nsDisplayFilter::TryMerge(nsDisplayItem* aItem)
{
if (aItem->GetType() != TYPE_FILTER) {
return false;
}
// items for the same content element should be merged into a single
// compositing group.
// aItem->Frame() returns non-null because it's nsDisplayFilter
if (aItem->Frame()->GetContent() != mFrame->GetContent()) {
return false;
}
if (aItem->GetClip() != GetClip()) {
return false;
}
if (aItem->ScrollClip() != ScrollClip()) {
return false;
}
nsDisplayFilter* other = static_cast<nsDisplayFilter*>(aItem);
MergeFromTrackingMergedFrames(other);
mEffectsBounds.UnionRect(mEffectsBounds,
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
return true;
}
LayerState
nsDisplayFilter::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
return LAYER_SVG_EFFECTS;
}
bool nsDisplayFilter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsPoint offset = ToReferenceFrame();
nsRect dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mFrame,
mVisibleRect - offset) +
offset;
// Our children may be made translucent or arbitrarily deformed so we should
// not allow them to subtract area from aVisibleRegion.
nsRegion childrenVisible(dirtyRect);
nsRect r = dirtyRect.Intersect(mList.GetBounds(aBuilder));
mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
return true;
}
void
nsDisplayFilter::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
mFrame, mVisibleRect,
borderArea, aBuilder,
aManager, mOpacityItemCreated);
image::DrawResult result =
nsSVGIntegrationUtils::PaintFilter(params);
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
}
#ifdef MOZ_DUMP_PAINTING
void
nsDisplayFilter::PrintEffects(nsACString& aTo)
{
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
bool first = true;
aTo += " effects=(";
if (mFrame->StyleEffects()->mOpacity != 1.0f) {
first = false;
aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
}
if (effectProperties.HasValidFilter()) {
if (!first) {
aTo += ", ";
}
aTo += "filter";
first = false;
}
aTo += ")";
}
#endif

Просмотреть файл

@ -3782,18 +3782,14 @@ private:
int32_t mAPD, mParentAPD;
};
/**
* A display item to paint a stacking context with effects
* set by the stacking context root frame's style.
*/
class nsDisplaySVGEffects : public nsDisplayWrapList {
class nsDisplaySVGEffects: public nsDisplayWrapList {
public:
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aOpacityItemCreated);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplaySVGEffects();
#endif
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) override;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@ -3804,22 +3800,10 @@ public:
*aSnap = false;
return mEffectsBounds + ToReferenceFrame();
}
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual bool TryMerge(nsDisplayItem* aItem) override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return false;
}
NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
gfxRect BBoxInUserSpace() const;
gfxPoint UserSpaceOffset() const;
@ -3831,16 +3815,9 @@ public:
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) override;
protected:
bool ValidateSVGFrame();
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
private:
// relative to mFrame
nsRect mEffectsBounds;
// True if the caller also created an nsDisplayOpacity item, and we should tell
@ -3848,6 +3825,68 @@ private:
bool mOpacityItemCreated;
};
/**
* A display item to paint a stacking context with mask and clip effects
* set by the stacking context root frame's style.
*/
class nsDisplayMask : public nsDisplaySVGEffects {
public:
nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aOpacityItemCreated);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayMask();
#endif
NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
virtual bool TryMerge(nsDisplayItem* aItem) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
};
class nsDisplayFilter : public nsDisplaySVGEffects {
public:
nsDisplayFilter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, bool aOpacityItemCreated);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayFilter();
#endif
NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
virtual bool TryMerge(nsDisplayItem* aItem) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
};
/* A display item that applies a transformation to all of its descendant
* elements. This wrapper should only be used if there is a transform applied
* to the root element.

Просмотреть файл

@ -196,9 +196,15 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
}
}
#ifdef MOZ_DUMP_PAINTING
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
nsCString str;
(static_cast<nsDisplaySVGEffects*>(aItem))->PrintEffects(str);
(static_cast<nsDisplayMask*>(aItem))->PrintEffects(str);
aStream << str.get();
}
if (aItem->GetType() == nsDisplayItem::TYPE_FILTER) {
nsCString str;
(static_cast<nsDisplayFilter*>(aItem))->PrintEffects(str);
aStream << str.get();
}
#endif

Просмотреть файл

@ -8,6 +8,8 @@
#include "nsBackdropFrame.h"
#include "nsDisplayList.h"
using namespace mozilla;
NS_IMPL_FRAMEARENA_HELPERS(nsBackdropFrame)

Просмотреть файл

@ -29,14 +29,15 @@ public:
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
virtual LogicalSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
WritingMode aWM,
const LogicalSize& aCBSize,
nscoord aAvailableISize,
const LogicalSize& aMargin,
const LogicalSize& aBorder,
const LogicalSize& aPadding,
bool aShrinkWrap) override;
virtual mozilla::LogicalSize
ComputeAutoSize(nsRenderingContext *aRenderingContext,
mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize,
nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding,
bool aShrinkWrap) override;
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,

Просмотреть файл

@ -2441,16 +2441,30 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
* output even if the element being filtered wouldn't otherwise do so.
*/
if (usingSVGEffects) {
MOZ_ASSERT(StyleEffects()->HasFilters() ||
nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this));
if (clipCapturedBy == ContainerItemType::eSVGEffects) {
clipState.ExitStackingContextContents(&containerItemScrollClip);
}
// Revert to the post-filter dirty rect.
buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects);
/* List now emptied, so add the new list to the top. */
resultList.AppendNewToTop(
new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList, useOpacity));
// Skip all filter effects while generating glyph mask.
if (StyleEffects()->HasFilters() && !aBuilder->IsForGenerateGlyphMask()) {
/* List now emptied, so add the new list to the top. */
resultList.AppendNewToTop(
new (aBuilder) nsDisplayFilter(aBuilder, this, &resultList, useOpacity));
}
if (nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this)) {
/* List now emptied, so add the new list to the top. */
resultList.AppendNewToTop(
new (aBuilder) nsDisplayMask(aBuilder, this, &resultList, useOpacity));
}
// Also add the hoisted scroll info items. We need those for APZ scrolling
// because nsDisplaySVGEffects items can't build active layers.
// because nsDisplayMask items can't build active layers.
aBuilder->ExitSVGEffectsContents();
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
}

Просмотреть файл

@ -7,10 +7,12 @@
#include "nsGfxScrollFrame.h"
#include "ActiveLayerTracker.h"
#include "base/compiler_specific.h"
#include "DisplayItemClip.h"
#include "DisplayItemScrollClip.h"
#include "nsCOMPtr.h"
#include "nsIContentViewer.h"
#include "nsPresContext.h"
#include "nsView.h"
#include "nsIScrollable.h"
@ -76,6 +78,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::layout;
static uint32_t

Просмотреть файл

@ -10,6 +10,7 @@
#ifndef _nsIStatefulFrame_h
#define _nsIStatefulFrame_h
#include "nsContentUtils.h"
#include "nsQueryFrame.h"
class nsPresState;

Просмотреть файл

@ -160,6 +160,15 @@ nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame)
style->mMask.HasLayerWithImage();
}
bool
nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(const nsIFrame* aFrame)
{
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
return style->HasClipPath() ||
style->mMask.HasLayerWithImage() ||
(aFrame->StyleEffects()->mOpacity != 1.0f);
}
// For non-SVG frames, this gives the offset to the frame's "user space".
// For SVG frames, this returns a zero offset.
static nsPoint
@ -410,6 +419,22 @@ private:
nsPoint mOffset;
};
static IntRect
ComputeClipExtsInDeviceSpace(gfxContext& aCtx)
{
gfxContextMatrixAutoSaveRestore matRestore(&aCtx);
// Get the clip extents in device space.
aCtx.SetMatrix(gfxMatrix());
gfxRect clippedFrameSurfaceRect = aCtx.GetClipExtents();
clippedFrameSurfaceRect.RoundOut();
IntRect result;
ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
: IntRect();
}
static IntRect
ComputeMaskGeometry(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
const nsStyleSVGReset *svgReset,
@ -463,17 +488,10 @@ ComputeMaskGeometry(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
ctx.Clip(maskInUserSpace);
}
// Get the clip extents in device space.
ctx.SetMatrix(gfxMatrix());
gfxRect clippedFrameSurfaceRect = ctx.GetClipExtents();
clippedFrameSurfaceRect.RoundOut();
IntRect result = ComputeClipExtsInDeviceSpace(ctx);
ctx.Restore();
IntRect result;
ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
: IntRect();
return result;
}
static DrawResult
@ -595,8 +613,28 @@ GenerateMaskSurface(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
return DrawResult::SUCCESS;
}
DrawResult
nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
static float
ComputeOpacity(const nsSVGIntegrationUtils::PaintFramesParams& aParams)
{
nsIFrame* frame = aParams.frame;
MOZ_ASSERT(!nsSVGUtils::CanOptimizeOpacity(frame) ||
!aParams.callerPaintsOpacity,
"How can we be optimizing the opacity into the svg as well as having the caller paint it?");
float opacity = frame->StyleEffects()->mOpacity;
if (opacity != 1.0f &&
(nsSVGUtils::CanOptimizeOpacity(frame) || aParams.callerPaintsOpacity)) {
return 1.0f;
}
return opacity;
}
static bool
ValidateSVGFrame(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
bool aHasSVGLayout, DrawResult* aResult)
{
#ifdef DEBUG
NS_ASSERTION(!(aParams.frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
@ -605,13 +643,128 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
"Should not use nsSVGIntegrationUtils on this SVG frame");
#endif
nsIFrame* frame = aParams.frame;
const nsIContent* content = frame->GetContent();
if (aHasSVGLayout) {
nsISVGChildFrame *svgChildFrame = do_QueryFrame(frame);
if (!svgChildFrame || !frame->GetContent()->IsSVGElement()) {
NS_ASSERTION(false, "why?");
*aResult = DrawResult::BAD_ARGS;
return false;
}
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
// The SVG spec says not to draw _anything_
*aResult = DrawResult::SUCCESS;
return false;
}
}
return true;
}
static void
SetupContextMatrix(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
nsPoint& aOffsetToBoundingBox,
nsPoint& aToUserSpace,
nsPoint& aOffsetToUserSpace)
{
nsIFrame* frame = aParams.frame;
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
nsPoint firstFrameOffset = GetOffsetToBoundingBox(firstFrame);
aOffsetToBoundingBox = aParams.builder->ToReferenceFrame(firstFrame) - firstFrameOffset;
if (!firstFrame->IsFrameOfType(nsIFrame::eSVG)) {
/* Snap the offset if the reference frame is not a SVG frame,
* since other frames will be snapped to pixel when rendering. */
aOffsetToBoundingBox = nsPoint(
frame->PresContext()->RoundAppUnitsToNearestDevPixels(aOffsetToBoundingBox.x),
frame->PresContext()->RoundAppUnitsToNearestDevPixels(aOffsetToBoundingBox.y));
}
// After applying only "aOffsetToBoundingBox", aCtx would have its origin at
// the top left corner of frame's bounding box (over all continuations).
// However, SVG painting needs the origin to be located at the origin of the
// SVG frame's "user space", i.e. the space in which, for example, the
// frame's BBox lives.
// SVG geometry frames and foreignObject frames apply their own offsets, so
// their position is relative to their user space. So for these frame types,
// if we want aCtx to be in user space, we first need to subtract the
// frame's position so that SVG painting can later add it again and the
// frame is painted in the right place.
gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(frame);
aToUserSpace =
nsPoint(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
aOffsetToUserSpace = aOffsetToBoundingBox - aToUserSpace;
#ifdef DEBUG
bool hasSVGLayout = (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
NS_ASSERTION(hasSVGLayout || aOffsetToBoundingBox == aOffsetToUserSpace,
"For non-SVG frames there shouldn't be any additional offset");
#endif
gfxPoint devPixelOffsetToUserSpace =
nsLayoutUtils::PointToGfxPoint(aOffsetToUserSpace,
frame->PresContext()->AppUnitsPerDevPixel());
aParams.ctx.SetMatrix(aParams.ctx.CurrentMatrix().Translate(devPixelOffsetToUserSpace));
}
static already_AddRefed<gfxContext>
CreateBlendTarget(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
IntPoint& aTargetOffset)
{
MOZ_ASSERT(aParams.frame->StyleEffects()->mMixBlendMode !=
NS_STYLE_BLEND_NORMAL);
// Create a temporary context to draw to so we can blend it back with
// another operator.
IntRect drawRect = ComputeClipExtsInDeviceSpace(aParams.ctx);
RefPtr<DrawTarget> targetDT = aParams.ctx.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
if (!targetDT || !targetDT->IsValid()) {
return nullptr;
}
RefPtr<gfxContext> target = gfxContext::CreateOrNull(targetDT);
MOZ_ASSERT(target); // already checked the draw target above
target->SetMatrix(aParams.ctx.CurrentMatrix() *
gfxMatrix::Translation(-drawRect.TopLeft()));
aTargetOffset = drawRect.TopLeft();
return target.forget();
}
static void
BlendToTarget(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
gfxContext* aTarget, const IntPoint& aTargetOffset)
{
MOZ_ASSERT(aParams.frame->StyleEffects()->mMixBlendMode !=
NS_STYLE_BLEND_NORMAL);
RefPtr<DrawTarget> targetDT = aTarget->GetDrawTarget();
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
gfxContext& context = aParams.ctx;
gfxContextAutoSaveRestore save(&context);
context.SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(aTargetOffset.x, aTargetOffset.y));
context.SetPattern(pattern);
context.Paint();
}
DrawResult
nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
{
/* SVG defines the following rendering model:
*
* 1. Render geometry
* 2. Apply filter
* 3. Apply clipping, masking, group opacity
*
* We follow this, but perform a couple of optimizations:
* We handle #3 here and perform a couple of optimizations:
*
* + Use cairo's clipPath when representable natively (single object
* clip region).
@ -619,30 +772,24 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
* + Merge opacity and masking if both used together.
*/
nsIFrame* frame = aParams.frame;
const nsIContent* content = frame->GetContent();
DrawResult result = DrawResult::SUCCESS;
bool hasSVGLayout = (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
if (hasSVGLayout) {
nsISVGChildFrame *svgChildFrame = do_QueryFrame(frame);
if (!svgChildFrame || !frame->GetContent()->IsSVGElement()) {
NS_ASSERTION(false, "why?");
return DrawResult::BAD_ARGS;
}
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
return DrawResult::SUCCESS; // The SVG spec says not to draw _anything_
}
if (!ValidateSVGFrame(aParams, hasSVGLayout, &result)) {
return result;
}
float opacity = frame->StyleEffects()->mOpacity;
if (opacity != 1.0f &&
(nsSVGUtils::CanOptimizeOpacity(frame) ||
aParams.callerPaintsOpacity)) {
opacity = 1.0f;
}
float opacity = ComputeOpacity(aParams);
if (opacity == 0.0f) {
return DrawResult::SUCCESS;
}
MOZ_ASSERT(!nsSVGUtils::CanOptimizeOpacity(frame) || !aParams.callerPaintsOpacity,
"How can we be optimizing the opacity into the svg as well as having the caller paint it?");
gfxContext& context = aParams.ctx;
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);
nsPoint offsetToBoundingBox;
nsPoint toUserSpace;
nsPoint offsetToUserSpace;
SetupContextMatrix(aParams, offsetToBoundingBox, toUserSpace,
offsetToUserSpace);
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
@ -655,46 +802,8 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
bool isTrivialClip = clipPathFrame ? clipPathFrame->IsTrivial() : true;
gfxContext& context = aParams.ctx;
DrawTarget* drawTarget = context.GetDrawTarget();
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);
nsPoint firstFrameOffset = GetOffsetToBoundingBox(firstFrame);
nsPoint offsetToBoundingBox = aParams.builder->ToReferenceFrame(firstFrame) - firstFrameOffset;
if (!firstFrame->IsFrameOfType(nsIFrame::eSVG)) {
/* Snap the offset if the reference frame is not a SVG frame,
* since other frames will be snapped to pixel when rendering. */
offsetToBoundingBox = nsPoint(
frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
}
// After applying only "offsetToBoundingBox", aCtx would have its origin at
// the top left corner of frame's bounding box (over all continuations).
// However, SVG painting needs the origin to be located at the origin of the
// SVG frame's "user space", i.e. the space in which, for example, the
// frame's BBox lives.
// SVG geometry frames and foreignObject frames apply their own offsets, so
// their position is relative to their user space. So for these frame types,
// if we want aCtx to be in user space, we first need to subtract the
// frame's position so that SVG painting can later add it again and the
// frame is painted in the right place.
gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(frame);
nsPoint toUserSpace(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
nsPoint offsetToUserSpace = offsetToBoundingBox - toUserSpace;
NS_ASSERTION(hasSVGLayout || offsetToBoundingBox == offsetToUserSpace,
"For non-SVG frames there shouldn't be any additional offset");
gfxPoint devPixelOffsetToUserSpace =
nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
frame->PresContext()->AppUnitsPerDevPixel());
context.SetMatrix(context.CurrentMatrix().Translate(devPixelOffsetToUserSpace));
gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(frame);
const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
@ -718,25 +827,34 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
bool shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
#endif
// These are used if we require a temporary surface for a custom blend mode.
RefPtr<gfxContext> target = &aParams.ctx;
IntPoint targetOffset;
bool shouldGenerateClipMaskLayer = clipPathFrame && !isTrivialClip;
bool shouldApplyClipPath = clipPathFrame && isTrivialClip;
bool shouldApplyBasicShape = !clipPathFrame && svgReset->HasClipPath();
MOZ_ASSERT_IF(shouldGenerateClipMaskLayer,
!shouldApplyClipPath && !shouldApplyBasicShape);
// These are used if we require a temporary surface for a custom blend mode.
IntPoint targetOffset;
RefPtr<gfxContext> target =
(aParams.frame->StyleEffects()->mMixBlendMode == NS_STYLE_BLEND_NORMAL)
? RefPtr<gfxContext>(&aParams.ctx).forget()
: CreateBlendTarget(aParams, targetOffset);
if (!target) {
return DrawResult::TEMPORARY_ERROR;
}
bool shouldGenerateMask = (opacity != 1.0f || shouldGenerateClipMaskLayer ||
shouldGenerateMaskLayer);
bool complexEffects = false;
DrawResult result = DrawResult::SUCCESS;
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (opacity != 1.0f || (clipPathFrame && !isTrivialClip)
|| frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|| shouldGenerateMaskLayer) {
complexEffects = true;
if (shouldGenerateMask) {
context.Save();
nsRect clipRect =
frame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
context.Clip(NSRectToSnappedRect(clipRect,
frame->PresContext()->AppUnitsPerDevPixel(),
*drawTarget));
*context.GetDrawTarget()));
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface;
if (shouldGenerateMaskLayer) {
@ -752,31 +870,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
return result;
}
if (frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
// Create a temporary context to draw to so we can blend it back with
// another operator.
gfxRect clipRect;
{
gfxContextMatrixAutoSaveRestore matRestore(&context);
context.SetMatrix(gfxMatrix());
clipRect = context.GetClipExtents();
}
IntRect drawRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> targetDT = context.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
if (!targetDT || !targetDT->IsValid()) {
context.Restore();
return result;
}
target = gfxContext::CreateOrNull(targetDT);
MOZ_ASSERT(target); // already checked the draw target above
target->SetMatrix(context.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
targetOffset = drawRect.TopLeft();
}
if (clipPathFrame && !isTrivialClip) {
if (shouldGenerateClipMaskLayer) {
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface =
clipPathFrame->GetClipMask(context, frame, cssPxToDevPxMatrix,
@ -789,69 +883,105 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
}
}
if (opacity != 1.0f || shouldGenerateMaskLayer ||
(clipPathFrame && !isTrivialClip)) {
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
}
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
}
/* If this frame has only a trivial clipPath, set up cairo's clipping now so
* we can just do normal painting and get it clipped appropriately.
*/
if (clipPathFrame && isTrivialClip) {
if (shouldApplyClipPath) {
context.Save();
clipPathFrame->ApplyClipPath(context, frame, cssPxToDevPxMatrix);
} else if (!clipPathFrame && svgReset->HasClipPath()) {
} else if (shouldApplyBasicShape) {
context.Save();
nsCSSClipPathInstance::ApplyBasicShapeClip(context, frame);
}
/* Paint the child */
if (effectProperties.HasValidFilter() && !aParams.builder->IsForGenerateGlyphMask()) {
RegularFramePaintCallback callback(aParams.builder, aParams.layerManager,
offsetToUserSpace);
target->SetMatrix(matrixAutoSaveRestore.Matrix());
BasicLayerManager* basic = static_cast<BasicLayerManager*>(aParams.layerManager);
RefPtr<gfxContext> oldCtx = basic->GetTarget();
basic->SetTarget(target);
aParams.layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
aParams.builder);
basic->SetTarget(oldCtx);
nsRegion dirtyRegion = aParams.dirtyRect - offsetToBoundingBox;
gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(frame);
nsFilterInstance::PaintFilteredFrame(frame, target->GetDrawTarget(),
tm, &callback, &dirtyRegion);
} else {
target->SetMatrix(matrixAutoSaveRestore.Matrix());
BasicLayerManager* basic = static_cast<BasicLayerManager*>(aParams.layerManager);
RefPtr<gfxContext> oldCtx = basic->GetTarget();
basic->SetTarget(target);
aParams.layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
aParams.builder);
basic->SetTarget(oldCtx);
}
if ((clipPathFrame && isTrivialClip) ||
(!clipPathFrame && svgReset->HasClipPath())) {
if (shouldApplyClipPath || shouldApplyBasicShape) {
context.Restore();
}
/* No more effects, we're done. */
if (!complexEffects) {
if (shouldGenerateMask) {
target->PopGroupAndBlend();
context.Restore();
}
if (aParams.frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
MOZ_ASSERT(target != &aParams.ctx);
BlendToTarget(aParams, target, targetOffset);
}
return result;
}
DrawResult
nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams)
{
MOZ_ASSERT(!aParams.builder->IsForGenerateGlyphMask());
nsIFrame* frame = aParams.frame;
DrawResult result = DrawResult::SUCCESS;
bool hasSVGLayout = (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
if (!ValidateSVGFrame(aParams, hasSVGLayout, &result)) {
return result;
}
if (opacity != 1.0f || shouldGenerateMaskLayer ||
(clipPathFrame && !isTrivialClip)) {
target->PopGroupAndBlend();
float opacity = ComputeOpacity(aParams);
if (opacity == 0.0f) {
return DrawResult::SUCCESS;
}
if (frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
target = nullptr;
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
gfxContext& context = aParams.ctx;
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);
nsPoint offsetToBoundingBox;
nsPoint toUserSpace;
nsPoint offsetToUserSpace;
SetupContextMatrix(aParams, offsetToBoundingBox, toUserSpace,
offsetToUserSpace);
context.SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
context.SetPattern(pattern);
context.Paint();
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
if (!effectProperties.HasValidFilter()) {
return DrawResult::NOT_READY;
}
// These are used if we require a temporary surface for a custom blend mode.
IntPoint targetOffset;
RefPtr<gfxContext> target =
(aParams.frame->StyleEffects()->mMixBlendMode == NS_STYLE_BLEND_NORMAL)
? RefPtr<gfxContext>(&aParams.ctx).forget()
: CreateBlendTarget(aParams, targetOffset);
if (!target) {
return DrawResult::TEMPORARY_ERROR;
}
/* Paint the child and apply filters */
RegularFramePaintCallback callback(aParams.builder, aParams.layerManager,
offsetToUserSpace);
nsRegion dirtyRegion = aParams.dirtyRect - offsetToBoundingBox;
gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(frame);
nsFilterInstance::PaintFilteredFrame(frame, target->GetDrawTarget(),
tm, &callback, &dirtyRegion);
if (aParams.frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
MOZ_ASSERT(target != &aParams.ctx);
BlendToTarget(aParams, target, targetOffset);
}
context.Restore();
return result;
}

Просмотреть файл

@ -46,6 +46,12 @@ public:
static bool
UsingEffectsForFrame(const nsIFrame* aFrame);
/**
* Returns true if mask or clippath are currently applied to this frame.
*/
static bool
UsingMaskOrClipPathForFrame(const nsIFrame* aFrame);
/**
* Returns the size of the union of the border-box rects of all of
* aNonSVGFrame's continuations.
@ -147,7 +153,10 @@ public:
* Paint non-SVG frame with SVG effects.
*/
static DrawResult
PaintFramesWithEffects(const PaintFramesParams& aParams);
PaintMaskAndClipPath(const PaintFramesParams& aParams);
static DrawResult
PaintFilter(const PaintFramesParams& aParams);
/**
* SVG frames expect to paint in SVG user units, which are equal to CSS px

Просмотреть файл

@ -41,7 +41,7 @@ payload:
# Note: This task is built server side without the context or tooling that
# exist in tree so we must hard code the version
image: 'taskcluster/decision:0.1.5'
image: 'taskcluster/decision:0.1.6'
# Virtually no network or other potentially risky operations happen as part
# of the task timeout aside from the initial clone. We intentionally have

Просмотреть файл

@ -1 +1 @@
0.1.5
0.1.6

Просмотреть файл

@ -7,8 +7,6 @@ test `whoami` == 'root'
apt-get update
apt-get install -y --force-yes --no-install-recommends \
ca-certificates \
curl \
jq \
python \
sudo

Просмотреть файл

@ -13,22 +13,22 @@ if [ -f /etc/lsb-release ]; then
if [ "${DISTRIB_ID}" = "Ubuntu" -a "${DISTRIB_RELEASE}" = "16.04" ]; then
HG_DEB=1
HG_DIGEST=7b1fc1217e0dcaeea852b0af2dc559b1aafb704fbee7e29cbec75af57bacb84910a7ec92b5c33f04ee98f23b3a57f1fa451173fe7c8a96f58faefe319dc7dde1
HG_SIZE=44878
HG_FILENAME=mercurial_3.8.4_amd64.deb
HG_DIGEST=09c7c80324158b755c23855d47caeb40b953218b1c89c7f5f21bbdea9de1d13a7ed5a7e647022ff626fb9674655baf05f6965361ccef3fa82b94d1fa8a684187
HG_SIZE=44956
HG_FILENAME=mercurial_3.9.1_amd64.deb
HG_COMMON_DIGEST=b476e2612e7495a1c7c5adfd84511aa7479e26cc9070289513ec705fbfc4c61806ce2dbcceca0e63f2e80669be416f3467a3cebb522dcb8a6aeb62cdd3df82f2
HG_COMMON_SIZE=1818422
HG_COMMON_FILENAME=mercurial-common_3.8.4_all.deb
HG_COMMON_DIGEST=ef281d1368a8cf2363bc08c050aff3825028ba4d47d491e50e10f4c78574d5e87231a0096c7d9cb3439dd4b5172057a050e02946b4cf8b2bdf239ffd50a85d06
HG_COMMON_SIZE=1847796
HG_COMMON_FILENAME=mercurial-common_3.9.1_all.deb
elif [ "${DISTRIB_ID}" = "Ubuntu" -a "${DISTRIB_RELEASE}" = "12.04" ]; then
HG_DEB=1
HG_DIGEST=96366b6baac26017a2ef9cd0bbbba4f18756e02921b0ff3541f677484d53d2041f01202b743ea8cdb96db58e88317da18befefc9711a085b054f9abc3dad1679
HG_SIZE=54992
HG_FILENAME=mercurial_3.8.4_amd64.deb
HG_DIGEST=f816a6ca91129c0723527d98a2978c253a3f941f4358f9f8abd6f3ab8e8601ed3efc347828aac8f0d0762f819f9b777299e31037c39eb0c5af05aa76ac25c3bf
HG_SIZE=55144
HG_FILENAME=mercurial_3.9.1_amd64.deb
HG_COMMON_SIZE=2946616
HG_COMMON_DIGEST=96c6bc305ae85f16885d0b6ac6800361d680811346a01338a56a2174a3c0ae5d86bbd827d93fe8c59d71acd2e1cc7d6e79e39a179836d5695cbfa3b370982ee5
HG_COMMON_FILENAME=mercurial-common_3.8.4_all.deb
HG_COMMON_DIGEST=ac2b2fab9f19438c77147dca8df5020d10b129052e6c5f77ebe9a4c21eb0cedb1acfe25b146577bf5e9b66f3d6cfca2474f7575adfba1b3849b66bf5bc321015
HG_COMMON_SIZE=2993590
HG_COMMON_FILENAME=mercurial-common_3.9.4_all.deb
fi
fi

Просмотреть файл

@ -50,6 +50,8 @@ try:
except ImportError:
import json
from cStringIO import StringIO
from mozprocess import ProcessHandler
from mozharness.base.config import BaseConfig
from mozharness.base.log import SimpleFileLogger, MultiFileLogger, \
@ -458,28 +460,157 @@ class ScriptMixin(PlatformMixin):
**retry_args
)
def download_unpack(self, url, extract_to, extract_dirs=None,
error_level=FATAL):
"""Generic method to download and extract a compressed file.
The downloaded file will always be saved to the working directory and is not getting
deleted after extracting.
def _filter_entries(self, namelist, extract_dirs):
"""Filter entries of the archive based on the specified list of to extract dirs."""
filter_partial = functools.partial(fnmatch.filter, namelist)
entries = itertools.chain(*map(filter_partial, extract_dirs or ['*']))
for entry in entries:
yield entry
def unzip(self, file_object, extract_to='.', extract_dirs='*', verbose=False):
"""This method allows to extract a zip file without writing to disk first.
Args:
file_object (object): Any file like object that is seekable.
extract_to (str, optional): where to extract the compressed file.
extract_dirs (list, optional): directories inside the archive file to extract.
Defaults to '*'.
"""
compressed_file = StringIO(file_object.read())
try:
with zipfile.ZipFile(compressed_file) as bundle:
entries = self._filter_entries(bundle.namelist(), extract_dirs)
for entry in entries:
if verbose:
self.info(' {}'.format(entry))
bundle.extract(entry, path=extract_to)
# ZipFile doesn't preserve permissions during extraction:
# http://bugs.python.org/issue15795
fname = os.path.realpath(os.path.join(extract_to, entry))
mode = bundle.getinfo(entry).external_attr >> 16 & 0x1FF
# Only set permissions if attributes are available. Otherwise all
# permissions will be removed eg. on Windows.
if mode:
os.chmod(fname, mode)
except zipfile.BadZipfile as e:
self.exception('{}'.format(e.message))
def deflate(self, file_object, mode, extract_to='.', extract_dirs='*', verbose=False):
"""This method allows to extract a tar, tar.bz2 and tar.gz file without writing to disk first.
Args:
file_object (object): Any file like object that is seekable.
extract_to (str, optional): where to extract the compressed file.
extract_dirs (list, optional): directories inside the archive file to extract.
Defaults to `*`.
verbose (bool, optional): whether or not extracted content should be displayed.
Defaults to False.
"""
compressed_file = StringIO(file_object.read())
t = tarfile.open(fileobj=compressed_file, mode=mode)
t.extractall(path=extract_to)
def download_unpack(self, url, extract_to='.', extract_dirs='*', verbose=False):
"""Generic method to download and extract a compressed file without writing it to disk first.
Args:
url (str): URL where the file to be downloaded is located.
extract_to (str): directory where the downloaded file will
be extracted to.
extract_to (str, optional): directory where the downloaded file will
be extracted to.
extract_dirs (list, optional): directories inside the archive to extract.
Defaults to `None`.
error_level (str, optional): log level to use in case an error occurs.
Defaults to `FATAL`.
Defaults to `*`. It currently only applies to zip files.
Raises:
IOError: on `filename` file not found.
"""
dirs = self.query_abs_dirs()
archive = self.download_file(url, parent_dir=dirs['abs_work_dir'],
error_level=error_level)
self.unpack(archive, extract_to, extract_dirs=extract_dirs,
error_level=error_level)
# Many scripts overwrite this method and set extract_dirs to None
extract_dirs = '*' if extract_dirs is None else extract_dirs
EXTENSION_TO_MIMETYPE = {
'bz2': 'application/x-bzip2',
'gz': 'application/x-gzip',
'tar': 'application/x-tar',
'zip': 'application/zip',
}
MIMETYPES = {
'application/x-bzip2': {
'function': self.deflate,
'kwargs': {'mode': 'r:bz2'},
},
'application/x-gzip': {
'function': self.deflate,
'kwargs': {'mode': 'r:gz'},
},
'application/x-tar': {
'function': self.deflate,
'kwargs': {'mode': 'r'},
},
'application/zip': {
'function': self.unzip,
},
}
parsed_url = urlparse.urlparse(url)
# In case we're referrencing a file without file://
if parsed_url.scheme == '':
if not os.path.isfile(url):
raise IOError('Could not find file to extract: {}'.format(url))
url = 'file://%s' % os.path.abspath(url)
parsed_fd = urlparse.urlparse(url)
request = urllib2.Request(url)
response = urllib2.urlopen(request)
if parsed_url.scheme == 'file':
filename = url.split('/')[-1]
# XXX: bz2/gz instead of tar.{bz2/gz}
extension = filename[filename.rfind('.')+1:]
mimetype = EXTENSION_TO_MIMETYPE[extension]
else:
mimetype = response.headers.type
self.debug('Url: {}'.format(url))
self.debug('Mimetype: {}'.format(mimetype))
self.debug('Content-Encoding {}'.format(response.headers.get('Content-Encoding')))
function = MIMETYPES[mimetype]['function']
kwargs = {
'file_object': response,
'extract_to': extract_to,
'extract_dirs': extract_dirs,
'verbose': verbose,
}
kwargs.update(MIMETYPES[mimetype].get('kwargs', {}))
self.info('Downloading and extracting to {} these dirs {} from {}'.format(
extract_to,
', '.join(extract_dirs),
url,
))
retry_args = dict(
failure_status=None,
retry_exceptions=(urllib2.HTTPError, urllib2.URLError,
httplib.BadStatusLine,
socket.timeout, socket.error),
error_message="Can't download from {}".format(url),
error_level=FATAL,
)
self.retry(
function,
kwargs=kwargs,
**retry_args
)
def load_json_url(self, url, error_level=None, *args, **kwargs):
""" Returns a json object from a url (it retries). """
@ -1409,12 +1540,6 @@ class ScriptMixin(PlatformMixin):
IOError: on `filename` file not found.
"""
def _filter_entries(namelist):
"""Filter entries of the archive based on the specified list of to extract dirs."""
filter_partial = functools.partial(fnmatch.filter, namelist)
for entry in itertools.chain(*map(filter_partial, extract_dirs or ['*'])):
yield entry
if not os.path.isfile(filename):
raise IOError('Could not find file to extract: %s' % filename)
@ -1422,7 +1547,7 @@ class ScriptMixin(PlatformMixin):
try:
self.info('Using ZipFile to extract {} to {}'.format(filename, extract_to))
with zipfile.ZipFile(filename) as bundle:
for entry in _filter_entries(bundle.namelist()):
for entry in self._filter_entries(bundle.namelist(), extract_dirs):
if verbose:
self.info(' %s' % entry)
bundle.extract(entry, path=extract_to)
@ -1444,7 +1569,7 @@ class ScriptMixin(PlatformMixin):
try:
self.info('Using TarFile to extract {} to {}'.format(filename, extract_to))
with tarfile.open(filename) as bundle:
for entry in _filter_entries(bundle.getnames()):
for entry in self._filter_entries(bundle.getnames(), extract_dirs):
if verbose:
self.info(' %s' % entry)
bundle.extract(entry, path=extract_to)

Просмотреть файл

@ -259,6 +259,50 @@ class TestScript(unittest.TestCase):
self.assertTrue(error_logsize > 0,
msg="error list not working properly")
def test_download_unpack(self):
# NOTE: The action is called *download*, however, it can work for files in disk
self.s = get_debug_script_obj()
archives_path = os.path.join(here, 'helper_files', 'archives')
# Test basic decompression
for archive in ('archive.tar', 'archive.tar.bz2', 'archive.tar.gz', 'archive.zip'):
self.s.download_unpack(
url=os.path.join(archives_path, archive),
extract_to=self.tmpdir
)
self.assertIn('script.sh', os.listdir(os.path.join(self.tmpdir, 'bin')))
self.assertIn('lorem.txt', os.listdir(self.tmpdir))
shutil.rmtree(self.tmpdir)
# Test permissions for extracted entries from zip archive
self.s.download_unpack(
url=os.path.join(archives_path, 'archive.zip'),
extract_to=self.tmpdir,
)
file_stats = os.stat(os.path.join(self.tmpdir, 'bin', 'script.sh'))
orig_fstats = os.stat(os.path.join(archives_path, 'reference', 'bin', 'script.sh'))
self.assertEqual(file_stats.st_mode, orig_fstats.st_mode)
shutil.rmtree(self.tmpdir)
# Test unzip specific dirs only
self.s.download_unpack(
url=os.path.join(archives_path, 'archive.zip'),
extract_to=self.tmpdir,
extract_dirs=['bin/*']
)
self.assertIn('bin', os.listdir(self.tmpdir))
self.assertNotIn('lorem.txt', os.listdir(self.tmpdir))
shutil.rmtree(self.tmpdir)
# Test for invalid filenames (Windows only)
if PYWIN32:
with self.assertRaises(IOError):
self.s.download_unpack(
url=os.path.join(archives_path, 'archive_invalid_filename.zip'),
extract_to=self.tmpdir
)
def test_unpack(self):
self.s = get_debug_script_obj()

Просмотреть файл

@ -15,12 +15,9 @@ var passwordmanager = null;
// password-manager lists
var signons = [];
var rejects = [];
var deletedSignons = [];
var deletedRejects = [];
var signonsTree;
var rejectsTree;
var showingPasswords = false;
@ -34,7 +31,6 @@ function Startup() {
kObserverService.addObserver(signonReloadDisplay, "passwordmgr-storage-changed", false);
signonsTree = document.getElementById("signonsTree");
rejectsTree = document.getElementById("rejectsTree");
}
function Shutdown() {
@ -59,17 +55,6 @@ var signonReloadDisplay = {
_filterPasswords();
}
break;
case "hostSavingEnabled":
case "hostSavingDisabled":
if (!rejectsTree) {
return;
}
rejects.length = 0;
if (lastRejectSortColumn == "hostname") {
lastRejectSortAscending = !lastRejectSortAscending; // prevents sort from being reversed
}
LoadRejects();
break;
}
kObserverService.notifyObservers(null, "passwordmgr-dialog-updated", null);
}

Просмотреть файл

@ -1,115 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*** =================== REJECTED SIGNONS CODE =================== ***/
Components.utils.import("resource://gre/modules/AppConstants.jsm");
function RejectsStartup() {
LoadRejects();
let treecols = document.getElementsByTagName("treecols")[0];
treecols.addEventListener("click", HandleTreeColumnClick.bind(null, RejectColumnSort));
}
var rejectsTreeView = {
rowCount : 0,
setTree : function(tree) {},
getImageSrc : function(row, column) {},
getProgressMode : function(row, column) {},
getCellValue : function(row, column) {},
getCellText : function(row, column) {
var rv="";
if (column.id=="rejectCol") {
rv = rejects[row].host;
}
return rv;
},
isSeparator : function(index) { return false; },
isSorted: function() { return false; },
isContainer : function(index) { return false; },
cycleHeader : function(column) {},
getRowProperties : function(row) { return ""; },
getColumnProperties : function(column) { return ""; },
getCellProperties : function(row, column) {
if (column.element.getAttribute("id") == "rejectCol")
return "ltr";
return "";
}
};
function Reject(number, host) {
this.number = number;
this.host = host;
}
function LoadRejects() {
var hosts = passwordmanager.getAllDisabledHosts();
rejects = hosts.map(function(host, i) { return new Reject(i, host); });
rejectsTreeView.rowCount = rejects.length;
// sort and display the table
rejectsTree.view = rejectsTreeView;
RejectColumnSort(lastRejectSortColumn);
var element = document.getElementById("removeAllRejects");
if (rejects.length == 0) {
element.setAttribute("disabled", "true");
} else {
element.removeAttribute("disabled");
}
}
function RejectSelected() {
var selections = GetTreeSelections(rejectsTree);
if (selections.length) {
document.getElementById("removeReject").removeAttribute("disabled");
}
}
function DeleteReject() {
DeleteSelectedItemFromTree(rejectsTree, rejectsTreeView,
rejects, deletedRejects,
"removeReject", "removeAllRejects");
FinalizeRejectDeletions();
}
function DeleteAllRejects() {
DeleteAllFromTree(rejectsTree, rejectsTreeView,
rejects, deletedRejects,
"removeReject", "removeAllRejects");
FinalizeRejectDeletions();
}
function FinalizeRejectDeletions() {
for (var r=0; r<deletedRejects.length; r++) {
passwordmanager.setLoginSavingEnabled(deletedRejects[r].host, true);
}
deletedRejects.length = 0;
}
function HandleRejectKeyPress(e) {
if (e.keyCode == KeyEvent.DOM_VK_DELETE ||
(AppConstants.platform == "macosx" &&
e.keyCode == KeyEvent.DOM_VK_BACK_SPACE))
{
DeleteReject();
}
}
var lastRejectSortColumn = "host";
var lastRejectSortAscending = false;
function RejectColumnSort(column) {
lastRejectSortAscending =
SortTree(rejectsTree, rejectsTreeView, rejects,
column, lastRejectSortColumn, lastRejectSortAscending);
lastRejectSortColumn = column;
// set the sortDirection attribute to get the styling going
var sortedCol = document.getElementById("rejectCol");
sortedCol.setAttribute("sortDirection", lastRejectSortAscending ?
"ascending" : "descending");
}

Просмотреть файл

@ -1,49 +0,0 @@
<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil -*- -->
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd" >
<prefwindow id="SignonViewerExceptionDialog"
windowtype="Toolkit:PasswordManagerExceptions"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept"
buttonlabelaccept="&closebutton.label;"
onload="Startup(); RejectsStartup();"
onunload="Shutdown();"
title="&savedLoginsExceptions.title;"
persist="width height screenX screenY">
<prefpane id="SignonViewerDialogPane" flex="1">
<script type="application/javascript" src="chrome://passwordmgr/content/passwordManagerCommon.js"/>
<script type="application/javascript" src="chrome://passwordmgr/content/passwordManagerExceptions.js"/>
<vbox id="rejectedsites" flex="1">
<description control="rejectsTree">&savedLoginsExceptions.desc;</description>
<separator class="thin"/>
<tree id="rejectsTree" flex="1" style="height: 10em;" hidecolumnpicker="true"
onkeypress="HandleRejectKeyPress(event)"
onselect="RejectSelected();">
<treecols>
<treecol id="rejectCol" label="&treehead.site.label;" flex="5"
data-field-name="host" sortDirection="ascending"/>
</treecols>
<treechildren/>
</tree>
<separator class="thin"/>
<hbox>
<button id="removeReject" disabled="true" icon="remove"
accesskey="&remove.accesskey;"
label="&remove.label;" oncommand="DeleteReject();"/>
<button id="removeAllRejects"
accesskey="&removeall.accesskey;"
icon="clear" label="&removeall.label;"
oncommand="DeleteAllRejects();"/>
</hbox>
</vbox>
</prefpane>
</prefwindow>

Просмотреть файл

@ -7,7 +7,5 @@ toolkit.jar:
content/passwordmgr/login.xml (content/login.xml)
* content/passwordmgr/passwordManager.xul (content/passwordManager.xul)
content/passwordmgr/passwordManager.js (content/passwordManager.js)
content/passwordmgr/passwordManagerExceptions.js (content/passwordManagerExceptions.js)
content/passwordmgr/passwordManagerExceptions.xul (content/passwordManagerExceptions.xul)
content/passwordmgr/passwordManagerCommon.js (content/passwordManagerCommon.js)
content/passwordmgr/recipes.json (content/recipes.json)

Просмотреть файл

@ -38,6 +38,7 @@ support-files =
subtst_notifications_change_p.html
[browser_DOMFormHasPassword.js]
[browser_DOMInputPasswordAdded.js]
[browser_exceptions_dialog.js]
[browser_filldoorhanger.js]
[browser_formless_submit_chrome.js]
[browser_hasInsecureLoginForms.js]

Просмотреть файл

@ -0,0 +1,56 @@
"use strict";
const LOGIN_HOST = "http://example.com";
function openExceptionsDialog() {
return window.openDialog(
"chrome://browser/content/preferences/permissions.xul",
"Toolkit:PasswordManagerExceptions", "",
{
blockVisible: true,
sessionVisible: false,
allowVisible: false,
hideStatusColumn: true,
prefilledHost: "",
permissionType: "login-saving"
}
);
}
function countDisabledHosts(dialog) {
let doc = dialog.document;
let rejectsTree = doc.getElementById("permissionsTree");
return rejectsTree.view.rowCount;
}
function promiseStorageChanged(expectedData) {
function observer(subject, data) {
return data == expectedData && subject.QueryInterface(Ci.nsISupportsString).data == LOGIN_HOST;
}
return TestUtils.topicObserved("passwordmgr-storage-changed", observer);
}
add_task(function* test_disable() {
let dialog = openExceptionsDialog();
let promiseChanged = promiseStorageChanged("hostSavingDisabled");
yield BrowserTestUtils.waitForEvent(dialog, "load");
Services.logins.setLoginSavingEnabled(LOGIN_HOST, false);
yield promiseChanged;
is(countDisabledHosts(dialog), 1, "Verify disabled host added");
yield BrowserTestUtils.closeWindow(dialog);
});
add_task(function* test_enable() {
let dialog = openExceptionsDialog();
let promiseChanged = promiseStorageChanged("hostSavingEnabled");
yield BrowserTestUtils.waitForEvent(dialog, "load");
Services.logins.setLoginSavingEnabled(LOGIN_HOST, true);
yield promiseChanged;
is(countDisabledHosts(dialog), 0, "Verify disabled host removed");
yield BrowserTestUtils.closeWindow(dialog);
});

Просмотреть файл

@ -12,9 +12,7 @@ function test() {
let pmDialog = window.openDialog(
"chrome://passwordmgr/content/passwordManager.xul",
"Toolkit:PasswordManager", "");
let pmexDialog = window.openDialog(
"chrome://passwordmgr/content/passwordManagerExceptions.xul",
"Toolkit:PasswordManagerExceptions", "");
let logins = [];
let loginCounter = 0;
let loginOrder = null;
@ -48,14 +46,6 @@ function test() {
is(countLogins(), 0, "Verify all logins removed");
runNextTest();
break;
case 9:
is(countDisabledHosts(), 1, "Verify disabled host added");
runNextTest();
break;
case 10:
is(countDisabledHosts(), 0, "Verify disabled host removed");
runNextTest();
break;
}
}
}
@ -75,12 +65,6 @@ function test() {
is(logins.length, LOGIN_COUNT, "Verify logins created");
}
function countDisabledHosts() {
let doc = pmexDialog.document;
let rejectsTree = doc.getElementById("rejectsTree");
return rejectsTree.view.rowCount;
}
function countLogins() {
let doc = pmDialog.document;
let signonsTree = doc.getElementById("signonsTree");
@ -134,19 +118,10 @@ function test() {
case 8: // remove all logins
Services.logins.removeAllLogins();
break;
case 9: // save a disabled host
pmDialog.close();
SimpleTest.waitForFocus(function() {
Services.logins.setLoginSavingEnabled(LOGIN_HOST, false);
}, pmexDialog);
break;
case 10: // remove a disabled host
Services.logins.setLoginSavingEnabled(LOGIN_HOST, true);
break;
case 11: // finish
case 9: // finish
Services.obs.removeObserver(
testObserver, "passwordmgr-dialog-updated", false);
pmexDialog.close();
pmDialog.close();
finish();
break;
}

Просмотреть файл

@ -3,8 +3,6 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY savedLogins.title "Saved Logins">
<!ENTITY savedLoginsExceptions.title "Exceptions - Saved Logins">
<!ENTITY savedLoginsExceptions.desc "Logins for the following sites will not be saved:">
<!ENTITY closebutton.label "Close">
<!ENTITY closebutton.accesskey "C">

Просмотреть файл

@ -46,10 +46,14 @@ const ADDONS = {
id: "jid0-GXjLLfbCoAx0LcltEdFrEkQdQPI@jetpack", minVersion: "3.0.10",
},
"PersonasPlus": {
"PersonasPlus": { // PersonasPlus
id: "personas@christopher.beard", minVersion: "1.8.0",
},
"ACR": { // Add-on Compatibility Reporter
id: "compatibility@addons.mozilla.org", minVersion: "2.2.0",
},
// Add-ons used for testing
"test1": {
id: "bootstrap1@tests.mozilla.org", minVersion: "1.0",
@ -62,10 +66,8 @@ const ADDONS = {
// NOTE: Do not modify sets or policies after they have already been
// published to users. They must remain unchanged to provide valid data.
const set1 = [ADDONS.Emoji,
ADDONS.ASP,
ADDONS.DYTV];
// Set 2 used during 48 Beta cycle. Kept here for historical reasons.
const set2 = [ADDONS.Greasemonkey,
ADDONS.DYTV,
ADDONS.VDH,
@ -76,16 +78,46 @@ const set2 = [ADDONS.Greasemonkey,
ADDONS.ASP,
ADDONS.PersonasPlus];
const set49Release = [
ADDONS.Greasemonkey,
ADDONS.DYTV,
ADDONS.VDH,
ADDONS.Lightbeam,
ADDONS.ABP,
ADDONS.uBlockOrigin,
ADDONS.Emoji,
ADDONS.ASP,
ADDONS.PersonasPlus,
ADDONS.ACR
];
// These are only the add-ons in the Add-Ons Manager Discovery
// pane. This set is here in case we need to reduce add-ons
// exposure live on Release.
const set49PaneOnly = [
ADDONS.ABP,
ADDONS.VDH,
ADDONS.Emoji,
ADDONS.ASP,
ADDONS.ACR
]
// We use these named policies to correlate the telemetry
// data with them, in order to understand how each set
// is behaving in the wild.
const RolloutPolicy = {
"1a": { addons: set1, webextensions: true },
// Used during 48 Beta cycle
"2a": { addons: set2, webextensions: true },
"1b": { addons: set1, webextensions: false },
"2b": { addons: set2, webextensions: false },
// Set agreed for Release 49
"49a": { addons: set49Release, webextensions: true },
"49b": { addons: set49Release, webextensions: false },
// Smaller set that can be used for Release 49
"49limiteda": { addons: set49PaneOnly, webextensions: true },
"49limitedb": { addons: set49PaneOnly, webextensions: false },
"xpcshell-test": { addons: [ADDONS.test1, ADDONS.test2], webextensions: false },
};

128
tools/coverity/model.cpp Normal file
Просмотреть файл

@ -0,0 +1,128 @@
/*
Coverity model file in order to avoid false-positive
*/
#define NULL (void *)0
typedef unsigned char jsbytecode;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned int int32_t;
typedef unsigned char uint8_t;
static const uint16_t CHUNK_HEAD_SIZE = 8;
void assert(bool expr) {
if (!expr) {
__coverity_panic__();
}
}
#define ERREXIT(cinfo, err) __coverity_panic__();
void MOZ_ASSUME_UNREACHABLE(char * str) {
__coverity_panic__();
}
static void MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename,
int aLine) {
__coverity_panic__();
}
static void MOZ_ReportCrash(const char* aStr, const char* aFilename,
int aLine) {
__coverity_panic__();
}
#define MOZ_ASSERT(expr, msg) assert(!!(expr))
#define MOZ_ASSERT(expr) assert(!!(expr))
#define NS_ASSERTION(expr, msg) assert(!!(expr))
#define PORT_Assert(expr) assert(!!(expr))
#define PR_ASSERT(expr) assert(!!(expr))
int GET_JUMP_OFFSET(jsbytecode* pc) {
__coverity_tainted_data_sanitize__(&pc[1]);
__coverity_tainted_data_sanitize__(&pc[2]);
__coverity_tainted_data_sanitize__(&pc[3]);
__coverity_tainted_data_sanitize__(&pc[4]);
return 0;
}
// Data sanity checkers
#define XPT_SWAB16(data) __coverity_tainted_data_sanitize__(&data)
#define XPT_SWAB32(data) __coverity_tainted_data_sanitize__(&data)
static unsigned GET_UINT24(const jsbytecode* pc) {
__coverity_tainted_data_sanitize__(static_cast<void*>(pc));
//return unsigned((pc[1] << 16) | (pc[2] << 8) | pc[3]);
return 0;
}
class HeaderParser {
private:
class ChunkHeader {
uint8_t mRaw[CHUNK_HEAD_SIZE];
HeaderParser::ChunkHeader::ChunkSize() const {
__coverity_tainted_data_sanitize__(static_cast<void*>(&mRaw[4]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&mRaw[5]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&mRaw[6]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&mRaw[7]));
return ((mRaw[7] << 24) | (mRaw[6] << 16) | (mRaw[5] << 8) | (mRaw[4]));
}
};
};
void NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr,
const char* aFile, int32_t aLine) {
__coverity_panic__();
}
static inline void Swap(uint32_t* value) {
__coverity_tainted_data_sanitize__(static_cast<void*>(&value));
*value = (*value >> 24) |
((*value >> 8) & 0x0000ff00) |
((*value << 8) & 0x00ff0000) |
(*value << 24);
}
static uint32_t xtolong (const uint8_t *ll) {
__coverity_tainted_data_sanitize__(static_cast<void*>(&ll[0]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&ll[1]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&ll[2]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&ll[3]));
return (uint32_t)( (ll [0] << 0) |
(ll [1] << 8) |
(ll [2] << 16) |
(ll [3] << 24) );
}
class ByteReader {
public:
const uint8_t* Read(size_t aCount);
uint32_t ReadU24() {
const uint8_t *ptr = Read(3);
if (!ptr) {
MOZ_ASSERT(false);
return 0;
}
__coverity_tainted_data_sanitize__(static_cast<void*>(&ptr[0]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&ptr[1]));
__coverity_tainted_data_sanitize__(static_cast<void*>(&ptr[2]));
return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
}
};

Просмотреть файл

@ -1392,7 +1392,7 @@ nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
if (inState.HasState(NS_EVENT_STATE_FOCUS) && isActive)
bdi.adornment |= kThemeAdornmentFocus;
if (inIsDefault && !isDisabled && isActive &&
if (inIsDefault && !isDisabled &&
!inState.HasState(NS_EVENT_STATE_ACTIVE)) {
bdi.adornment |= kThemeAdornmentDefault;
bdi.animation.time.start = 0;
@ -2468,11 +2468,22 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
case NS_THEME_BUTTON:
if (IsDefaultButton(aFrame)) {
if (!IsDisabled(aFrame, eventState) && FrameIsInActiveWindow(aFrame) &&
// Check whether the default button is in a document that does not
// match the :-moz-window-inactive pseudoclass. This activeness check
// is different from the other "active window" checks in this file
// because we absolutely need the button's default button appearance to
// be in sync with its text color, and the text color is changed by
// such a :-moz-window-inactive rule. (That's because on 10.10 and up,
// default buttons in active windows have blue background and white
// text, and default buttons in inactive windows have white background
// and black text.)
EventStates docState = aFrame->GetContent()->OwnerDoc()->GetDocumentState();
bool isInActiveWindow = !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
if (!IsDisabled(aFrame, eventState) && isInActiveWindow &&
!QueueAnimatedContentForRefresh(aFrame->GetContent(), 10)) {
NS_WARNING("Unable to animate button!");
}
DrawButton(cgContext, kThemePushButton, macRect, true,
DrawButton(cgContext, kThemePushButton, macRect, isInActiveWindow,
kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame);
} else if (IsButtonTypeMenu(aFrame)) {
DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);