Merge last green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Matt Brubeck 2011-10-10 11:01:32 -07:00
commit 4151b38db0
45 changed files with 875 additions and 359 deletions

View File

@ -100,7 +100,6 @@
accesskey="&helpSafeMode.accesskey;"
label="&helpSafeMode.label;"
oncommand="safeModeRestart();"/>
<menuseparator/>
<menuseparator id="aboutSeparator"/>
<menuitem id="aboutName"
accesskey="&aboutProduct.accesskey;"

View File

@ -472,6 +472,7 @@
<toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
context="backForwardMenu" removable="true"
forwarddisabled="true"
title="&backForwardItem.title;">
<toolbarbutton id="back-button" class="toolbarbutton-1"
label="&backCmd.label;"
@ -483,6 +484,13 @@
command="Browser:ForwardOrForwardDuplicate"
onclick="checkForMiddleClick(this, event);"
tooltip="forward-button-tooltip"/>
<dummyobservertarget hidden="true"
onbroadcast="if (this.getAttribute('disabled') == 'true')
this.parentNode.setAttribute('forwarddisabled', 'true');
else
this.parentNode.removeAttribute('forwarddisabled');">
<observes element="Browser:ForwardOrForwardDuplicate" attribute="disabled"/>
</dummyobservertarget>
</toolbaritem>
<toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true"
@ -1002,6 +1010,10 @@
<svg:rect x="0" y="0" width="1" height="1" fill="white"/>
<svg:circle cx="-0.35" cy="0.5" r="0.58"/>
</svg:mask>
<svg:mask id="winstripe-urlbar-back-button-mask" maskContentUnits="userSpaceOnUse">
<svg:rect x="0" y="0" width="10000" height="50" fill="white"/>
<svg:circle cx="-11" cy="12" r="15"/>
</svg:mask>
</svg:svg>
#endif
#ifdef XP_MACOSX

View File

@ -878,6 +878,10 @@
this.mCurrentTab = this.selectedTab;
this.showTab(this.mCurrentTab);
var backForwardContainer = document.getElementById("unified-back-forward-button");
if (backForwardContainer)
backForwardContainer.setAttribute("switchingtabs", "true");
if (updatePageReport)
this.mCurrentBrowser.updatePageReport();
@ -945,6 +949,9 @@
true, false);
}
if (backForwardContainer)
backForwardContainer.removeAttribute("switchingtabs");
if (this.mCurrentTab.selected)
this._setCloseKeyState(!this.mCurrentTab.pinned);

View File

@ -604,18 +604,37 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
#forward-button {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
-moz-transition: 250ms ease-out;
}
#forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
}
#forward-button:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
}
#forward-button[disabled="true"]:-moz-locale-dir(rtl) {
toolbar:not([mode=icons]) #forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
}
toolbar:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled");
}
toolbar[mode=icons] #forward-button[disabled="true"] {
-moz-transform: scale(0);
opacity: 0;
pointer-events: none;
}
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
margin-left: -36px;
}
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
margin-right: -36px;
}
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
margin-left: -28px;
}
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
margin-right: -28px;
}
#reload-button {
list-style-image: url("moz-icon://stock/gtk-refresh?size=toolbar");
}
@ -787,7 +806,7 @@ toolbar[iconsize="small"] #forward-button {
.unified-nav-forward[_moz-menuactive] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
}
toolbar[iconsize="small"] #forward-button[disabled="true"] {
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"] {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
}
@ -797,7 +816,7 @@ toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl) {
.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
}
toolbar[iconsize="small"] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
}

View File

@ -59,6 +59,9 @@
%define bgTabTextureHover -moz-linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2))
%define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32);
%define navbarLargeIcons #navigator-toolbox[iconsize=large][mode=icons] > #nav-bar
%define forwardTransitionLength 150ms
%define conditionalForwardWithUrlbar window:not([chromehidden~=toolbar]) #navigator-toolbox[iconsize=large][mode=icons] > :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"],#nav-bar:not([currentset])) > #unified-back-forward-button
%define conditionalForwardWithUrlbarWidth 27
%ifdef MOZ_OFFICIAL_BRANDING
%define appMenuButtonBorderColor rgba(255,255,255,.5) rgba(83,42,6,.9)
@ -845,6 +848,20 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-moz-margin-start: 0 !important;
}
@conditionalForwardWithUrlbar@ > #forward-button {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
-moz-margin-end: 0;
}
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
-moz-transition: opacity @forwardTransitionLength@ ease-out;
}
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
opacity: 0;
}
@navbarLargeIcons@ #back-button:-moz-locale-dir(ltr) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
@ -1216,6 +1233,57 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
color: black;
}
@conditionalForwardWithUrlbar@ + #urlbar-container {
padding-left: @conditionalForwardWithUrlbarWidth@px;
-moz-margin-start: -@conditionalForwardWithUrlbarWidth@px;
position: relative;
pointer-events: none;
}
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar {
-moz-border-start: none;
margin-left: 0;
pointer-events: all;
}
@conditionalForwardWithUrlbar@:not([switchingtabs]) + #urlbar-container > #urlbar {
-moz-transition: margin-left @forwardTransitionLength@ ease-out;
}
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(ltr) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container {
mask: url("chrome://browser/content/browser.xul#winstripe-urlbar-back-button-mask");
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar {
margin-left: -@conditionalForwardWithUrlbarWidth@px;
}
@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) + #urlbar-container > #urlbar {
/* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */
-moz-transition-delay: 100s;
}
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar {
/* when not hovered anymore, trigger a new transition to hide the forward button immediately */
margin-left: -@conditionalForwardWithUrlbarWidth@.01px;
}
@conditionalForwardWithUrlbar@ + #urlbar-container:-moz-locale-dir(rtl),
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
/* let winstripe-urlbar-back-button-mask clip the urlbar's right side for RTL */
-moz-transform: scaleX(-1);
}
html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
.searchbar-textbox:-moz-lwtheme > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input:-moz-placeholder {
color: #777;
@ -1304,6 +1372,40 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
border-bottom-right-radius: 1.5px;
}
#notification-popup-box:not([hidden]) + #identity-box {
-moz-padding-start: 10px;
border-radius: 0;
}
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar > #identity-box {
border-radius: 0;
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
padding-left: 5px;
-moz-transition: padding-left;
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
padding-right: 5px;
-moz-transition: padding-right;
}
@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box {
/* forward button hiding is delayed when hovered */
-moz-transition-delay: 100s;
}
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
padding-left: 5.01px;
}
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
padding-right: 5.01px;
}
#identity-box:hover {
background-image: -moz-linear-gradient(hsl(0,0%,95%), hsl(0,0%,87%));
}
@ -2234,9 +2336,8 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-margin-end: -8px;
}
#notification-popup-box:not([hidden]) + #identity-box {
-moz-padding-start: 10px;
border-radius: 0;
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box {
padding-left: 5px;
}
#notification-popup-box:-moz-locale-dir(rtl),

View File

@ -226,9 +226,7 @@ ToPreserveAspectRatio(const nsAString &aString,
nsresult
SVGAnimatedPreserveAspectRatio::SetBaseValueString(
const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
const nsAString &aValueAsString, nsSVGElement *aSVGElement)
{
SVGPreserveAspectRatio val;
nsresult res = ToPreserveAspectRatio(aValueAsString, &val);
@ -247,7 +245,9 @@ SVGAnimatedPreserveAspectRatio::SetBaseValueString(
}
#endif
aSVGElement->DidChangePreserveAspectRatio(aDoSetAttr);
// We don't need to call DidChange* here - we're only called by
// nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
// which takes care of notifying.
return NS_OK;
}

View File

@ -110,8 +110,7 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
nsresult SetBaseAlign(PRUint16 aAlign, nsSVGElement *aSVGElement);

View File

@ -74,8 +74,7 @@ GetValueFromString(const nsAString &aValueAsString,
nsresult
nsSVGBoolean::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
bool val;

View File

@ -52,8 +52,7 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
void SetBaseValue(bool aValue, nsSVGElement *aSVGElement);

View File

@ -382,7 +382,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
NumberAttributesInfo numberInfo = GetNumberInfo();
for (i = 0; i < numberInfo.mNumberCount; i++) {
if (aAttribute == *numberInfo.mNumberInfo[i].mName) {
rv = numberInfo.mNumbers[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = numberInfo.mNumbers[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
numberInfo.Reset(i);
}
@ -397,7 +397,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
NumberPairAttributesInfo numberPairInfo = GetNumberPairInfo();
for (i = 0; i < numberPairInfo.mNumberPairCount; i++) {
if (aAttribute == *numberPairInfo.mNumberPairInfo[i].mName) {
rv = numberPairInfo.mNumberPairs[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = numberPairInfo.mNumberPairs[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
numberPairInfo.Reset(i);
}
@ -412,7 +412,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
IntegerAttributesInfo integerInfo = GetIntegerInfo();
for (i = 0; i < integerInfo.mIntegerCount; i++) {
if (aAttribute == *integerInfo.mIntegerInfo[i].mName) {
rv = integerInfo.mIntegers[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = integerInfo.mIntegers[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
integerInfo.Reset(i);
}
@ -427,7 +427,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
IntegerPairAttributesInfo integerPairInfo = GetIntegerPairInfo();
for (i = 0; i < integerPairInfo.mIntegerPairCount; i++) {
if (aAttribute == *integerPairInfo.mIntegerPairInfo[i].mName) {
rv = integerPairInfo.mIntegerPairs[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = integerPairInfo.mIntegerPairs[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
integerPairInfo.Reset(i);
}
@ -457,7 +457,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
BooleanAttributesInfo booleanInfo = GetBooleanInfo();
for (i = 0; i < booleanInfo.mBooleanCount; i++) {
if (aAttribute == *booleanInfo.mBooleanInfo[i].mName) {
rv = booleanInfo.mBooleans[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = booleanInfo.mBooleans[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
booleanInfo.Reset(i);
}
@ -472,7 +472,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
EnumAttributesInfo enumInfo = GetEnumInfo();
for (i = 0; i < enumInfo.mEnumCount; i++) {
if (aAttribute == *enumInfo.mEnumInfo[i].mName) {
rv = enumInfo.mEnums[i].SetBaseValueString(aValue, this, PR_FALSE);
rv = enumInfo.mEnums[i].SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
enumInfo.Reset(i);
}
@ -487,7 +487,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
if (aAttribute == nsGkAtoms::viewBox) {
nsSVGViewBox* viewBox = GetViewBox();
if (viewBox) {
rv = viewBox->SetBaseValueString(aValue, this, PR_FALSE);
rv = viewBox->SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
viewBox->Init();
}
@ -498,7 +498,7 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
GetPreserveAspectRatio();
if (preserveAspectRatio) {
rv = preserveAspectRatio->SetBaseValueString(aValue, this, PR_FALSE);
rv = preserveAspectRatio->SetBaseValueString(aValue, this);
if (NS_FAILED(rv)) {
preserveAspectRatio->Init();
}

View File

@ -70,8 +70,7 @@ nsSVGEnum::GetMapping(nsSVGElement *aSVGElement)
nsresult
nsSVGEnum::SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
nsCOMPtr<nsIAtom> valAtom = do_GetAtom(aValue);
@ -121,8 +120,7 @@ nsSVGEnum::GetBaseValueString(nsAString& aValue, nsSVGElement *aSVGElement)
nsresult
nsSVGEnum::SetBaseValue(PRUint16 aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
@ -139,7 +137,7 @@ nsSVGEnum::SetBaseValue(PRUint16 aValue,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeEnum(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeEnum(mAttrEnum, true);
}
return NS_OK;
}

View File

@ -59,14 +59,12 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue,
nsSVGElement *aSVGElement);
nsresult SetBaseValue(PRUint16 aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
PRUint16 GetBaseValue() const
{ return mBaseVal; }
@ -107,7 +105,7 @@ public:
NS_IMETHOD GetBaseVal(PRUint16* aResult)
{ *aResult = mVal->GetBaseValue(); return NS_OK; }
NS_IMETHOD SetBaseVal(PRUint16 aValue)
{ return mVal->SetBaseValue(aValue, mSVGElement, PR_TRUE); }
{ return mVal->SetBaseValue(aValue, mSVGElement); }
// Script may have modified animation parameters or timeline -- DOM getters
// need to flush any resample requests to reflect these modifications.

View File

@ -161,7 +161,7 @@ NS_IMETHODIMP nsSVGFilterElement::GetFilterResY(nsIDOMSVGAnimatedInteger * *aFil
NS_IMETHODIMP
nsSVGFilterElement::SetFilterRes(PRUint32 filterResX, PRUint32 filterResY)
{
mIntegerPairAttributes[FILTERRES].SetBaseValues(filterResX, filterResY, this, PR_FALSE);
mIntegerPairAttributes[FILTERRES].SetBaseValues(filterResX, filterResY, this);
return NS_OK;
}
@ -241,36 +241,3 @@ nsSVGFilterElement::GetStringInfo()
return StringAttributesInfo(mStringAttributes, sStringInfo,
NS_ARRAY_LENGTH(sStringInfo));
}
inline static void DidAnimateAttr(nsSVGFilterElement *aFilterElement)
{
// nsSVGFilterFrame doesn't implement a useful AttributeChanged
nsIFrame* frame = aFilterElement->GetPrimaryFrame();
if (frame) {
nsSVGEffects::InvalidateRenderingObservers(frame);
}
}
void
nsSVGFilterElement::DidAnimateLength(PRUint8 aAttrEnum)
{
DidAnimateAttr(this);
}
void
nsSVGFilterElement::DidAnimateIntegerPair(PRUint8 aAttrEnum)
{
DidAnimateAttr(this);
}
void
nsSVGFilterElement::DidAnimateEnum(PRUint8 aAttrEnum)
{
DidAnimateAttr(this);
}
void
nsSVGFilterElement::DidAnimateString(PRUint8 aAttrEnum)
{
DidAnimateAttr(this);
}

View File

@ -88,11 +88,6 @@ protected:
virtual EnumAttributesInfo GetEnumInfo();
virtual StringAttributesInfo GetStringInfo();
virtual void DidAnimateLength(PRUint8 aAttrEnum);
virtual void DidAnimateIntegerPair(PRUint8 aAttrEnum);
virtual void DidAnimateEnum(PRUint8 aAttrEnum);
virtual void DidAnimateString(PRUint8 aAttrEnum);
enum { X, Y, WIDTH, HEIGHT };
nsSVGLength2 mLengthAttributes[4];
static LengthInfo sLengthInfo[4];

View File

@ -512,7 +512,7 @@ NS_IMETHODIMP
nsSVGFEGaussianBlurElement::SetStdDeviation(float stdDeviationX, float stdDeviationY)
{
NS_ENSURE_FINITE2(stdDeviationX, stdDeviationY, NS_ERROR_ILLEGAL_VALUE);
mNumberPairAttributes[STD_DEV].SetBaseValues(stdDeviationX, stdDeviationY, this, PR_TRUE);
mNumberPairAttributes[STD_DEV].SetBaseValues(stdDeviationX, stdDeviationY, this);
return NS_OK;
}
@ -1526,10 +1526,10 @@ NS_IMETHODIMP
nsSVGFECompositeElement::SetK(float k1, float k2, float k3, float k4)
{
NS_ENSURE_FINITE4(k1, k2, k3, k4, NS_ERROR_ILLEGAL_VALUE);
mNumberAttributes[K1].SetBaseValue(k1, this, PR_TRUE);
mNumberAttributes[K2].SetBaseValue(k2, this, PR_TRUE);
mNumberAttributes[K3].SetBaseValue(k3, this, PR_TRUE);
mNumberAttributes[K4].SetBaseValue(k4, this, PR_TRUE);
mNumberAttributes[K1].SetBaseValue(k1, this);
mNumberAttributes[K2].SetBaseValue(k2, this);
mNumberAttributes[K3].SetBaseValue(k3, this);
mNumberAttributes[K4].SetBaseValue(k4, this);
return NS_OK;
}
@ -3647,7 +3647,7 @@ NS_IMETHODIMP
nsSVGFEMorphologyElement::SetRadius(float rx, float ry)
{
NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE);
mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this, PR_TRUE);
mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
return NS_OK;
}

View File

@ -80,8 +80,7 @@ GetValueFromString(const nsAString &aValueAsString,
nsresult
nsSVGInteger::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
PRInt32 value;
@ -112,8 +111,7 @@ nsSVGInteger::GetBaseValueString(nsAString & aValueAsString)
void
nsSVGInteger::SetBaseValue(int aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
mBaseVal = aValue;
mIsBaseSet = PR_TRUE;
@ -125,7 +123,7 @@ nsSVGInteger::SetBaseValue(int aValue,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeInteger(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeInteger(mAttrEnum, true);
}
void

View File

@ -53,11 +53,10 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
void SetBaseValue(PRInt32 aValue, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValue(PRInt32 aValue, nsSVGElement *aSVGElement);
PRInt32 GetBaseValue() const
{ return mBaseVal; }
@ -103,7 +102,7 @@ public:
NS_IMETHOD GetBaseVal(PRInt32* aResult)
{ *aResult = mVal->GetBaseValue(); return NS_OK; }
NS_IMETHOD SetBaseVal(PRInt32 aValue)
{ mVal->SetBaseValue(aValue, mSVGElement, PR_TRUE); return NS_OK; }
{ mVal->SetBaseValue(aValue, mSVGElement); return NS_OK; }
// Script may have modified animation parameters or timeline -- DOM getters
// need to flush any resample requests to reflect these modifications.

View File

@ -102,8 +102,7 @@ ParseIntegerOptionalInteger(const nsAString& aValue,
nsresult
nsSVGIntegerPair::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
PRInt32 val[2];
@ -145,8 +144,7 @@ nsSVGIntegerPair::GetBaseValueString(nsAString &aValueAsString)
void
nsSVGIntegerPair::SetBaseValue(PRInt32 aValue, PairIndex aPairIndex,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
PRUint32 index = (aPairIndex == eFirst ? 0 : 1);
mBaseVal[index] = aValue;
@ -159,13 +157,12 @@ nsSVGIntegerPair::SetBaseValue(PRInt32 aValue, PairIndex aPairIndex,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeIntegerPair(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeIntegerPair(mAttrEnum, true);
}
void
nsSVGIntegerPair::SetBaseValues(PRInt32 aValue1, PRInt32 aValue2,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
mBaseVal[0] = aValue1;
mBaseVal[1] = aValue2;
@ -179,7 +176,7 @@ nsSVGIntegerPair::SetBaseValues(PRInt32 aValue1, PRInt32 aValue2,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeIntegerPair(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeIntegerPair(mAttrEnum, true);
}
void

View File

@ -65,12 +65,11 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
void SetBaseValue(PRInt32 aValue, PairIndex aIndex, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValues(PRInt32 aValue1, PRInt32 aValue2, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValue(PRInt32 aValue, PairIndex aIndex, nsSVGElement *aSVGElement);
void SetBaseValues(PRInt32 aValue1, PRInt32 aValue2, nsSVGElement *aSVGElement);
PRInt32 GetBaseValue(PairIndex aIndex) const
{ return mBaseVal[aIndex == eFirst ? 0 : 1]; }
void SetAnimValue(const PRInt32 aValue[2], nsSVGElement *aSVGElement);
@ -118,7 +117,7 @@ public:
{ *aResult = mVal->GetBaseValue(mIndex); return NS_OK; }
NS_IMETHOD SetBaseVal(PRInt32 aValue)
{
mVal->SetBaseValue(aValue, mIndex, mSVGElement, PR_TRUE);
mVal->SetBaseValue(aValue, mIndex, mSVGElement);
return NS_OK;
}

View File

@ -116,8 +116,7 @@ GetValueFromString(const nsAString &aValueAsString,
nsresult
nsSVGNumber2::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
float val;
@ -154,8 +153,7 @@ nsSVGNumber2::GetBaseValueString(nsAString & aValueAsString)
void
nsSVGNumber2::SetBaseValue(float aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
mBaseVal = aValue;
mIsBaseSet = PR_TRUE;
@ -167,7 +165,7 @@ nsSVGNumber2::SetBaseValue(float aValue,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeNumber(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeNumber(mAttrEnum, true);
}
void

View File

@ -61,11 +61,10 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
void SetBaseValue(float aValue, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValue(float aValue, nsSVGElement *aSVGElement);
float GetBaseValue() const
{ return mBaseVal; }
void SetAnimValue(float aValue, nsSVGElement *aSVGElement);
@ -114,7 +113,7 @@ public:
if (!NS_finite(aValue)) {
return NS_ERROR_ILLEGAL_VALUE;
}
mVal->SetBaseValue(aValue, mSVGElement, PR_TRUE);
mVal->SetBaseValue(aValue, mSVGElement);
return NS_OK;
}

View File

@ -103,8 +103,7 @@ ParseNumberOptionalNumber(const nsAString& aValue,
nsresult
nsSVGNumberPair::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
float val[2];
@ -145,8 +144,7 @@ nsSVGNumberPair::GetBaseValueString(nsAString &aValueAsString)
void
nsSVGNumberPair::SetBaseValue(float aValue, PairIndex aPairIndex,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
PRUint32 index = (aPairIndex == eFirst ? 0 : 1);
mBaseVal[index] = aValue;
@ -159,13 +157,12 @@ nsSVGNumberPair::SetBaseValue(float aValue, PairIndex aPairIndex,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeNumberPair(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeNumberPair(mAttrEnum, true);
}
void
nsSVGNumberPair::SetBaseValues(float aValue1, float aValue2,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
mBaseVal[0] = aValue1;
mBaseVal[1] = aValue2;
@ -179,7 +176,7 @@ nsSVGNumberPair::SetBaseValues(float aValue1, float aValue2,
aSVGElement->AnimationNeedsResample();
}
#endif
aSVGElement->DidChangeNumberPair(mAttrEnum, aDoSetAttr);
aSVGElement->DidChangeNumberPair(mAttrEnum, true);
}
void

View File

@ -67,12 +67,11 @@ public:
}
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue);
void SetBaseValue(float aValue, PairIndex aIndex, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValues(float aValue1, float aValue2, nsSVGElement *aSVGElement, bool aDoSetAttr);
void SetBaseValue(float aValue, PairIndex aIndex, nsSVGElement *aSVGElement);
void SetBaseValues(float aValue1, float aValue2, nsSVGElement *aSVGElement);
float GetBaseValue(PairIndex aIndex) const
{ return mBaseVal[aIndex == eFirst ? 0 : 1]; }
void SetAnimValue(const float aValue[2], nsSVGElement *aSVGElement);
@ -123,7 +122,7 @@ public:
if (!NS_finite(aValue)) {
return NS_ERROR_ILLEGAL_VALUE;
}
mVal->SetBaseValue(aValue, mIndex, mSVGElement, PR_TRUE);
mVal->SetBaseValue(aValue, mIndex, mSVGElement);
return NS_OK;
}

View File

@ -804,7 +804,7 @@ nsSVGSVGElement::SetZoomAndPan(PRUint16 aZoomAndPan)
{
if (aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE ||
aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY) {
mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this, PR_TRUE);
mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this);
return NS_OK;
}

View File

@ -127,12 +127,12 @@ nsSVGViewBox::SetAnimValue(float aX, float aY, float aWidth, float aHeight,
void
nsSVGViewBox::SetBaseValue(float aX, float aY, float aWidth, float aHeight,
nsSVGElement *aSVGElement, bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
mBaseVal = nsSVGViewBoxRect(aX, aY, aWidth, aHeight);
mHasBaseVal = PR_TRUE;
aSVGElement->DidChangeViewBox(aDoSetAttr);
aSVGElement->DidChangeViewBox(true);
#ifdef MOZ_SMIL
if (mAnimVal) {
aSVGElement->AnimationNeedsResample();
@ -178,13 +178,22 @@ ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox)
nsresult
nsSVGViewBox::SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
nsSVGElement *aSVGElement)
{
nsSVGViewBoxRect viewBox;
nsresult res = ToSVGViewBoxRect(aValue, &viewBox);
if (NS_SUCCEEDED(res)) {
SetBaseValue(viewBox.x, viewBox.y, viewBox.width, viewBox.height, aSVGElement, aDoSetAttr);
mBaseVal = nsSVGViewBoxRect(viewBox.x, viewBox.y, viewBox.width, viewBox.height);
mHasBaseVal = PR_TRUE;
#ifdef MOZ_SMIL
if (mAnimVal) {
aSVGElement->AnimationNeedsResample();
}
#endif
// We don't need to call DidChange* here - we're only called by
// nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
// which takes care of notifying.
}
return res;
}
@ -237,7 +246,7 @@ nsSVGViewBox::DOMBaseVal::SetX(float aX)
nsSVGViewBoxRect rect = mVal->GetBaseValue();
rect.x = aX;
mVal->SetBaseValue(rect.x, rect.y, rect.width, rect.height,
mSVGElement, PR_TRUE);
mSVGElement);
return NS_OK;
}
@ -247,7 +256,7 @@ nsSVGViewBox::DOMBaseVal::SetY(float aY)
nsSVGViewBoxRect rect = mVal->GetBaseValue();
rect.y = aY;
mVal->SetBaseValue(rect.x, rect.y, rect.width, rect.height,
mSVGElement, PR_TRUE);
mSVGElement);
return NS_OK;
}
@ -257,7 +266,7 @@ nsSVGViewBox::DOMBaseVal::SetWidth(float aWidth)
nsSVGViewBoxRect rect = mVal->GetBaseValue();
rect.width = aWidth;
mVal->SetBaseValue(rect.x, rect.y, rect.width, rect.height,
mSVGElement, PR_TRUE);
mSVGElement);
return NS_OK;
}
@ -267,7 +276,7 @@ nsSVGViewBox::DOMBaseVal::SetHeight(float aHeight)
nsSVGViewBoxRect rect = mVal->GetBaseValue();
rect.height = aHeight;
mVal->SetBaseValue(rect.x, rect.y, rect.width, rect.height,
mSVGElement, PR_TRUE);
mSVGElement);
return NS_OK;
}

View File

@ -71,7 +71,7 @@ public:
const nsSVGViewBoxRect& GetBaseValue() const
{ return mBaseVal; }
void SetBaseValue(float aX, float aY, float aWidth, float aHeight,
nsSVGElement *aSVGElement, bool aDoSetAttr);
nsSVGElement *aSVGElement);
const nsSVGViewBoxRect& GetAnimValue() const
{ return mAnimVal ? *mAnimVal : mBaseVal; }
@ -79,8 +79,7 @@ public:
nsSVGElement *aSVGElement);
nsresult SetBaseValueString(const nsAString& aValue,
nsSVGElement *aSVGElement,
bool aDoSetAttr);
nsSVGElement *aSVGElement);
void GetBaseValueString(nsAString& aValue) const;
nsresult ToDOMAnimatedRect(nsIDOMSVGAnimatedRect **aResult,

View File

@ -313,14 +313,18 @@ ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
return imageSurface.forget().get();
}
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageOGL *cairoImage =
static_cast<CairoImageOGL*>(mActiveImage.get());
size = cairoImage->mSize;
gl = cairoImage->mTexture.GetGLContext();
tex1 = cairoImage->mTexture.GetTextureID();
if (mActiveImage->GetFormat() != Image::CAIRO_SURFACE)
{
*aSize = gfxIntSize(0, 0);
return nsnull;
}
CairoImageOGL *cairoImage =
static_cast<CairoImageOGL*>(mActiveImage.get());
size = cairoImage->mSize;
gl = cairoImage->mTexture.GetGLContext();
tex1 = cairoImage->mTexture.GetTextureID();
nsRefPtr<gfxImageSurface> s = gl->ReadTextureImage(tex1, size, LOCAL_GL_RGBA);
*aSize = size;
return s.forget();

View File

@ -38,6 +38,7 @@
#include "nsIDocument.h"
#include "nsSVGOuterSVGFrame.h"
#include "nsGkAtoms.h"
#include "nsSVGEffects.h"
#include "nsSVGUtils.h"
#include "nsSVGFilterElement.h"
#include "nsSVGFilters.h"
@ -227,6 +228,27 @@ nsAutoFilterInstance::~nsAutoFilterInstance()
{
}
NS_IMETHODIMP
nsSVGFilterFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if ((aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::x ||
aAttribute == nsGkAtoms::y ||
aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height ||
aAttribute == nsGkAtoms::filterRes ||
aAttribute == nsGkAtoms::filterUnits ||
aAttribute == nsGkAtoms::primitiveUnits)) ||
(aNameSpaceID == kNameSpaceID_XLink &&
aAttribute == nsGkAtoms::href)) {
nsSVGEffects::InvalidateRenderingObservers(this);
}
return nsSVGFilterFrameBase::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
nsresult
nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsIFrame *aTarget,

View File

@ -54,6 +54,10 @@ protected:
public:
NS_DECL_FRAMEARENA_HELPERS
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
nsresult FilterPaint(nsSVGRenderState *aContext,
nsIFrame *aTarget, nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect* aDirtyRect);

View File

@ -4,25 +4,27 @@ Version=0.1
Encoding=UTF-8
Name=@MOZ_APP_DISPLAYNAME@
Comment=@MOZ_APP_DISPLAYNAME@ mobile browser
Exec=@installdir@/fennec
StartupWMClass=Navigator
StartupNotify=true
Terminal=false
Type=Application
Categories=Application;Network;
#if MOZ_PLATFORM_MAEMO == 6
Exec=@installdir@/fennec %U
Icon=/usr/share/themes/blanco/meegotouch/icons/@MOZ_APP_NAME@.png
Categories=X-MeeGo;
OnlyShownIn=X-MeeGo;
MimeType=x-maemo-urischeme/http;x-maemo-urischeme/https;x-maemo-urischeme/ftp;x-maemo-urischeme/file;text/html;x-maemo-highlight/ftp-url;x-maemo-highlight/http-url;
#else
Exec=@installdir@/fennec
Icon=@MOZ_APP_NAME@
X-Icon-Path=/usr/share/icons
X-Window-Icon=@MOZ_APP_NAME@
X-Window-Icon-dimmed=@MOZ_APP_NAME@
X-Osso-Service=mozilla.@MOZ_APP_NAME@
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;
#endif
X-Osso-Type=application/x-executable
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;
[X-Osso-URI-Actions]
http=X-Osso-URI-Action-Open

View File

@ -39,7 +39,7 @@
/*
* This interface allows any module to access the routine
* for MIME header parameter parsing (RFC 2231)
* for MIME header parameter parsing (RFC 2231/5987)
*/
#include "nsISupports.idl"
@ -97,6 +97,18 @@ interface nsIMIMEHeaderParam : nsISupports {
in ACString aFallbackCharset,
in boolean aTryLocaleCharset,
out string aLang);
/**
* Like getParameter, but using RFC 5987 instead of 2231. This removes
* support for header parameter continuations (foo*0, foo*1, etc).
*/
AString getParameter5987(in ACString aHeaderVal,
in string aParamName,
in ACString aFallbackCharset,
in boolean aTryLocaleCharset,
out string aLang);
/**
* Given the value of a single header field (such as
* Content-Disposition and Content-Type) and the name of a parameter

View File

@ -75,23 +75,47 @@ static nsresult DecodeRFC2047Str(const char *, const char *, bool, nsACString&);
NS_IMPL_ISUPPORTS1(nsMIMEHeaderParamImpl, nsIMIMEHeaderParam)
// XXX : aTryLocaleCharset is not yet effective.
NS_IMETHODIMP
nsMIMEHeaderParamImpl::GetParameter(const nsACString& aHeaderVal,
const char *aParamName,
const nsACString& aFallbackCharset,
bool aTryLocaleCharset,
char **aLang, nsAString& aResult)
{
return DoGetParameter(aHeaderVal, aParamName, RFC_2231_DECODING,
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
}
NS_IMETHODIMP
nsMIMEHeaderParamImpl::GetParameter5987(const nsACString& aHeaderVal,
const char *aParamName,
const nsACString& aFallbackCharset,
bool aTryLocaleCharset,
char **aLang, nsAString& aResult)
{
return DoGetParameter(aHeaderVal, aParamName, RFC_5987_DECODING,
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
}
// XXX : aTryLocaleCharset is not yet effective.
nsresult
nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal,
const char *aParamName,
ParamDecoding aDecoding,
const nsACString& aFallbackCharset,
bool aTryLocaleCharset,
char **aLang, nsAString& aResult)
{
aResult.Truncate();
nsresult rv;
// get parameter (decode RFC 2231 if it's RFC 2231-encoded and
// return charset.)
// get parameter (decode RFC 2231/5987 when applicable, as specified by
// aDecoding (5987 being a subset of 2231) and return charset.)
nsXPIDLCString med;
nsXPIDLCString charset;
rv = GetParameterInternal(PromiseFlatCString(aHeaderVal).get(), aParamName,
getter_Copies(charset), aLang, getter_Copies(med));
rv = DoParameterInternal(PromiseFlatCString(aHeaderVal).get(), aParamName,
aDecoding, getter_Copies(charset), aLang,
getter_Copies(med));
if (NS_FAILED(rv))
return rv;
@ -159,6 +183,20 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
char **aLang,
char **aResult)
{
return DoParameterInternal(aHeaderValue, aParamName, RFC_2231_DECODING,
aCharset, aLang, aResult);
}
nsresult
nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
const char *aParamName,
ParamDecoding aDecoding,
char **aCharset,
char **aLang,
char **aResult)
{
if (!aHeaderValue || !*aHeaderValue || !aResult)
return NS_ERROR_INVALID_ARG;
@ -215,9 +253,13 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
// title*2="Else..."
// D. title*0="Hey, what you think you are doing?"
// title*1="There is no charset and lang info."
// RFC5987: only A and B
PRInt32 paramLen = strlen(aParamName);
bool haveCaseAValue = false;
PRInt32 nextContinuation = 0; // next value in series, or -1 if error
while (*str) {
const char *tokenStart = str;
const char *tokenEnd = 0;
@ -276,6 +318,12 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
seenEquals &&
!nsCRT::strncasecmp(tokenStart, aParamName, paramLen))
{
if (*aResult)
{
// either seen earlier caseA value already--we prefer first--or caseA
// came after a continuation: either way, prefer other value
goto increment_str;
}
// if the parameter spans across multiple lines we have to strip out the
// line continuation -- jht 4/29/98
nsCAutoString tempStr(valueStart, valueEnd - valueStart);
@ -288,7 +336,8 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
*aResult = res;
// keep going, we may find a RFC 2231 encoded alternative
haveCaseAValue = true;
// keep going, we may find a RFC 2231/5987 encoded alternative
}
// case B, C, and D
else if (tokenEnd - tokenStart > paramLen &&
@ -296,14 +345,26 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
seenEquals &&
*(tokenStart + paramLen) == '*')
{
const char *cp = tokenStart + paramLen + 1; // 1st char pass '*'
const char *cp = tokenStart + paramLen + 1; // 1st char past '*'
bool needUnescape = *(tokenEnd - 1) == '*';
// the 1st line of a multi-line parameter or a single line that needs
// unescaping. ( title*0*= or title*= )
// only allowed for token form, not for quoted-string
if (!needUnquote &&
((*cp == '0' && needUnescape) || (tokenEnd - tokenStart == paramLen + 1)))
bool caseB = (tokenEnd - tokenStart) == paramLen + 1;
bool caseCorDStart = (*cp == '0') && needUnescape;
bool acceptContinuations = (aDecoding != RFC_5987_DECODING);
// CaseB and start of CaseC: requires charset and optional language
// in quotes (quotes required even if lang is blank)
if (!needUnquote && (caseB || (caseCorDStart && acceptContinuations)))
{
if (caseCorDStart) {
if (nextContinuation++ != 0)
{
// error: already started a continuation. Skip future
// continuations and return whatever initial parts were in order.
nextContinuation = -1;
goto increment_str;
}
}
// look for single quotation mark(')
const char *sQuote1 = PL_strchr(valueStart, 0x27);
const char *sQuote2 = (char *) (sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nsnull);
@ -340,9 +401,10 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
{
if (*aResult)
{
// drop non-2231-encoded value, instead prefer the one using
// the RFC2231 encoding
// caseA value already read, or caseC/D value already read
// but we're now reading caseB: either way, drop old value
nsMemory::Free(*aResult);
haveCaseAValue = false;
}
*aResult = (char *) nsMemory::Alloc(valueEnd - (sQuote2 + 1) + 1);
if (*aResult)
@ -352,17 +414,35 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
if (needUnescape)
{
nsUnescape(*aResult);
if (tokenEnd - tokenStart == paramLen + 1)
// we're done; this is case B
return NS_OK;
if (caseB)
return NS_OK; // caseB wins over everything else
}
}
}
} // end of if-block : title*0*= or title*=
// a line of multiline param with no need for unescaping : title*[0-9]=
// or 2nd or later lines of a multiline param : title*[1-9]*=
else if (nsCRT::IsAsciiDigit(PRUnichar(*cp)))
// caseD: a line of multiline param with no need for unescaping : title*[0-9]=
// or 2nd or later lines of a caseC param : title*[1-9]*=
else if (acceptContinuations && nsCRT::IsAsciiDigit(PRUnichar(*cp)))
{
PRInt32 nextSegment = atoi(cp);
// no leading zeros allowed except for ... position 0
bool broken = nextSegment > 0 && *cp == '0';
if (broken || nextSegment != nextContinuation++)
{
// error: gap in continuation or unneccessary leading 0.
// Skip future continuations and return whatever initial parts were
// in order.
nextContinuation = -1;
goto increment_str;
}
if (haveCaseAValue && *aResult)
{
// drop caseA value
nsMemory::Free(*aResult);
*aResult = 0;
haveCaseAValue = false;
}
PRInt32 len = 0;
if (*aResult) // 2nd or later lines of multiline parameter
{
@ -374,11 +454,11 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
}
*aResult = ns;
}
else if (*cp == '0') // must be; 1st line : title*0=
else
{
NS_ASSERTION(*cp == '0', "Not first value in continuation"); // must be; 1st line : title*0=
*aResult = (char *) nsMemory::Alloc(valueEnd - valueStart + 1);
}
// else {} something is really wrong; out of memory
if (*aResult)
{
// append a partial value
@ -394,7 +474,7 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
// str now points after the end of the value.
// skip over whitespace, ';', whitespace.
increment_str:
while (nsCRT::IsAsciiSpace(*str)) ++str;
if (*str == ';') ++str;
while (nsCRT::IsAsciiSpace(*str)) ++str;
@ -425,8 +505,8 @@ nsMIMEHeaderParamImpl::DecodeRFC2047Header(const char* aHeaderVal,
// aDefaultCharset is specified, decodes RFC 2047 encoding and converts
// to UTF-8. Otherwise, just strips away CRLF.
if (PL_strstr(aHeaderVal, "=?") ||
aDefaultCharset && (!IsUTF8(nsDependentCString(aHeaderVal)) ||
Is7bitNonAsciiString(aHeaderVal, PL_strlen(aHeaderVal)))) {
(aDefaultCharset && (!IsUTF8(nsDependentCString(aHeaderVal)) ||
Is7bitNonAsciiString(aHeaderVal, PL_strlen(aHeaderVal))))) {
DecodeRFC2047Str(aHeaderVal, aDefaultCharset, aOverrideCharset, aResult);
} else if (aEatContinuations &&
(PL_strchr(aHeaderVal, '\n') || PL_strchr(aHeaderVal, '\r'))) {
@ -455,7 +535,7 @@ nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
nsACString& aResult)
{
aResult.Truncate();
// If aCharset is given, aParamValue was obtained from RFC2231
// If aCharset is given, aParamValue was obtained from RFC2231/5987
// encoding and we're pretty sure that it's in aCharset.
if (aCharset && *aCharset)
{
@ -501,9 +581,9 @@ nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
}
#define ISHEXCHAR(c) \
(0x30 <= PRUint8(c) && PRUint8(c) <= 0x39 || \
0x41 <= PRUint8(c) && PRUint8(c) <= 0x46 || \
0x61 <= PRUint8(c) && PRUint8(c) <= 0x66)
((0x30 <= PRUint8(c) && PRUint8(c) <= 0x39) || \
(0x41 <= PRUint8(c) && PRUint8(c) <= 0x46) || \
(0x61 <= PRUint8(c) && PRUint8(c) <= 0x66))
// Decode Q encoding (RFC 2047).
// static

View File

@ -47,6 +47,29 @@ public:
nsMIMEHeaderParamImpl() {}
virtual ~nsMIMEHeaderParamImpl() {}
private:
// Toggles support for RFC 2231 decoding, or RFC 5987 (5987 profiles 2231
// for use in HTTP, and, for instance, drops support for continuations)
enum ParamDecoding {
RFC_2231_DECODING = 1,
RFC_5987_DECODING
};
nsresult DoGetParameter(const nsACString& aHeaderVal,
const char *aParamName,
ParamDecoding aDecoding,
const nsACString& aFallbackCharset,
bool aTryLocaleCharset,
char **aLang,
nsAString& aResult);
nsresult DoParameterInternal(const char *aHeaderValue,
const char *aParamName,
ParamDecoding aDecoding,
char **aCharset,
char **aLang,
char **aResult);
};
#endif

View File

@ -6,106 +6,185 @@
*
* See also <http://greenbytes.de/tech/webdav/rfc5987.html#rfc.section.4.2>
*/
const Cr = Components.results;
// Test array:
// - element 0: "Content-Disposition" header to test for 'filename' parameter
// - element 1: correct value returned under RFC 2231 (email)
// - element 2: correct value returned under RFC 5987 (HTTP)
var tests = [
// No filename parameter: return nothing
["attachment;",
Cr.NS_ERROR_INVALID_ARG, Cr.NS_ERROR_INVALID_ARG],
// basic
["attachment; filename=basic",
"basic", "basic"],
// extended
["attachment; filename*=UTF-8''extended",
"extended", "extended"],
// prefer extended to basic
["attachment; filename=basic; filename*=UTF-8''extended",
"extended", "extended"],
// prefer extended to basic
["attachment; filename*=UTF-8''extended; filename=basic",
"extended", "extended"],
// use first basic value
["attachment; filename=first; filename=wrong",
"first", "first"],
// old school bad HTTP servers: missing 'attachment' or 'inline'
["filename=old",
"old", "old"],
["attachment; filename*=UTF-8''extended",
"extended", "extended"],
["attachment; filename*0=foo; filename*1=bar",
"foobar", Cr.NS_ERROR_INVALID_ARG],
// Return first continuation
["attachment; filename*0=first; filename*0=wrong; filename=basic",
"first", "basic"],
// Only use correctly ordered continuations
["attachment; filename*0=first; filename*1=second; filename*0=wrong",
"firstsecond", Cr.NS_ERROR_INVALID_ARG],
// prefer continuation to basic (unless RFC 5987)
["attachment; filename=basic; filename*0=foo; filename*1=bar",
"foobar", "basic"],
// Prefer extended to basic and/or (broken or not) continuation
["attachment; filename=basic; filename*0=first; filename*0=wrong; filename*=UTF-8''extended",
"extended", "extended"],
var succeed = [
["Content-Disposition: attachment; filename=basic; filename*=UTF-8''extended",
"extended"],
["Content-Disposition: attachment; filename*=UTF-8''extended; filename=basic",
"extended"],
["Content-Disposition: attachment; filename=basic",
"basic"],
["Content-Disposition: attachment; filename*=UTF-8''extended",
"extended"],
["Content-Disposition: attachment; filename*0=foo; filename*1=bar",
"foobar"],
/* BROKEN: we prepend 'basic' to result
["Content-Disposition: attachment; filename=basic; filename*0=foo; filename*1=bar",
"foobar"],
*/
// RFC 2231 not clear on correct outcome: we prefer non-continued extended
["Content-Disposition: attachment; filename=basic; filename*=UTF-8''extended; filename*0=foo; filename*1=bar",
"extended"],
/* BROKEN: not checking order yet
["attachment; filename=basic; filename*=UTF-8''extended; filename*0=foo; filename*1=bar",
"extended", "extended"],
// Gaps should result in returning only value until gap hit
["Content-Disposition: attachment; filename*0=foo; filename*2=bar",
"foo"],
*/
/* BROKEN: don't check for leading 0s yet
// Don't handle leading 0's (*01)
["Content-Disposition: attachment; filename*0=foo; filename*01=bar",
"foo"],
*/
["Content-Disposition: attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
["attachment; filename*0=foo; filename*2=bar",
"foo", Cr.NS_ERROR_INVALID_ARG],
// Don't allow leading 0's (*01)
["attachment; filename*0=foo; filename*01=bar",
"foo", Cr.NS_ERROR_INVALID_ARG],
// continuations should prevail over non-extended (unless RFC 5987)
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
+ " filename*1=line\r\n"
+ " filename*2*=%20extended",
"multiline extended"],
/* BROKEN: not checking order yet
"multiline extended", "basic"],
// Gaps should result in returning only value until gap hit
["Content-Disposition: attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
+ " filename*1=line\r\n"
+ " filename*3*=%20extended",
"multiline"],
*/
"multiline", "basic"],
// First series, only please, and don't slurp up higher elements (*2 in this
// case) from later series into earlier one
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
+ " filename*1=line\r\n"
+ " filename*0*=UTF-8''wrong\r\n"
+ " filename*1=bad\r\n"
+ " filename*2=evil",
"multiline", "basic"],
// RFC 2231 not clear on correct outcome: we prefer non-continued extended
["Content-Disposition: attachment; filename=basic; filename*0=UTF-8''multi\r\n"
["attachment; filename=basic; filename*0=UTF-8''multi\r\n"
+ " filename*=UTF-8''extended\r\n"
+ " filename*1=line\r\n"
+ " filename*2*=%20extended",
"extended"],
"extended", "extended"],
// sneaky: if unescaped, make sure we leave UTF-8'' in value
["Content-Disposition: attachment; filename*0=UTF-8''unescaped\r\n"
["attachment; filename*0=UTF-8''unescaped\r\n"
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"UTF-8''unescaped so includes UTF-8'' in value"],
/* BROKEN: we prepend 'basic' to result
"UTF-8''unescaped so includes UTF-8'' in value", Cr.NS_ERROR_INVALID_ARG],
// sneaky: if unescaped, make sure we leave UTF-8'' in value
["Content-Disposition: attachment; filename=basic; filename*0=UTF-8''unescaped\r\n"
["attachment; filename=basic; filename*0=UTF-8''unescaped\r\n"
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"UTF-8''unescaped so includes UTF-8'' in value"],
*/
/* BROKEN: we append filename*1 to 'basic'
// Also not sure if this is the spec'd behavior here:
["Content-Disposition: attachment; filename=basic; filename*1=multi\r\n"
"UTF-8''unescaped so includes UTF-8'' in value", "basic"],
// Prefer basic over invalid continuation
["attachment; filename=basic; filename*1=multi\r\n"
+ " filename*2=line\r\n"
+ " filename*3*=%20extended",
"basic"],
*/
];
"basic", "basic"],
var broken = [
["Content-Disposition: attachment; filename*1=multi\r\n"
// support digits over 10
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
+ " filename*11=b; filename*12=c;filename*13=d;filename*14=e;filename*15=f\r\n",
"0123456789abcdef", "basic"],
// support digits over 10 (check ordering)
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
+ " filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e\r\n",
"0123456789abcd" /* should see the 'f', see bug 588414 */, "basic"],
// support digits over 10 (detect gaps)
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
+ " filename*11=b; filename*12=c;filename*14=e\r\n",
"0123456789abc", "basic"],
// return nothing: invalid
["attachment; filename*1=multi\r\n"
+ " filename*2=line\r\n"
+ " filename*3*=%20extended",
"param continuation must start from 0: should fail"],
Cr.NS_ERROR_INVALID_ARG, Cr.NS_ERROR_INVALID_ARG],
];
function run_test() {
function do_tests(whichRFC)
{
var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
.getService(Components.interfaces.nsIMIMEHeaderParam);
var unused = { value : null };
for (var i = 0; i < succeed.length; ++i) {
dump("Testing " + succeed[i] + "\n");
for (var i = 0; i < tests.length; ++i) {
dump("Testing " + tests[i] + "\n");
try {
do_check_eq(mhp.getParameter(succeed[i][0], "filename", "UTF-8", true, unused),
succeed[i][1]);
} catch (e) {}
}
// Check failure cases
for (var i = 0; i < broken.length; ++i) {
dump("Testing " + broken[i] + "\n");
try {
var result = mhp.getParameter(broken[i][0], "filename", "UTF-8", true, unused);
// No exception? Error.
do_check_eq(broken[i][1], "instead got: " + result);
} catch (e) {
// .result set if getParameter failed: check for correct error code
if (e.result)
do_check_eq(e.result, Components.results.NS_ERROR_OUT_OF_MEMORY);
var result;
if (whichRFC == 1)
result = mhp.getParameter(tests[i][0], "filename", "UTF-8", true, unused);
else
result = mhp.getParameter5987(tests[i][0], "filename", "UTF-8", true, unused);
do_check_eq(result, tests[i][whichRFC]);
}
catch (e) {
// Tests can also succeed by expecting to fail with given error code
if (e.result) {
// Allow following tests to run by catching exception from do_check_eq()
try {
do_check_eq(e.result, tests[i][whichRFC]);
} catch(e) {}
}
continue;
}
}
}
function run_test() {
// Test RFC 2231
do_tests(1);
// Test RFC 5987
do_tests(2);
}

View File

@ -705,24 +705,21 @@ let PlacesDBUtils = {
")");
cleanupStatements.push(fixInvalidFaviconIds);
/* XXX needs test
// L.2 recalculate visit_count
let detectWrongCountPlaces = DBConn.createStatement(
"SELECT id FROM moz_places h " +
"WHERE h.visit_count <> " +
"(SELECT count(*) FROM moz_historyvisits " +
"WHERE place_id = h.id AND visit_type NOT IN (0,4,7,8))");
while (detectWrongCountPlaces.executeStep()) {
let placeId = detectWrongCountPlaces.getInt64(0);
let fixCountForPlace = DBConn.createStatement(
"UPDATE moz_places SET visit_count = ( " +
"(SELECT count(*) FROM moz_historyvisits " +
"WHERE place_id = :place_id AND visit_type NOT IN (0,4,7,8)) + "
") WHERE id = :place_id");
fixCountForPlace.params["place_id"] = placeId;
cleanupStatements.push(fixCountForPlace);
}
*/
// L.2 recalculate visit_count and last_visit_date
let fixVisitStats = DBConn.createAsyncStatement(
"UPDATE moz_places " +
"SET visit_count = (SELECT count(*) FROM moz_historyvisits " +
"WHERE place_id = moz_places.id AND visit_type NOT IN (0,4,7,8)), " +
"last_visit_date = (SELECT MAX(visit_date) FROM moz_historyvisits " +
"WHERE place_id = moz_places.id) " +
"WHERE id IN ( " +
"SELECT h.id FROM moz_places h " +
"WHERE visit_count <> (SELECT count(*) FROM moz_historyvisits v " +
"WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8)) " +
"OR last_visit_date <> (SELECT MAX(visit_date) FROM moz_historyvisits v " +
"WHERE v.place_id = h.id) " +
")");
cleanupStatements.push(fixVisitStats);
// MAINTENANCE STATEMENTS SHOULD GO ABOVE THIS POINT!

View File

@ -87,6 +87,7 @@ const TOPIC_DEBUG_START_EXPIRATION = "places-debug-start-expiration";
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
const TOPIC_IDLE_BEGIN = "idle";
const TOPIC_IDLE_END = "back";
const TOPIC_IDLE_DAILY = "idle-daily";
// Branch for all expiration preferences.
const PREF_BRANCH = "places.history.expiration.";
@ -150,6 +151,10 @@ const IDLE_TIMEOUT_SECONDS = 5 * 60;
// clearHistory to decide to skip expiration at shutdown.
const SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS = 10;
// If the pages delta from the last ANALYZE is over this threashold, the tables
// should be analyzed again.
const ANALYZE_PAGES_THRESHOLD = 100;
const USECS_PER_DAY = 86400000000;
const ANNOS_EXPIRE_POLICIES = [
{ bind: "expire_days",
@ -184,22 +189,22 @@ const STATUS = {
// Represents actions on which a query will run.
const ACTION = {
TIMED: 1 << 0, // happens every this._interval
CLEAR_HISTORY: 1 << 1, // happens when history is cleared
SHUTDOWN: 1 << 2, // happens at shutdown when the db has a DIRTY state
CLEAN_SHUTDOWN: 1 << 3, // happens at shutdown when the db has a CLEAN or
// UNKNOWN state
IDLE: 1 << 4, // happens once on idle
DEBUG: 1 << 5, // happens whenever TOPIC_DEBUG_START_EXPIRATION is dispatched
TIMED_OVERLIMIT: 1 << 6, // just like TIMED, but also when we have too much
// history
TIMED: 1 << 0, // happens every this._interval
TIMED_OVERLIMIT: 1 << 1, // like TIMED but only when history is over limits
TIMED_ANALYZE: 1 << 2, // happens when ANALYZE statistics should be updated
CLEAR_HISTORY: 1 << 3, // happens when history is cleared
SHUTDOWN_DIRTY: 1 << 4, // happens at shutdown for DIRTY state
SHUTDOWN_CLEAN: 1 << 5, // happens at shutdown for CLEAN or UNKNOWN states
IDLE_DIRTY: 1 << 6, // happens on idle for DIRTY state
IDLE_DAILY: 1 << 7, // happens once a day on idle
DEBUG: 1 << 8, // happens on TOPIC_DEBUG_START_EXPIRATION
};
// The queries we use to expire.
const EXPIRATION_QUERIES = {
// Finds visits to be expired. Will return nothing if we are not over the
// unique URIs limit.
// Finds visits to be expired when history is over the unique pages limit,
// otherwise will return nothing.
// This explicitly excludes any visits added in the last 7 days, to protect
// users with thousands of bookmarks from constantly losing history.
QUERY_FIND_VISITS_TO_EXPIRE: {
@ -212,7 +217,7 @@ const EXPIRATION_QUERIES = {
+ "AND visit_date < strftime('%s','now','localtime','start of day','-7 days','utc') * 1000000 "
+ "ORDER BY v.visit_date ASC "
+ "LIMIT :limit_visits",
actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN | ACTION.IDLE |
actions: ACTION.TIMED_OVERLIMIT | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
@ -221,7 +226,7 @@ const EXPIRATION_QUERIES = {
sql: "DELETE FROM moz_historyvisits WHERE id IN ( "
+ "SELECT v_id FROM expiration_notify WHERE v_id NOTNULL "
+ ")",
actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN | ACTION.IDLE |
actions: ACTION.TIMED_OVERLIMIT | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
@ -243,8 +248,8 @@ const EXPIRATION_QUERIES = {
+ "AND b.id IS NULL "
+ "AND frecency <> -1 "
+ "LIMIT :limit_uris",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire found URIs from the database.
@ -252,8 +257,8 @@ const EXPIRATION_QUERIES = {
sql: "DELETE FROM moz_places WHERE id IN ( "
+ "SELECT p_id FROM expiration_notify WHERE p_id NOTNULL "
+ ")",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire orphan URIs from the database.
@ -279,7 +284,8 @@ const EXPIRATION_QUERIES = {
+ "LIMIT :limit_favicons "
+ ")",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire orphan page annotations from the database.
@ -293,7 +299,8 @@ const EXPIRATION_QUERIES = {
+ "LIMIT :limit_annos "
+ ")",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire page annotations based on expiration policy.
@ -306,7 +313,8 @@ const EXPIRATION_QUERIES = {
+ "OR (expiration = :expire_months "
+ "AND :expire_months_time > MAX(lastModified, dateAdded))",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire items annotations based on expiration policy.
@ -319,7 +327,8 @@ const EXPIRATION_QUERIES = {
+ "OR (expiration = :expire_months "
+ "AND :expire_months_time > MAX(lastModified, dateAdded))",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire page annotations based on expiration policy.
@ -329,7 +338,8 @@ const EXPIRATION_QUERIES = {
+ "AND NOT EXISTS (SELECT id FROM moz_historyvisits "
+ "WHERE place_id = moz_annos.place_id LIMIT 1)",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire item annos without a corresponding item id.
@ -340,7 +350,7 @@ const EXPIRATION_QUERIES = {
+ "WHERE b.id IS NULL "
+ "LIMIT :limit_annos "
+ ")",
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
actions: ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire all annotation names without a corresponding annotation.
@ -353,7 +363,8 @@ const EXPIRATION_QUERIES = {
+ "AND t.anno_attribute_id IS NULL "
+ "LIMIT :limit_annos"
+ ")",
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY |
ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire orphan inputhistory.
@ -364,21 +375,23 @@ const EXPIRATION_QUERIES = {
+ "WHERE h.id IS NULL "
+ "LIMIT :limit_inputhistory "
+ ")",
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Expire all session annotations. Should only be called at shutdown.
QUERY_EXPIRE_ANNOS_SESSION: {
sql: "DELETE FROM moz_annos WHERE expiration = :expire_session",
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.CLEAN_SHUTDOWN |
ACTION.DEBUG
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN_DIRTY |
ACTION.SHUTDOWN_CLEAN | ACTION.DEBUG
},
// Expire all session item annotations. Should only be called at shutdown.
QUERY_EXPIRE_ITEMS_ANNOS_SESSION: {
sql: "DELETE FROM moz_items_annos WHERE expiration = :expire_session",
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.CLEAN_SHUTDOWN |
ACTION.DEBUG
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN_DIRTY |
ACTION.SHUTDOWN_CLEAN | ACTION.DEBUG
},
// Select entries for notifications.
@ -390,15 +403,15 @@ const EXPIRATION_QUERIES = {
+ "expected_results "
+ "FROM expiration_notify "
+ "GROUP BY url",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Empty the notifications table.
QUERY_DELETE_NOTIFICATIONS: {
sql: "DELETE FROM expiration_notify",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// The following queries are used to adjust the sqlite_stat1 table to help the
@ -409,22 +422,22 @@ const EXPIRATION_QUERIES = {
QUERY_ANALYZE_MOZ_PLACES: {
sql: "ANALYZE moz_places",
actions: ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY | ACTION.IDLE |
ACTION.DEBUG
actions: ACTION.TIMED_OVERLIMIT | ACTION.TIMED_ANALYZE |
ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
QUERY_ANALYZE_MOZ_BOOKMARKS: {
sql: "ANALYZE moz_bookmarks",
actions: ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED_ANALYZE | ACTION.IDLE_DAILY | ACTION.DEBUG
},
QUERY_ANALYZE_MOZ_HISTORYVISITS: {
sql: "ANALYZE moz_historyvisits",
actions: ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY | ACTION.IDLE |
ACTION.DEBUG
actions: ACTION.TIMED_OVERLIMIT | ACTION.TIMED_ANALYZE |
ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
QUERY_ANALYZE_MOZ_INPUTHISTORY: {
sql: "ANALYZE moz_inputhistory",
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.IDLE | ACTION.DEBUG
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.TIMED_ANALYZE |
ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
};
@ -480,6 +493,7 @@ function nsPlacesExpiration()
// Register topic observers.
Services.obs.addObserver(this, TOPIC_SHUTDOWN, false);
Services.obs.addObserver(this, TOPIC_DEBUG_START_EXPIRATION, false);
Services.obs.addObserver(this, TOPIC_IDLE_DAILY, false);
// Create our expiration timer.
this._newTimer();
@ -496,6 +510,7 @@ nsPlacesExpiration.prototype = {
this._shuttingDown = true;
Services.obs.removeObserver(this, TOPIC_SHUTDOWN);
Services.obs.removeObserver(this, TOPIC_DEBUG_START_EXPIRATION);
Services.obs.removeObserver(this, TOPIC_IDLE_DAILY);
this._prefBranch.removeObserver("", this);
@ -512,8 +527,8 @@ nsPlacesExpiration.prototype = {
Date.now() - this._lastClearHistoryTime <
SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS * 1000;
let action = hasRecentClearHistory ||
this.status != STATUS.DIRTY ? ACTION.CLEAN_SHUTDOWN
: ACTION.SHUTDOWN;
this.status != STATUS.DIRTY ? ACTION.SHUTDOWN_CLEAN
: ACTION.SHUTDOWN_DIRTY;
this._expireWithActionAndLimit(action, LIMIT.LARGE);
this._finalizeInternalStatements();
}
@ -558,13 +573,16 @@ nsPlacesExpiration.prototype = {
this._timer = null;
}
if (this.expireOnIdle)
this._expireWithActionAndLimit(ACTION.IDLE, LIMIT.LARGE);
this._expireWithActionAndLimit(ACTION.IDLE_DIRTY, LIMIT.LARGE);
}
else if (aTopic == TOPIC_IDLE_END) {
// Restart the expiration timer.
if (!this._timer)
this._newTimer();
}
else if (aTopic == TOPIC_IDLE_DAILY) {
this._expireWithActionAndLimit(ACTION.IDLE_DAILY, LIMIT.LARGE);
}
},
//////////////////////////////////////////////////////////////////////////////
@ -612,28 +630,18 @@ nsPlacesExpiration.prototype = {
notify: function PEX_timerCallback()
{
// Check if we are over history capacity, if so visits must be expired.
if (!this._cachedStatements["LIMIT_COUNT"]) {
this._cachedStatements["LIMIT_COUNT"] = this._db.createAsyncStatement(
"SELECT COUNT(*) FROM moz_places"
);
}
let self = this;
this._cachedStatements["LIMIT_COUNT"].executeAsync({
handleResult: function(aResults) {
let row = aResults.getNextRow();
self._overLimit = row.getResultByIndex(0) > self._urisLimit;
},
handleCompletion: function (aReason) {
if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED)
return;
let action = self._overLimit ? ACTION.TIMED_OVERLIMIT : ACTION.TIMED;
self._expireWithActionAndLimit(action, LIMIT.SMALL);
},
handleError: function(aError) {
Cu.reportError("Async statement execution returned with '" +
aError.result + "', '" + aError.message + "'");
this._getPagesStats((function onPagesCount(aPagesCount, aStatsCount) {
this._overLimit = aPagesCount > this._urisLimit;
let action = this._overLimit ? ACTION.TIMED_OVERLIMIT : ACTION.TIMED;
// If the number of pages changed significantly from the last ANALYZE
// update SQLite statistics.
if (Math.abs(aPagesCount - aStatsCount) >= ANALYZE_PAGES_THRESHOLD) {
action = action | ACTION.TIMED_ANALYZE;
}
});
this._expireWithActionAndLimit(action, LIMIT.SMALL);
}).bind(this));
},
//////////////////////////////////////////////////////////////////////////////
@ -789,6 +797,41 @@ nsPlacesExpiration.prototype = {
this._interval = PREF_INTERVAL_SECONDS_NOTSET;
},
/**
* Evaluates the real number of pages in the database and the value currently
* used by the SQLite query planner.
*
* @param aCallback
* invoked on success, function (aPagesCount, aStatsCount).
*/
_getPagesStats: function PEX__getPagesStats(aCallback) {
if (!this._cachedStatements["LIMIT_COUNT"]) {
this._cachedStatements["LIMIT_COUNT"] = this._db.createAsyncStatement(
"SELECT (SELECT COUNT(*) FROM moz_places), "
+ "(SELECT SUBSTR(stat,1,LENGTH(stat)-2) FROM sqlite_stat1 "
+ "WHERE idx = 'moz_places_url_uniqueindex')"
);
}
this._cachedStatements["LIMIT_COUNT"].executeAsync({
_pagesCount: 0,
_statsCount: 0,
handleResult: function(aResults) {
let row = aResults.getNextRow();
this._pagesCount = row.getResultByIndex(0);
this._statsCount = row.getResultByIndex(1);
},
handleCompletion: function (aReason) {
if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
aCallback(this._pagesCount, this._statsCount);
}
},
handleError: function(aError) {
Cu.reportError("Async statement execution returned with '" +
aError.result + "', '" + aError.message + "'");
}
});
},
/**
* Execute async statements to expire with the specified queries.
*
@ -806,7 +849,7 @@ nsPlacesExpiration.prototype = {
return;
// Don't try to further expire after shutdown.
if (this._shuttingDown &&
aAction != ACTION.SHUTDOWN && aAction != ACTION.CLEAN_SHUTDOWN) {
aAction != ACTION.SHUTDOWN_DIRTY && aAction != ACTION.SHUTDOWN_CLEAN) {
return;
}

View File

@ -0,0 +1,21 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that expiration runs on idle-daily.
function run_test() {
do_test_pending();
// Set interval to a large value so we don't expire on it.
setInterval(3600); // 1h
Services.obs.addObserver(function observeExpiration(aSubject, aTopic, aData) {
Services.obs.removeObserver(observeExpiration,
PlacesUtils.TOPIC_EXPIRATION_FINISHED);
do_test_finished();
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
let expire = Cc["@mozilla.org/places/expiration;1"].
getService(Ci.nsIObserver);
expire.observe(null, "idle-daily", null);
}

View File

@ -0,0 +1,72 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that expiration executes ANALYZE when statistics are outdated.
const TEST_URL = "http://www.mozilla.org/";
XPCOMUtils.defineLazyServiceGetter(this, "gHistory",
"@mozilla.org/browser/history;1",
"mozIAsyncHistory");
/**
* Object that represents a mozIVisitInfo object.
*
* @param [optional] aTransitionType
* The transition type of the visit. Defaults to TRANSITION_LINK if not
* provided.
* @param [optional] aVisitTime
* The time of the visit. Defaults to now if not provided.
*/
function VisitInfo(aTransitionType, aVisitTime) {
this.transitionType =
aTransitionType === undefined ? TRANSITION_LINK : aTransitionType;
this.visitDate = aVisitTime || Date.now() * 1000;
}
function run_test() {
do_test_pending();
// Init expiration before "importing".
force_expiration_start();
// Add a bunch of pages (at laast IMPORT_PAGES_THRESHOLD pages).
let places = [];
for (let i = 0; i < 100; i++) {
places.push({
uri: NetUtil.newURI(TEST_URL + i),
title: "Title" + i,
visits: [new VisitInfo]
});
};
gHistory.updatePlaces(places);
// Set interval to a small value to expire on it.
setInterval(1); // 1s
Services.obs.addObserver(function observeExpiration(aSubject, aTopic, aData) {
Services.obs.removeObserver(observeExpiration,
PlacesUtils.TOPIC_EXPIRATION_FINISHED);
// Check that statistica are up-to-date.
let stmt = DBConn().createAsyncStatement(
"SELECT (SELECT COUNT(*) FROM moz_places) - "
+ "(SELECT SUBSTR(stat,1,LENGTH(stat)-2) FROM sqlite_stat1 "
+ "WHERE idx = 'moz_places_url_uniqueindex')"
);
stmt.executeAsync({
handleResult: function(aResultSet) {
let row = aResultSet.getNextRow();
this._difference = row.getResultByIndex(0);
},
handleError: function(aError) {
do_throw("Unexpected error (" + aError.result + "): " + aError.message);
},
handleCompletion: function(aReason) {
do_check_true(this._difference === 0);
do_test_finished();
}
});
stmt.finalize();
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
}

View File

@ -9,10 +9,12 @@ skip-if = os == "android"
[test_annos_expire_never.js]
[test_annos_expire_policy.js]
[test_annos_expire_session.js]
[test_debug_expiration.js]
[test_idle_daily.js]
[test_notifications.js]
[test_notifications_onDeleteURI.js]
[test_notifications_onDeleteVisits.js]
[test_outdated_analyze.js]
[test_pref_interval.js]
[test_pref_maxpages.js]
[test_removeAllPages.js]
[test_debug_expiration.js]

View File

@ -1165,17 +1165,79 @@ tests.push({
});
//------------------------------------------------------------------------------
//XXX TODO
tests.push({
name: "L.2",
desc: "Recalculate visit_count",
desc: "Recalculate visit_count and last_visit_date",
setup: function() {
function setVisitCount(aURL, aValue) {
let stmt = mDBConn.createStatement(
"UPDATE moz_places SET visit_count = :count WHERE url = :url"
);
stmt.params.count = aValue;
stmt.params.url = aURL;
stmt.execute();
stmt.finalize();
}
function setLastVisitDate(aURL, aValue) {
let stmt = mDBConn.createStatement(
"UPDATE moz_places SET last_visit_date = :date WHERE url = :url"
);
stmt.params.date = aValue;
stmt.params.url = aURL;
stmt.execute();
stmt.finalize();
}
let now = Date.now() * 1000;
// Add a page with 1 visit.
let url = "http://1.moz.org/";
hs.addVisit(NetUtil.newURI(url), now++, null, hs.TRANSITION_TYPED, false, 0);
// Add a page with 1 visit and set wrong visit_count.
url = "http://2.moz.org/";
hs.addVisit(NetUtil.newURI(url), now++, null, hs.TRANSITION_TYPED, false, 0);
setVisitCount(url, 10);
// Add a page with 1 visit and set wrong last_visit_date.
url = "http://3.moz.org/";
hs.addVisit(NetUtil.newURI(url), now++, null, hs.TRANSITION_TYPED, false, 0);
setLastVisitDate(url, now++);
// Add a page with 1 visit and set wrong stats.
url = "http://4.moz.org/";
hs.addVisit(NetUtil.newURI(url), now++, null, hs.TRANSITION_TYPED, false, 0);
setVisitCount(url, 10);
setLastVisitDate(url, now++);
// Add a page without visits.
let url = "http://5.moz.org/";
addPlace(url);
// Add a page without visits and set wrong visit_count.
url = "http://6.moz.org/";
addPlace(url);
setVisitCount(url, 10);
// Add a page without visits and set wrong last_visit_date.
url = "http://7.moz.org/";
addPlace(url);
setLastVisitDate(url, now++);
// Add a page without visits and set wrong stats.
url = "http://8.moz.org/";
addPlace(url);
setVisitCount(url, 10);
setLastVisitDate(url, now++);
},
check: function() {
let stmt = mDBConn.createStatement(
"SELECT h.id FROM moz_places h " +
"JOIN moz_historyvisits v ON v.place_id = h.id AND visit_type NOT IN (0,4,7,8) " +
"GROUP BY h.id HAVING h.visit_count <> count(*) " +
"UNION ALL " +
"SELECT h.id FROM moz_places h " +
"JOIN moz_historyvisits v ON v.place_id = h.id " +
"GROUP BY h.id HAVING h.last_visit_date <> MAX(v.visit_date) "
);
do_check_false(stmt.executeStep());
stmt.finalize();
}
});

View File

@ -762,11 +762,12 @@ nsAppStartup::GetStartupInfo()
MaybeDefineProperty(cx, obj, "process", gProcessCreationTimestamp);
if (gXRE_mainTimestamp >= gProcessCreationTimestamp)
MaybeDefineProperty(cx, obj, "main", gXRE_mainTimestamp);
else
if (gXRE_mainTimestamp < gProcessCreationTimestamp)
Telemetry::Accumulate(Telemetry::STARTUP_MEASUREMENT_ERRORS, INVALID_MAIN);
// always define main to aid with bug 689256
MaybeDefineProperty(cx, obj, "main", gXRE_mainTimestamp);
if (gCreateTopLevelWindowTimestamp >= gProcessCreationTimestamp)
MaybeDefineProperty(cx, obj, "createTopLevelWindow", gCreateTopLevelWindowTimestamp);
else

View File

@ -373,10 +373,12 @@ function ViewSourceReload()
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
}
// Strips the |view-source:| for saveURL()
// Strips the |view-source:| for internalSave()
function ViewSourceSavePage()
{
saveURL(window.content.location.href.substring(12), null, "SaveLinkTitle");
internalSave(window.content.location.href.substring(12),
null, null, null, null, null,
"SaveLinkTitle", null, null, null, gPageLoader);
}
var PrintPreviewListener = {

View File

@ -3116,21 +3116,16 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
if (!mWnd)
return NS_ERROR_NOT_INITIALIZED;
// Don't flash if the flash count is 0 or if the
// top level window is already active.
HWND flashWnd = GetTopLevelHWND(mWnd, false, false);
HWND fgWnd = ::GetForegroundWindow();
if (aCycleCount == 0 || fgWnd == GetTopLevelHWND(mWnd))
// Don't flash if the flash count is 0 or if the foreground window is our
// window handle or that of our owned-most window.
if (aCycleCount == 0 ||
flashWnd == fgWnd ||
flashWnd == GetTopLevelHWND(fgWnd, false, false)) {
return NS_OK;
HWND flashWnd = mWnd;
while (HWND ownerWnd = ::GetWindow(flashWnd, GW_OWNER)) {
flashWnd = ownerWnd;
}
// Don't flash if the owner window is active either.
if (fgWnd == flashWnd)
return NS_OK;
DWORD defaultCycleCount = 0;
::SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &defaultCycleCount, 0);
@ -8895,7 +8890,9 @@ nsWindow* nsWindow::GetTopLevelWindow(bool aStopOnDialogOrPopup)
// of GetTopLevelWindow method. Because this is checking whether the window
// is top level only in Win32 window system. Therefore, the result window
// may not be managed by us.
HWND nsWindow::GetTopLevelHWND(HWND aWnd, bool aStopOnDialogOrPopup)
HWND nsWindow::GetTopLevelHWND(HWND aWnd,
bool aStopIfNotChild,
bool aStopIfNotPopup)
{
HWND curWnd = aWnd;
HWND topWnd = NULL;
@ -8904,7 +8901,7 @@ HWND nsWindow::GetTopLevelHWND(HWND aWnd, bool aStopOnDialogOrPopup)
while (curWnd) {
topWnd = curWnd;
if (aStopOnDialogOrPopup) {
if (aStopIfNotChild) {
DWORD_PTR style = ::GetWindowLongPtrW(curWnd, GWL_STYLE);
VERIFY_WINDOW_STYLE(style);
@ -8914,6 +8911,12 @@ HWND nsWindow::GetTopLevelHWND(HWND aWnd, bool aStopOnDialogOrPopup)
}
upWnd = ::GetParent(curWnd); // Parent or owner (if has no parent)
// GetParent will only return the owner if the passed in window
// has the WS_POPUP style.
if (!upWnd && !aStopIfNotPopup) {
upWnd = ::GetWindow(curWnd, GW_OWNER);
}
curWnd = upWnd;
}

View File

@ -242,7 +242,9 @@ public:
*/
static void GlobalMsgWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
nsWindow* GetTopLevelWindow(bool aStopOnDialogOrPopup);
static HWND GetTopLevelHWND(HWND aWnd, bool aStopOnDialogOrPopup = false);
static HWND GetTopLevelHWND(HWND aWnd,
bool aStopIfNotChild = false,
bool aStopIfNotPopup = true);
HWND GetWindowHandle() { return mWnd; }
WNDPROC GetPrevWindowProc() { return mPrevWndProc; }
static nsWindow* GetNSWindowPtr(HWND aWnd);

View File

@ -391,9 +391,7 @@ NS_MEMORY_REPORTER_IMPLEMENT(HeapUnallocated,
GetHeapUnallocated,
"Memory mapped by the heap allocator that is not part of an active "
"allocation. Much of this memory may be uncommitted -- that is, it does not "
"take up space in physical memory or in the swap file. Committed and "
"unallocated memory, perhaps a result of fragmentation, is reported in "
"heap-dirty, if that measure is available.")
"take up space in physical memory or in the swap file.")
NS_MEMORY_REPORTER_IMPLEMENT(HeapAllocated,
"heap-allocated",