mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Merge last green changeset from inbound to mozilla-central
This commit is contained in:
commit
c52c92d647
@ -43,6 +43,8 @@
|
||||
#include "nsHyperTextAccessible.h"
|
||||
#include "nsRoleMap.h"
|
||||
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
|
||||
|
||||
void
|
||||
|
@ -112,7 +112,7 @@ StyleInfo::Margin(css::Side aSide, nsAString& aValue)
|
||||
}
|
||||
|
||||
void
|
||||
StyleInfo::Format(const nscolor& aValue, nsString& aFormattedValue)
|
||||
StyleInfo::FormatColor(const nscolor& aValue, nsString& aFormattedValue)
|
||||
{
|
||||
// Combine the string like rgb(R, G, B) from nscolor.
|
||||
aFormattedValue.AppendLiteral("rgb(");
|
||||
@ -123,3 +123,11 @@ StyleInfo::Format(const nscolor& aValue, nsString& aFormattedValue)
|
||||
aFormattedValue.AppendInt(NS_GET_B(aValue));
|
||||
aFormattedValue.Append(')');
|
||||
}
|
||||
|
||||
void
|
||||
StyleInfo::FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
nsCSSKeyword keyword =
|
||||
nsCSSProps::ValueToKeywordEnum(aValue, nsCSSProps::kFontStyleKTable);
|
||||
AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue);
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ public:
|
||||
void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
|
||||
void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
|
||||
|
||||
static void Format(const nscolor& aValue, nsString& aFormattedValue);
|
||||
static void FormatColor(const nscolor& aValue, nsString& aFormattedValue);
|
||||
static void FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue);
|
||||
|
||||
private:
|
||||
StyleInfo() MOZ_DELETE;
|
||||
|
@ -74,8 +74,6 @@ const char* const kCopyValue = nsnull;
|
||||
static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
|
||||
{
|
||||
// CSS name CSS value Attribute name Attribute value
|
||||
{ "font-family", kAnyValue, &nsGkAtoms::font_family, kCopyValue },
|
||||
{ "font-style", kAnyValue, &nsGkAtoms::font_style, kCopyValue },
|
||||
{ "text-decoration", "line-through", &nsGkAtoms::textLineThroughStyle, "solid" },
|
||||
{ "text-decoration", "underline", &nsGkAtoms::textUnderlineStyle, "solid" },
|
||||
{ "vertical-align", kAnyValue, &nsGkAtoms::textPosition, kCopyValue }
|
||||
@ -155,43 +153,43 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes,
|
||||
|
||||
// "language" text attribute
|
||||
nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&langTextAttr));
|
||||
|
||||
// "font-family" text attribute
|
||||
nsCSSTextAttr fontFamilyTextAttr(0, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontFamilyTextAttr));
|
||||
|
||||
// "font-style" text attribute
|
||||
nsCSSTextAttr fontStyleTextAttr(1, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontStyleTextAttr));
|
||||
textAttrArray.AppendElement(&langTextAttr);
|
||||
|
||||
// "text-line-through-style" text attribute
|
||||
nsCSSTextAttr lineThroughTextAttr(2, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&lineThroughTextAttr));
|
||||
nsCSSTextAttr lineThroughTextAttr(0, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(&lineThroughTextAttr);
|
||||
|
||||
// "text-underline-style" text attribute
|
||||
nsCSSTextAttr underlineTextAttr(3, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&underlineTextAttr));
|
||||
nsCSSTextAttr underlineTextAttr(1, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(&underlineTextAttr);
|
||||
|
||||
// "text-position" text attribute
|
||||
nsCSSTextAttr posTextAttr(4, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&posTextAttr));
|
||||
nsCSSTextAttr posTextAttr(2, hyperTextElm, offsetElm);
|
||||
textAttrArray.AppendElement(&posTextAttr);
|
||||
|
||||
// "background-color" text attribute
|
||||
nsBGColorTextAttr bgColorTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&bgColorTextAttr));
|
||||
textAttrArray.AppendElement(&bgColorTextAttr);
|
||||
|
||||
// "color" text attribute
|
||||
ColorTextAttr colorTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
|
||||
textAttrArray.AppendElement(&colorTextAttr);
|
||||
|
||||
// "font-family" text attribute
|
||||
FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(&fontFamilyTextAttr);
|
||||
|
||||
// "font-size" text attribute
|
||||
nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontSizeTextAttr));
|
||||
textAttrArray.AppendElement(&fontSizeTextAttr);
|
||||
|
||||
// "font-style" text attribute
|
||||
FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(&fontStyleTextAttr);
|
||||
|
||||
// "font-weight" text attribute
|
||||
nsFontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontWeightTextAttr));
|
||||
textAttrArray.AppendElement(&fontWeightTextAttr);
|
||||
|
||||
// Expose text attributes if applicable.
|
||||
if (aAttributes) {
|
||||
@ -391,7 +389,7 @@ void
|
||||
nsBGColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
nsAutoString value;
|
||||
StyleInfo::Format(aValue, value);
|
||||
StyleInfo::FormatColor(aValue, value);
|
||||
aFormattedValue = value;
|
||||
}
|
||||
|
||||
@ -453,11 +451,55 @@ void
|
||||
ColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
nsAutoString value;
|
||||
StyleInfo::Format(aValue, value);
|
||||
StyleInfo::FormatColor(aValue, value);
|
||||
aFormattedValue = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FontFamilyTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FontFamilyTextAttr::FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
|
||||
nsTextAttr<nsAutoString>(aFrame == nsnull)
|
||||
{
|
||||
mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue);
|
||||
|
||||
if (aFrame)
|
||||
mIsDefined = GetFontFamily(aFrame, mNativeValue);
|
||||
}
|
||||
|
||||
bool
|
||||
FontFamilyTextAttr::GetValueFor(nsIContent* aElm, nsAutoString* aValue)
|
||||
{
|
||||
nsIFrame* frame = aElm->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
return false;
|
||||
|
||||
return GetFontFamily(frame, *aValue);
|
||||
}
|
||||
|
||||
void
|
||||
FontFamilyTextAttr::Format(const nsAutoString& aValue,
|
||||
nsAString& aFormattedValue)
|
||||
{
|
||||
aFormattedValue = aValue;
|
||||
}
|
||||
|
||||
bool
|
||||
FontFamilyTextAttr::GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily)
|
||||
{
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
|
||||
|
||||
gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
|
||||
gfxFont* font = fontGroup->GetFontAt(0);
|
||||
gfxFontEntry* fontEntry = font->GetFontEntry();
|
||||
aFamily = fontEntry->FamilyName();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsFontSizeTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -482,7 +524,7 @@ nsFontSizeTextAttr::GetValueFor(nsIContent *aContent, nscoord *aValue)
|
||||
nsIFrame *frame = aContent->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
return false;
|
||||
|
||||
|
||||
*aValue = GetFontSize(frame);
|
||||
return true;
|
||||
}
|
||||
@ -494,7 +536,7 @@ nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue)
|
||||
//
|
||||
// Note: according to IA2, "The conversion doesn't have to be exact.
|
||||
// The intent is to give the user a feel for the size of the text."
|
||||
//
|
||||
//
|
||||
// ATK does not specify a unit and will likely follow IA2 here.
|
||||
//
|
||||
// XXX todo: consider sharing this code with layout module? (bug 474621)
|
||||
@ -516,6 +558,41 @@ nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FontStyleTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FontStyleTextAttr::FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
|
||||
nsTextAttr<nscoord>(!aFrame)
|
||||
{
|
||||
mRootNativeValue = aRootFrame->GetStyleFont()->mFont.style;
|
||||
mIsRootDefined = true;
|
||||
|
||||
if (aFrame) {
|
||||
mNativeValue = aFrame->GetStyleFont()->mFont.style;
|
||||
mIsDefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FontStyleTextAttr::GetValueFor(nsIContent* aContent, nscoord* aValue)
|
||||
{
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
*aValue = frame->GetStyleFont()->mFont.style;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FontStyleTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue)
|
||||
{
|
||||
StyleInfo::FormatFontStyle(aValue, aFormattedValue);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsFontWeightTextAttr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -41,17 +41,10 @@
|
||||
|
||||
class nsHyperTextAccessible;
|
||||
|
||||
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsITextAttr;
|
||||
|
||||
/**
|
||||
@ -100,7 +93,6 @@ public:
|
||||
PRInt32 *aEndHTOffset = nsnull);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Calculates range (start and end offsets) of text where the text attributes
|
||||
* are stretched. New offsets may be smaller if one of text attributes changes
|
||||
@ -326,6 +318,30 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with "font-family" text attribute in
|
||||
* nsTextAttrsMgr class.
|
||||
*/
|
||||
class FontFamilyTextAttr : public nsTextAttr<nsAutoString>
|
||||
{
|
||||
public:
|
||||
FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
|
||||
|
||||
// nsITextAttr
|
||||
virtual nsIAtom* GetName() const { return nsGkAtoms::font_family; }
|
||||
|
||||
protected:
|
||||
|
||||
// nsTextAttr
|
||||
virtual bool GetValueFor(nsIContent* aContent, nsAutoString* aValue);
|
||||
virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue);
|
||||
|
||||
private:
|
||||
|
||||
bool GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with "font-size" text attribute in nsTextAttrsMgr
|
||||
* class.
|
||||
@ -358,6 +374,26 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with "font-style" text attribute in nsTextAttrsMgr
|
||||
* class.
|
||||
*/
|
||||
class FontStyleTextAttr : public nsTextAttr<nscoord>
|
||||
{
|
||||
public:
|
||||
FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
|
||||
|
||||
// nsITextAttr
|
||||
virtual nsIAtom* GetName() const { return nsGkAtoms::font_style; }
|
||||
|
||||
protected:
|
||||
|
||||
// nsTextAttr
|
||||
virtual bool GetValueFor(nsIContent* aContent, nscoord* aValue);
|
||||
virtual void Format(const nscoord &aValue, nsAString &aFormattedValue);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class is used for the work with "font-weight" text attribute in
|
||||
* nsTextAttrsMgr class.
|
||||
|
@ -46,7 +46,6 @@
|
||||
|
||||
#include "AccCollector.h"
|
||||
#include "nsAccessibleWrap.h"
|
||||
#include "nsTextAttrs.h"
|
||||
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
|
@ -45,6 +45,8 @@
|
||||
|
||||
#include "nsHyperTextAccessible.h"
|
||||
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
|
@ -208,6 +208,39 @@ const kBoldFontWeight =
|
||||
const kInputFontSize = WIN ?
|
||||
"10pt" : (MAC ? "8pt" : function() { return true; });
|
||||
|
||||
const kAbsentFontFamily =
|
||||
function(aFontFamily) { return aFontFamily != "sans-serif"; }
|
||||
const kInputFontFamily =
|
||||
function(aFontFamily) { return aFontFamily != "sans-serif"; }
|
||||
|
||||
const kMonospaceFontFamily =
|
||||
function(aFontFamily) { return aFontFamily != "monospace"; }
|
||||
const kSansSerifFontFamily =
|
||||
function(aFontFamily) { return aFontFamily != "sans-serif"; }
|
||||
const kSerifFontFamily =
|
||||
function(aFontFamily) { return aFontFamily != "serif"; }
|
||||
|
||||
const kCursiveFontFamily = WIN ? "Comic Sans MS" :
|
||||
(LINUX ? "DejaVu Serif" : "MacFont");
|
||||
|
||||
/**
|
||||
* Return used font from the given computed style.
|
||||
*/
|
||||
function fontFamily(aComputedStyle)
|
||||
{
|
||||
var name = aComputedStyle.fontFamily;
|
||||
switch (name) {
|
||||
case "monospace":
|
||||
return kMonospaceFontFamily;
|
||||
case "sans-serif":
|
||||
return kSansSerifFontFamily;
|
||||
case "serif":
|
||||
return kSerifFontFamily;
|
||||
default:
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an object of default text attributes expected for the given accessible.
|
||||
*
|
||||
@ -216,7 +249,7 @@ const kInputFontSize = WIN ?
|
||||
* @param aFontWeight [in, optional] kBoldFontWeight or kNormalFontWeight,
|
||||
* default value is kNormalFontWeight
|
||||
*/
|
||||
function buildDefaultTextAttrs(aID, aFontSize, aFontWeight)
|
||||
function buildDefaultTextAttrs(aID, aFontSize, aFontWeight, aFontFamily)
|
||||
{
|
||||
var elm = getNode(aID);
|
||||
var computedStyle = document.defaultView.getComputedStyle(elm, "");
|
||||
@ -229,7 +262,7 @@ function buildDefaultTextAttrs(aID, aFontSize, aFontWeight)
|
||||
"background-color": bgColor,
|
||||
"font-weight": aFontWeight ? aFontWeight : kNormalFontWeight,
|
||||
"color": computedStyle.color,
|
||||
"font-family": computedStyle.fontFamily,
|
||||
"font-family": aFontFamily ? aFontFamily : fontFamily(computedStyle),
|
||||
"text-position": computedStyle.verticalAlign
|
||||
};
|
||||
|
||||
|
@ -263,7 +263,7 @@
|
||||
// Walk from span with font-style to the one with font-family.
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = { "font-family": gComputedStyle.fontFamily };
|
||||
attrs = { "font-family": kMonospaceFontFamily };
|
||||
testTextAttrs(ID, 70, attrs, defAttrs, 69, 83);
|
||||
|
||||
attrs = {};
|
||||
@ -281,6 +281,7 @@
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 123, attrs, defAttrs, 122, 130);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area10, different single style spans in non-styled paragraph
|
||||
ID = "area10";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt");
|
||||
@ -316,7 +317,7 @@
|
||||
// Walk from span with font-style to the one with font-family.
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-family": gComputedStyle.fontFamily};
|
||||
attrs = { "font-family": kMonospaceFontFamily };
|
||||
testTextAttrs(ID, 71, attrs, defAttrs, 70, 84);
|
||||
|
||||
attrs = {};
|
||||
@ -334,6 +335,7 @@
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 124, attrs, defAttrs, 123, 131);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area11, "font-weight" tests
|
||||
ID = "area11";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt", kBoldFontWeight);
|
||||
@ -373,7 +375,8 @@
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
|
||||
ID = "area14";
|
||||
defAttrs = buildDefaultTextAttrs(ID, kInputFontSize);
|
||||
defAttrs = buildDefaultTextAttrs(ID, kInputFontSize,
|
||||
kNormalFontWeight, kInputFontFamily);
|
||||
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
@ -404,6 +407,36 @@
|
||||
// p
|
||||
testTextAttrs(ID, 23, { }, { }, 23, 24);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area16, "font-family" tests
|
||||
ID = "area16";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt");
|
||||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
attrs = { "font-family": kMonospaceFontFamily };
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 4);
|
||||
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 4, attrs, defAttrs, 4, 9);
|
||||
|
||||
attrs = { "font-family": kSerifFontFamily };
|
||||
testTextAttrs(ID, 9, attrs, defAttrs, 9, 13);
|
||||
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 13, attrs, defAttrs, 13, 18);
|
||||
|
||||
attrs = { "font-family": kAbsentFontFamily };
|
||||
testTextAttrs(ID, 18, attrs, defAttrs, 18, 22);
|
||||
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
|
||||
|
||||
attrs = { "font-family": kCursiveFontFamily };
|
||||
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
|
||||
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 31, attrs, defAttrs, 31, 45);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -417,6 +450,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
|
||||
title="Implement text attributes">
|
||||
Mozilla Bug 345759
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
|
||||
title="font-family text attribute should expose actual font used">
|
||||
Mozilla Bug 473576
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -469,7 +507,7 @@
|
||||
<span style="font-size: 120%">bigger</span> smaller
|
||||
<span style="background-color: blue;">background blue</span> normal
|
||||
<span style="font-style: italic;">Different styling</span> normal
|
||||
<span style="font-family: tahoma;">Different font</span> normal
|
||||
<span style="font-family: monospace;">Different font</span> normal
|
||||
<span style="text-decoration: underline;">underlined</span> normal
|
||||
<span style="text-decoration: line-through;">strikethrough</span> normal
|
||||
</p>
|
||||
@ -478,7 +516,7 @@
|
||||
<span style="font-size: 120%">bigger</span> smaller
|
||||
<span style="background-color: blue;">background blue</span> normal
|
||||
<span style="font-style: italic;">Different styling</span> normal
|
||||
<span style="font-family: tahoma;">Different font</span> normal
|
||||
<span style="font-family: monospace;">Different font</span> normal
|
||||
<span style="text-decoration: underline;">underlined</span> normal
|
||||
<span style="text-decoration: line-through;">strikethrough</span> normal
|
||||
</p>
|
||||
@ -500,5 +538,13 @@
|
||||
|
||||
<!-- *plain*plain**bold*bold*-->
|
||||
<div id="area15"><p>embed</p>plain<p>embed</p>plain<p>embed</p><img src="../moz.png" alt="image"/><b>bold</b><p>embed</p><b>bold</b><p>embed</p></div>
|
||||
|
||||
<p id="area16" style="font-family: sans-serif;">
|
||||
<span style="font-family: monospace;">text</span>text
|
||||
<span style="font-family: serif;">text</span>text
|
||||
<span style="font-family: BodoniThatDoesntExist;">text</span>text
|
||||
<span style="font-family: Comic Sans MS, cursive;">text</span>text
|
||||
<span style="font-family: sans-serif, fantasy;">text</span>text
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -49,7 +49,9 @@
|
||||
|
||||
this.finalCheck = function spelledTextInvoker_finalCheck()
|
||||
{
|
||||
var defAttrs = buildDefaultTextAttrs(this.DOMNode, kInputFontSize);
|
||||
var defAttrs = buildDefaultTextAttrs(this.DOMNode, kInputFontSize,
|
||||
kNormalFontWeight,
|
||||
kInputFontFamily);
|
||||
testDefaultTextAttrs(aID, defAttrs);
|
||||
|
||||
var attrs = { };
|
||||
|
@ -410,6 +410,10 @@ pref("dom.mozBrowserFramesWhitelist", "http://localhost:7777");
|
||||
pref("dom.sms.enabled", true);
|
||||
pref("dom.sms.whitelist", "file://,http://localhost:7777");
|
||||
|
||||
// Temporary permission hack for WebContacts
|
||||
pref("dom.mozContacts.enabled", true);
|
||||
pref("dom.mozContacts.whitelist", "http://localhost:7777");
|
||||
|
||||
// Ignore X-Frame-Options headers.
|
||||
pref("b2g.ignoreXFrameOptions", true);
|
||||
|
||||
|
@ -16,6 +16,7 @@ const LocalFile = CC('@mozilla.org/file/local;1',
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'env', function() {
|
||||
return Cc['@mozilla.org/process/environment;1']
|
||||
@ -60,7 +61,7 @@ function startupHttpd(baseDir, port) {
|
||||
// XXX never grant 'content-camera' to non-gaia apps
|
||||
function addPermissions(urls) {
|
||||
let permissions = [
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera'
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera', 'webcontacts-manage'
|
||||
];
|
||||
urls.forEach(function(url) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
|
@ -155,6 +155,7 @@
|
||||
@BINPATH@/components/dom_bluetooth.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_canvas.xpt
|
||||
@BINPATH@/components/dom_contacts.xpt
|
||||
@BINPATH@/components/dom_core.xpt
|
||||
@BINPATH@/components/dom_css.xpt
|
||||
@BINPATH@/components/dom_events.xpt
|
||||
@ -294,6 +295,8 @@
|
||||
; JavaScript components
|
||||
@BINPATH@/components/ConsoleAPI.manifest
|
||||
@BINPATH@/components/ConsoleAPI.js
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
@BINPATH@/components/FeedProcessor.manifest
|
||||
@BINPATH@/components/FeedProcessor.js
|
||||
@BINPATH@/components/BrowserFeeds.manifest
|
||||
|
@ -1,7 +0,0 @@
|
||||
richlistitem[type="tab"] {
|
||||
-moz-binding: url(chrome://browser/content/aboutSyncTabs-bindings.xml#tab-listing);
|
||||
}
|
||||
|
||||
richlistitem[type="client"] {
|
||||
-moz-binding: url(chrome://browser/content/aboutSyncTabs-bindings.xml#client-listing);
|
||||
}
|
@ -101,25 +101,25 @@ var StarUI = {
|
||||
this._restoreCommandsState();
|
||||
this._itemId = -1;
|
||||
if (this._batching) {
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
PlacesUtils.transactionManager.endBatch();
|
||||
this._batching = false;
|
||||
}
|
||||
|
||||
switch (this._actionOnHide) {
|
||||
case "cancel": {
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
// Remove all bookmarks for the bookmark's url, this also removes
|
||||
// the tags for the url.
|
||||
PlacesUIUtils.ptm.beginBatch();
|
||||
PlacesUtils.transactionManager.beginBatch();
|
||||
let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
|
||||
for (let i = 0; i < itemIds.length; i++) {
|
||||
let txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
let txn = new PlacesRemoveItemTransaction(itemIds[i]);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
PlacesUtils.transactionManager.endBatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -275,7 +275,7 @@ var StarUI = {
|
||||
|
||||
beginBatch: function SU_beginBatch() {
|
||||
if (!this._batching) {
|
||||
PlacesUIUtils.ptm.beginBatch();
|
||||
PlacesUtils.transactionManager.beginBatch();
|
||||
this._batching = true;
|
||||
}
|
||||
}
|
||||
@ -325,9 +325,10 @@ var PlacesCommandHook = {
|
||||
var parent = aParent != undefined ?
|
||||
aParent : PlacesUtils.unfiledBookmarksFolderId;
|
||||
var descAnno = { name: PlacesUIUtils.DESCRIPTION_ANNO, value: description };
|
||||
var txn = PlacesUIUtils.ptm.createItem(uri, parent, -1,
|
||||
title, null, [descAnno]);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesCreateBookmarkTransaction(uri, parent,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
title, null, [descAnno]);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
// Set the character-set
|
||||
if (charset)
|
||||
PlacesUtils.history.setCharsetForURI(uri, charset);
|
||||
|
@ -291,7 +291,7 @@ let gSyncUI = {
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/syncSetup.xul",
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
}
|
||||
@ -305,7 +305,7 @@ let gSyncUI = {
|
||||
if (win)
|
||||
win.focus();
|
||||
else
|
||||
window.openDialog("chrome://browser/content/syncAddDevice.xul",
|
||||
window.openDialog("chrome://browser/content/sync/addDevice.xul",
|
||||
"syncAddDevice", "centerscreen,chrome,resizable=no");
|
||||
},
|
||||
|
||||
@ -315,7 +315,7 @@ let gSyncUI = {
|
||||
win.focus();
|
||||
else
|
||||
Services.ww.activeWindow.openDialog(
|
||||
"chrome://browser/content/syncQuota.xul", "",
|
||||
"chrome://browser/content/sync/quota.xul", "",
|
||||
"centerscreen,chrome,dialog,modal");
|
||||
},
|
||||
|
||||
|
@ -329,12 +329,12 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
%ifdef MOZ_SERVICES_SYNC
|
||||
/* Sync notification UI */
|
||||
#sync-notifications {
|
||||
-moz-binding: url("chrome://browser/content/syncNotification.xml#notificationbox");
|
||||
-moz-binding: url("chrome://browser/content/sync/notification.xml#notificationbox");
|
||||
overflow-y: visible !important;
|
||||
}
|
||||
|
||||
#sync-notifications notification {
|
||||
-moz-binding: url("chrome://browser/content/syncNotification.xml#notification");
|
||||
-moz-binding: url("chrome://browser/content/sync/notification.xml#notification");
|
||||
}
|
||||
%endif
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<p><b>Binaries</b> of this product have been made available to you by the
|
||||
<a href="http://www.mozilla.org/">Mozilla Project</a> under the Mozilla
|
||||
Public License. <a href="about:rights">Know your rights</a>.</p>
|
||||
Public License 2.0 (MPL). <a href="about:rights">Know your rights</a>.</p>
|
||||
|
7
browser/base/content/sync/aboutSyncTabs.css
Normal file
7
browser/base/content/sync/aboutSyncTabs.css
Normal file
@ -0,0 +1,7 @@
|
||||
richlistitem[type="tab"] {
|
||||
-moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#tab-listing);
|
||||
}
|
||||
|
||||
richlistitem[type="client"] {
|
||||
-moz-binding: url(chrome://browser/content/sync/aboutSyncTabs-bindings.xml#client-listing);
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/aboutSyncTabs.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/aboutSyncTabs.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/sync/aboutSyncTabs.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % aboutSyncTabsDTD SYSTEM "chrome://browser/locale/aboutSyncTabs.dtd">
|
||||
@ -53,7 +53,7 @@
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="&tabs.otherComputers.label;">
|
||||
<script type="application/javascript;version=1.8" src="chrome://browser/content/aboutSyncTabs.js"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://browser/content/sync/aboutSyncTabs.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
|
||||
<html:head>
|
||||
<html:link rel="icon" href="chrome://browser/skin/sync-16.png"/>
|
@ -61,9 +61,9 @@
|
||||
onload="gSyncAddDevice.init();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncAddDevice.js"/>
|
||||
src="chrome://browser/content/sync/addDevice.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncUtils.js"/>
|
||||
src="chrome://browser/content/sync/utils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
<script type="application/javascript"
|
@ -60,9 +60,9 @@
|
||||
onwizardfinish="return Change.onDialogAccept();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncGenericChange.js"/>
|
||||
src="chrome://browser/content/sync/genericChange.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncUtils.js"/>
|
||||
src="chrome://browser/content/sync/utils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/printUtils.js"/>
|
||||
|
@ -61,7 +61,7 @@
|
||||
href="chrome://browser/skin/sync-16.png"/>
|
||||
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/syncProgress.js"/>
|
||||
src="chrome://browser/content/sync/progress.js"/>
|
||||
</head>
|
||||
<body onload="onLoad(event)" onunload="onUnload(event)">
|
||||
<title>&setup.successPage.title;</title>
|
@ -60,7 +60,7 @@
|
||||
ondialogaccept="return gSyncQuota.onAccept();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncQuota.js"/>
|
||||
src="chrome://browser/content/sync/quota.js"/>
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="quotaStrings"
|
@ -65,9 +65,9 @@
|
||||
onload="gSyncSetup.init()">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncSetup.js"/>
|
||||
src="chrome://browser/content/sync/setup.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncUtils.js"/>
|
||||
src="chrome://browser/content/sync/utils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
<script type="application/javascript"
|
@ -76,7 +76,7 @@ let gSyncUtils = {
|
||||
}
|
||||
|
||||
// Open up the change dialog
|
||||
let changeXUL = "chrome://browser/content/syncGenericChange.xul";
|
||||
let changeXUL = "chrome://browser/content/sync/genericChange.xul";
|
||||
let changeOpt = "centerscreen,chrome,resizable=no";
|
||||
Services.ww.activeWindow.openDialog(changeXUL, "", changeOpt,
|
||||
type, duringSetup);
|
||||
@ -125,7 +125,7 @@ let gSyncUtils = {
|
||||
|
||||
// Create an invisible iframe whose contents we can print.
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", "chrome://browser/content/syncKey.xhtml");
|
||||
iframe.setAttribute("src", "chrome://browser/content/sync/key.xhtml");
|
||||
iframe.collapsed = true;
|
||||
document.documentElement.appendChild(iframe);
|
||||
iframe.contentWindow.addEventListener("load", function() {
|
@ -41,6 +41,25 @@ browser.jar:
|
||||
* content/browser/pageinfo/feeds.xml (content/pageinfo/feeds.xml)
|
||||
* content/browser/pageinfo/permissions.js (content/pageinfo/permissions.js)
|
||||
* content/browser/pageinfo/security.js (content/pageinfo/security.js)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
* content/browser/sync/aboutSyncTabs.xul (content/sync/aboutSyncTabs.xul)
|
||||
content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js)
|
||||
content/browser/sync/aboutSyncTabs.css (content/sync/aboutSyncTabs.css)
|
||||
* content/browser/sync/aboutSyncTabs-bindings.xml (content/sync/aboutSyncTabs-bindings.xml)
|
||||
* content/browser/sync/setup.xul (content/sync/setup.xul)
|
||||
content/browser/sync/addDevice.js (content/sync/addDevice.js)
|
||||
* content/browser/sync/addDevice.xul (content/sync/addDevice.xul)
|
||||
content/browser/sync/setup.js (content/sync/setup.js)
|
||||
* content/browser/sync/genericChange.xul (content/sync/genericChange.xul)
|
||||
content/browser/sync/genericChange.js (content/sync/genericChange.js)
|
||||
* content/browser/sync/key.xhtml (content/sync/key.xhtml)
|
||||
* content/browser/sync/notification.xml (content/sync/notification.xml)
|
||||
* content/browser/sync/quota.xul (content/sync/quota.xul)
|
||||
content/browser/sync/quota.js (content/sync/quota.js)
|
||||
content/browser/sync/utils.js (content/sync/utils.js)
|
||||
content/browser/sync/progress.js (content/sync/progress.js)
|
||||
* content/browser/sync/progress.xhtml (content/sync/progress.xhtml)
|
||||
#endif
|
||||
* content/browser/openLocation.js (content/openLocation.js)
|
||||
* content/browser/openLocation.xul (content/openLocation.xul)
|
||||
* content/browser/safeMode.js (content/safeMode.js)
|
||||
@ -57,25 +76,6 @@ browser.jar:
|
||||
* content/browser/web-panels.xul (content/web-panels.xul)
|
||||
* content/browser/baseMenuOverlay.xul (content/baseMenuOverlay.xul)
|
||||
* content/browser/nsContextMenu.js (content/nsContextMenu.js)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
* content/browser/aboutSyncTabs.xul (content/aboutSyncTabs.xul)
|
||||
content/browser/aboutSyncTabs.js (content/aboutSyncTabs.js)
|
||||
content/browser/aboutSyncTabs.css (content/aboutSyncTabs.css)
|
||||
* content/browser/aboutSyncTabs-bindings.xml (content/aboutSyncTabs-bindings.xml)
|
||||
* content/browser/syncSetup.xul (content/syncSetup.xul)
|
||||
content/browser/syncAddDevice.js (content/syncAddDevice.js)
|
||||
* content/browser/syncAddDevice.xul (content/syncAddDevice.xul)
|
||||
content/browser/syncSetup.js (content/syncSetup.js)
|
||||
* content/browser/syncGenericChange.xul (content/syncGenericChange.xul)
|
||||
content/browser/syncGenericChange.js (content/syncGenericChange.js)
|
||||
* content/browser/syncKey.xhtml (content/syncKey.xhtml)
|
||||
* content/browser/syncNotification.xml (content/syncNotification.xml)
|
||||
* content/browser/syncQuota.xul (content/syncQuota.xul)
|
||||
content/browser/syncQuota.js (content/syncQuota.js)
|
||||
content/browser/syncUtils.js (content/syncUtils.js)
|
||||
content/browser/syncProgress.js (content/syncProgress.js)
|
||||
* content/browser/syncProgress.xhtml (content/syncProgress.xhtml)
|
||||
#endif
|
||||
# XXX: We should exclude this one as well (bug 71895)
|
||||
* content/browser/hiddenWindow.xul (content/hiddenWindow.xul)
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -97,9 +97,9 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
{ "sync-progress", "chrome://browser/content/syncProgress.xhtml",
|
||||
{ "sync-progress", "chrome://browser/content/sync/progress.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "sync-tabs", "chrome://browser/content/aboutSyncTabs.xul",
|
||||
{ "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
{ "home", "chrome://browser/content/aboutHome.xhtml",
|
||||
|
@ -1,3 +1,4 @@
|
||||
# -*- indent-tabs-mode: nil -*-
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
@ -774,18 +775,71 @@ BrowserGlue.prototype = {
|
||||
const PREF_TELEMETRY_REJECTED = "toolkit.telemetry.rejected";
|
||||
const PREF_TELEMETRY_INFOURL = "toolkit.telemetry.infoURL";
|
||||
const PREF_TELEMETRY_SERVER_OWNER = "toolkit.telemetry.server_owner";
|
||||
const PREF_TELEMETRY_ENABLED_BY_DEFAULT = "toolkit.telemetry.enabledByDefault";
|
||||
const PREF_TELEMETRY_NOTIFIED_OPTOUT = "toolkit.telemetry.notifiedOptOut";
|
||||
// This is used to reprompt users when privacy message changes
|
||||
const TELEMETRY_PROMPT_REV = 2;
|
||||
|
||||
function appendTelemetryNotification(notifyBox, message, buttons, hideclose) {
|
||||
// Stick notifications onto the selected tab of the active browser window.
|
||||
var win = this.getMostRecentBrowserWindow();
|
||||
var tabbrowser = win.gBrowser;
|
||||
var notifyBox = tabbrowser.getNotificationBox();
|
||||
|
||||
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
var productName = brandBundle.GetStringFromName("brandFullName");
|
||||
var serverOwner = Services.prefs.getCharPref(PREF_TELEMETRY_SERVER_OWNER);
|
||||
|
||||
function appendTelemetryNotification(message, buttons, hideclose) {
|
||||
let notification = notifyBox.appendNotification(message, "telemetry", null,
|
||||
notifyBox.PRIORITY_INFO_LOW,
|
||||
buttons);
|
||||
notification.setAttribute("hideclose", hideclose);
|
||||
notifyBox.PRIORITY_INFO_LOW,
|
||||
buttons);
|
||||
if (hideclose)
|
||||
notification.setAttribute("hideclose", hideclose);
|
||||
notification.persistence = -1; // Until user closes it
|
||||
return notification;
|
||||
}
|
||||
|
||||
function appendLearnMoreLink(notification) {
|
||||
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
link.className = "text-link telemetry-text-link";
|
||||
link.setAttribute("value", browserBundle.GetStringFromName("telemetryLinkLabel"));
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
var telemetryEnabledByDefault = false;
|
||||
try {
|
||||
telemetryEnabledByDefault = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED_BY_DEFAULT);
|
||||
} catch(e) {}
|
||||
if (telemetryEnabledByDefault) {
|
||||
var telemetryNotifiedOptOut = false;
|
||||
try {
|
||||
telemetryNotifiedOptOut = Services.prefs.getBoolPref(PREF_TELEMETRY_NOTIFIED_OPTOUT);
|
||||
} catch(e) {}
|
||||
if (telemetryNotifiedOptOut)
|
||||
return;
|
||||
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryOptOutPrompt",
|
||||
[productName, serverOwner, productName], 3);
|
||||
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_NOTIFIED_OPTOUT, true);
|
||||
|
||||
let notification = appendTelemetryNotification(telemetryPrompt, null, false);
|
||||
let link = appendLearnMoreLink(notification);
|
||||
link.addEventListener('click', function() {
|
||||
// Open the learn more url in a new tab
|
||||
let url = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||
url += "how-can-i-help-submitting-performance-data";
|
||||
tabbrowser.selectedTab = tabbrowser.addTab(url);
|
||||
// Remove the notification on which the user clicked
|
||||
notification.parentNode.removeNotification(notification, true);
|
||||
}, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var telemetryPrompted = null;
|
||||
try {
|
||||
telemetryPrompted = Services.prefs.getIntPref(PREF_TELEMETRY_PROMPTED);
|
||||
@ -798,17 +852,7 @@ BrowserGlue.prototype = {
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_PROMPTED);
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
|
||||
|
||||
// Stick the notification onto the selected tab of the active browser window.
|
||||
var win = this.getMostRecentBrowserWindow();
|
||||
var browser = win.gBrowser; // for closure in notification bar callback
|
||||
var notifyBox = browser.getNotificationBox();
|
||||
|
||||
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
|
||||
var productName = brandBundle.GetStringFromName("brandFullName");
|
||||
var serverOwner = Services.prefs.getCharPref(PREF_TELEMETRY_SERVER_OWNER);
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryPrompt", [productName, serverOwner], 2);
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryPrompt", [productName, serverOwner], 2);
|
||||
|
||||
var buttons = [
|
||||
{
|
||||
@ -832,23 +876,17 @@ BrowserGlue.prototype = {
|
||||
// Set pref to indicate we've shown the notification.
|
||||
Services.prefs.setIntPref(PREF_TELEMETRY_PROMPTED, TELEMETRY_PROMPT_REV);
|
||||
|
||||
let notification = appendTelemetryNotification(notifyBox, telemetryPrompt,
|
||||
buttons, true);
|
||||
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
link.className = "text-link telemetry-text-link";
|
||||
link.setAttribute("value", browserBundle.GetStringFromName("telemetryLinkLabel"));
|
||||
let notification = appendTelemetryNotification(telemetryPrompt, buttons, true);
|
||||
let link = appendLearnMoreLink(notification);
|
||||
link.addEventListener('click', function() {
|
||||
// Open the learn more url in a new tab
|
||||
browser.selectedTab = browser.addTab(Services.prefs.getCharPref(PREF_TELEMETRY_INFOURL));
|
||||
tabbrowser.selectedTab = tabbrowser.addTab(Services.prefs.getCharPref(PREF_TELEMETRY_INFOURL));
|
||||
// Remove the notification on which the user clicked
|
||||
notification.parentNode.removeNotification(notification, true);
|
||||
// Add a new notification to that tab, with no "Learn more" link
|
||||
notifyBox = browser.getNotificationBox();
|
||||
appendTelemetryNotification(notifyBox, telemetryPrompt, buttons, true);
|
||||
notifyBox = tabbrowser.getNotificationBox();
|
||||
appendTelemetryNotification(telemetryPrompt, buttons, true);
|
||||
}, false);
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
},
|
||||
#endif
|
||||
|
||||
|
@ -436,7 +436,7 @@ var BookmarkPropertiesPanel = {
|
||||
if (this._batching)
|
||||
return;
|
||||
|
||||
PlacesUIUtils.ptm.beginBatch();
|
||||
PlacesUtils.transactionManager.beginBatch();
|
||||
this._batching = true;
|
||||
},
|
||||
|
||||
@ -444,7 +444,7 @@ var BookmarkPropertiesPanel = {
|
||||
if (!this._batching)
|
||||
return;
|
||||
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
PlacesUtils.transactionManager.endBatch();
|
||||
this._batching = false;
|
||||
},
|
||||
|
||||
@ -514,7 +514,7 @@ var BookmarkPropertiesPanel = {
|
||||
gEditItemOverlay.uninitPanel(true);
|
||||
gEditItemOverlay = null;
|
||||
this._endBatch();
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
window.arguments[0].performed = false;
|
||||
},
|
||||
|
||||
@ -577,32 +577,44 @@ var BookmarkPropertiesPanel = {
|
||||
var childTransactions = [];
|
||||
|
||||
if (this._description) {
|
||||
childTransactions.push(
|
||||
PlacesUIUtils.ptm.editItemDescription(-1, this._description));
|
||||
let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
|
||||
type : Ci.nsIAnnotationService.TYPE_STRING,
|
||||
flags : 0,
|
||||
value : this._description,
|
||||
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
|
||||
let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
|
||||
childTransactions.push(editItemTxn);
|
||||
}
|
||||
|
||||
if (this._loadInSidebar) {
|
||||
childTransactions.push(
|
||||
PlacesUIUtils.ptm.setLoadInSidebar(-1, this._loadInSidebar));
|
||||
let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
|
||||
type : Ci.nsIAnnotationService.TYPE_INT32,
|
||||
flags : 0,
|
||||
value : this._loadInSidebar,
|
||||
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
|
||||
let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
|
||||
childTransactions.push(setLoadTxn);
|
||||
}
|
||||
|
||||
if (this._postData) {
|
||||
childTransactions.push(
|
||||
PlacesUIUtils.ptm.editBookmarkPostData(-1, this._postData));
|
||||
let postDataTxn = new PlacesEditBookmarkPostDataTransaction(-1, this._postData);
|
||||
childTransactions.push(postDataTxn);
|
||||
}
|
||||
|
||||
//XXX TODO: this should be in a transaction!
|
||||
if (this._charSet)
|
||||
PlacesUtils.history.setCharsetForURI(this._uri, this._charSet);
|
||||
|
||||
var transactions = [PlacesUIUtils.ptm.createItem(this._uri,
|
||||
aContainer, aIndex,
|
||||
this._title, this._keyword,
|
||||
annotations,
|
||||
childTransactions)];
|
||||
let createTxn = new PlacesCreateBookmarkTransaction(this._uri,
|
||||
aContainer,
|
||||
aIndex,
|
||||
this._title,
|
||||
this._keyword,
|
||||
annotations,
|
||||
childTransactions);
|
||||
|
||||
return PlacesUIUtils.ptm.aggregateTransactions(this._getDialogTitle(),
|
||||
transactions);
|
||||
return new PlacesAggregatedTransaction(this._getDialogTitle(),
|
||||
[createTxn]);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -614,7 +626,10 @@ var BookmarkPropertiesPanel = {
|
||||
for (var i = 0; i < this._URIs.length; ++i) {
|
||||
var uri = this._URIs[i];
|
||||
var title = this._getURITitleFromHistory(uri);
|
||||
transactions.push(PlacesUIUtils.ptm.createItem(uri, -1, -1, title));
|
||||
var createTxn = new PlacesCreateBookmarkTransaction(uri, -1,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
title);
|
||||
transactions.push(createTxn);
|
||||
}
|
||||
return transactions;
|
||||
},
|
||||
@ -633,8 +648,9 @@ var BookmarkPropertiesPanel = {
|
||||
if (this._description)
|
||||
annotations.push(this._getDescriptionAnnotation(this._description));
|
||||
|
||||
return PlacesUIUtils.ptm.createFolder(this._title, aContainer, aIndex,
|
||||
annotations, childItemsTransactions);
|
||||
return new PlacesCreateFolderTransaction(this._title, aContainer,
|
||||
aIndex, annotations,
|
||||
childItemsTransactions);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -643,9 +659,9 @@ var BookmarkPropertiesPanel = {
|
||||
*/
|
||||
_getCreateNewLivemarkTransaction:
|
||||
function BPP__getCreateNewLivemarkTransaction(aContainer, aIndex) {
|
||||
return PlacesUIUtils.ptm.createLivemark(this._feedURI, this._siteURI,
|
||||
this._title,
|
||||
aContainer, aIndex);
|
||||
return new PlacesCreateLivemarkTransaction(this._feedURI, this._siteURI,
|
||||
this._title,
|
||||
aContainer, aIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -666,7 +682,7 @@ var BookmarkPropertiesPanel = {
|
||||
txn = this._getCreateNewBookmarkTransaction(container, index);
|
||||
}
|
||||
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container, index);
|
||||
}
|
||||
};
|
||||
|
@ -1858,13 +1858,16 @@ PlacesMenu.prototype = {
|
||||
_onPopupHidden: function PM__onPopupHidden(aEvent) {
|
||||
// Avoid handling popuphidden of inner views.
|
||||
let popup = aEvent.originalTarget;
|
||||
if (!popup._placesNode || PlacesUIUtils.getViewForNode(popup) != this)
|
||||
let placesNode = popup._placesNode;
|
||||
if (!placesNode || PlacesUIUtils.getViewForNode(popup) != this)
|
||||
return;
|
||||
|
||||
// UI performance: folder queries are cheap, keep the resultnode open
|
||||
// so we don't rebuild its contents whenever the popup is reopened.
|
||||
if (!PlacesUtils.nodeIsFolder(popup._placesNode))
|
||||
popup._placesNode.containerOpen = false;
|
||||
// Though, we want to always close feed containers so their expiration
|
||||
// status will be checked at next opening.
|
||||
if (!PlacesUtils.nodeIsFolder(placesNode) || placesNode._feedURI)
|
||||
placesNode.containerOpen = false;
|
||||
|
||||
// The autoopened attribute is set for folders which have been
|
||||
// automatically opened when dragged over. Turn off this attribute
|
||||
|
@ -157,9 +157,9 @@ PlacesController.prototype = {
|
||||
isCommandEnabled: function PC_isCommandEnabled(aCommand) {
|
||||
switch (aCommand) {
|
||||
case "cmd_undo":
|
||||
return PlacesUIUtils.ptm.numberOfUndoItems > 0;
|
||||
return PlacesUtils.transactionManager.numberOfUndoItems > 0;
|
||||
case "cmd_redo":
|
||||
return PlacesUIUtils.ptm.numberOfRedoItems > 0;
|
||||
return PlacesUtils.transactionManager.numberOfRedoItems > 0;
|
||||
case "cmd_cut":
|
||||
case "placesCmd_cut":
|
||||
var nodes = this._view.selectedNodes;
|
||||
@ -230,10 +230,10 @@ PlacesController.prototype = {
|
||||
doCommand: function PC_doCommand(aCommand) {
|
||||
switch (aCommand) {
|
||||
case "cmd_undo":
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
break;
|
||||
case "cmd_redo":
|
||||
PlacesUIUtils.ptm.redoTransaction();
|
||||
PlacesUtils.transactionManager.redoTransaction();
|
||||
break;
|
||||
case "cmd_cut":
|
||||
case "placesCmd_cut":
|
||||
@ -785,8 +785,8 @@ PlacesController.prototype = {
|
||||
var ip = this._view.insertionPoint;
|
||||
if (!ip)
|
||||
throw Cr.NS_ERROR_NOT_AVAILABLE;
|
||||
var txn = PlacesUIUtils.ptm.createSeparator(ip.itemId, ip.index);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesCreateSeparatorTransaction(ip.itemId, ip.index);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
// select the new item
|
||||
var insertedNodeId = PlacesUtils.bookmarks
|
||||
.getIdForItemAt(ip.itemId, ip.index);
|
||||
@ -807,8 +807,8 @@ PlacesController.prototype = {
|
||||
*/
|
||||
sortFolderByName: function PC_sortFolderByName() {
|
||||
var itemId = PlacesUtils.getConcreteItemId(this._view.selectedNode);
|
||||
var txn = PlacesUIUtils.ptm.sortFolderByName(itemId);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesSortFolderByNameTransaction(itemId);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -872,7 +872,8 @@ PlacesController.prototype = {
|
||||
// untag transaction.
|
||||
var tagItemId = PlacesUtils.getConcreteItemId(node.parent);
|
||||
var uri = NetUtil.newURI(node.uri);
|
||||
transactions.push(PlacesUIUtils.ptm.untagURI(uri, [tagItemId]));
|
||||
let txn = new PlacesUntagURITransaction(uri, [tagItemId]);
|
||||
transactions.push(txn);
|
||||
}
|
||||
else if (PlacesUtils.nodeIsTagQuery(node) && node.parent &&
|
||||
PlacesUtils.nodeIsQuery(node.parent) &&
|
||||
@ -884,8 +885,10 @@ PlacesController.prototype = {
|
||||
// must only remove the query node.
|
||||
var tag = node.title;
|
||||
var URIs = PlacesUtils.tagging.getURIsForTag(tag);
|
||||
for (var j = 0; j < URIs.length; j++)
|
||||
transactions.push(PlacesUIUtils.ptm.untagURI(URIs[j], [tag]));
|
||||
for (var j = 0; j < URIs.length; j++) {
|
||||
let txn = new PlacesUntagURITransaction(URIs[j], [tag]);
|
||||
transactions.push(txn);
|
||||
}
|
||||
}
|
||||
else if (PlacesUtils.nodeIsURI(node) &&
|
||||
PlacesUtils.nodeIsQuery(node.parent) &&
|
||||
@ -912,7 +915,8 @@ PlacesController.prototype = {
|
||||
// to skip nodes that are children of an already removed folder.
|
||||
removedFolders.push(node);
|
||||
}
|
||||
transactions.push(PlacesUIUtils.ptm.removeItem(node.itemId));
|
||||
let txn = new PlacesRemoveItemTransaction(node.itemId);
|
||||
transactions.push(txn);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -931,8 +935,8 @@ PlacesController.prototype = {
|
||||
this._removeRange(ranges[i], transactions, removedFolders);
|
||||
|
||||
if (transactions.length > 0) {
|
||||
var txn = PlacesUIUtils.ptm.aggregateTransactions(txnName, transactions);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesAggregatedTransaction(txnName, transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1278,10 +1282,9 @@ PlacesController.prototype = {
|
||||
if (ip.isTag) {
|
||||
// Pasting into a tag container means tagging the item, regardless of
|
||||
// the requested action.
|
||||
transactions.push(
|
||||
new PlacesTagURITransaction(NetUtil.newURI(items[i].uri),
|
||||
[ip.itemId])
|
||||
);
|
||||
let tagTxn = new PlacesTagURITransaction(NetUtil.newURI(items[i].uri),
|
||||
[ip.itemId]);
|
||||
transactions.push(tagTxn);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1296,9 +1299,8 @@ PlacesController.prototype = {
|
||||
);
|
||||
}
|
||||
|
||||
PlacesUtils.transactionManager.doTransaction(
|
||||
new PlacesAggregatedTransaction("Paste", transactions)
|
||||
);
|
||||
let aggregatedTxn = new PlacesAggregatedTransaction("Paste", transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(aggregatedTxn);
|
||||
|
||||
// Cut/past operations are not repeatable, so clear the clipboard.
|
||||
if (action == "cut") {
|
||||
@ -1548,7 +1550,8 @@ let PlacesControllerDragHelper = {
|
||||
insertionPoint.orientation == Ci.nsITreeView.DROP_ON) {
|
||||
let uri = NetUtil.newURI(unwrapped.uri);
|
||||
let tagItemId = insertionPoint.itemId;
|
||||
transactions.push(PlacesUIUtils.ptm.tagURI(uri,[tagItemId]));
|
||||
let tagTxn = new PlacesTagURITransaction(uri, [tagItemId]);
|
||||
transactions.push(tagTxn);
|
||||
}
|
||||
else {
|
||||
transactions.push(PlacesUIUtils.makeTransaction(unwrapped,
|
||||
@ -1557,8 +1560,8 @@ let PlacesControllerDragHelper = {
|
||||
}
|
||||
}
|
||||
|
||||
let txn = PlacesUIUtils.ptm.aggregateTransactions("DropItems", transactions);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
let txn = new PlacesAggregatedTransaction("DropItems", transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -435,15 +435,18 @@ var gEditItemOverlay = {
|
||||
tagsToAdd.push(tags[i]);
|
||||
}
|
||||
|
||||
if (tagsToRemove.length > 0)
|
||||
txns.push(PlacesUIUtils.ptm.untagURI(this._uri, tagsToRemove));
|
||||
if (tagsToAdd.length > 0)
|
||||
txns.push(PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd));
|
||||
if (tagsToRemove.length > 0) {
|
||||
let untagTxn = new PlacesUntagURITransaction(this._uri, tagsToRemove);
|
||||
txns.push(untagTxn);
|
||||
}
|
||||
if (tagsToAdd.length > 0) {
|
||||
let tagTxn = new PlacesTagURITransaction(this._uri, tagsToAdd);
|
||||
txns.push(tagTxn);
|
||||
}
|
||||
|
||||
if (txns.length > 0) {
|
||||
var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update tags",
|
||||
txns);
|
||||
PlacesUIUtils.ptm.doTransaction(aggregate);
|
||||
let aggregate = new PlacesAggregatedTransaction("Update tags", txns);
|
||||
PlacesUtils.transactionManager.doTransaction(aggregate);
|
||||
|
||||
// Ensure the tagsField is in sync, clean it up from empty tags
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(this._uri).join(", ");
|
||||
@ -495,25 +498,31 @@ var gEditItemOverlay = {
|
||||
}
|
||||
|
||||
if (tagsToAdd.length > 0) {
|
||||
for (i = 0; i < this._uris.length; i++) {
|
||||
if (tagsToAdd[i].length > 0)
|
||||
txns.push(PlacesUIUtils.ptm.tagURI(this._uris[i], tagsToAdd[i]));
|
||||
for (let i = 0; i < this._uris.length; i++) {
|
||||
if (tagsToAdd[i].length > 0) {
|
||||
let tagTxn = new PlacesTagURITransaction(this._uris[i],
|
||||
tagsToAdd[i]);
|
||||
txns.push(tagTxn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tagsToRemove.length > 0) {
|
||||
for (var i = 0; i < this._uris.length; i++)
|
||||
txns.push(PlacesUIUtils.ptm.untagURI(this._uris[i], tagsToRemove));
|
||||
for (let i = 0; i < this._uris.length; i++) {
|
||||
let untagTxn = new PlacesUntagURITransaction(this._uris[i],
|
||||
tagsToRemove);
|
||||
txns.push(untagTxn);
|
||||
}
|
||||
}
|
||||
|
||||
if (txns.length > 0) {
|
||||
var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update tags",
|
||||
txns);
|
||||
PlacesUIUtils.ptm.doTransaction(aggregate);
|
||||
let aggregate = new PlacesAggregatedTransaction("Update tags", txns);
|
||||
PlacesUtils.transactionManager.doTransaction(aggregate);
|
||||
|
||||
this._allTags = tags;
|
||||
this._tags = [];
|
||||
for (i = 0; i < this._uris.length; i++)
|
||||
for (let i = 0; i < this._uris.length; i++) {
|
||||
this._tags[i] = PlacesUtils.tagging.getTagsForURI(this._uris[i]);
|
||||
}
|
||||
|
||||
// Ensure the tagsField is in sync, clean it up from empty tags
|
||||
this._initTextField("tagsField", tags, false);
|
||||
@ -528,8 +537,6 @@ var gEditItemOverlay = {
|
||||
return;
|
||||
|
||||
var namePicker = this._element("namePicker")
|
||||
var txns = [];
|
||||
const ptm = PlacesUIUtils.ptm;
|
||||
|
||||
// Here we update either the item title or its cached static title
|
||||
var newTitle = namePicker.value;
|
||||
@ -540,19 +547,21 @@ var gEditItemOverlay = {
|
||||
}
|
||||
else if (this._getItemStaticTitle() != newTitle) {
|
||||
this._mayUpdateFirstEditField("namePicker");
|
||||
txns.push(ptm.editItemTitle(this._itemId, newTitle));
|
||||
let txn = new PlacesEditItemTitleTransaction(this._itemId, newTitle);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
|
||||
var aggregate = ptm.aggregateTransactions("Edit Item Title", txns);
|
||||
ptm.doTransaction(aggregate);
|
||||
},
|
||||
|
||||
onDescriptionFieldBlur: function EIO_onDescriptionFieldBlur() {
|
||||
var description = this._element("descriptionField").value;
|
||||
if (description != PlacesUIUtils.getItemDescription(this._itemId)) {
|
||||
var txn = PlacesUIUtils.ptm
|
||||
.editItemDescription(this._itemId, description);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
|
||||
type : Ci.nsIAnnotationService.TYPE_STRING,
|
||||
flags : 0,
|
||||
value : description,
|
||||
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
|
||||
var txn = new PlacesSetItemAnnotationTransaction(this._itemId, annoObj);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
},
|
||||
|
||||
@ -564,8 +573,8 @@ var gEditItemOverlay = {
|
||||
catch(ex) { return; }
|
||||
|
||||
if (!this._uri.equals(uri)) {
|
||||
var txn = PlacesUIUtils.ptm.editBookmarkURI(this._itemId, uri);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesEditBookmarkURITransaction(this._itemId, uri);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
this._uri = uri;
|
||||
}
|
||||
},
|
||||
@ -573,17 +582,22 @@ var gEditItemOverlay = {
|
||||
onKeywordFieldBlur: function EIO_onKeywordFieldBlur() {
|
||||
var keyword = this._element("keywordField").value;
|
||||
if (keyword != PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId)) {
|
||||
var txn = PlacesUIUtils.ptm.editBookmarkKeyword(this._itemId, keyword);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesEditBookmarkKeywordTransaction(this._itemId, keyword);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
},
|
||||
|
||||
onLoadInSidebarCheckboxCommand:
|
||||
function EIO_onLoadInSidebarCheckboxCommand() {
|
||||
var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
|
||||
var txn = PlacesUIUtils.ptm.setLoadInSidebar(this._itemId,
|
||||
loadInSidebarChecked);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
|
||||
type : Ci.nsIAnnotationService.TYPE_INT32,
|
||||
flags : 0,
|
||||
value : loadInSidebarChecked,
|
||||
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
|
||||
var txn = new PlacesSetItemAnnotationTransaction(this._itemId,
|
||||
annoObj);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
},
|
||||
|
||||
toggleFolderTreeVisibility: function EIO_toggleFolderTreeVisibility() {
|
||||
@ -672,8 +686,10 @@ var gEditItemOverlay = {
|
||||
// Move the item
|
||||
var container = this._getFolderIdFromMenuList();
|
||||
if (PlacesUtils.bookmarks.getFolderIdForItem(this._itemId) != container) {
|
||||
var txn = PlacesUIUtils.ptm.moveItem(this._itemId, container, -1);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesMoveItemTransaction(this._itemId,
|
||||
container,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
|
||||
// Mark the containing folder as recently-used if it isn't in the
|
||||
// static list
|
||||
@ -720,15 +736,17 @@ var gEditItemOverlay = {
|
||||
var anno = this._getLastUsedAnnotationObject(false);
|
||||
while (this._recentFolders.length > MAX_FOLDER_ITEM_IN_MENU_LIST) {
|
||||
var folderId = this._recentFolders.pop().folderId;
|
||||
txns.push(PlacesUIUtils.ptm.setItemAnnotation(folderId, anno));
|
||||
let annoTxn = new PlacesSetItemAnnotationTransaction(folderId, anno);
|
||||
txns.push(annoTxn);
|
||||
}
|
||||
|
||||
// Mark folder as recently used
|
||||
anno = this._getLastUsedAnnotationObject(true);
|
||||
txns.push(PlacesUIUtils.ptm.setItemAnnotation(aFolderId, anno));
|
||||
let annoTxn = new PlacesSetItemAnnotationTransaction(aFolderId, anno);
|
||||
txns.push(annoTxn);
|
||||
|
||||
var aggregate = PlacesUIUtils.ptm.aggregateTransactions("Update last used folders", txns);
|
||||
PlacesUIUtils.ptm.doTransaction(aggregate);
|
||||
let aggregate = new PlacesAggregatedTransaction("Update last used folders", txns);
|
||||
PlacesUtils.transactionManager.doTransaction(aggregate);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -840,8 +858,8 @@ var gEditItemOverlay = {
|
||||
|
||||
// XXXmano: add a separate "New Folder" string at some point...
|
||||
var defaultLabel = this._element("newFolderButton").label;
|
||||
var txn = PlacesUIUtils.ptm.createFolder(defaultLabel, ip.itemId, ip.index);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesCreateFolderTransaction(defaultLabel, ip.itemId, ip.index);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
this._folderTree.focus();
|
||||
this._folderTree.selectItems([this._lastNewItem]);
|
||||
this._folderTree.startEditing(this._folderTree.view.selection.currentIndex,
|
||||
|
@ -67,13 +67,15 @@ var gMoveBookmarksDialog = {
|
||||
if (this._nodes[i].parent.itemId == selectedFolderID)
|
||||
continue;
|
||||
|
||||
transactions.push(new
|
||||
PlacesUIUtils.ptm.moveItem(this._nodes[i].itemId, selectedFolderID, -1));
|
||||
let txn = new PlacesMoveItemTransaction(this._nodes[i].itemId,
|
||||
selectedFolderID,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
transactions.push(txn);
|
||||
}
|
||||
|
||||
if (transactions.length != 0) {
|
||||
var txn = PlacesUIUtils.ptm.aggregateTransactions("Move Items", transactions);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
let txn = new PlacesAggregatedTransaction("Move Items", transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -828,11 +828,11 @@ var PlacesOrganizer = {
|
||||
return;
|
||||
|
||||
// Add the place: uri as a bookmark under the bookmarks root.
|
||||
var txn = PlacesUIUtils.ptm.createItem(placeURI,
|
||||
PlacesUtils.bookmarksMenuFolderId,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
input.value);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
var txn = new PlacesCreateBookmarkTransaction(placeURI,
|
||||
PlacesUtils.bookmarksMenuFolderId,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
input.value);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
|
||||
// select and load the new query
|
||||
this._places.selectPlaceURI(placeSpec);
|
||||
|
@ -1660,8 +1660,8 @@ PlacesTreeView.prototype = {
|
||||
// We may only get here if the cell is editable.
|
||||
let node = this._rows[aRow];
|
||||
if (node.title != aText) {
|
||||
let txn = PlacesUIUtils.ptm.editItemTitle(node.itemId, aText);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
let txn = new PlacesEditItemTitleTransaction(node.itemId, aText);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -86,7 +86,7 @@ function test() {
|
||||
-1,
|
||||
true);
|
||||
ok(transaction, "create transaction");
|
||||
PlacesUIUtils.ptm.doTransaction(transaction);
|
||||
PlacesUtils.transactionManager.doTransaction(transaction);
|
||||
// confirm copy
|
||||
is(testRootNode.childCount, 2, "create test folder via copy");
|
||||
|
||||
@ -95,11 +95,11 @@ function test() {
|
||||
validate(folderBNode);
|
||||
|
||||
// undo the transaction, confirm the removal
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
is(testRootNode.childCount, 1, "confirm undo removed the copied folder");
|
||||
|
||||
// redo the transaction
|
||||
PlacesUIUtils.ptm.redoTransaction();
|
||||
PlacesUtils.transactionManager.redoTransaction();
|
||||
is(testRootNode.childCount, 2, "confirm redo re-copied the folder");
|
||||
folderBNode = testRootNode.getChild(1);
|
||||
validate(folderBNode);
|
||||
@ -109,7 +109,7 @@ function test() {
|
||||
toolbarNode.containerOpen = false;
|
||||
|
||||
// clean up
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
PlacesUtils.bookmarks.removeItem(folderAId);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ function test() {
|
||||
ok(transaction, "create transaction");
|
||||
|
||||
// execute it, copying to the test root folder
|
||||
PlacesUIUtils.ptm.doTransaction(transaction);
|
||||
PlacesUtils.transactionManager.doTransaction(transaction);
|
||||
is(testRootNode.childCount, 2, "create test folder via copy");
|
||||
|
||||
// check GUIDs are different
|
||||
@ -95,12 +95,12 @@ function test() {
|
||||
ok(checkGUIDs(folderBNode, folderBGUIDs, true), "confirm test of new GUIDs");
|
||||
|
||||
// undo the transaction, confirm the removal
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
is(testRootNode.childCount, 1, "confirm undo removed the copied folder");
|
||||
|
||||
// redo the transaction
|
||||
// confirming GUIDs persist through undo/redo
|
||||
PlacesUIUtils.ptm.redoTransaction();
|
||||
PlacesUtils.transactionManager.redoTransaction();
|
||||
is(testRootNode.childCount, 2, "confirm redo re-copied the folder");
|
||||
folderBNode = testRootNode.getChild(1);
|
||||
ok(checkGUIDs(folderBNode, folderAGUIDs, false), "folder B GUIDs after undo/redo don't match folder A GUIDs"); // sanity check
|
||||
@ -111,7 +111,7 @@ function test() {
|
||||
toolbarNode.containerOpen = false;
|
||||
|
||||
// clean up
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
PlacesUtils.transactionManager.undoTransaction();
|
||||
PlacesUtils.bookmarks.removeItem(testRootId);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,4 @@ tail =
|
||||
[test_browserGlue_smartBookmarks.js]
|
||||
[test_clearHistory_shutdown.js]
|
||||
[test_leftpane_corruption_handling.js]
|
||||
[test_placesTxn.js]
|
||||
[test_PUIU_makeTransaction.js]
|
||||
[test_txnGUIDs.js]
|
||||
|
@ -157,7 +157,7 @@ let gSyncPane = {
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/syncSetup.xul",
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
}
|
||||
@ -168,7 +168,7 @@ let gSyncPane = {
|
||||
if (win)
|
||||
win.focus();
|
||||
else
|
||||
window.openDialog("chrome://browser/content/syncQuota.xul", "",
|
||||
window.openDialog("chrome://browser/content/sync/quota.xul", "",
|
||||
"centerscreen,chrome,dialog,modal");
|
||||
},
|
||||
|
||||
@ -180,7 +180,7 @@ let gSyncPane = {
|
||||
if (win)
|
||||
win.focus();
|
||||
else
|
||||
window.openDialog("chrome://browser/content/syncAddDevice.xul",
|
||||
window.openDialog("chrome://browser/content/sync/addDevice.xul",
|
||||
"syncAddDevice", "centerscreen,chrome,resizable=no");
|
||||
},
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/preferences/sync.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncUtils.js"/>
|
||||
src="chrome://browser/content/sync/utils.js"/>
|
||||
|
||||
|
||||
<deck id="weavePrefsDeck">
|
||||
|
@ -42,8 +42,8 @@ MOZ_UPDATER=1
|
||||
MOZ_PHOENIX=1
|
||||
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
MOZ_VERIFY_MAR_SIGNATURE=1
|
||||
if ! test "$HAVE_64BIT_OS"; then
|
||||
MOZ_VERIFY_MAR_SIGNATURE=1
|
||||
MOZ_MAINTENANCE_SERVICE=1
|
||||
fi
|
||||
fi
|
||||
@ -54,8 +54,13 @@ MOZ_SERVICES_SYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
|
||||
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
|
||||
# Changing either of these values requires a clobber to ensure correct results,
|
||||
# Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results,
|
||||
# because branding dependencies are broken.
|
||||
# MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
|
||||
# specified. It should never point to the "official" branding directory.
|
||||
# For mozilla-beta, mozilla-release, or mozilla-central repositories, use
|
||||
# "nightly" branding (until bug 659568 is fixed).
|
||||
# For the mozilla-aurora repository, use "aurora".
|
||||
MOZ_BRANDING_DIRECTORY=browser/branding/nightly
|
||||
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
|
||||
MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
|
@ -155,6 +155,7 @@
|
||||
@BINPATH@/components/dom_bluetooth.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_canvas.xpt
|
||||
@BINPATH@/components/dom_contacts.xpt
|
||||
@BINPATH@/components/dom_core.xpt
|
||||
@BINPATH@/components/dom_css.xpt
|
||||
@BINPATH@/components/dom_events.xpt
|
||||
@ -409,6 +410,9 @@
|
||||
@BINPATH@/components/messageWakeupService.js
|
||||
@BINPATH@/components/messageWakeupService.manifest
|
||||
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
|
||||
|
@ -333,3 +333,7 @@ telemetryYesButtonLabel2 = Yes, I want to help
|
||||
telemetryYesButtonAccessKey = Y
|
||||
telemetryNoButtonLabel = No
|
||||
telemetryNoButtonAccessKey = N
|
||||
# Telemetry opt-out prompt for Aurora and Nightly
|
||||
# LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
|
||||
# brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
|
||||
telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* The following are used by both syncSetup.xul and syncGenericChange.xul */
|
||||
/* The following are used by both sync/setup.xul and sync/genericChange.xul */
|
||||
.status {
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-info?size=menu");
|
||||
}
|
||||
|
||||
/* .data is only used by syncGenericChange.xul, but it seems unnecessary to have
|
||||
/* .data is only used by sync/genericChange.xul, but it seems unnecessary to have
|
||||
a separate stylesheet for it. */
|
||||
.data {
|
||||
font-size: 90%;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* The following are used by both syncSetup.xul and syncGenericChange.xul */
|
||||
/* The following are used by both sync/setup.xul and sync/genericChange.xul */
|
||||
.status {
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
list-style-image: url("chrome://global/skin/icons/information-16.png");
|
||||
}
|
||||
|
||||
/* .data is only used by syncGenericChange.xul, but it seems unnecessary to have
|
||||
/* .data is only used by sync/genericChange.xul, but it seems unnecessary to have
|
||||
a separate stylesheet for it. */
|
||||
.data {
|
||||
font-size: 90%;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* The following are used by both syncSetup.xul and syncGenericChange.xul */
|
||||
/* The following are used by both sync/setup.xul and sync/genericChange.xul */
|
||||
.status {
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
list-style-image: url("chrome://global/skin/icons/information-16.png");
|
||||
}
|
||||
|
||||
/* .data is only used by syncGenericChange.xul, but it seems unnecessary to have
|
||||
/* .data is only used by sync/genericChange.xul, but it seems unnecessary to have
|
||||
a separate stylesheet for it. */
|
||||
.data {
|
||||
font-size: 90%;
|
||||
|
@ -1,89 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is remote test framework.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import devicemanager
|
||||
import devicemanagerUtils
|
||||
import sys
|
||||
import os
|
||||
|
||||
def main():
|
||||
ip_addr = os.environ.get("DEVICE_IP")
|
||||
port = os.environ.get("DEVICE_PORT")
|
||||
gre_path = os.environ.get("REMOTE_GRE_PATH").replace('\\','/')
|
||||
|
||||
if ip_addr == None:
|
||||
print "Error: please define the environment variable DEVICE_IP before running this test"
|
||||
sys.exit(1)
|
||||
|
||||
if port == None:
|
||||
print "Error: please define the environment variable DEVICE_PORT before running this test"
|
||||
sys.exit(1)
|
||||
|
||||
if gre_path == None:
|
||||
print "Error: please define the environment variable REMOTE_GRE_PATH before running this test"
|
||||
sys.exit(1)
|
||||
|
||||
dm = devicemanagerUtils.getDeviceManager(ip_addr, int(port))
|
||||
if len(sys.argv) < 2:
|
||||
print "usage python devicemanager-run-test.py <test program> [args1 [arg2..]]"
|
||||
sys.exit(1)
|
||||
|
||||
cmd = sys.argv[1]
|
||||
args = ' '
|
||||
if len(sys.argv) > 2:
|
||||
args = ' ' + ' '.join(sys.argv[2:])
|
||||
|
||||
dm.debug = 0
|
||||
lastslash = cmd.rfind('/');
|
||||
if lastslash == -1:
|
||||
lastslash = 0
|
||||
dm.pushFile(cmd, gre_path + cmd[lastslash:])
|
||||
process = dm.launchProcess([gre_path + cmd[lastslash:] + args])
|
||||
output_list = dm.communicate(process)
|
||||
ret = -1
|
||||
if (output_list != None and output_list[0] != None):
|
||||
try:
|
||||
output = output_list[0]
|
||||
index = output.find('exited with return code')
|
||||
print output[0:index]
|
||||
retstr = (output[index + 24 : output.find('\n', index)])
|
||||
ret = int(retstr)
|
||||
except ValueError:
|
||||
ret = -1
|
||||
sys.exit(ret)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -197,31 +197,6 @@ class DeviceManager:
|
||||
failure: None
|
||||
"""
|
||||
|
||||
def communicate(self, process, timeout = 600, interval = 5):
|
||||
"""
|
||||
loops until 'process' has exited or 'timeout' seconds is reached
|
||||
loop sleeps for 'interval' seconds between iterations
|
||||
external function
|
||||
returns:
|
||||
success: [file contents, None]
|
||||
failure: [None, None]
|
||||
"""
|
||||
|
||||
timed_out = True
|
||||
if (timeout > 0):
|
||||
total_time = 0
|
||||
while total_time < timeout:
|
||||
time.sleep(interval)
|
||||
if self.processExist(process) == None:
|
||||
timed_out = False
|
||||
break
|
||||
total_time += interval
|
||||
|
||||
if (timed_out == True):
|
||||
return [None, None]
|
||||
|
||||
return [self.getFile(process, "temp.txt"), None]
|
||||
|
||||
def processExist(self, appname):
|
||||
"""
|
||||
iterates process list and returns pid if exists, otherwise None
|
||||
@ -601,14 +576,14 @@ def _pop_last_line(file):
|
||||
bytes_from_end = 1
|
||||
file.seek(0, 2)
|
||||
length = file.tell() + 1
|
||||
while bytes_from_end <= length:
|
||||
while bytes_from_end < length:
|
||||
file.seek((-1)*bytes_from_end, 2)
|
||||
data = file.read()
|
||||
|
||||
if bytes_from_end == length and len(data) == 0: # no data, return None
|
||||
if bytes_from_end == length-1 and len(data) == 0: # no data, return None
|
||||
return None
|
||||
|
||||
if data[0] == '\n' or bytes_from_end == length:
|
||||
if data[0] == '\n' or bytes_from_end == length-1:
|
||||
# found the last line, which should have the return value
|
||||
if data[0] == '\n':
|
||||
data = data[1:]
|
||||
|
@ -25,11 +25,17 @@ class DeviceManagerADB(DeviceManager):
|
||||
packageName = 'org.mozilla.fennec_'
|
||||
self.Init(packageName)
|
||||
|
||||
def __del__(self):
|
||||
if self.host:
|
||||
self.disconnectRemoteADB()
|
||||
|
||||
def Init(self, packageName):
|
||||
# Initialization code that may fail: Catch exceptions here to allow
|
||||
# successful initialization even if, for example, adb is not installed.
|
||||
try:
|
||||
self.verifyADB()
|
||||
if self.host:
|
||||
self.connectRemoteADB()
|
||||
self.verifyRunAs(packageName)
|
||||
except:
|
||||
self.useRunAs = False
|
||||
@ -78,7 +84,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
# to get it
|
||||
# FIXME: this function buffers all output of the command into memory,
|
||||
# always. :(
|
||||
cmdline = subprocess.list2cmdline(cmd) + "; echo $?"
|
||||
cmdline = " ".join(cmd) + "; echo $?"
|
||||
|
||||
# prepend cwd and env to command if necessary
|
||||
if cwd:
|
||||
@ -104,6 +110,12 @@ class DeviceManagerADB(DeviceManager):
|
||||
|
||||
return None
|
||||
|
||||
def connectRemoteADB(self):
|
||||
self.checkCmd(["connect", self.host + ":" + str(self.port)])
|
||||
|
||||
def disconnectRemoteADB(self):
|
||||
self.checkCmd(["disconnect", self.host + ":" + str(self.port)])
|
||||
|
||||
# external function
|
||||
# returns:
|
||||
# success: True
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
from devicemanagerADB import DeviceManagerADB
|
||||
from devicemanagerSUT import DeviceManagerSUT
|
||||
import StringIO
|
||||
|
||||
class DroidMixin(object):
|
||||
"""Mixin to extend DeviceManager with Android-specific functionality"""
|
||||
@ -59,7 +60,7 @@ class DroidMixin(object):
|
||||
acmd = [ "am", "start", "-a", intent, "-W", "-n", "%s/.%s" % (app, activity)]
|
||||
|
||||
if extra_args:
|
||||
acmd.extend(["--es", "args", " ".join(args)])
|
||||
acmd.extend(["--es", "args", " ".join(extra_args)])
|
||||
|
||||
if env:
|
||||
envCnt = 0
|
||||
@ -69,7 +70,7 @@ class DroidMixin(object):
|
||||
envCnt += 1
|
||||
|
||||
if url:
|
||||
acmd.extend(["-d", ''.join(['"', url, '"'])])
|
||||
acmd.extend(["-d", ''.join(["'", url, "'"])])
|
||||
|
||||
# shell output not that interesting and debugging logs should already
|
||||
# show what's going on here... so just create an empty memory buffer
|
||||
|
@ -141,7 +141,7 @@ class RemoteAutomation(Automation):
|
||||
nettools = NetworkTools()
|
||||
return nettools.getLanIp()
|
||||
|
||||
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
||||
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = None):
|
||||
if stdout == None or stdout == -1 or stdout == subprocess.PIPE:
|
||||
stdout = self._remoteLog
|
||||
|
||||
@ -151,7 +151,7 @@ class RemoteAutomation(Automation):
|
||||
class RProcess(object):
|
||||
# device manager process
|
||||
dm = None
|
||||
def __init__(self, dm, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
||||
def __init__(self, dm, cmd, stdout = None, stderr = None, env = None, cwd = None):
|
||||
self.dm = dm
|
||||
self.stdoutlen = 0
|
||||
self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
|
||||
|
@ -67,6 +67,7 @@ import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
import java.util.zip.Adler32;
|
||||
import java.util.zip.CheckedInputStream;
|
||||
@ -136,7 +137,7 @@ public class DoCommand {
|
||||
String ffxProvider = "org.mozilla.ffxcp";
|
||||
String fenProvider = "org.mozilla.fencp";
|
||||
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.06";
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.07";
|
||||
|
||||
public enum Command
|
||||
{
|
||||
@ -2449,6 +2450,48 @@ private void CancelNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// To kill processes other than Java applications - processes
|
||||
// like xpcshell - a different strategy is necessary: use ps
|
||||
// to find the process' PID.
|
||||
try
|
||||
{
|
||||
pProc = Runtime.getRuntime().exec("ps");
|
||||
RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
|
||||
outThrd.start();
|
||||
outThrd.join(10000);
|
||||
sTmp = outThrd.strOutput;
|
||||
StringTokenizer stokLines = new StringTokenizer(sTmp, "\n");
|
||||
while(stokLines.hasMoreTokens())
|
||||
{
|
||||
String sLine = stokLines.nextToken();
|
||||
StringTokenizer stokColumns = new StringTokenizer(sLine, " \t\n");
|
||||
stokColumns.nextToken();
|
||||
String sPid = stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
stokColumns.nextToken();
|
||||
String sName = null;
|
||||
if (stokColumns.hasMoreTokens())
|
||||
{
|
||||
sName = stokColumns.nextToken();
|
||||
if (sName.contains(sProcName))
|
||||
{
|
||||
NewKillProc(sPid, out);
|
||||
sRet = "Successfully killed " + sPid + " " + sName + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return (sRet);
|
||||
}
|
||||
@ -2872,15 +2915,10 @@ private void CancelNotification()
|
||||
public String NewKillProc(String sProcId, OutputStream out)
|
||||
{
|
||||
String sRet = "";
|
||||
String [] theArgs = new String [3];
|
||||
|
||||
theArgs[0] = "su";
|
||||
theArgs[1] = "-c";
|
||||
theArgs[2] = "kill " + sProcId;
|
||||
|
||||
try
|
||||
{
|
||||
pProc = Runtime.getRuntime().exec(theArgs);
|
||||
pProc = Runtime.getRuntime().exec("kill "+sProcId);
|
||||
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
|
||||
outThrd.start();
|
||||
outThrd.join(5000);
|
||||
|
@ -250,6 +250,8 @@ if not os.path.exists(source_dir):
|
||||
patch('plugin_finish_decl.diff', 0, gcc_source_dir)
|
||||
patch('pr49911.diff', 1, gcc_source_dir)
|
||||
patch('r159628-r163231-r171807.patch', 1, gcc_source_dir)
|
||||
patch('gcc-fixinc.patch', 1, gcc_source_dir)
|
||||
patch('gcc-include.patch', 1, gcc_source_dir)
|
||||
|
||||
if os.path.exists(build_dir):
|
||||
shutil.rmtree(build_dir)
|
||||
|
12
build/unix/build-toolchain/gcc-fixinc.patch
Normal file
12
build/unix/build-toolchain/gcc-fixinc.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff -ru a/fixincludes/Makefile.in b/fixincludes/Makefile.in
|
||||
--- a/fixincludes/Makefile.in 2009-07-30 18:33:49.000000000 -0400
|
||||
+++ b/fixincludes/Makefile.in 2012-02-27 14:59:09.371875951 -0500
|
||||
@@ -126,7 +126,7 @@
|
||||
fixlib.o : fixlib.c
|
||||
|
||||
fixinc.sh : fixinc.in mkfixinc.sh Makefile
|
||||
- srcdir="$(srcdir)" $(SHELL) $(srcdir)/mkfixinc.sh $(target)
|
||||
+ echo "#!/bin/sh" > $@
|
||||
|
||||
$(srcdir)/fixincl.x: @MAINT@ fixincl.tpl inclhack.def
|
||||
cd $(srcdir) ; $(SHELL) ./genfixes
|
24
build/unix/build-toolchain/gcc-include.patch
Normal file
24
build/unix/build-toolchain/gcc-include.patch
Normal file
@ -0,0 +1,24 @@
|
||||
diff -ru a/configure b/configure
|
||||
--- a/configure 2010-10-06 06:29:55.000000000 -0400
|
||||
+++ b/configure 2012-02-27 20:46:26.303460301 -0500
|
||||
@@ -8047,7 +8047,7 @@
|
||||
# being built; programs in there won't even run.
|
||||
if test "${build}" = "${host}" && test -d ${srcdir}/gcc; then
|
||||
# Search for pre-installed headers if nothing else fits.
|
||||
- FLAGS_FOR_TARGET=$FLAGS_FOR_TARGET' -B$(build_tooldir)/bin/ -B$(build_tooldir)/lib/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include'
|
||||
+ FLAGS_FOR_TARGET=$FLAGS_FOR_TARGET' -B$(exec_prefix)/bin/ -B$(exec_prefix)/lib/ -isystem $(exec_prefix)/include -isystem $(exec_prefix)/sys-include'
|
||||
fi
|
||||
|
||||
if test "x${use_gnu_ld}" = x &&
|
||||
diff -ru a/configure.ac b/configure.ac
|
||||
--- a/configure.ac 2010-10-06 06:29:55.000000000 -0400
|
||||
+++ b/configure.ac 2012-02-27 20:46:22.587442745 -0500
|
||||
@@ -3100,7 +3100,7 @@
|
||||
# being built; programs in there won't even run.
|
||||
if test "${build}" = "${host}" && test -d ${srcdir}/gcc; then
|
||||
# Search for pre-installed headers if nothing else fits.
|
||||
- FLAGS_FOR_TARGET=$FLAGS_FOR_TARGET' -B$(build_tooldir)/bin/ -B$(build_tooldir)/lib/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include'
|
||||
+ FLAGS_FOR_TARGET=$FLAGS_FOR_TARGET' -B$(exec_prefix)/bin/ -B$(exec_prefix)/lib/ -isystem $(exec_prefix)/include -isystem $(exec_prefix)/sys-include'
|
||||
fi
|
||||
|
||||
if test "x${use_gnu_ld}" = x &&
|
@ -73,7 +73,7 @@ nsSecurityNameSet::~nsSecurityNameSet()
|
||||
NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
|
||||
|
||||
static JSString *
|
||||
getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv)
|
||||
getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, unsigned argc, jsval *argv)
|
||||
{
|
||||
if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
|
||||
JS_ReportError(cx, "String argument expected");
|
||||
@ -88,7 +88,7 @@ getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsv
|
||||
}
|
||||
|
||||
static bool
|
||||
getBytesArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv,
|
||||
getBytesArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, unsigned argc, jsval *argv,
|
||||
JSAutoByteString *bytes)
|
||||
{
|
||||
JSString *str = getStringArgument(cx, obj, argNum, argc, argv);
|
||||
@ -97,7 +97,7 @@ getBytesArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsva
|
||||
|
||||
static void
|
||||
getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum,
|
||||
uintN argc, jsval *argv, nsCString& aRetval)
|
||||
unsigned argc, jsval *argv, nsCString& aRetval)
|
||||
{
|
||||
aRetval.Truncate();
|
||||
|
||||
@ -122,7 +122,7 @@ getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum,
|
||||
}
|
||||
|
||||
static JSBool
|
||||
netscape_security_isPrivilegeEnabled(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_isPrivilegeEnabled(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -153,7 +153,7 @@ netscape_security_isPrivilegeEnabled(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
||||
|
||||
static JSBool
|
||||
netscape_security_enablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_enablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -196,7 +196,7 @@ netscape_security_enablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
netscape_security_disablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_disablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -222,7 +222,7 @@ netscape_security_disablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
netscape_security_revertPrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_revertPrivilege(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -248,7 +248,7 @@ netscape_security_revertPrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
netscape_security_setCanEnablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_setCanEnablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -280,7 +280,7 @@ netscape_security_setCanEnablePrivilege(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
netscape_security_invalidate(JSContext *cx, uintN argc, jsval *vp)
|
||||
netscape_security_invalidate(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
|
@ -42,6 +42,7 @@ interface nsIObjectFrame;
|
||||
interface nsIPluginTag;
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMClientRect;
|
||||
interface nsIURI;
|
||||
|
||||
%{C++
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
@ -51,7 +52,7 @@ interface nsIDOMClientRect;
|
||||
/**
|
||||
* This interface represents a content node that loads objects.
|
||||
*/
|
||||
[scriptable, uuid(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
|
||||
[scriptable, uuid(3FF07AB3-5BAC-4D98-9549-5BD15CCEBCD3)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
const unsigned long TYPE_LOADING = 0;
|
||||
@ -79,6 +80,14 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
|
||||
|
||||
/**
|
||||
* Gets the base URI to be used for this object. This differs from
|
||||
* nsIContent::GetBaseURI in that it takes codebase attributes into
|
||||
* account. The MIME type is required as some plugins (java) calculate
|
||||
* this differently.
|
||||
*/
|
||||
nsIURI GetObjectBaseURI(in ACString aMimeType);
|
||||
|
||||
/**
|
||||
* Returns the plugin instance if it has already been instantiated. This
|
||||
* will never instantiate the plugin and so is safe to call even when
|
||||
|
@ -408,9 +408,10 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
nsISelectionController* selcon = textControl->GetSelectionController();
|
||||
if (selcon) {
|
||||
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
if (!selection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!selection)
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
mWindow->GetSelection(getter_AddRefs(selection));
|
||||
@ -449,11 +450,14 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
return NS_OK;
|
||||
|
||||
if (isChromeShell && textControl) {
|
||||
// Only use the selection if it isn't collapsed.
|
||||
bool isCollapsed = false;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
if (!isCollapsed)
|
||||
selection.swap(*aSelection);
|
||||
// Only use the selection if the target node is in the selection.
|
||||
bool selectionContainsTarget = false;
|
||||
nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(mSelectionTargetNode);
|
||||
selection->ContainsNode(targetNode, false, &selectionContainsTarget);
|
||||
if (!selectionContainsTarget)
|
||||
return NS_OK;
|
||||
|
||||
selection.swap(*aSelection);
|
||||
}
|
||||
else {
|
||||
// In content shells, a number of checks are made below to determine
|
||||
|
@ -176,7 +176,7 @@ nsWrapperCache::RemoveExpandoObject()
|
||||
if (expando) {
|
||||
JSCompartment *compartment = js::GetObjectCompartment(expando);
|
||||
xpc::CompartmentPrivate *priv =
|
||||
static_cast<xpc::CompartmentPrivate *>(js_GetCompartmentPrivate(compartment));
|
||||
static_cast<xpc::CompartmentPrivate *>(JS_GetCompartmentPrivate(compartment));
|
||||
priv->RemoveDOMExpandoObject(expando);
|
||||
}
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI*
|
||||
if (!aURI) {
|
||||
// We need some URI. If we have nothing else, use the base URI.
|
||||
// XXX(biesi): The code used to do this. Not sure why this is correct...
|
||||
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
||||
GetObjectBaseURI(nsCString(aMimeType), getter_AddRefs(baseURI));
|
||||
aURI = baseURI;
|
||||
}
|
||||
|
||||
@ -1163,7 +1163,7 @@ nsObjectLoadingContent::LoadObject(const nsAString& aURI,
|
||||
|
||||
nsIDocument* doc = thisContent->OwnerDoc();
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
||||
GetObjectBaseURI(aTypeHint, getter_AddRefs(baseURI));
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
||||
@ -1194,6 +1194,51 @@ nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsObjectLoadingContent::IsFileCodebaseAllowable(nsIURI* aBaseURI, nsIURI* aOriginURI)
|
||||
{
|
||||
nsCOMPtr<nsIFileURL> baseFileURL(do_QueryInterface(aBaseURI));
|
||||
nsCOMPtr<nsIFileURL> originFileURL(do_QueryInterface(aOriginURI));
|
||||
|
||||
// get IFile handles and normalize
|
||||
nsCOMPtr<nsIFile> originFile;
|
||||
nsCOMPtr<nsIFile> baseFile;
|
||||
if (!originFileURL || !baseFileURL ||
|
||||
NS_FAILED(originFileURL->GetFile(getter_AddRefs(originFile))) ||
|
||||
NS_FAILED(baseFileURL->GetFile(getter_AddRefs(baseFile))) ||
|
||||
NS_FAILED(baseFile->Normalize()) ||
|
||||
NS_FAILED(originFile->Normalize())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the origin is a directory, it should contain/equal baseURI
|
||||
// Otherwise, its parent directory should contain/equal baseURI
|
||||
bool origin_is_dir;
|
||||
bool contained = false;
|
||||
nsresult rv = originFile->IsDirectory(&origin_is_dir);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (origin_is_dir) {
|
||||
// originURI is a directory, ensure it contains the baseURI
|
||||
rv = originFile->Contains(baseFile, true, &contained);
|
||||
if (NS_SUCCEEDED(rv) && !contained) {
|
||||
rv = originFile->Equals(baseFile, &contained);
|
||||
}
|
||||
} else {
|
||||
// originURI is a file, ensure its parent contains the baseURI
|
||||
nsCOMPtr<nsIFile> originParent;
|
||||
rv = originFile->GetParent(getter_AddRefs(originParent));
|
||||
if (NS_SUCCEEDED(rv) && originParent) {
|
||||
rv = originParent->Contains(baseFile, true, &contained);
|
||||
if (NS_SUCCEEDED(rv) && !contained) {
|
||||
rv = originParent->Equals(baseFile, &contained);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv) && contained;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||
bool aNotify,
|
||||
@ -1291,6 +1336,28 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||
HandleBeingBlockedByContentPolicy(rv, shouldLoad);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If this is a file:// URI, require that the codebase (baseURI)
|
||||
// is contained within the same folder as the document origin (originURI)
|
||||
// or within the document origin, if it is a folder.
|
||||
// No originURI implies chrome, which bypasses the check
|
||||
// -- bug 406541
|
||||
nsCOMPtr<nsIURI> originURI;
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
GetObjectBaseURI(aTypeHint, getter_AddRefs(baseURI));
|
||||
rv = thisContent->NodePrincipal()->GetURI(getter_AddRefs(originURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
Fallback(aNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
if (originURI) {
|
||||
bool isfile;
|
||||
if (NS_FAILED(originURI->SchemeIs("file", &isfile)) ||
|
||||
(isfile && !IsFileCodebaseAllowable(baseURI, originURI))) {
|
||||
Fallback(aNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
@ -1408,7 +1475,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
||||
// XXX(biesi). The plugin instantiation code used to pass the base URI
|
||||
// here instead of the plugin URI for instantiation via class ID, so I
|
||||
// continue to do so. Why that is, no idea...
|
||||
GetObjectBaseURI(thisContent, getter_AddRefs(mURI));
|
||||
GetObjectBaseURI(mContentType, getter_AddRefs(mURI));
|
||||
if (!mURI) {
|
||||
mURI = aURI;
|
||||
}
|
||||
@ -1785,25 +1852,29 @@ nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI)
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetObjectBaseURI(const nsACString & aMimeType, nsIURI** aURI)
|
||||
{
|
||||
// We want to use swap(); since this is just called from this file,
|
||||
// we can assert this (callers use comptrs)
|
||||
NS_PRECONDITION(*aURI == nsnull, "URI must be inited to zero");
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
// For plugins, the codebase attribute is the base URI
|
||||
nsCOMPtr<nsIURI> baseURI = thisContent->GetBaseURI();
|
||||
nsAutoString codebase;
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase,
|
||||
codebase);
|
||||
if (!codebase.IsEmpty()) {
|
||||
nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
|
||||
thisContent->OwnerDoc(),
|
||||
baseURI);
|
||||
} else {
|
||||
baseURI.swap(*aURI);
|
||||
|
||||
if (codebase.IsEmpty() && aMimeType.Equals("application/x-java-vm")) {
|
||||
// bug 406541
|
||||
// Java resolves codebase="" as "/" -- so we replicate that quirk, to ensure
|
||||
// we run security checks against the same path.
|
||||
codebase.AssignLiteral("/");
|
||||
}
|
||||
|
||||
nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
|
||||
thisContent->OwnerDoc(),
|
||||
baseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsObjectFrame*
|
||||
|
@ -253,6 +253,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
*/
|
||||
static bool IsSuccessfulRequest(nsIRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Check if the given baseURI is contained in the same directory as the
|
||||
* aOriginURI (or a child thereof)
|
||||
*/
|
||||
static bool IsFileCodebaseAllowable(nsIURI* aBaseURI, nsIURI* aOriginURI);
|
||||
|
||||
/**
|
||||
* Check whether the URI can be handled internally.
|
||||
*/
|
||||
@ -299,14 +305,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
*/
|
||||
nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
|
||||
|
||||
/**
|
||||
* Gets the base URI to be used for this object. This differs from
|
||||
* nsIContent::GetBaseURI in that it takes codebase attributes into
|
||||
* account.
|
||||
*/
|
||||
void GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the frame that's associated with this content node.
|
||||
* Does not flush.
|
||||
|
@ -246,7 +246,7 @@ GetImageDataDimensions(JSContext *cx, JSObject *dataObject, uint32_t *width, uin
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
|
||||
@ -292,7 +292,7 @@ nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, uintN argc, jsval
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMCanvasRenderingContext2D_GetImageData(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMCanvasRenderingContext2D_GetImageData(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
|
||||
@ -349,7 +349,7 @@ nsIDOMCanvasRenderingContext2D_GetImageData(JSContext *cx, uintN argc, jsval *vp
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
|
||||
|
@ -83,7 +83,7 @@ helper_isFloat32Array(JSObject *obj) {
|
||||
* BufferData_array (int, js::TypedArray *, int)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_BufferData(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_BufferData(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -156,7 +156,7 @@ nsIDOMWebGLRenderingContext_BufferData(JSContext *cx, uintN argc, jsval *vp)
|
||||
* BufferSubData_array (int, int, js::TypedArray *)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_BufferSubData(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -228,7 +228,7 @@ nsIDOMWebGLRenderingContext_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
|
||||
* CompressedTexImage2D(uint, int, uint, int, int, int, ArrayBufferView)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_CompressedTexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_CompressedTexImage2D(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -278,7 +278,7 @@ nsIDOMWebGLRenderingContext_CompressedTexImage2D(JSContext *cx, uintN argc, jsva
|
||||
* CompressedTexSubImage2D(uint, int, int, int, int, int, uint, ArrayBufferView)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_CompressedTexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_CompressedTexSubImage2D(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -329,7 +329,7 @@ nsIDOMWebGLRenderingContext_CompressedTexSubImage2D(JSContext *cx, uintN argc, j
|
||||
* ReadPixels(int, int, int, int, uint, uint, ArrayBufferView)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -389,7 +389,7 @@ nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
* TexImage2D(uint, int, uint, uint, uint, ImageData)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -510,7 +510,7 @@ nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
* TexSubImage2D(uint, int, int, int, uint, uint, ImageData)
|
||||
*/
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -621,7 +621,7 @@ nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
||||
/* NOTE: There is a TN version of this below, update it as well */
|
||||
static inline JSBool
|
||||
helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements)
|
||||
helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(JSContext *cx, unsigned argc, jsval *vp, int nElements)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -695,7 +695,7 @@ helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(JSContext *cx, uintN argc, jsval
|
||||
|
||||
/* NOTE: There is a TN version of this below, update it as well */
|
||||
static inline JSBool
|
||||
helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
|
||||
helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(JSContext *cx, unsigned argc, jsval *vp, int nElements)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -769,7 +769,7 @@ helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(JSContext *cx, uintN argc, jsval
|
||||
|
||||
/* NOTE: There is a TN version of this below, update it as well */
|
||||
static inline JSBool
|
||||
helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
|
||||
helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, unsigned argc, jsval *vp, int nElements)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -842,7 +842,7 @@ helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc,
|
||||
}
|
||||
|
||||
static inline JSBool
|
||||
helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
|
||||
helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, unsigned argc, jsval *vp, int nElements)
|
||||
{
|
||||
XPC_QS_ASSERT_CONTEXT_OK(cx);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
@ -910,91 +910,91 @@ helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc,
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform1iv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform1iv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 1);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform2iv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform2iv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 2);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform3iv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform3iv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 3);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform4iv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform4iv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 4);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform1fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform1fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 1);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform2fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform2fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 2);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform3fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform3fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 3);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_Uniform4fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_Uniform4fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 4);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix2fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix2fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 2);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix3fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix3fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 3);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix4fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_UniformMatrix4fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 4);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib1fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib1fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 1);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib2fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib2fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 2);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib3fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib3fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 3);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsIDOMWebGLRenderingContext_VertexAttrib4fv(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 4);
|
||||
}
|
||||
|
@ -64,6 +64,34 @@ function start() {
|
||||
.getService(Components.interfaces.nsIPropertyBag2)
|
||||
.getProperty("version");
|
||||
kIsWindowsVistaOrHigher = (parseFloat(version) >= 6.0);
|
||||
// Workaround for Windows 2000 (driver?) which may crash itself.
|
||||
if (parseFloat(version) <= 5.0) {
|
||||
todo(false, "Test disabled on Windows 2000 and older. (To prevent possible system crash.)");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we currently disable this test on version of Mac OSX older than 10.6,
|
||||
// due to various weird failures, including one making getRenderbufferParameter tests
|
||||
// on DEPTH_STENCIL fail
|
||||
var kDarwinVersion = 0;
|
||||
if (kIsMac) {
|
||||
// code borrowed from browser/modules/test/browser_taskbar_preview.js
|
||||
var is106orHigher = false;
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
kDarwinVersion = parseFloat(Components.classes["@mozilla.org/system-info;1"]
|
||||
.getService(Components.interfaces.nsIPropertyBag2)
|
||||
.getProperty("version"));
|
||||
// the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
|
||||
// Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
|
||||
// is the Darwin version.
|
||||
is106orHigher = (kDarwinVersion >= 10.0);
|
||||
if (!is106orHigher) {
|
||||
dump("WebGL mochitest disabled on Mac OSX versions older than 10.6\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we currently disable this test on version of Mac OSX older than 10.6,
|
||||
@ -404,6 +432,7 @@ function start() {
|
||||
todo(false, errmsg + " (This is expected on SeaMonkey (tinderboxes).)");
|
||||
else
|
||||
ok(false, errmsg);
|
||||
dump("WebGL mochitest failed: " + errmsg + "\n");
|
||||
reporter.finishedTestSuite();
|
||||
}
|
||||
};
|
||||
|
@ -2160,7 +2160,7 @@ nsMediaCacheStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
|
||||
PRUint32 streamBlock = PRUint32(mStreamOffset/BLOCK_SIZE);
|
||||
PRUint32 offsetInStreamBlock =
|
||||
PRUint32(mStreamOffset - streamBlock*BLOCK_SIZE);
|
||||
PRInt32 size = NS_MIN(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
|
||||
PRInt64 size = NS_MIN(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
|
||||
|
||||
if (mStreamLength >= 0) {
|
||||
// Don't try to read beyond the end of the stream
|
||||
@ -2169,7 +2169,9 @@ nsMediaCacheStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
|
||||
// Get out of here and return NS_OK
|
||||
break;
|
||||
}
|
||||
size = NS_MIN(size, PRInt32(bytesRemaining));
|
||||
size = NS_MIN(size, bytesRemaining);
|
||||
// Clamp size until 64-bit file size issues (bug 500784) are fixed.
|
||||
size = NS_MIN(size, PRInt64(PR_INT32_MAX));
|
||||
}
|
||||
|
||||
PRInt32 bytes;
|
||||
@ -2224,7 +2226,8 @@ nsMediaCacheStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
|
||||
gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now());
|
||||
|
||||
PRInt64 offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
|
||||
nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, size, &bytes);
|
||||
NS_ASSERTION(size >= 0 && size <= PR_INT32_MAX, "Size out of range.");
|
||||
nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, PRInt32(size), &bytes);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (count == 0)
|
||||
return rv;
|
||||
|
@ -116,7 +116,7 @@ XBLFinalize(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XBLResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
XBLResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
// Note: if we get here, that means that the implementation for some binding
|
||||
|
@ -80,7 +80,7 @@ protected:
|
||||
PRUnichar* mFieldText;
|
||||
PRUint32 mFieldTextLength;
|
||||
PRUint32 mLineNumber;
|
||||
uintN mJSAttributes;
|
||||
unsigned mJSAttributes;
|
||||
};
|
||||
|
||||
#endif // nsXBLProtoImplField_h__
|
||||
|
@ -97,7 +97,7 @@ protected:
|
||||
JSObject * mJSSetterObject;
|
||||
};
|
||||
|
||||
uintN mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
|
||||
unsigned mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mIsCompiled;
|
||||
|
@ -47,6 +47,7 @@ MODULE = dom
|
||||
DIRS = \
|
||||
interfaces/base \
|
||||
interfaces/canvas \
|
||||
interfaces/contacts \
|
||||
interfaces/core \
|
||||
interfaces/html \
|
||||
interfaces/events \
|
||||
@ -77,6 +78,7 @@ endif
|
||||
DIRS += \
|
||||
base \
|
||||
battery \
|
||||
contacts \
|
||||
power \
|
||||
sms \
|
||||
src \
|
||||
|
@ -684,11 +684,6 @@ public:
|
||||
NS_IMETHOD PreCreate(nsISupports *aNativeObj, JSContext *aCx,
|
||||
JSObject *aGlobalObj, JSObject **aParentObj);
|
||||
|
||||
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *aWrapper, JSContext *aCx,
|
||||
JSObject *aObj, jsid aId, jsval *aVp, bool *aRetval);
|
||||
|
||||
virtual void PreserveWrapper(nsISupports *aNative);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData *aData)
|
||||
{
|
||||
return new IDBEventTargetSH(aData);
|
||||
@ -5240,7 +5235,7 @@ GetDocument(JSObject *obj)
|
||||
// static
|
||||
JSBool
|
||||
nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING |
|
||||
@ -5546,7 +5541,7 @@ FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
|
||||
static nsresult
|
||||
BaseStubConstructor(nsIWeakReference* aWeakOwner,
|
||||
const nsGlobalNameStruct *name_struct, JSContext *cx,
|
||||
JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSObject *obj, unsigned argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupports> native;
|
||||
@ -6640,7 +6635,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
// Native code for window._content getter, this simply maps
|
||||
// window._content to window.content for backwards compatibility only.
|
||||
static JSBool
|
||||
ContentWindowGetter(JSContext *cx, uintN argc, jsval *vp)
|
||||
ContentWindowGetter(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
@ -7700,25 +7695,6 @@ IDBEventTargetSH::PreCreate(nsISupports *aNativeObj, JSContext *aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBEventTargetSH::AddProperty(nsIXPConnectWrappedNative *aWrapper,
|
||||
JSContext *aCx, JSObject *aObj, jsid aId,
|
||||
jsval *aVp, bool *aRetval)
|
||||
{
|
||||
if (aId != sAddEventListener_id) {
|
||||
IDBEventTargetSH::PreserveWrapper(GetNative(aWrapper, aObj));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
IDBEventTargetSH::PreserveWrapper(nsISupports *aNative)
|
||||
{
|
||||
IDBWrapperCache *target = IDBWrapperCache::FromSupports(aNative);
|
||||
nsContentUtils::PreserveWrapper(aNative, target);
|
||||
}
|
||||
|
||||
// Element helper
|
||||
|
||||
static bool
|
||||
@ -8901,7 +8877,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj,
|
||||
|
||||
JSBool
|
||||
nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
|
||||
uintN flags, JSObject **objp)
|
||||
unsigned flags, JSObject **objp)
|
||||
{
|
||||
if (flags & JSRESOLVE_ASSIGNING) {
|
||||
// Nothing to do here if we're assigning
|
||||
@ -8971,7 +8947,7 @@ nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
JSBool
|
||||
nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, uintN argc, jsval *vp)
|
||||
nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
// Handle document.all("foo") style access to document.all.
|
||||
|
||||
@ -9097,7 +9073,7 @@ nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
|
||||
|
||||
JSBool
|
||||
nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
if (id == nsDOMClassInfo::sAll_id) {
|
||||
@ -9120,7 +9096,7 @@ nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
|
||||
|
||||
JSBool
|
||||
nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
if (JSID_IS_STRING(id)) {
|
||||
|
@ -425,7 +425,7 @@ public:
|
||||
JSObject * obj, JSObject * *_retval);
|
||||
|
||||
static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp);
|
||||
static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id, jsval *vp);
|
||||
@ -863,16 +863,16 @@ public:
|
||||
static JSBool DocumentAllGetProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
jsval *vp);
|
||||
static JSBool DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
|
||||
uintN flags, JSObject **objp);
|
||||
unsigned flags, JSObject **objp);
|
||||
static void ReleaseDocument(JSContext *cx, JSObject *obj);
|
||||
static JSBool CallToGetPropMapper(JSContext *cx, uintN argc, jsval *vp);
|
||||
static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
|
||||
static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id, jsval *vp);
|
||||
static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp);
|
||||
static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
jsid id, unsigned flags,
|
||||
JSObject **objp);
|
||||
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
|
@ -1227,48 +1227,8 @@ nsGlobalWindow::ClearControllers()
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsGlobalWindow::TryClearWindowScope(nsISupports *aWindow)
|
||||
{
|
||||
nsGlobalWindow *window =
|
||||
static_cast<nsGlobalWindow *>(static_cast<nsIDOMWindow*>(aWindow));
|
||||
|
||||
// This termination function might be called when any script evaluation in our
|
||||
// context terminated, even if there are other scripts in the stack. Thus, we
|
||||
// have to check again if a script is executing and post a new termination
|
||||
// function if necessary.
|
||||
window->ClearScopeWhenAllScriptsStop();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ClearScopeWhenAllScriptsStop()
|
||||
{
|
||||
NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
|
||||
|
||||
// We cannot clear scope safely until all the scripts in our script context
|
||||
// stopped. This might be a long wait, for example if one script is busy
|
||||
// because it started a nested event loop for a modal dialog.
|
||||
nsIScriptContext *jsscx = GetContextInternal();
|
||||
if (jsscx && jsscx->GetExecutingScript()) {
|
||||
// We ignore the return value because the only reason that we clear scope
|
||||
// here is to try to prevent leaks. Failing to clear scope might mean that
|
||||
// we'll leak more but if we don't have enough memory to allocate a
|
||||
// termination function we probably don't have to worry about this anyway.
|
||||
jsscx->SetTerminationFunction(TryClearWindowScope,
|
||||
static_cast<nsIDOMWindow *>(this));
|
||||
return;
|
||||
}
|
||||
|
||||
NotifyWindowIDDestroyed("inner-window-destroyed");
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
if (scx) {
|
||||
scx->ClearScope(mJSObject, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::FreeInnerObjects(bool aClearScope)
|
||||
nsGlobalWindow::FreeInnerObjects()
|
||||
{
|
||||
NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
|
||||
|
||||
@ -1330,9 +1290,7 @@ nsGlobalWindow::FreeInnerObjects(bool aClearScope)
|
||||
|
||||
mIndexedDB = nsnull;
|
||||
|
||||
if (aClearScope) {
|
||||
ClearScopeWhenAllScriptsStop();
|
||||
}
|
||||
NotifyWindowIDDestroyed("inner-window-destroyed");
|
||||
|
||||
if (mDummyJavaPluginOwner) {
|
||||
// Tear down the dummy java plugin.
|
||||
@ -1666,7 +1624,6 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
|
||||
// Great, we're the original document, check for one of the other
|
||||
// conditions.
|
||||
if (mDoc == aNewDocument) {
|
||||
// aClearScopeHint is false.
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1840,10 +1797,8 @@ WindowStateHolder::~WindowStateHolder()
|
||||
// free it up.
|
||||
// Note that FreeInnerObjects may already have been called on the
|
||||
// inner window if its outer has already had SetDocShell(null)
|
||||
// called. In this case the contexts will all be null and the
|
||||
// true for aClearScope won't do anything; this is OK since
|
||||
// SetDocShell(null) already did it.
|
||||
mInnerWindow->FreeInnerObjects(true);
|
||||
// called.
|
||||
mInnerWindow->FreeInnerObjects();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2006,12 +1961,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
|
||||
NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
|
||||
|
||||
// Make sure to clear scope on the outer window *before* we
|
||||
// initialize the new inner window. If we don't, things
|
||||
// (Object.prototype etc) could leak from the old outer to the new
|
||||
// inner scope.
|
||||
mContext->ClearScope(mJSObject, false);
|
||||
|
||||
if (reUseInnerWindow) {
|
||||
// We're reusing the current inner window.
|
||||
NS_ASSERTION(!currentInner->IsFrozen(),
|
||||
@ -2081,8 +2030,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
}
|
||||
|
||||
if (currentInner && currentInner->mJSObject) {
|
||||
bool termFuncSet = false;
|
||||
|
||||
if (oldDoc == aDocument) {
|
||||
// Move the navigator from the old inner window to the new one since
|
||||
// this is a document.write. This is safe from a same-origin point of
|
||||
@ -2092,45 +2039,12 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
if (newInnerWindow->mNavigator) {
|
||||
newInnerWindow->mNavigator->SetWindow(newInnerWindow);
|
||||
}
|
||||
|
||||
// Suspend the current context's request before Pop() resumes the old
|
||||
// context's request.
|
||||
JSAutoSuspendRequest asr(cx);
|
||||
|
||||
// Pop our context here so that we get the correct one for the
|
||||
// termination function.
|
||||
cxPusher.Pop();
|
||||
|
||||
JSContext *oldCx = nsContentUtils::GetCurrentJSContext();
|
||||
|
||||
nsIScriptContext *callerScx;
|
||||
if (oldCx && (callerScx = GetScriptContextFromJSContext(oldCx))) {
|
||||
// We're called from document.open() (and document.open() is
|
||||
// called from JS), clear the scope etc in a termination
|
||||
// function on the calling context to prevent clearing the
|
||||
// calling scope.
|
||||
NS_ASSERTION(!currentInner->IsFrozen(),
|
||||
"How does this opened window get into session history");
|
||||
|
||||
JSAutoRequest ar(oldCx);
|
||||
|
||||
callerScx->SetTerminationFunction(ClearWindowScope,
|
||||
static_cast<nsIDOMWindow *>
|
||||
(currentInner));
|
||||
|
||||
termFuncSet = true;
|
||||
}
|
||||
|
||||
// Re-push our context.
|
||||
cxPusher.Push(cx);
|
||||
}
|
||||
|
||||
// Don't clear scope on our current inner window if it's going to be
|
||||
// Don't free objects on our current inner window if it's going to be
|
||||
// held in the bfcache.
|
||||
if (!currentInner->IsFrozen()) {
|
||||
// Skip the ClearScope if we set a termination function to do
|
||||
// it ourselves, later.
|
||||
currentInner->FreeInnerObjects(!termFuncSet);
|
||||
currentInner->FreeInnerObjects();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2177,7 +2091,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
|
||||
JSCompartment *compartment = js::GetObjectCompartment(mJSObject);
|
||||
xpc::CompartmentPrivate *priv =
|
||||
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, compartment));
|
||||
static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
|
||||
if (priv && priv->waiverWrapperMap) {
|
||||
NS_ASSERTION(!JS_IsExceptionPending(cx),
|
||||
"We might overwrite a pending exception!");
|
||||
@ -2433,7 +2347,7 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
|
||||
NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
|
||||
"bad outer window pointer");
|
||||
inner->FreeInnerObjects(true);
|
||||
inner->FreeInnerObjects();
|
||||
}
|
||||
|
||||
// Make sure that this is called before we null out the document.
|
||||
@ -2455,10 +2369,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
mFocusedNode = nsnull;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
mContext->ClearScope(mJSObject, true);
|
||||
}
|
||||
|
||||
ClearControllers();
|
||||
|
||||
mChromeEventHandler = nsnull; // force release now
|
||||
@ -8985,17 +8895,6 @@ nsGlobalWindow::CloseWindow(nsISupports *aWindow)
|
||||
// else if OOM, better not to close. That might cause a crash.
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsGlobalWindow::ClearWindowScope(nsISupports *aWindow)
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aWindow));
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
if (scx) {
|
||||
scx->ClearScope(sgo->GetGlobalJSObject(), true);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsGlobalWindow: Timeout Functions
|
||||
//*****************************************************************************
|
||||
|
@ -236,7 +236,7 @@ private:
|
||||
class nsOuterWindowProxy : public js::Wrapper
|
||||
{
|
||||
public:
|
||||
nsOuterWindowProxy() : js::Wrapper((uintN)0) {}
|
||||
nsOuterWindowProxy() : js::Wrapper((unsigned)0) {}
|
||||
|
||||
virtual bool isOuterWindow() {
|
||||
return true;
|
||||
@ -595,11 +595,9 @@ protected:
|
||||
virtual ~nsGlobalWindow();
|
||||
void CleanUp(bool aIgnoreModalDialog);
|
||||
void ClearControllers();
|
||||
static void TryClearWindowScope(nsISupports* aWindow);
|
||||
void ClearScopeWhenAllScriptsStop();
|
||||
nsresult FinalClose();
|
||||
|
||||
void FreeInnerObjects(bool aClearScope);
|
||||
void FreeInnerObjects();
|
||||
nsGlobalWindow *CallerInnerWindow();
|
||||
|
||||
nsresult InnerSetNewDocument(nsIDocument* aDocument);
|
||||
@ -677,7 +675,6 @@ protected:
|
||||
nsIDOMWindow **aReturn);
|
||||
|
||||
static void CloseWindow(nsISupports* aWindow);
|
||||
static void ClearWindowScope(nsISupports* aWindow);
|
||||
|
||||
// Timeout Functions
|
||||
// Language agnostic timeout function (all args passed).
|
||||
|
@ -75,8 +75,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
|
||||
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
|
||||
|
||||
#define NS_ISCRIPTCONTEXT_IID \
|
||||
{ 0xf3840057, 0x4fe5, 0x4f92, \
|
||||
{ 0xa3, 0xb8, 0x27, 0xd7, 0x44, 0x6f, 0x72, 0x4d } }
|
||||
{ 0x6d69fbee, 0x0723, 0x48f5, \
|
||||
{ 0x82, 0x48, 0xcd, 0xcf, 0x88, 0xac, 0x25, 0x74 } }
|
||||
|
||||
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
|
||||
know what language we have is a little silly... */
|
||||
@ -427,20 +427,6 @@ public:
|
||||
*/
|
||||
virtual nsresult InitClasses(JSObject* aGlobalObj) = 0;
|
||||
|
||||
/**
|
||||
* Clear the scope object - may be called either as we are being torn down,
|
||||
* or before we are attached to a different document.
|
||||
*
|
||||
* aClearFromProtoChain is probably somewhat JavaScript specific. It
|
||||
* indicates that the global scope polluter should be removed from the
|
||||
* prototype chain and that the objects in the prototype chain should
|
||||
* also have their scopes cleared. We don't do this all the time
|
||||
* because the prototype chain is shared between inner and outer
|
||||
* windows, and needs to stay with inner windows that we're keeping
|
||||
* around.
|
||||
*/
|
||||
virtual void ClearScope(void* aGlobalObj, bool aClearFromProtoChain) = 0;
|
||||
|
||||
/**
|
||||
* Tell the context we're about to be reinitialize it.
|
||||
*/
|
||||
|
@ -2722,7 +2722,7 @@ CheckUniversalXPConnectForTraceMalloc(JSContext *cx)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocDisable(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocDisable(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2733,7 +2733,7 @@ TraceMallocDisable(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocEnable(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocEnable(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2744,7 +2744,7 @@ TraceMallocEnable(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocOpenLogFile(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocOpenLogFile(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
int fd;
|
||||
JSString *str;
|
||||
@ -2772,7 +2772,7 @@ TraceMallocOpenLogFile(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocChangeLogFD(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocChangeLogFD(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2794,7 +2794,7 @@ TraceMallocChangeLogFD(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocCloseLogFD(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocCloseLogFD(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2810,7 +2810,7 @@ TraceMallocCloseLogFD(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocLogTimestamp(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocLogTimestamp(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2827,7 +2827,7 @@ TraceMallocLogTimestamp(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocDumpAllocations(JSContext *cx, uintN argc, jsval *vp)
|
||||
TraceMallocDumpAllocations(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return JS_FALSE;
|
||||
@ -2875,7 +2875,7 @@ void NS_JProfStopProfiling();
|
||||
void NS_JProfClearCircular();
|
||||
|
||||
static JSBool
|
||||
JProfStartProfilingJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
JProfStartProfilingJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
NS_JProfStartProfiling();
|
||||
return JS_TRUE;
|
||||
@ -2917,7 +2917,7 @@ void NS_JProfStartProfiling()
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JProfStopProfilingJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
JProfStopProfilingJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
NS_JProfStopProfiling();
|
||||
return JS_TRUE;
|
||||
@ -2931,7 +2931,7 @@ NS_JProfStopProfiling()
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JProfClearCircularJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
JProfClearCircularJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
NS_JProfClearCircular();
|
||||
return JS_TRUE;
|
||||
@ -2945,7 +2945,7 @@ NS_JProfClearCircular()
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JProfSaveCircularJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
JProfSaveCircularJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
// Not ideal...
|
||||
NS_JProfStopProfiling();
|
||||
@ -2969,7 +2969,7 @@ static JSFunctionSpec JProfFunctions[] = {
|
||||
// how to use DMD.
|
||||
|
||||
static JSBool
|
||||
DMDCheckJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
DMDCheckJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
mozilla::DMDCheckAndDump();
|
||||
return JS_TRUE;
|
||||
@ -3015,82 +3015,6 @@ nsJSContext::InitClasses(JSObject* aGlobalObj)
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsJSContext::ClearScope(void *aGlobalObj, bool aClearFromProtoChain)
|
||||
{
|
||||
// Push our JSContext on our thread's context stack.
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
if (stack && NS_FAILED(stack->Push(mContext))) {
|
||||
stack = nsnull;
|
||||
}
|
||||
|
||||
if (aGlobalObj) {
|
||||
JSObject *obj = (JSObject *)aGlobalObj;
|
||||
JSAutoRequest ar(mContext);
|
||||
|
||||
JSAutoEnterCompartment ac;
|
||||
ac.enterAndIgnoreErrors(mContext, obj);
|
||||
|
||||
// Grab a reference to the window property, which is the outer
|
||||
// window, so that we can re-define it once we've cleared
|
||||
// scope. This is what keeps the outer window alive in cases where
|
||||
// nothing else does.
|
||||
jsval window;
|
||||
if (!JS_GetProperty(mContext, obj, "window", &window)) {
|
||||
window = JSVAL_VOID;
|
||||
|
||||
JS_ClearPendingException(mContext);
|
||||
}
|
||||
|
||||
JS_ClearScope(mContext, obj);
|
||||
|
||||
NS_ABORT_IF_FALSE(!xpc::WrapperFactory::IsXrayWrapper(obj), "unexpected wrapper");
|
||||
|
||||
if (window != JSVAL_VOID) {
|
||||
if (!JS_DefineProperty(mContext, obj, "window", window,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY |
|
||||
JSPROP_PERMANENT)) {
|
||||
JS_ClearPendingException(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (!js::GetObjectParent(obj)) {
|
||||
JS_ClearRegExpStatics(mContext, obj);
|
||||
}
|
||||
|
||||
// Always clear watchpoints, to deal with two cases:
|
||||
// 1. The first document for this window is loading, and a miscreant has
|
||||
// preset watchpoints on the window object in order to attack the new
|
||||
// document's privileged information.
|
||||
// 2. A document loaded and used watchpoints on its own window, leaving
|
||||
// them set until the next document loads. We must clean up window
|
||||
// watchpoints here.
|
||||
// Watchpoints set on document and subordinate objects are all cleared
|
||||
// when those sub-window objects are finalized, after JS_ClearScope and
|
||||
// a GC run that finds them to be garbage.
|
||||
::JS_ClearWatchPointsForObject(mContext, obj);
|
||||
|
||||
// Since the prototype chain is shared between inner and outer (and
|
||||
// stays with the inner), we don't clear things from the prototype
|
||||
// chain when we're clearing an outer window whose current inner we
|
||||
// still want.
|
||||
if (aClearFromProtoChain) {
|
||||
nsWindowSH::InvalidateGlobalScopePolluter(mContext, obj);
|
||||
|
||||
// Clear up obj's prototype chain, but not Object.prototype.
|
||||
for (JSObject *o = ::JS_GetPrototype(obj), *next;
|
||||
o && (next = ::JS_GetPrototype(o)); o = next)
|
||||
::JS_ClearScope(mContext, o);
|
||||
}
|
||||
}
|
||||
|
||||
if (stack) {
|
||||
stack->Pop(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsJSContext::WillInitializeContext()
|
||||
{
|
||||
|
@ -161,7 +161,6 @@ public:
|
||||
virtual void SetGCOnDestruction(bool aGCOnDestruction);
|
||||
|
||||
virtual nsresult InitClasses(JSObject* aGlobalObj);
|
||||
virtual void ClearScope(void* aGlobalObj, bool bClearPolluters);
|
||||
|
||||
virtual void WillInitializeContext();
|
||||
virtual void DidInitializeContext();
|
||||
|
404
dom/contacts/ContactManager.js
Normal file
404
dom/contacts/ContactManager.js
Normal file
@ -0,0 +1,404 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
/* static functions */
|
||||
let DEBUG = 0;
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- ContactManager: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
const CONTACTPROPERTIES_CID = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}");
|
||||
const nsIDOMContactProperties = Ci.nsIDOMContactProperties;
|
||||
|
||||
// ContactProperties is not directly instantiated. It is used as interface.
|
||||
|
||||
ContactProperties.prototype = {
|
||||
|
||||
classID : CONTACTPROPERTIES_CID,
|
||||
classInfo : XPCOMUtils.generateCI({classID: CONTACTPROPERTIES_CID,
|
||||
contractID:"@mozilla.org/contactProperties;1",
|
||||
classDescription: "ContactProperties",
|
||||
interfaces: [nsIDOMContactProperties],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactProperties])
|
||||
}
|
||||
|
||||
//ContactAddress
|
||||
|
||||
const CONTACTADDRESS_CONTRACTID = "@mozilla.org/contactAddress;1";
|
||||
const CONTACTADDRESS_CID = Components.ID("{27a568b0-cee1-11e0-9572-0800200c9a66}");
|
||||
const nsIDOMContactAddress = Components.interfaces.nsIDOMContactAddress;
|
||||
|
||||
function ContactAddress(aStreetAddress, aLocality, aRegion, aPostalCode, aCountryName) {
|
||||
this.streetAddress = aStreetAddress || null;
|
||||
this.locality = aLocality || null;
|
||||
this.region = aRegion || null;
|
||||
this.postalCode = aPostalCode || null;
|
||||
this.countryName = aCountryName || null;
|
||||
};
|
||||
|
||||
function ContactProperties(aProp) { debug("ContactProperties Constructor"); }
|
||||
|
||||
ContactAddress.prototype = {
|
||||
|
||||
classID : CONTACTADDRESS_CID,
|
||||
classInfo : XPCOMUtils.generateCI({classID: CONTACTADDRESS_CID,
|
||||
contractID: CONTACTADDRESS_CONTRACTID,
|
||||
classDescription: "ContactAddress",
|
||||
interfaces: [nsIDOMContactAddress],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactAddress])
|
||||
}
|
||||
|
||||
//ContactFindOptions
|
||||
|
||||
const CONTACTFINDOPTIONS_CONTRACTID = "@mozilla.org/contactFindOptions;1";
|
||||
const CONTACTFINDOPTIONS_CID = Components.ID("{e31daea0-0cb6-11e1-be50-0800200c9a66}");
|
||||
const nsIDOMContactFindOptions = Components.interfaces.nsIDOMContactFindOptions;
|
||||
|
||||
function ContactFindOptions(aFilterValue, aFilterBy, aFilterOp, aFilterLimit) {
|
||||
this.filterValue = aFilterValue || '';
|
||||
|
||||
this.filterBy = new Array();
|
||||
for (let field in aFilterBy)
|
||||
this.filterBy.push(field);
|
||||
|
||||
this.filterOp = aFilterOp || '';
|
||||
this.filterLimit = aFilterLimit || 0;
|
||||
};
|
||||
|
||||
ContactFindOptions.prototype = {
|
||||
|
||||
classID : CONTACTFINDOPTIONS_CID,
|
||||
classInfo : XPCOMUtils.generateCI({classID: CONTACTFINDOPTIONS_CID,
|
||||
contractID: CONTACTFINDOPTIONS_CONTRACTID,
|
||||
classDescription: "ContactFindOptions",
|
||||
interfaces: [nsIDOMContactFindOptions],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactFindOptions])
|
||||
}
|
||||
|
||||
//Contact
|
||||
|
||||
const CONTACT_CONTRACTID = "@mozilla.org/contact;1";
|
||||
const CONTACT_CID = Components.ID("{da0f7040-388b-11e1-b86c-0800200c9a66}");
|
||||
const nsIDOMContact = Components.interfaces.nsIDOMContact;
|
||||
|
||||
function Contact() { debug("Contact constr: "); };
|
||||
|
||||
Contact.prototype = {
|
||||
|
||||
init: function init(aProp) {
|
||||
// Accept non-array strings for DOMString[] properties and convert them.
|
||||
function _create(aField) {
|
||||
if (typeof aField == "string")
|
||||
return new Array(aField);
|
||||
return aField;
|
||||
};
|
||||
|
||||
this.name = _create(aProp.name) || null;
|
||||
this.honorificPrefix = _create(aProp.honorificPrefix) || null;
|
||||
this.givenName = _create(aProp.givenName) || null;
|
||||
this.additionalName = _create(aProp.additionalName) || null;
|
||||
this.familyName = _create(aProp.familyName) || null;
|
||||
this.honorificSuffix = _create(aProp.honorificSuffix) || null;
|
||||
this.nickname = _create(aProp.nickname) || null;
|
||||
this.email = _create(aProp.email) || null;
|
||||
this.photo = _create(aProp.photo) || null;
|
||||
this.url = _create(aProp.url) || null;
|
||||
this.category = _create(aProp.category) || null;
|
||||
|
||||
if (aProp.adr) {
|
||||
// Make sure adr argument is an array. Instanceof doesn't work.
|
||||
aProp.adr = aProp.adr.length == undefined ? [aProp.adr] : aProp.adr;
|
||||
|
||||
this.adr = new Array();
|
||||
for (let i = 0; i < aProp.adr.length; i++)
|
||||
this.adr.push(new ContactAddress(aProp.adr[i].streetAddress, aProp.adr[i].locality,
|
||||
aProp.adr[i].region, aProp.adr[i].postalCode,
|
||||
aProp.adr[i].countryName));
|
||||
} else {
|
||||
this.adr = null;
|
||||
}
|
||||
|
||||
this.tel = _create(aProp.tel) || null;
|
||||
this.org = _create(aProp.org) || null;
|
||||
this.bday = (aProp.bday == "undefined" || aProp.bday == null) ? null : new Date(aProp.bday);
|
||||
this.note = _create(aProp.note) || null;
|
||||
this.impp = _create(aProp.impp) || null;
|
||||
this.anniversary = (aProp.anniversary == "undefined" || aProp.anniversary == null) ? null : new Date(aProp.anniversary);
|
||||
this.sex = (aProp.sex != "undefined") ? aProp.sex : null;
|
||||
this.genderIdentity = (aProp.genderIdentity != "undefined") ? aProp.genderIdentity : null;
|
||||
},
|
||||
|
||||
get published () {
|
||||
return this._published;
|
||||
},
|
||||
|
||||
set published(aPublished) {
|
||||
this._published = aPublished;
|
||||
},
|
||||
|
||||
get updated () {
|
||||
return this._updated;
|
||||
},
|
||||
|
||||
set updated(aUpdated) {
|
||||
this._updated = aUpdated;
|
||||
},
|
||||
|
||||
classID : CONTACT_CID,
|
||||
classInfo : XPCOMUtils.generateCI({classID: CONTACT_CID,
|
||||
contractID: CONTACT_CONTRACTID,
|
||||
classDescription: "Contact",
|
||||
interfaces: [nsIDOMContact, nsIDOMContactProperties],
|
||||
flags: nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContact, nsIDOMContactProperties])
|
||||
}
|
||||
|
||||
// ContactManager
|
||||
|
||||
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
|
||||
const CONTACTMANAGER_CID = Components.ID("{50a820b0-ced0-11e0-9572-0800200c9a66}");
|
||||
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
|
||||
|
||||
function ContactManager()
|
||||
{
|
||||
debug("Constructor");
|
||||
}
|
||||
|
||||
ContactManager.prototype = {
|
||||
|
||||
save: function save(aContact) {
|
||||
let request;
|
||||
if (this.hasPrivileges) {
|
||||
debug("save: " + JSON.stringify(aContact) + " :" + aContact.id);
|
||||
let newContact = {};
|
||||
newContact.properties = {
|
||||
name: [],
|
||||
honorificPrefix: [],
|
||||
givenName: [],
|
||||
additionalName: [],
|
||||
familyName: [],
|
||||
honorificSuffix: [],
|
||||
nickname: [],
|
||||
email: [],
|
||||
photo: [],
|
||||
url: [],
|
||||
category: [],
|
||||
adr: [],
|
||||
tel: [],
|
||||
org: [],
|
||||
bday: null,
|
||||
note: [],
|
||||
impp: [],
|
||||
anniversary: null,
|
||||
sex: null,
|
||||
genderIdentity: null
|
||||
};
|
||||
for (let field in newContact.properties)
|
||||
newContact.properties[field] = aContact[field];
|
||||
|
||||
if (aContact.id == "undefined") {
|
||||
debug("Create id!");
|
||||
aContact.id = this._getRandomId();
|
||||
}
|
||||
|
||||
this._setMetaData(newContact, aContact);
|
||||
debug("send: " + JSON.stringify(newContact));
|
||||
request = this._rs.createRequest(this._window);
|
||||
this._mm.sendAsyncMessage("Contact:Save", {contact: newContact,
|
||||
requestID: this.getRequestId({ request: request })});
|
||||
return request;
|
||||
} else {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
},
|
||||
|
||||
remove: function removeContact(aRecord) {
|
||||
let request;
|
||||
if (this.hasPrivileges) {
|
||||
request = this._rs.createRequest(this._window);
|
||||
this._mm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
|
||||
requestID: this.getRequestId({ request: request })});
|
||||
return request;
|
||||
} else {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
},
|
||||
|
||||
_setMetaData: function(aNewContact, aRecord) {
|
||||
aNewContact.id = aRecord.id;
|
||||
aNewContact.published = aRecord.published;
|
||||
aNewContact.updated = aRecord.updated;
|
||||
},
|
||||
|
||||
_convertContactsArray: function(aContacts) {
|
||||
let contacts = new Array();
|
||||
for (let i in aContacts) {
|
||||
let newContact = new Contact();
|
||||
newContact.init(aContacts[i].properties);
|
||||
this._setMetaData(newContact, aContacts[i]);
|
||||
contacts.push(newContact);
|
||||
}
|
||||
return contacts;
|
||||
},
|
||||
|
||||
getRequestId: function(aRequest) {
|
||||
let id = "id" + this._getRandomId();
|
||||
this._requests[id] = aRequest;
|
||||
return id;
|
||||
},
|
||||
|
||||
getRequest: function(aId) {
|
||||
if (this._requests[aId])
|
||||
return this._requests[aId].request;
|
||||
},
|
||||
|
||||
removeRequest: function(aId) {
|
||||
if (this._requests[aId])
|
||||
delete this._requests[aId];
|
||||
},
|
||||
|
||||
_getRandomId: function() {
|
||||
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("Contactmanager::receiveMessage: " + aMessage.name);
|
||||
let msg = aMessage.json;
|
||||
let contacts = msg.contacts;
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Contacts:Find:Return:OK":
|
||||
let req = this.getRequest(msg.requestID);
|
||||
if (req) {
|
||||
let result = this._convertContactsArray(contacts);
|
||||
debug("result: " + JSON.stringify(result));
|
||||
this._rs.fireSuccess(req, result);
|
||||
} else {
|
||||
debug("no request stored!" + msg.requestID);
|
||||
}
|
||||
break;
|
||||
case "Contact:Save:Return:OK":
|
||||
case "Contacts:Clear:Return:OK":
|
||||
case "Contact:Remove:Return:OK":
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req)
|
||||
this._rs.fireSuccess(req, 0);
|
||||
break;
|
||||
case "Contacts:Find:Return:KO":
|
||||
case "Contact:Save:Return:KO":
|
||||
case "Contact:Remove:Return:KO":
|
||||
case "Contacts:Clear:Return:KO":
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req)
|
||||
this._rs.fireError(req, msg.errorMsg);
|
||||
break;
|
||||
default:
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
}
|
||||
this.removeRequest(msg.requestID);
|
||||
},
|
||||
|
||||
find: function(aOptions) {
|
||||
let request;
|
||||
if (this.hasPrivileges) {
|
||||
request = this._rs.createRequest(this._window);
|
||||
this._mm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
|
||||
requestID: this.getRequestId({ request: request })});
|
||||
return request;
|
||||
} else {
|
||||
debug("find not allowed");
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
let request;
|
||||
if (this.hasPrivileges) {
|
||||
request = this._rs.createRequest(this._window);
|
||||
this._mm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({ request: request })});
|
||||
return request;
|
||||
} else {
|
||||
debug("clear not allowed");
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
},
|
||||
|
||||
init: function(aWindow) {
|
||||
// Set navigator.mozContacts to null.
|
||||
if (!Services.prefs.getBoolPref("dom.mozContacts.enabled"))
|
||||
return null;
|
||||
|
||||
this._window = aWindow;
|
||||
this._messages = ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
|
||||
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
|
||||
"Contact:Save:Return:OK", "Contact:Save:Return:KO",
|
||||
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO"];
|
||||
|
||||
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
this._messages.forEach((function(msgName) {
|
||||
this._mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this._rs = Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
|
||||
this._requests = [];
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
this._innerWindowID = util.currentInnerWindowID;
|
||||
|
||||
let principal = aWindow.document.nodePrincipal;
|
||||
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
|
||||
let perm = principal == secMan.getSystemPrincipal() ?
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION :
|
||||
Services.perms.testExactPermission(principal.URI, "webcontacts-manage");
|
||||
|
||||
//only pages with perm set can use the contacts
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
debug("has privileges :" + this.hasPrivileges);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this.innerWindowID) {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._messages.forEach((function(msgName) {
|
||||
this._mm.removeMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
this._mm = null;
|
||||
this._messages = null;
|
||||
this._requests = null;
|
||||
this._window = null;
|
||||
this._innerWindowID = null;
|
||||
}
|
||||
},
|
||||
|
||||
classID : CONTACTMANAGER_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: CONTACTMANAGER_CID,
|
||||
contractID: CONTACTMANAGER_CONTRACTID,
|
||||
classDescription: "ContactManager",
|
||||
interfaces: [nsIDOMContactManager],
|
||||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Contact, ContactManager, ContactProperties, ContactAddress, ContactFindOptions])
|
16
dom/contacts/ContactManager.manifest
Normal file
16
dom/contacts/ContactManager.manifest
Normal file
@ -0,0 +1,16 @@
|
||||
component {53ed7c20-ceda-11e0-9572-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactProperties;1 {53ed7c20-ceda-11e0-9572-0800200c9a66}
|
||||
|
||||
component {27a568b0-cee1-11e0-9572-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactAddress;1 {27a568b0-cee1-11e0-9572-0800200c9a66}
|
||||
|
||||
component {e31daea0-0cb6-11e1-be50-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactFindOptions;1 {e31daea0-0cb6-11e1-be50-0800200c9a66}
|
||||
|
||||
component {da0f7040-388b-11e1-b86c-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contact;1 {da0f7040-388b-11e1-b86c-0800200c9a66}
|
||||
category JavaScript-global-constructor mozContact @mozilla.org/contact;1
|
||||
|
||||
component {50a820b0-ced0-11e0-9572-0800200c9a66} ContactManager.js
|
||||
contract @mozilla.org/contactManager;1 {50a820b0-ced0-11e0-9572-0800200c9a66}
|
||||
category JavaScript-navigator-property mozContacts @mozilla.org/contactManager;1
|
47
dom/contacts/Makefile.in
Normal file
47
dom/contacts/Makefile.in
Normal file
@ -0,0 +1,47 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = \
|
||||
$(srcdir) \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
VPATH += $(srcdir)/fallback
|
||||
endif
|
||||
|
||||
MODULE = dom
|
||||
LIBRARY_NAME = jsdomcontacts_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
ContactManager.js \
|
||||
ContactManager.manifest \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
EXTRA_JS_MODULES = ContactService.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES += ContactDB.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
|
||||
# Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
|
||||
# subdirectory (and the ipc one).
|
||||
LOCAL_INCLUDES += $(VPATH:%=-I%)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
410
dom/contacts/fallback/ContactDB.jsm
Normal file
410
dom/contacts/fallback/ContactDB.jsm
Normal file
@ -0,0 +1,410 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const EXPORTED_SYMBOLS = ['ContactDB'];
|
||||
|
||||
let DEBUG = 0;
|
||||
/* static functions */
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- ContactDB component: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const DB_NAME = "contacts";
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = "contacts";
|
||||
|
||||
function ContactDB(aGlobal) {
|
||||
debug("Constructor");
|
||||
this._indexedDB = aGlobal.mozIndexedDB;
|
||||
}
|
||||
|
||||
ContactDB.prototype = {
|
||||
|
||||
// Cache the DB
|
||||
db: null,
|
||||
|
||||
close: function close() {
|
||||
debug("close");
|
||||
if (this.db)
|
||||
this.db.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare the database. This may include opening the database and upgrading
|
||||
* it to the latest schema version.
|
||||
*
|
||||
* @return (via callback) a database ready for use.
|
||||
*/
|
||||
ensureDB: function ensureDB(callback, failureCb) {
|
||||
if (this.db) {
|
||||
debug("ensureDB: already have a database, returning early.");
|
||||
callback(this.db);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
debug("try to open database:" + DB_NAME + " " + DB_VERSION);
|
||||
let request = this._indexedDB.open(DB_NAME, DB_VERSION);
|
||||
request.onsuccess = function (event) {
|
||||
debug("Opened database:", DB_NAME, DB_VERSION);
|
||||
self.db = event.target.result;
|
||||
self.db.onversionchange = function(event) {
|
||||
debug("WARNING: DB modified from a different window.");
|
||||
}
|
||||
callback(self.db);
|
||||
};
|
||||
request.onupgradeneeded = function (event) {
|
||||
debug("Database needs upgrade:" + DB_NAME + event.oldVersion + event.newVersion);
|
||||
debug("Correct new database version:" + event.newVersion == DB_VERSION);
|
||||
|
||||
let db = event.target.result;
|
||||
switch (event.oldVersion) {
|
||||
case 0:
|
||||
debug("New database");
|
||||
self.createSchema(db);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("No idea what to do with old database version:" + event.oldVersion);
|
||||
failureCb(event.target.errorMessage);
|
||||
break;
|
||||
}
|
||||
};
|
||||
request.onerror = function (event) {
|
||||
debug("Failed to open database:", DB_NAME);
|
||||
failureCb(event.target.errorMessage);
|
||||
};
|
||||
request.onblocked = function (event) {
|
||||
debug("Opening database request is blocked.");
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the initial database schema.
|
||||
*
|
||||
* The schema of records stored is as follows:
|
||||
*
|
||||
* {id: "...", // UUID
|
||||
* published: Date(...), // First published date.
|
||||
* updated: Date(...), // Last updated date.
|
||||
* properties: {...} // Object holding the ContactProperties
|
||||
* }
|
||||
*/
|
||||
createSchema: function createSchema(db) {
|
||||
let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
|
||||
|
||||
// Metadata indexes
|
||||
objectStore.createIndex("published", "published", { unique: false });
|
||||
objectStore.createIndex("updated", "updated", { unique: false });
|
||||
|
||||
// Properties indexes
|
||||
objectStore.createIndex("nickname", "properties.nickname", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("name", "properties.name", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("familyName", "properties.familyName", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("givenName", "properties.givenName", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("tel", "properties.tel", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("email", "properties.email", { unique: false, multiEntry: true });
|
||||
objectStore.createIndex("note", "properties.note", { unique: false, multiEntry: true });
|
||||
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new transaction.
|
||||
*
|
||||
* @param txn_type
|
||||
* Type of transaction (e.g. IDBTransaction.READ_WRITE)
|
||||
* @param callback
|
||||
* Function to call when the transaction is available. It will
|
||||
* be invoked with the transaction and the 'contacts' object store.
|
||||
* @param successCb [optional]
|
||||
* Success callback to call on a successful transaction commit.
|
||||
* @param failureCb [optional]
|
||||
* Error callback to call when an error is encountered.
|
||||
*/
|
||||
newTxn: function newTxn(txn_type, callback, successCb, failureCb) {
|
||||
this.ensureDB(function (db) {
|
||||
debug("Starting new transaction" + txn_type);
|
||||
let txn = db.transaction(STORE_NAME, txn_type);
|
||||
debug("Retrieving object store", STORE_NAME);
|
||||
let store = txn.objectStore(STORE_NAME);
|
||||
|
||||
txn.oncomplete = function (event) {
|
||||
debug("Transaction complete. Returning to callback.");
|
||||
successCb(txn.result);
|
||||
};
|
||||
|
||||
txn.onabort = function (event) {
|
||||
debug("Caught error on transaction" + event.target.errorCode);
|
||||
switch(event.target.errorCode) {
|
||||
case Ci.nsIIDBDatabaseException.ABORT_ERR:
|
||||
case Ci.nsIIDBDatabaseException.CONSTRAINT_ERR:
|
||||
case Ci.nsIIDBDatabaseException.DATA_ERR:
|
||||
case Ci.nsIIDBDatabaseException.TRANSIENT_ERR:
|
||||
case Ci.nsIIDBDatabaseException.NOT_ALLOWED_ERR:
|
||||
case Ci.nsIIDBDatabaseException.NOT_FOUND_ERR:
|
||||
case Ci.nsIIDBDatabaseException.QUOTA_ERR:
|
||||
case Ci.nsIIDBDatabaseException.READ_ONLY_ERR:
|
||||
case Ci.nsIIDBDatabaseException.TIMEOUT_ERR:
|
||||
case Ci.nsIIDBDatabaseException.TRANSACTION_INACTIVE_ERR:
|
||||
case Ci.nsIIDBDatabaseException.VERSION_ERR:
|
||||
case Ci.nsIIDBDatabaseException.UNKNOWN_ERR:
|
||||
failureCb("UnknownError");
|
||||
break;
|
||||
default:
|
||||
debug("Unknown errorCode", event.target.errorCode);
|
||||
failureCb("UnknownError");
|
||||
break;
|
||||
}
|
||||
};
|
||||
callback(txn, store);
|
||||
}, failureCb);
|
||||
},
|
||||
|
||||
// Todo: add searchfields. "Tom" should be a result with T, t, To, to...
|
||||
makeImport: function makeImport(aContact) {
|
||||
let contact = {};
|
||||
contact.properties = {
|
||||
name: [],
|
||||
honorificPrefix: [],
|
||||
givenName: [],
|
||||
additionalName: [],
|
||||
familyName: [],
|
||||
honorificSuffix: [],
|
||||
nickname: [],
|
||||
email: [],
|
||||
photo: [],
|
||||
url: [],
|
||||
category: [],
|
||||
adr: [],
|
||||
tel: [],
|
||||
org: [],
|
||||
bday: null,
|
||||
note: [],
|
||||
impp: [],
|
||||
anniversary: null,
|
||||
sex: null,
|
||||
genderIdentity: null
|
||||
};
|
||||
|
||||
for (let field in aContact.properties) {
|
||||
contact.properties[field] = aContact.properties[field];
|
||||
}
|
||||
|
||||
contact.updated = aContact.updated;
|
||||
contact.published = aContact.published;
|
||||
contact.id = aContact.id;
|
||||
|
||||
return contact;
|
||||
},
|
||||
|
||||
// Needed to remove searchfields
|
||||
makeExport: function makeExport(aRecord) {
|
||||
let contact = {};
|
||||
contact.properties = aRecord.properties;
|
||||
|
||||
for (let field in aRecord.properties)
|
||||
contact.properties[field] = aRecord.properties[field];
|
||||
|
||||
contact.updated = aRecord.updated;
|
||||
contact.published = aRecord.published;
|
||||
contact.id = aRecord.id;
|
||||
return contact;
|
||||
},
|
||||
|
||||
updateRecordMetadata: function updateRecordMetadata(record) {
|
||||
if (!record.id) {
|
||||
Cu.reportError("Contact without ID");
|
||||
}
|
||||
if (!record.published) {
|
||||
record.published = new Date();
|
||||
}
|
||||
record.updated = new Date();
|
||||
},
|
||||
|
||||
saveContact: function saveContact(aContact, successCb, errorCb) {
|
||||
let contact = this.makeImport(aContact);
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
debug("Going to update" + JSON.stringify(contact));
|
||||
|
||||
// Look up the existing record and compare the update timestamp.
|
||||
// If no record exists, just add the new entry.
|
||||
let newRequest = store.get(contact.id);
|
||||
newRequest.onsuccess = function (event) {
|
||||
if (!event.target.result) {
|
||||
debug("new record!")
|
||||
this.updateRecordMetadata(contact);
|
||||
store.put(contact);
|
||||
} else {
|
||||
debug("old record!")
|
||||
if (new Date(typeof contact.updated === "undefined" ? 0 : contact.updated) < new Date(event.target.result.updated)) {
|
||||
debug("rev check fail!");
|
||||
txn.abort();
|
||||
return;
|
||||
} else {
|
||||
debug("rev check OK");
|
||||
contact.published = event.target.result.published;
|
||||
contact.updated = new Date();
|
||||
store.put(contact);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}.bind(this), successCb, errorCb);
|
||||
},
|
||||
|
||||
removeContact: function removeContact(aId, aSuccessCb, aErrorCb) {
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
debug("Going to delete" + aId);
|
||||
store.delete(aId);
|
||||
}, aSuccessCb, aErrorCb);
|
||||
},
|
||||
|
||||
clear: function clear(aSuccessCb, aErrorCb) {
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) {
|
||||
debug("Going to clear all!");
|
||||
store.clear();
|
||||
}, aSuccessCb, aErrorCb);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param successCb
|
||||
* Callback function to invoke with result array.
|
||||
* @param failureCb [optional]
|
||||
* Callback function to invoke when there was an error.
|
||||
* @param options [optional]
|
||||
* Object specifying search options. Possible attributes:
|
||||
* - filterBy
|
||||
* - filterOp
|
||||
* - filterValue
|
||||
* - count
|
||||
* Possibly supported in the future:
|
||||
* - fields
|
||||
* - sortBy
|
||||
* - sortOrder
|
||||
* - startIndex
|
||||
*/
|
||||
find: function find(aSuccessCb, aFailureCb, aOptions) {
|
||||
debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n");
|
||||
|
||||
let self = this;
|
||||
this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (txn, store) {
|
||||
if (aOptions && aOptions.filterOp == "equals") {
|
||||
self._findWithIndex(txn, store, aOptions);
|
||||
} else if (aOptions && aOptions.filterBy) {
|
||||
self._findWithSearch(txn, store, aOptions);
|
||||
} else {
|
||||
self._findAll(txn, store, aOptions);
|
||||
}
|
||||
}, aSuccessCb, aFailureCb);
|
||||
},
|
||||
|
||||
_findWithIndex: function _findWithIndex(txn, store, options) {
|
||||
debug("_findWithIndex: " + options.filterValue +" " + options.filterOp + " " + options.filterBy + " ");
|
||||
let fields = options.filterBy;
|
||||
for (let key in fields) {
|
||||
debug("key: " + fields[key]);
|
||||
if (!store.indexNames.contains(fields[key]) && !fields[key] == "id") {
|
||||
debug("Key not valid!" + fields[key] + ", " + store.indexNames);
|
||||
txn.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// lookup for all keys
|
||||
if (options.filterBy.length == 0) {
|
||||
debug("search in all fields!" + JSON.stringify(store.indexNames));
|
||||
for(let myIndex = 0; myIndex < store.indexNames.length; myIndex++) {
|
||||
fields = Array.concat(fields, store.indexNames[myIndex])
|
||||
}
|
||||
}
|
||||
|
||||
let filter_keys = fields.slice();
|
||||
for (let key = filter_keys.shift(); key; key = filter_keys.shift()) {
|
||||
let request;
|
||||
if (key == "id") {
|
||||
// store.get would return an object and not an array
|
||||
request = store.getAll(options.filterValue);
|
||||
} else {
|
||||
debug("Getting index: " + key);
|
||||
let index = store.index(key);
|
||||
request = index.getAll(options.filterValue, options.filterLimit);
|
||||
}
|
||||
if (!txn.result)
|
||||
txn.result = {};
|
||||
|
||||
request.onsuccess = function (event) {
|
||||
debug("Request successful. Record count:" + event.target.result.length);
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
}.bind(this);
|
||||
}
|
||||
},
|
||||
|
||||
// Will be replaced by _findWithIndex once all searchfields are added.
|
||||
_findWithSearch: function _findWithSearch(txn, store, options) {
|
||||
debug("_findWithSearch:" + options.filterValue + options.filterOp)
|
||||
store.getAll().onsuccess = function (event) {
|
||||
debug("Request successful." + event.target.result);
|
||||
txn.result = event.target.result.filter(function (record) {
|
||||
let properties = record.properties;
|
||||
for (let i = 0; i < options.filterBy.length; i++) {
|
||||
let field = options.filterBy[i];
|
||||
if (!properties[field])
|
||||
continue;
|
||||
let value = '';
|
||||
switch (field) {
|
||||
case "name":
|
||||
case "familyName":
|
||||
case "givenName":
|
||||
case "nickname":
|
||||
case "email":
|
||||
case "tel":
|
||||
case "note":
|
||||
value = [f for each (f in [properties[field]])].join("\n") || '';
|
||||
break;
|
||||
default:
|
||||
value = properties[field];
|
||||
debug("unknown field: " + field);
|
||||
}
|
||||
let match = false;
|
||||
switch (options.filterOp) {
|
||||
case "icontains":
|
||||
match = value.toLowerCase().indexOf(options.filterValue.toLowerCase()) != -1;
|
||||
break;
|
||||
case "contains":
|
||||
match = value.indexOf(options.filterValue) != -1;
|
||||
break;
|
||||
case "equals":
|
||||
match = value == options.filterValue;
|
||||
break
|
||||
}
|
||||
if (match)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).map(this.makeExport.bind(this));
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
_findAll: function _findAll(txn, store, options) {
|
||||
debug("ContactDB:_findAll: " + JSON.stringify(options));
|
||||
if (!txn.result)
|
||||
txn.result = {};
|
||||
|
||||
store.getAll(null, options.filterLimit).onsuccess = function (event) {
|
||||
debug("Request successful. Record count:", event.target.result.length);
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
}.bind(this);
|
||||
}
|
||||
};
|
96
dom/contacts/fallback/ContactService.jsm
Normal file
96
dom/contacts/fallback/ContactService.jsm
Normal file
@ -0,0 +1,96 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
let DEBUG = 0;
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- Fallback ContactService component: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["DOMContactManager"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ContactDB.jsm");
|
||||
|
||||
let myGlobal = this;
|
||||
|
||||
let DOMContactManager = {
|
||||
|
||||
init: function() {
|
||||
debug("Init");
|
||||
this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"];
|
||||
this._messages.forEach((function(msgName) {
|
||||
this._mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._db = new ContactDB(myGlobal);
|
||||
|
||||
Services.obs.addObserver(this, "profile-before-change", false);
|
||||
|
||||
try {
|
||||
let hosts = Services.prefs.getCharPref("dom.mozContacts.whitelist")
|
||||
hosts.split(",").forEach(function(aHost) {
|
||||
debug("Add host: " + JSON.stringify(aHost));
|
||||
if (aHost.length > 0)
|
||||
Services.perms.add(Services.io.newURI(aHost, null, null), "webcontacts-manage",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
});
|
||||
} catch(e) { debug(e); }
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
myGlobal = null;
|
||||
this._messages.forEach((function(msgName) {
|
||||
this._mm.removeMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
Services.obs.removeObserver(this, "profile-before-change");
|
||||
this._mm = null;
|
||||
this._messages = null;
|
||||
if (this._db)
|
||||
this._db.close();
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("Fallback DOMContactManager::receiveMessage " + aMessage.name);
|
||||
let msg = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "Contacts:Find":
|
||||
let result = new Array();
|
||||
this._db.find(
|
||||
function(contacts) {
|
||||
for (let i in contacts)
|
||||
result.push(contacts[i]);
|
||||
debug("result:" + JSON.stringify(result));
|
||||
this._mm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
|
||||
}.bind(this),
|
||||
function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
|
||||
msg.findOptions);
|
||||
break;
|
||||
case "Contact:Save":
|
||||
this._db.saveContact(msg.contact, function() {this._mm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this),
|
||||
function(aErrorMsg) { this._mm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
|
||||
break;
|
||||
case "Contact:Remove":
|
||||
this._db.removeContact(msg.id,
|
||||
function() {this._mm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this),
|
||||
function(aErrorMsg) {this._mm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
|
||||
break;
|
||||
case "Contacts:Clear":
|
||||
this._db.clear(function() { this._mm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
|
||||
function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOMContactManager.init();
|
28
dom/contacts/tests/Makefile.in
Normal file
28
dom/contacts/tests/Makefile.in
Normal file
@ -0,0 +1,28 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/contacts/tests
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
test_contacts_basics.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_TEST_FILES = \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
666
dom/contacts/tests/test_contacts_basics.html
Normal file
666
dom/contacts/tests/test_contacts_basics.html
Normal file
@ -0,0 +1,666 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {674720} WebContacts</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={674720}">Mozilla Bug {674720}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
"use strict"
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager)
|
||||
.add(SpecialPowers.getDocumentURIObject(window.document),
|
||||
"webcontacts-manage",
|
||||
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
var adr1 = {
|
||||
streetAddress: "street 1",
|
||||
locality: "locality 1",
|
||||
region: "region 1",
|
||||
postalCode: "postal code 1",
|
||||
countryName: "country 1"
|
||||
};
|
||||
|
||||
var adr2 = {
|
||||
streetAddress: "street2",
|
||||
locality: "locality2",
|
||||
region: "region2",
|
||||
postalCode: "postal code2",
|
||||
countryName: "country2"
|
||||
};
|
||||
|
||||
var properties1 = {
|
||||
name: "Testname1",
|
||||
familyName: "TestFamilyName",
|
||||
givenName: ["Test1","Test2"],
|
||||
nickname: "nicktest",
|
||||
tel: ["123456"],
|
||||
adr: adr1
|
||||
};
|
||||
|
||||
var properties2 = {
|
||||
name: ["dummyName", "dummyName2"],
|
||||
familyName: "dummyFamilyName",
|
||||
givenName: "dummyGivenName",
|
||||
honorificPrefix: ["dummyHonorificPrefix","dummyHonorificPrefix2"],
|
||||
honorificSuffix: "dummyHonorificSuffix",
|
||||
additionalName: "dummyadditionalName",
|
||||
nickname: "dummyNickname",
|
||||
tel: ["123456789", "234567890"],
|
||||
email: ["a@b.c", "b@c.d"],
|
||||
adr: [adr1, adr2],
|
||||
impp: ["im1", "im2"],
|
||||
org: ["org1", "org2"],
|
||||
bday: new Date("1980, 12, 01"),
|
||||
note: "test note",
|
||||
photo: ["pic1", "pic2"],
|
||||
category: ["cat1", "cat2"],
|
||||
url: ["www.1.com", "www.2.com"],
|
||||
anniversary: new Date("2000, 12, 01"),
|
||||
sex: "male",
|
||||
genderIdentity: "test"
|
||||
};
|
||||
|
||||
var sample_id1;
|
||||
var sample_id2;
|
||||
|
||||
var createResult1;
|
||||
var createResult2;
|
||||
|
||||
var findResult1;
|
||||
var findResult2;
|
||||
|
||||
function clearTemps() {
|
||||
sample_id1 = null;
|
||||
sample_id2 = null;
|
||||
createResult1 = null;
|
||||
createResult2 = null;
|
||||
findResult1 = null;
|
||||
findResult2 = null;
|
||||
}
|
||||
|
||||
function onUnwantedSuccess() {
|
||||
ok(false, "onUnwantedSuccess: shouldn't get here");
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
ok(false, "in on Failure!");
|
||||
}
|
||||
|
||||
function checkStr(str1, str2, msg) {
|
||||
if (str1)
|
||||
ok(typeof str1 == "string" ? [str1] : str1, (typeof str2 == "string") ? [str2] : str2, msg);
|
||||
}
|
||||
|
||||
function checkAddress(adr1, adr2) {
|
||||
checkStr(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
|
||||
checkStr(adr1.locality, adr2.locality, "Same locality");
|
||||
checkStr(adr1.region, adr2.region, "Same region");
|
||||
checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode");
|
||||
checkStr(adr1.countryName, adr2.countryName, "Same countryName");
|
||||
}
|
||||
|
||||
function checkContacts(contact1, contact2) {
|
||||
checkStr(contact1.name, contact2.name, "Same name");
|
||||
checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
|
||||
checkStr(contact1.givenName, contact2.givenName, "Same givenName");
|
||||
checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
|
||||
checkStr(contact1.familyName, contact2.familyName, "Same familyName");
|
||||
checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
|
||||
checkStr(contact1.nickname, contact2.nickname, "Same nickname");
|
||||
checkStr(contact1.email, contact2.email, "Same email");
|
||||
checkStr(contact1.photo, contact2.photo, "Same photo");
|
||||
checkStr(contact1.url, contact2.url, "Same url");
|
||||
checkStr(contact1.category, contact2.category, "Same category");
|
||||
is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
|
||||
checkStr(contact1.note, contact2.note, "Same note");
|
||||
checkStr(contact1.impp, contact2.impp, "Same impp");
|
||||
is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
|
||||
is(contact1.sex, contact2.sex, "Same sex");
|
||||
is(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
|
||||
|
||||
for (var i in contact1.adr)
|
||||
checkAddress(contact1.adr[i], contact2.adr[i]);
|
||||
}
|
||||
|
||||
var req;
|
||||
var index = 0;
|
||||
|
||||
var mozContacts = window.navigator.mozContacts
|
||||
|
||||
var steps = [
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.clear();
|
||||
req.onsuccess = function () {
|
||||
ok(true, "Deleted the database");
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 0, "Empty database is empty.");
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Adding empty contact");
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init({});
|
||||
req = navigator.mozContacts.save(createResult1);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "One contact.");
|
||||
findResult1 = req.result[0];
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting empty contact");
|
||||
req = navigator.mozContacts.remove(findResult1);
|
||||
req.onsuccess = function () {
|
||||
var req2 = mozContacts.find({});
|
||||
req2.onsuccess = function () {
|
||||
ok(req2.result.length == 0, "Empty Database.");
|
||||
clearTemps();
|
||||
next();
|
||||
}
|
||||
req2.onerror = onFailure;
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Adding a new contact1");
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = navigator.mozContacts.save(createResult1);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
checkContacts(properties1, createResult1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function() {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, findResult1);
|
||||
ok(findResult1.updated, "Has updated field");
|
||||
ok(findResult1.published, "Has published field");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Modifying contact1");
|
||||
findResult1.impp = properties1.impp = (["phil impp"]);
|
||||
req = navigator.mozContacts.save(findResult1);
|
||||
req.onsuccess = function () {
|
||||
var req2 = mozContacts.find({});
|
||||
req2.onsuccess = function() {
|
||||
ok(req2.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult2 = req2.result[0];
|
||||
ok(findResult2.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult2, properties1);
|
||||
ok(findResult2.impp.length == 1, "Found exactly 1 IMS info.");
|
||||
next();
|
||||
};
|
||||
req2.onerror = onFailure;
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Saving old contact, should abort!");
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = onUnwantedSuccess;
|
||||
req.onerror = function() { ok(true, "Successfully declined updating old contact!"); next(); };
|
||||
},
|
||||
function() {
|
||||
ok(true, "Saving old contact, should abort!");
|
||||
req = mozContacts.save(findResult1)
|
||||
req.onsuccess = onUnwantedSuccess;
|
||||
req.onerror = function() { ok(true, "Successfully declined updating old contact!"); next(); };
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving a specific contact by ID");
|
||||
var options = {filterBy: ["id"],
|
||||
filterOp: "equals",
|
||||
filterValue: sample_id1};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving a specific contact by givenName");
|
||||
var options = {filterBy: ["givenName"],
|
||||
filterOp: "equals",
|
||||
filterValue: properties1.givenName[0]};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Modifying contact2");
|
||||
findResult1.impp = properties1.impp = (["phil impp"]);
|
||||
req = mozContacts.save(findResult1);
|
||||
req.onsuccess = function () {
|
||||
var req2 = mozContacts.find({});
|
||||
req2.onsuccess = function () {
|
||||
ok(req2.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req2.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
ok(findResult1.impp.length == 1, "Found exactly 1 IMS info.");
|
||||
next();
|
||||
}
|
||||
req2.onerror = onFailure;
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts by query");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties1.name[0].substring(0,4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts by query");
|
||||
var options = {filterBy: ["nickname", "email"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties1.nickname};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts with multiple indices");
|
||||
var options = {filterBy: ["nickname", "email", "name"],
|
||||
filterOp: "equals",
|
||||
filterValue: properties1.nickname};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Modifying contact3");
|
||||
findResult1.email = (properties1.nickname);
|
||||
findResult1.nickname = "TEST";
|
||||
var newContact = new mozContact();
|
||||
newContact.init(findResult1);
|
||||
req = mozContacts.save(newContact);
|
||||
req.onsuccess = function () {
|
||||
var options = {filterBy: ["nickname", "email", "name"],
|
||||
filterOp: "equals",
|
||||
filterValue: properties1.nickname};
|
||||
// One contact has it in nickname and the other in email
|
||||
var req2 = mozContacts.find(options);
|
||||
req2.onsuccess = function () {
|
||||
ok(req2.result.length == 2, "Found exactly 2 contacts.");
|
||||
ok(req2.result[0].id != req2.result[1].id, "Different ID");
|
||||
next();
|
||||
}
|
||||
req2.onerror = onFailure;
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting contact" + findResult1.id);
|
||||
req = mozContacts.remove(findResult1);
|
||||
req.onsuccess = function () {
|
||||
var req2 = mozContacts.find({});
|
||||
req2.onsuccess = function () {
|
||||
ok(req2.result.length == 1, "One contact left.");
|
||||
findResult1 = req2.result[0];
|
||||
next();
|
||||
}
|
||||
req2.onerror = onFailure;
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.remove(findResult1);
|
||||
req.onsuccess = function () {
|
||||
clearTemps();
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Adding a new contact");
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1)
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Adding a new contact2");
|
||||
createResult2 = new mozContact();
|
||||
createResult2.init(properties2);
|
||||
req = mozContacts.save(createResult2);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult2.id, "The contact now has an ID.");
|
||||
sample_id2 = createResult2.id;
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({})
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 2, "Found exactly 2 contact.");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
console.log("Searching contacts by query1");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties1.name[0].substring(0, 4)}
|
||||
req = mozContacts.find(options)
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id1, "Same ID");
|
||||
checkContacts(findResult1, createResult1);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts by query2");
|
||||
var options = {filterBy: ["name", "email"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.adr.length == 2, "Adr length 2");
|
||||
checkContacts(findResult1, createResult2);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts by tel");
|
||||
var options = {filterBy: ["tel"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties2.tel[0].substring(0, 7)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id2, "Same ID");
|
||||
checkContacts(findResult1, createResult2);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Searching contacts by email");
|
||||
var options = {filterBy: ["email"],
|
||||
filterOp: "contains",
|
||||
filterValue: properties2.email[0].substring(0, 4)};
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 1, "Found exactly 1 contact.");
|
||||
findResult1 = req.result[0];
|
||||
ok(findResult1.id == sample_id2, "Same ID");
|
||||
checkContacts(findResult1, createResult2);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.clear();
|
||||
req.onsuccess = function () {
|
||||
clearTemps();
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Adding 100 contacts");
|
||||
for (var i=0; i<99; i++) {
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
};
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
ok(createResult1.name == properties1.name, "Same Name");
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 100, "100 Entries.");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts with limit 10");
|
||||
var options = { filterLimit: 10 };
|
||||
req = mozContacts.find(options);
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 10, "10 Entries.");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts2");
|
||||
var options = {filterBy: ["name"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 100, "100 Entries.");
|
||||
checkContacts(createResult1, req.result[99]);
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.clear();
|
||||
req.onsuccess = function () {
|
||||
clearTemps();
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Testing clone contact");
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init(properties1);
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
ok(createResult1.name == properties1.name, "Same Name");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Testing clone contact2");
|
||||
var cloned = new mozContact(createResult1);
|
||||
ok(cloned.id != createResult1.id, "Cloned contact has new ID");
|
||||
cloned.email = "new email!";
|
||||
cloned.givenName = "Tom";
|
||||
req = mozContacts.save(cloned);
|
||||
req.onsuccess = function () {
|
||||
ok(cloned.id, "The contact now has an ID.");
|
||||
ok(cloned.email == "new email!", "Same Email");
|
||||
ok(createResult1.email != cloned.email, "Clone has different email");
|
||||
ok(cloned.givenName == "Tom", "New Name");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Retrieving all contacts");
|
||||
var options = {filterBy: ["name"],
|
||||
filterOp: "icontains",
|
||||
filterValue: properties2.name[0].substring(0, 4)};
|
||||
req = mozContacts.find({});
|
||||
req.onsuccess = function () {
|
||||
ok(req.result.length == 2, "2 Entries.");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Search with redundant fields should only return 1 contact");
|
||||
createResult1 = new mozContact();
|
||||
createResult1.init({name: "XXX", nickname: "XXX", email: "XXX", tel: "XXX"});
|
||||
req = mozContacts.save(createResult1);
|
||||
req.onsuccess = function() {
|
||||
var options = {filterBy: [],
|
||||
filterOp: "equals",
|
||||
filterValue: "XXX"};
|
||||
var req2 = mozContacts.find(options);
|
||||
req2.onsuccess = function() {
|
||||
ok(req2.result.length == 1, "1 Entry");
|
||||
next();
|
||||
}
|
||||
req2.onerror = onFailure;
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
req = mozContacts.clear()
|
||||
req.onsuccess = function () {
|
||||
ok(true, "Deleted the database");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
clearTemps();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
function next() {
|
||||
ok(true, "Begin!");
|
||||
if (index >= steps.length) {
|
||||
ok(false, "Shouldn't get here!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
steps[index]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
function permissionTest() {
|
||||
if (gContactsEnabled) {
|
||||
next();
|
||||
} else {
|
||||
is(mozContacts, null, "mozContacts is null when not enabled.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
var gContactsEnabled = SpecialPowers.getBoolPref("dom.mozContacts.enabled");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(permissionTest);
|
||||
|
||||
ok(true, "test passed");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -4,6 +4,7 @@ DOM_SRCDIRS = \
|
||||
dom/power \
|
||||
dom/network/src \
|
||||
dom/sms/src \
|
||||
dom/contacts \
|
||||
dom/src/events \
|
||||
dom/src/storage \
|
||||
dom/src/offline \
|
||||
|
@ -266,6 +266,14 @@ IDBCursor::CreateCommon(IDBRequest* aRequest,
|
||||
cursor->mOwner = database->GetOwner();
|
||||
cursor->mScriptOwner = database->GetScriptOwner();
|
||||
|
||||
if (cursor->mScriptOwner) {
|
||||
if (NS_FAILED(NS_HOLD_JS_OBJECTS(cursor, IDBCursor))) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
cursor->mRooted = true;
|
||||
}
|
||||
|
||||
cursor->mRequest = aRequest;
|
||||
cursor->mTransaction = aTransaction;
|
||||
cursor->mObjectStore = aObjectStore;
|
||||
|
@ -164,7 +164,9 @@ IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
|
||||
|
||||
db->mScriptContext = aOwnerCache->GetScriptContext();
|
||||
db->mOwner = aOwnerCache->GetOwner();
|
||||
db->mScriptOwner = aOwnerCache->GetScriptOwner();
|
||||
if (!db->SetScriptOwner(aOwnerCache->GetScriptOwner())) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
db->mDatabaseId = databaseInfo->id;
|
||||
db->mName = databaseInfo->name;
|
||||
|
@ -138,7 +138,7 @@ GetKeyFromJSValOrThrow(JSContext* aCx,
|
||||
|
||||
JSBool
|
||||
MakeOnlyKeyRange(JSContext* aCx,
|
||||
uintN aArgc,
|
||||
unsigned aArgc,
|
||||
jsval* aVp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -159,7 +159,7 @@ MakeOnlyKeyRange(JSContext* aCx,
|
||||
|
||||
JSBool
|
||||
MakeLowerBoundKeyRange(JSContext* aCx,
|
||||
uintN aArgc,
|
||||
unsigned aArgc,
|
||||
jsval* aVp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -181,7 +181,7 @@ MakeLowerBoundKeyRange(JSContext* aCx,
|
||||
|
||||
JSBool
|
||||
MakeUpperBoundKeyRange(JSContext* aCx,
|
||||
uintN aArgc,
|
||||
unsigned aArgc,
|
||||
jsval* aVp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -203,7 +203,7 @@ MakeUpperBoundKeyRange(JSContext* aCx,
|
||||
|
||||
JSBool
|
||||
MakeBoundKeyRange(JSContext* aCx,
|
||||
uintN aArgc,
|
||||
unsigned aArgc,
|
||||
jsval* aVp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
@ -88,7 +88,9 @@ IDBRequest::Create(nsISupports* aSource,
|
||||
request->mTransaction = aTransaction;
|
||||
request->mScriptContext = aOwnerCache->GetScriptContext();
|
||||
request->mOwner = aOwnerCache->GetOwner();
|
||||
request->mScriptOwner = aOwnerCache->GetScriptOwner();
|
||||
if (!request->SetScriptOwner(aOwnerCache->GetScriptOwner())) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -129,7 +131,7 @@ IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
|
||||
|
||||
// Otherwise we need to get the result from the helper.
|
||||
JSContext* cx;
|
||||
if (mScriptOwner) {
|
||||
if (GetScriptOwner()) {
|
||||
nsIThreadJSContextStack* cxStack = nsContentUtils::ThreadJSContextStack();
|
||||
NS_ASSERTION(cxStack, "Failed to get thread context stack!");
|
||||
|
||||
@ -317,7 +319,9 @@ IDBOpenDBRequest::Create(nsIScriptContext* aScriptContext,
|
||||
|
||||
request->mScriptContext = aScriptContext;
|
||||
request->mOwner = aOwner;
|
||||
request->mScriptOwner = aScriptOwner;
|
||||
if (!request->SetScriptOwner(aScriptOwner)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -119,7 +119,9 @@ IDBTransaction::Create(IDBDatabase* aDatabase,
|
||||
|
||||
transaction->mScriptContext = aDatabase->GetScriptContext();
|
||||
transaction->mOwner = aDatabase->GetOwner();
|
||||
transaction->mScriptOwner = aDatabase->GetScriptOwner();
|
||||
if (!transaction->SetScriptOwner(aDatabase->GetScriptOwner())) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
transaction->mDatabase = aDatabase;
|
||||
transaction->mMode = aMode;
|
||||
|
@ -5,6 +5,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IDBWrapperCache.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
@ -18,7 +19,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBWrapperCache,
|
||||
nsDOMEventTargetHelper)
|
||||
tmp->mScriptOwner = nsnull;
|
||||
if (tmp->mScriptOwner) {
|
||||
NS_DROP_JS_OBJECTS(tmp, IDBWrapperCache);
|
||||
tmp->mScriptOwner = nsnull;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBWrapperCache,
|
||||
@ -36,3 +40,36 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(IDBWrapperCache, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(IDBWrapperCache, nsDOMEventTargetHelper)
|
||||
|
||||
IDBWrapperCache::~IDBWrapperCache()
|
||||
{
|
||||
if (mScriptOwner) {
|
||||
NS_DROP_JS_OBJECTS(this, IDBWrapperCache);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBWrapperCache::SetScriptOwner(JSObject* aScriptOwner)
|
||||
{
|
||||
if (!aScriptOwner) {
|
||||
NS_ASSERTION(!mScriptOwner,
|
||||
"Don't null out existing owner, we need to call "
|
||||
"DropJSObjects!");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mScriptOwner = aScriptOwner;
|
||||
|
||||
nsISupports* thisSupports = NS_CYCLE_COLLECTION_UPCAST(this, IDBWrapperCache);
|
||||
nsXPCOMCycleCollectionParticipant* participant;
|
||||
CallQueryInterface(this, &participant);
|
||||
nsresult rv = nsContentUtils::HoldJSObjects(thisSupports, participant);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsContentUtils::HoldJSObjects failed.");
|
||||
mScriptOwner = nsnull;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user