--- a/.hgignore
+++ b/.hgignore
@@ -1,14 +1,15 @@
# .hgignore - List of filenames hg should ignore
# Filenames that should be ignored wherever they appear
~$
\.pyc$
(^|/)TAGS$
+\.DS_Store$
# User files that may appear at the root
^\.mozconfig$
^mozconfig$
^\.mozconfig\.mk$
^\.mozconfig\.out$
^configure$
^config\.cache$
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -165,16 +165,17 @@ ACCESSIBILITY_ATOM(data, "data")
ACCESSIBILITY_ATOM(droppable, "droppable") // XUL combo box
ACCESSIBILITY_ATOM(editable, "editable")
ACCESSIBILITY_ATOM(_for, "for")
ACCESSIBILITY_ATOM(hidden, "hidden") // XUL tree columns
ACCESSIBILITY_ATOM(href, "href") // XUL, XLink
ACCESSIBILITY_ATOM(increment, "increment") // XUL
ACCESSIBILITY_ATOM(lang, "lang")
ACCESSIBILITY_ATOM(linkedPanel, "linkedpanel") // XUL
+ACCESSIBILITY_ATOM(longDesc, "longdesc")
ACCESSIBILITY_ATOM(maxpos, "maxpos") // XUL
ACCESSIBILITY_ATOM(minpos, "minpos") // XUL
ACCESSIBILITY_ATOM(multiline, "multiline") // XUL
ACCESSIBILITY_ATOM(name, "name")
ACCESSIBILITY_ATOM(onclick, "onclick")
ACCESSIBILITY_ATOM(readonly, "readonly")
ACCESSIBILITY_ATOM(simple, "simple") // XLink
ACCESSIBILITY_ATOM(src, "src")
@@ -182,16 +183,17 @@ ACCESSIBILITY_ATOM(selected, "selected")
ACCESSIBILITY_ATOM(summary, "summary")
ACCESSIBILITY_ATOM(tabindex, "tabindex")
ACCESSIBILITY_ATOM(title, "title")
ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
ACCESSIBILITY_ATOM(type, "type")
ACCESSIBILITY_ATOM(value, "value")
// Alphabetical list of text attributes (AT API)
+ACCESSIBILITY_ATOM(backgroundColor, "background-color")
ACCESSIBILITY_ATOM(invalid, "invalid")
ACCESSIBILITY_ATOM(language, "language")
// ARIA (DHTML accessibility) attributes
// Also add to nsARIAMap.cpp and nsARIAMap.h
// ARIA role attribute
ACCESSIBILITY_ATOM(role, "role")
ACCESSIBILITY_ATOM(aria_activedescendant, "aria-activedescendant")
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -796,16 +796,30 @@ nsAccUtils::GetDocShellTreeItemFor(nsIDO
nsCOMPtr<nsISupports> container = doc->GetContainer();
nsIDocShellTreeItem *docShellTreeItem = nsnull;
if (container)
CallQueryInterface(container, &docShellTreeItem);
return docShellTreeItem;
}
+nsIFrame*
+nsAccUtils::GetFrameFor(nsIDOMElement *aElm)
+{
+ nsCOMPtr<nsIPresShell> shell = nsAccessNode::GetPresShellFor(aElm);
+ if (!shell)
+ return nsnull;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
+ if (!content)
+ return nsnull;
+
+ return shell->GetPrimaryFrameFor(content);
+}
+
PRBool
nsAccUtils::GetID(nsIContent *aContent, nsAString& aID)
{
nsIAtom *idAttribute = aContent->GetIDAttributeName();
return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : PR_FALSE;
}
PRBool
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -303,16 +303,21 @@ public:
/**
* Return document shell tree item for the given DOM node.
*/
static already_AddRefed<nsIDocShellTreeItem>
GetDocShellTreeItemFor(nsIDOMNode *aNode);
/**
+ * Retrun frame for the given DOM element.
+ */
+ static nsIFrame* GetFrameFor(nsIDOMElement *aElm);
+
+ /**
* Get the ID for an element, in some types of XML this may not be the ID attribute
* @param aContent Node to get the ID for
* @param aID Where to put ID string
* @return PR_TRUE if there is an ID set for this node
*/
static PRBool GetID(nsIContent *aContent, nsAString& aID);
/**
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -100,16 +100,18 @@ nsApplicationAccessible::Init()
return rv;
}
// nsIAccessible
NS_IMETHODIMP
nsApplicationAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID);
NS_ASSERTION(bundleService, "String bundle service must be present!");
NS_ENSURE_STATE(bundleService);
nsCOMPtr<nsIStringBundle> bundle;
bundleService->CreateBundle("chrome://branding/locale/brand.properties",
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -113,18 +113,21 @@ nsRootAccessible::nsRootAccessible(nsIDO
// destruction
//-----------------------------------------------------
nsRootAccessible::~nsRootAccessible()
{
}
// helpers
/* readonly attribute AString name; */
-NS_IMETHODIMP nsRootAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsRootAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
if (!mDocument) {
return NS_ERROR_FAILURE;
}
if (mRoleMapEntry) {
nsAccessible::GetName(aName);
if (!aName.IsEmpty()) {
return NS_OK;
--- a/accessible/src/base/nsTextUtils.cpp
+++ b/accessible/src/base/nsTextUtils.cpp
@@ -34,22 +34,23 @@
* 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 ***** */
#include "nsTextUtils.h"
#include "nsAccessNode.h"
+#include "nsAccessibilityUtils.h"
////////////////////////////////////////////////////////////////////////////////
// nsLangTextAttr
PRBool
-nsLangTextAttr::equal(nsIDOMElement *aElm)
+nsLangTextAttr::Equal(nsIDOMElement *aElm)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
if (!content)
return PR_FALSE;
nsAutoString lang;
nsAccUtils::GetLanguageFor(content, mRootContent, lang);
@@ -75,17 +76,16 @@ struct nsCSSTextAttrMapItem
*/
const char* const kAnyValue = nsnull;
const char* const kCopyName = nsnull;
const char* const kCopyValue = nsnull;
static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = {
// CSS name CSS value Attribute name Attribute name
- { "background-color", kAnyValue, kCopyName, kCopyValue },
{ "color", kAnyValue, kCopyName, kCopyValue },
{ "font-family", kAnyValue, kCopyName, kCopyValue },
{ "font-size", kAnyValue, kCopyName, kCopyValue },
{ "font-style", kAnyValue, kCopyName, kCopyValue },
{ "font-weight", kAnyValue, kCopyName, kCopyValue },
{ "text-decoration", "line-through", "text-line-through-style", "solid" },
{ "text-decoration", "underline", "text-underline-style", "solid" },
{ "text-align", kAnyValue, kCopyName, kCopyValue },
@@ -101,17 +101,17 @@ nsCSSTextAttr::nsCSSTextAttr(PRBool aInc
getter_AddRefs(mStyleDecl));
if (!mIncludeDefAttrValue)
nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aRootElm,
getter_AddRefs(mDefStyleDecl));
}
PRBool
-nsCSSTextAttr::equal(nsIDOMElement *aElm)
+nsCSSTextAttr::Equal(nsIDOMElement *aElm)
{
if (!aElm || !mStyleDecl)
return PR_FALSE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl;
nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
getter_AddRefs(currStyleDecl));
if (!currStyleDecl)
@@ -125,23 +125,23 @@ nsCSSTextAttr::equal(nsIDOMElement *aElm
return PR_FALSE;
nsAutoString value;
rv = mStyleDecl->GetPropertyValue(cssName, value);
return NS_SUCCEEDED(rv) && value == currValue;
}
PRBool
-nsCSSTextAttr::iterate()
+nsCSSTextAttr::Iterate()
{
return ++mIndex < static_cast<PRInt32>(NS_ARRAY_LENGTH(gCSSTextAttrsMap));
}
PRBool
-nsCSSTextAttr::get(nsACString& aName, nsAString& aValue)
+nsCSSTextAttr::Get(nsACString& aName, nsAString& aValue)
{
if (!mStyleDecl)
return PR_FALSE;
NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
nsresult rv = mStyleDecl->GetPropertyValue(cssName, aValue);
if (NS_FAILED(rv))
return PR_FALSE;
@@ -174,8 +174,70 @@ nsCSSTextAttr::get(nsACString& aName, ns
// Get the value of text attribute.
const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
if (attrValue != kCopyValue)
AppendASCIItoUTF16(attrValue, aValue);
return PR_TRUE;
}
+////////////////////////////////////////////////////////////////////////////////
+// nsBackgroundTextAttr
+
+nsBackgroundTextAttr::nsBackgroundTextAttr(nsIFrame *aFrame,
+ nsIFrame *aRootFrame) :
+ mFrame(aFrame), mRootFrame(aRootFrame)
+{
+}
+
+PRBool
+nsBackgroundTextAttr::Equal(nsIDOMElement *aElm)
+{
+ nsIFrame *frame = nsAccUtils::GetFrameFor(aElm);
+ if (!frame)
+ return PR_FALSE;
+
+ return GetColor(mFrame) == GetColor(frame);
+}
+
+PRBool
+nsBackgroundTextAttr::Get(nsAString& aValue)
+{
+ // Do not expose "background-color" text attribute if its value is matched
+ // with the default value.
+ nscolor color = GetColor(mFrame);
+ if (mRootFrame && color == GetColor(mRootFrame))
+ return PR_FALSE;
+
+ // Combine the string like rgb(R, G, B) from nscolor.
+ nsAutoString value;
+ value.AppendLiteral("rgb(");
+ value.AppendInt(NS_GET_R(color));
+ value.AppendLiteral(", ");
+ value.AppendInt(NS_GET_G(color));
+ value.AppendLiteral(", ");
+ value.AppendInt(NS_GET_B(color));
+ value.Append(')');
+
+ aValue = value;
+ return PR_TRUE;
+}
+
+nscolor
+nsBackgroundTextAttr::GetColor(nsIFrame *aFrame)
+{
+ const nsStyleBackground *styleBackground = aFrame->GetStyleBackground();
+
+ if (!styleBackground->IsTransparent())
+ return styleBackground->mBackgroundColor;
+
+ nsIFrame *parentFrame = aFrame->GetParent();
+ if (!parentFrame)
+ return styleBackground->mBackgroundColor;
+
+ // Each frame of parents chain for the initially passed 'aFrame' has
+ // transparent background color. So background color isn't changed from
+ // 'mRootFrame' to initially passed 'aFrame'.
+ if (parentFrame == mRootFrame)
+ return GetColor(mRootFrame);
+
+ return GetColor(parentFrame);
+}
--- a/accessible/src/base/nsTextUtils.h
+++ b/accessible/src/base/nsTextUtils.h
@@ -38,44 +38,45 @@
#ifndef nsTextUtils_h_
#define nsTextUtils_h_
#include "nsIDOMElement.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIContent.h"
+#include "nsIFrame.h"
#include "nsCOMPtr.h"
#include "nsString.h"
/**
* Base class to work with text attributes. See derived classes below.
*/
class nsTextAttr
{
public:
/**
* Return true if the text attribute for the given element equals with
* predefined attribute.
*/
- virtual PRBool equal(nsIDOMElement *aElm) = 0;
+ virtual PRBool Equal(nsIDOMElement *aElm) = 0;
};
/**
* Class is used for the work with 'lang' text attributes. Used in
* nsHyperTextAccessible.
*/
class nsLangTextAttr : public nsTextAttr
{
public:
nsLangTextAttr(nsAString& aLang, nsIContent *aRootContent) :
mLang(aLang), mRootContent(aRootContent) { }
- virtual PRBool equal(nsIDOMElement *aElm);
+ virtual PRBool Equal(nsIDOMElement *aElm);
private:
nsString mLang;
nsCOMPtr<nsIContent> mRootContent;
};
/**
* Class is used for the work with CSS based text attributes. Used in
@@ -83,30 +84,66 @@ private:
*/
class nsCSSTextAttr : public nsTextAttr
{
public:
nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
nsIDOMElement *aRootElm);
// nsTextAttr
- virtual PRBool equal(nsIDOMElement *aElm);
+ virtual PRBool Equal(nsIDOMElement *aElm);
// nsCSSTextAttr
/**
* Interates through attributes.
*/
- PRBool iterate();
+ PRBool Iterate();
/**
* Get name and value of attribute.
*/
- PRBool get(nsACString& aName, nsAString& aValue);
+ PRBool Get(nsACString& aName, nsAString& aValue);
private:
PRInt32 mIndex;
PRBool mIncludeDefAttrValue;
nsCOMPtr<nsIDOMCSSStyleDeclaration> mStyleDecl;
nsCOMPtr<nsIDOMCSSStyleDeclaration> mDefStyleDecl;
};
+/**
+ * Class is used for the work with "background-color" text attribute. It is
+ * used in nsHyperTextAccessible.
+ */
+class nsBackgroundTextAttr : public nsTextAttr
+{
+public:
+ nsBackgroundTextAttr(nsIFrame *aFrame, nsIFrame *aRootFrame);
+
+ // nsTextAttr
+ virtual PRBool Equal(nsIDOMElement *aElm);
+
+ /**
+ * Returns true and background color value if "background-color" text
+ * attribute should be exposed.
+ */
+ virtual PRBool Get(nsAString& aValue);
+
+private:
+ /**
+ * Return background color for the given frame.
+ *
+ * @note If background color for the given frame is transparent then walk
+ * trhough the frame parents chain until we'll got either a frame with
+ * not transparent background color or the given root frame. In the
+ * last case return background color for the root frame.
+ *
+ * @param aFrame [in] the given frame to calculate background-color
+ * @return background color
+ */
+ nscolor GetColor(nsIFrame *aFrame);
+
+ nsIFrame *mFrame;
+ nsIFrame *mRootFrame;
+};
+
#endif
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -270,18 +270,21 @@ nsHTMLButtonAccessible::GetState(PRUint3
}
NS_IMETHODIMP nsHTMLButtonAccessible::GetRole(PRUint32 *_retval)
{
*_retval = nsIAccessibleRole::ROLE_PUSHBUTTON;
return NS_OK;
}
-NS_IMETHODIMP nsHTMLButtonAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLButtonAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content) {
return NS_ERROR_FAILURE; // Node shut down
}
nsAutoString name;
// Prefer aria-labelledby attribute for name
if (content->HasAttr(kNameSpaceID_None,
@@ -393,18 +396,21 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible:
if (content &&
content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
nsAccessibilityAtoms::password, eIgnoreCase)) {
*aRole = nsIAccessibleRole::ROLE_PASSWORD_TEXT;
}
return NS_OK;
}
-NS_IMETHODIMP nsHTMLTextFieldAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLTextFieldAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
if (!content) {
return NS_ERROR_FAILURE;
}
nsresult rv = GetHTMLName(aName, PR_FALSE);
if (NS_FAILED(rv) || !aName.IsEmpty() || !content->GetBindingParent()) {
return rv;
}
@@ -601,22 +607,24 @@ nsIContent* nsHTMLGroupboxAccessible::Ge
// Either XHTML namespace or no namespace
return testLegendContent;
}
}
return nsnull;
}
-NS_IMETHODIMP nsHTMLGroupboxAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLGroupboxAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
if (!mDOMNode) {
return NS_ERROR_FAILURE;
}
- aName.Truncate();
if (mRoleMapEntry) {
nsAccessible::GetName(aName);
if (!aName.IsEmpty()) {
return NS_OK;
}
}
nsIContent *legendContent = GetLegend();
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -205,19 +205,56 @@ void nsHTMLImageAccessible::CacheChildre
privatePrevAccessible = do_QueryInterface(areaAccessible);
NS_ASSERTION(privatePrevAccessible, "nsIAccessible impl's should always support nsPIAccessible as well");
privatePrevAccessible->SetParent(this);
}
mAccChildCount = childCount;
}
-NS_IMETHODIMP nsHTMLImageAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsHTMLImageAccessible::GetNumActions(PRUint8 *aNumActions)
{
- if (index == eAction_ShowLongDescription) {
+ NS_ENSURE_ARG_POINTER(aNumActions);
+ *aNumActions = 0;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsresult rv= nsLinkableAccessible::GetNumActions(aNumActions);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (HasLongDesc())
+ (*aNumActions)++;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLImageAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+ aName.Truncate();
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ if (IsValidLongDescIndex(aIndex)) {
+ aName.AssignLiteral("showlongdesc");
+ return NS_OK;
+ }
+ return nsLinkableAccessible::GetActionName(aIndex, aName);
+}
+
+NS_IMETHODIMP
+nsHTMLImageAccessible::DoAction(PRUint8 aIndex)
+{
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ if (IsValidLongDescIndex(aIndex)) {
//get the long description uri and open in a new window
nsCOMPtr<nsIDOMHTMLImageElement> element(do_QueryInterface(mDOMNode));
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
nsAutoString longDesc;
nsresult rv = element->GetLongDesc(longDesc);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> domDocument;
rv = mDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
@@ -225,17 +262,17 @@ NS_IMETHODIMP nsHTMLImageAccessible::DoA
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow();
nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(piWindow));
NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMWindow> tmp;
return win->Open(longDesc, NS_LITERAL_STRING(""), NS_LITERAL_STRING(""),
getter_AddRefs(tmp));
}
- return nsLinkableAccessible::DoAction(index);
+ return nsLinkableAccessible::DoAction(aIndex);
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleHyperLink
NS_IMETHODIMP
nsHTMLImageAccessible::GetAnchorCount(PRInt32 *aAnchorCount)
{
NS_ENSURE_ARG_POINTER(aAnchorCount);
@@ -400,8 +437,34 @@ nsHTMLImageAccessible::GetAreaAccessible
PutCacheEntry(*mAccessNodeCache, (void*)(aAreaNum), accessNode);
}
nsIAccessible *accessible = nsnull;
CallQueryInterface(accessNode, &accessible);
return accessible;
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private methods
+
+PRBool
+nsHTMLImageAccessible::HasLongDesc()
+{
+ if (IsDefunct())
+ return PR_FALSE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ return (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::longDesc));
+}
+
+PRBool
+nsHTMLImageAccessible::IsValidLongDescIndex(PRUint8 aIndex)
+{
+ if (!HasLongDesc())
+ return PR_FALSE;
+
+ PRUint8 numActions = 0;
+ nsresult rv = nsLinkableAccessible::GetNumActions(&numActions);
+ NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+ return (aIndex == numActions);
+}
--- a/accessible/src/html/nsHTMLImageAccessible.h
+++ b/accessible/src/html/nsHTMLImageAccessible.h
@@ -50,25 +50,24 @@
*/
class nsHTMLImageAccessible : public nsLinkableAccessible,
public nsIAccessibleImage
{
NS_DECL_ISUPPORTS_INHERITED
public:
- //action0 may exist depends on whether an onclick is associated with it
- enum { eAction_ShowLongDescription = 1 };
-
nsHTMLImageAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
// nsIAccessible
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetRole(PRUint32 *_retval);
+ NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+ NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index);
// nsIAccessibleHyperLink
NS_IMETHOD GetAnchorCount(PRInt32 *aAnchorCount);
NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
NS_IMETHOD GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible);
// nsPIAccessNode
@@ -90,12 +89,31 @@ protected:
// Reference on linked map element if any.
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
// Cache of area accessibles. We do not use common cache because images can
// share area elements but we need to have separate area accessibles for
// each image accessible.
nsAccessNodeHashtable *mAccessNodeCache;
+
+private:
+ /**
+ * Determine if this image accessible has a longdesc attribute.
+ *
+ * @returns true if the longdesc attribute is present.
+ */
+ PRBool HasLongDesc();
+
+ /**
+ * Used by GetActionName and DoAction to ensure the index for opening the
+ * longdesc URL is valid.
+ * It is always assumed that the highest possible index opens the longdesc.
+ *
+ * @param aIndex The 0-based index to be tested.
+ *
+ * @returns true if index is valid for longdesc action.
+ */
+ PRBool IsValidLongDescIndex(PRUint8 aIndex);
};
#endif
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -508,18 +508,21 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessib
*aRole = nsIAccessibleRole::ROLE_OPTION;
}
return NS_OK;
}
/**
* Get our Name from our Content's subtree
*/
-NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLSelectOptionAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
// CASE #1 -- great majority of the cases
// find the label attribute - this is what the W3C says we should use
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
if (!domElement)
return NS_ERROR_FAILURE;
nsresult rv = domElement->GetAttribute(NS_LITERAL_STRING("label"), aName) ;
if (NS_SUCCEEDED(rv) && !aName.IsEmpty()) {
@@ -1378,18 +1381,21 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccess
{
NS_IF_ADDREF(*aParent = mParent);
return NS_OK;
}
/**
* Gets the name from GetActionName()
*/
-NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsHTMLComboboxButtonAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
return GetActionName(eAction_Click, aName);
}
/**
* As a nsHTMLComboboxButtonAccessible we can have the following states:
* STATE_PRESSED
* STATE_FOCUSED
* STATE_FOCUSABLE
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -730,16 +730,40 @@ nsHyperTextAccessible::HypertextOffsetsT
*aStartOffset = -1;
NS_ENSURE_ARG_POINTER(aEndNode);
*aEndNode = nsnull;
NS_ENSURE_ARG_POINTER(aEndOffset);
*aEndOffset = -1;
+ // If the given offsets are 0 and associated editor is empty then return
+ // collapsed range with editor root element as range container.
+ if (aStartHTOffset == 0 && aEndHTOffset == 0) {
+ nsCOMPtr<nsIEditor> editor;
+ GetAssociatedEditor(getter_AddRefs(editor));
+ if (editor) {
+ PRBool isEmpty = PR_FALSE;
+ editor->GetDocumentIsEmpty(&isEmpty);
+ if (isEmpty) {
+ nsCOMPtr<nsIDOMElement> editorRootElm;
+ editor->GetRootElement(getter_AddRefs(editorRootElm));
+
+ nsCOMPtr<nsIDOMNode> editorRoot(do_QueryInterface(editorRootElm));
+ if (editorRoot) {
+ *aStartOffset = *aEndOffset = 0;
+ NS_ADDREF(*aStartNode = editorRoot);
+ NS_ADDREF(*aEndNode = editorRoot);
+
+ return NS_OK;
+ }
+ }
+ }
+ }
+
nsCOMPtr<nsIAccessible> startAcc, endAcc;
PRInt32 startOffset = aStartHTOffset, endOffset = aEndHTOffset;
nsIFrame *startFrame = nsnull, *endFrame = nsnull;
startFrame = GetPosAndText(startOffset, endOffset, nsnull, &endFrame, nsnull,
getter_AddRefs(startAcc), getter_AddRefs(endAcc));
if (!startAcc || !endAcc)
return NS_ERROR_FAILURE;
@@ -1175,22 +1199,34 @@ nsHyperTextAccessible::GetDefaultTextAtt
NS_ADDREF(*aAttributes = attributes);
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> element = nsAccUtils::GetDOMElementFor(mDOMNode);
nsCSSTextAttr textAttr(PR_TRUE, element, nsnull);
- while (textAttr.iterate()) {
+ while (textAttr.Iterate()) {
nsCAutoString name;
nsAutoString value, oldValue;
- if (textAttr.get(name, value))
+ if (textAttr.Get(name, value))
attributes->SetStringProperty(name, value, oldValue);
}
+
+ nsIFrame *sourceFrame = nsAccUtils::GetFrameFor(element);
+ if (sourceFrame) {
+ nsBackgroundTextAttr backgroundTextAttr(sourceFrame, nsnull);
+
+ nsAutoString value;
+ if (backgroundTextAttr.Get(value)) {
+ nsAccUtils::SetAccAttr(attributes,
+ nsAccessibilityAtoms::backgroundColor, value);
+ }
+ }
+
return NS_OK;
}
nsresult
nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
if (!mDOMNode) {
return NS_ERROR_FAILURE; // Node already shut down
@@ -2283,27 +2319,46 @@ nsHyperTextAccessible::GetCSSTextAttribu
PRInt32 *aStartHTOffset,
PRInt32 *aEndHTOffset,
nsIPersistentProperties *aAttributes)
{
nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm);
- while (textAttr.iterate()) {
+ while (textAttr.Iterate()) {
nsCAutoString name;
nsAutoString value, oldValue;
- if (aAttributes && textAttr.get(name, value))
+ if (aAttributes && textAttr.Get(name, value))
aAttributes->SetStringProperty(name, value, oldValue);
nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr,
aStartHTOffset, aEndHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
+ nsIFrame *sourceFrame = nsAccUtils::GetFrameFor(sourceElm);
+ if (sourceFrame) {
+ nsIFrame *rootFrame = nsnull;
+
+ if (!aIncludeDefAttrs)
+ rootFrame = nsAccUtils::GetFrameFor(rootElm);
+
+ nsBackgroundTextAttr backgroundTextAttr(sourceFrame, rootFrame);
+ nsAutoString value;
+ if (backgroundTextAttr.Get(value)) {
+ nsAccUtils::SetAccAttr(aAttributes,
+ nsAccessibilityAtoms::backgroundColor, value);
+ }
+
+ nsresult rv = GetRangeForTextAttr(aSourceNode, &backgroundTextAttr,
+ aStartHTOffset, aEndHTOffset);
+ return rv;
+ }
+
return NS_OK;
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode,
nsTextAttr *aComparer,
PRInt32 *aStartHTOffset,
@@ -2323,17 +2378,17 @@ nsHyperTextAccessible::GetRangeForTextAt
// to it through whole tree of the traversed sibling.
// 3. Get the parent and cycle algorithm until the root node.
// Navigate backwards (find the start offset).
while (currNode && currNode != rootElm) {
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
NS_ENSURE_STATE(currElm);
- if (currNode != aNode && !aComparer->equal(currElm)) {
+ if (currNode != aNode && !aComparer->Equal(currElm)) {
PRInt32 startHTOffset = 0;
nsCOMPtr<nsIAccessible> startAcc;
nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
getter_AddRefs(startAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (!startAcc)
startHTOffset = 0;
@@ -2359,17 +2414,17 @@ nsHyperTextAccessible::GetRangeForTextAt
PRBool moveIntoSubtree = PR_TRUE;
currNode = aNode;
while (currNode && currNode != rootElm) {
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
NS_ENSURE_STATE(currElm);
// Stop new end offset searching if the given text attribute changes its
// value.
- if (!aComparer->equal(currElm)) {
+ if (!aComparer->Equal(currElm)) {
PRInt32 endHTOffset = 0;
nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (endHTOffset < *aEndHTOffset)
*aEndHTOffset = endHTOffset;
break;
@@ -2405,17 +2460,17 @@ nsHyperTextAccessible::FindEndOffsetInSu
if (!aCurrNode)
return PR_FALSE;
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
NS_ENSURE_STATE(currElm);
// If the given text attribute (pointed by nsTextAttr object) changes its
// value on the traversed element then fit the end of range.
- if (!aComparer->equal(currElm)) {
+ if (!aComparer->Equal(currElm)) {
PRInt32 endHTOffset = 0;
nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (endHTOffset < *aHTOffset)
*aHTOffset = endHTOffset;
return PR_TRUE;
@@ -2456,17 +2511,17 @@ nsHyperTextAccessible::FindStartOffsetIn
return PR_TRUE;
}
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
NS_ENSURE_STATE(currElm);
// If the given text attribute (pointed by nsTextAttr object) changes its
// value on the traversed element then fit the start of range.
- if (!aComparer->equal(currElm)) {
+ if (!aComparer->Equal(currElm)) {
PRInt32 startHTOffset = 0;
nsCOMPtr<nsIAccessible> startAcc;
nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
getter_AddRefs(startAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (!startAcc)
startHTOffset = 0;
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -32,17 +32,16 @@
* 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 ***** */
#include "nsAccessNodeWrap.h"
-#include <tchar.h>
#include "ISimpleDOMNode_i.c"
#include "nsAccessibilityAtoms.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessible.h"
#include "nsAttrName.h"
#include "nsIDocument.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMNodeList.h"
@@ -67,16 +66,20 @@ LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmN
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
// Used to determine whether an IAccessible2 compatible screen reader is loaded.
PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
nsIAccessibleTextChangeEvent *nsAccessNodeWrap::gTextEvent = nsnull;
+// Pref to disallow CtrlTab preview functionality if JAWS or Window-Eyes are
+// running.
+#define CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF "browser.ctrlTab.disallowForScreenReaders"
+
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
/*
* Class nsAccessNodeWrap
*/
@@ -587,17 +590,17 @@ void nsAccessNodeWrap::InitAccessibility
}
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefBranch) {
prefBranch->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
}
if (!gmUserLib) {
- gmUserLib =::LoadLibrary("USER32.DLL");
+ gmUserLib =::LoadLibraryW(L"USER32.DLL");
}
if (gmUserLib) {
if (!gmNotifyWinEvent)
gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
if (!gmGetGUIThreadInfo)
gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
}
@@ -657,17 +660,17 @@ GetHRESULT(nsresult aResult)
default:
return E_FAIL;
}
}
PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
{
- HMODULE jhookhandle = ::GetModuleHandleW(NS_LITERAL_STRING("jhook").get());
+ HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
if (!jhookhandle)
return PR_FALSE; // No JAWS, or some other screen reader, use IA2
PRUnichar fileName[MAX_PATH];
::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
DWORD dummy;
DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
@@ -686,14 +689,49 @@ PRBool nsAccessNodeWrap::IsOnlyMsaaCompa
// DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
DWORD dwSecondRight = HIWORD(dwFileVersionLS);
// DWORD dwRightMost = LOWORD(dwFileVersionLS);
return (dwLeftMost < 8
|| (dwLeftMost == 8 && dwSecondRight < 2173));
}
+void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
+{
+ HMODULE srHandle = ::GetModuleHandleW(L"jhook");
+ if (!srHandle) {
+ // No JAWS, try Window-Eyes
+ srHandle = ::GetModuleHandleW(L"gwm32inc");
+ if (!srHandle) {
+ // no screen reader we're interested in. Bail out.
+ return;
+ }
+ }
+
+ // Check to see if the pref for disallowing CtrlTab is already set.
+ // If so, bail out.
+ // If not, set it.
+ nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (prefs) {
+ PRBool hasDisallowNewCtrlTabPref = PR_FALSE;
+ nsresult rv = prefs->PrefHasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF,
+ &hasDisallowNewCtrlTabPref);
+ if (NS_SUCCEEDED(rv) && hasDisallowNewCtrlTabPref) {
+ // This pref has been set before. There is no default for it.
+ // Do nothing further, respect the setting that's there.
+ // That way, if noone touches it, it'll stay on after toggled once.
+ // If someone decided to turn it off, we respect that, too.
+ return;
+ }
+
+ // Value has never been set, set it.
+ prefs->SetBoolPref(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
+ }
+}
+
void nsAccessNodeWrap::DoATSpecificProcessing()
{
if (IsOnlyMsaaCompatibleJawsPresent())
// All versions below 8.0.2173 are not compatible
gIsIA2Disabled = PR_TRUE;
+
+ TurnOffNewTabSwitchingForJawsAndWE();
}
--- a/accessible/src/msaa/nsAccessNodeWrap.h
+++ b/accessible/src/msaa/nsAccessNodeWrap.h
@@ -154,16 +154,19 @@ class nsAccessNodeWrap : public nsAcces
static HINSTANCE gmUserLib;
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
static int FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo);
static PRBool IsOnlyMsaaCompatibleJawsPresent();
+
+ static void TurnOffNewTabSwitchingForJawsAndWE();
+
static void DoATSpecificProcessing();
protected:
void GetAccessibleFor(nsIDOMNode *node, nsIAccessible **newAcc);
ISimpleDOMNode* MakeAccessNode(nsIDOMNode *node);
static PRBool gIsEnumVariantSupportDisabled;
/**
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -153,17 +153,17 @@ STDMETHODIMP nsAccessibleWrap::QueryInte
STDMETHODIMP nsAccessibleWrap::AccessibleObjectFromWindow(HWND hwnd,
DWORD dwObjectID,
REFIID riid,
void **ppvObject)
{
// open the dll dynamically
if (!gmAccLib)
- gmAccLib =::LoadLibrary("OLEACC.DLL");
+ gmAccLib =::LoadLibraryW(L"OLEACC.DLL");
if (gmAccLib) {
if (!gmAccessibleObjectFromWindow)
gmAccessibleObjectFromWindow = (LPFNACCESSIBLEOBJECTFROMWINDOW)GetProcAddress(gmAccLib,"AccessibleObjectFromWindow");
if (gmAccessibleObjectFromWindow)
return gmAccessibleObjectFromWindow(hwnd, dwObjectID, riid, ppvObject);
}
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -87,19 +87,22 @@ nsXULColorPickerTileAccessible::GetState
PRBool isSelected = PR_FALSE;
element->HasAttribute(NS_LITERAL_STRING("selected"), &isSelected);
if (isFocused)
*aState |= nsIAccessibleStates::STATE_SELECTED;
return NS_OK;
}
-NS_IMETHODIMP nsXULColorPickerTileAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULColorPickerTileAccessible::GetName(nsAString& aName)
{
- return GetXULName(_retval);
+ aName.Truncate();
+
+ return GetXULName(aName);
}
NS_IMETHODIMP nsXULColorPickerTileAccessible::GetValue(nsAString& _retval)
{
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -384,23 +384,26 @@ nsXULMenuitemAccessible::GetState(PRUint
}
}
*aState|= (nsIAccessibleStates::STATE_FOCUSABLE |
nsIAccessibleStates::STATE_SELECTABLE);
return NS_OK;
}
-NS_IMETHODIMP nsXULMenuitemAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenuitemAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if (!element) {
return NS_ERROR_FAILURE;
}
- element->GetAttribute(NS_LITERAL_STRING("label"), _retval);
+ element->GetAttribute(NS_LITERAL_STRING("label"), aName);
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetDescription(nsAString& aDescription)
{
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if (!element) {
@@ -573,19 +576,21 @@ nsXULMenuSeparatorAccessible::GetState(P
}
*aState &= (nsIAccessibleStates::STATE_OFFSCREEN |
nsIAccessibleStates::STATE_INVISIBLE);
return NS_OK;
}
-NS_IMETHODIMP nsXULMenuSeparatorAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenuSeparatorAccessible::GetName(nsAString& aName)
{
- _retval.Truncate();
+ aName.Truncate();
+
return NS_OK;
}
NS_IMETHODIMP nsXULMenuSeparatorAccessible::GetRole(PRUint32 *_retval)
{
*_retval = nsIAccessibleRole::ROLE_SEPARATOR;
return NS_OK;
}
@@ -747,19 +752,20 @@ nsXULMenubarAccessible::GetState(PRUint3
}
// Menu bar iteself is not actually focusable
*aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
return rv;
}
-NS_IMETHODIMP nsXULMenubarAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULMenubarAccessible::GetName(nsAString& aName)
{
- _retval.AssignLiteral("Application");
+ aName.AssignLiteral("Application");
return NS_OK;
}
NS_IMETHODIMP nsXULMenubarAccessible::GetRole(PRUint32 *_retval)
{
*_retval = nsIAccessibleRole::ROLE_MENUBAR;
return NS_OK;
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -105,16 +105,18 @@ nsXULColumnItemAccessible::GetState(PRUi
*aExtraState = mDOMNode ? 0 : nsIAccessibleStates::EXT_STATE_DEFUNCT ;
}
return NS_OK;
}
NS_IMETHODIMP
nsXULColumnItemAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
return GetXULName(aName);
}
NS_IMETHODIMP
nsXULColumnItemAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
@@ -852,34 +854,37 @@ nsXULListitemAccessible::GetListAccessib
////////////////////////////////////////////////////////////////////////////////
// nsXULListitemAccessible. nsIAccessible
/**
* If there is a Listcell as a child ( not anonymous ) use it, otherwise
* default to getting the name from GetXULName
*/
-NS_IMETHODIMP nsXULListitemAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULListitemAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> child;
if (NS_SUCCEEDED(mDOMNode->GetFirstChild(getter_AddRefs(child)))) {
nsCOMPtr<nsIDOMElement> childElement (do_QueryInterface(child));
if (childElement) {
nsAutoString tagName;
childElement->GetLocalName(tagName);
if (tagName.EqualsLiteral("listcell")) {
- childElement->GetAttribute(NS_LITERAL_STRING("label"), _retval);
+ childElement->GetAttribute(NS_LITERAL_STRING("label"), aName);
return NS_OK;
}
}
}
- return GetXULName(_retval);
+ return GetXULName(aName);
}
/**
*
*/
NS_IMETHODIMP nsXULListitemAccessible::GetRole(PRUint32 *aRole)
{
nsCOMPtr<nsIAccessible> listAcc = GetListAccessible();
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -292,19 +292,21 @@ NS_IMETHODIMP nsXULTabsAccessible::GetNu
/** no value */
NS_IMETHODIMP nsXULTabsAccessible::GetValue(nsAString& _retval)
{
return NS_OK;
}
/** no name*/
-NS_IMETHODIMP nsXULTabsAccessible::GetName(nsAString& _retval)
+NS_IMETHODIMP
+nsXULTabsAccessible::GetName(nsAString& aName)
{
- _retval.Truncate();
+ aName.Truncate();
+
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULTabpanelAccessible
nsXULTabpanelAccessible::
nsXULTabpanelAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -51,18 +51,21 @@
* For XUL descriptions and labels
*/
nsXULTextAccessible::nsXULTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
/* wstring getName (); */
-NS_IMETHODIMP nsXULTextAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTextAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content) {
return NS_ERROR_FAILURE; // Node shut down
}
// if the value attr doesn't exist, the screen reader must get the accessible text
// from the accessible text interface or from the children
return content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
}
@@ -112,18 +115,21 @@ nsXULTextAccessible::GetAccessibleRelate
/**
* For XUL tooltip
*/
nsXULTooltipAccessible::nsXULTooltipAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
nsLeafAccessible(aDomNode, aShell)
{
}
-NS_IMETHODIMP nsXULTooltipAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTooltipAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
return GetXULName(aName, PR_TRUE);
}
NS_IMETHODIMP
nsXULTooltipAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsLeafAccessible::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -778,18 +778,21 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeit
NS_IMETHODIMP nsXULTreeitemAccessible::Shutdown()
{
mTree = nsnull;
mTreeView = nsnull;
mColumn = nsnull;
return nsLeafAccessible::Shutdown();
}
-NS_IMETHODIMP nsXULTreeitemAccessible::GetName(nsAString& aName)
+NS_IMETHODIMP
+nsXULTreeitemAccessible::GetName(nsAString& aName)
{
+ aName.Truncate();
+
if (IsDefunct())
return NS_ERROR_FAILURE;
mTreeView->GetCellText(mRow, mColumn, aName);
// If there is still no name try the cell value:
// This is for graphical cells. We need tree/table view implementors to implement
// FooView::GetCellValue to return a meaningful string for cases where there is
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -42,43 +42,48 @@ srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = accessible
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
moz.png \
+ longdesc_src.html \
+ common.js \
nsIAccessible_actions.js \
nsIAccessible_name.css \
nsIAccessible_name.xbl \
+ nsIAccessibleEditableText.js \
test_aria_activedescendant.html \
test_aria_role_article.html \
test_bug368835.xul \
test_bug420863.html \
test_cssattrs.html \
test_groupattrs.xul \
$(warning test_table_indexes.html temporarily disabled) \
test_nsIAccessible_actions.html \
test_nsIAccessible_actions.xul \
test_nsIAccessible_name.html \
test_nsIAccessible_name.xul \
+ test_nsIAccessibleDocument.html \
+ test_nsIAccessibleEditableText.html \
+ test_nsIAccessibleHyperLink.html \
+ test_nsIAccessibleHyperLink.xul \
+ test_nsIAccessibleHyperText.html \
+ test_nsIAccessibleImage.html \
test_nsIAccessibleTable_1.html \
test_nsIAccessibleTable_2.html \
test_nsIAccessibleTable_3.html \
test_nsIAccessibleTable_4.html \
test_nsIAccessibleTable_listboxes.xul \
- test_nsIAccessibleDocument.html \
- test_nsIAccessibleHyperLink.html \
- test_nsIAccessibleHyperLink.xul \
- test_nsIAccessibleHyperText.html \
- test_nsIAccessibleImage.html \
test_nsOuterDocAccessible.html \
test_textattrs.html \
test_textboxes.html \
test_textboxes.xul \
testTextboxes.js \
test_bug428479.html \
test_bug429285.html \
+ test_bug434464.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/common.js
@@ -0,0 +1,118 @@
+////////////////////////////////////////////////////////////////////////////////
+// Interfaces
+
+const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+
+const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
+const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
+const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+const nsIAccessibleTypes = Components.interfaces.nsIAccessibleTypes;
+
+const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
+
+const nsIAccessNode = Components.interfaces.nsIAccessNode;
+const nsIAccessible = Components.interfaces.nsIAccessible;
+
+const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument;
+
+const nsIAccessibleText = Components.interfaces.nsIAccessibleText;
+const nsIAccessibleEditableText = Components.interfaces.nsIAccessibleEditableText;
+
+const nsIAccessibleHyperLink = Components.interfaces.nsIAccessibleHyperLink;
+const nsIAccessibleHyperText = Components.interfaces.nsIAccessibleHyperText;
+
+const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage;
+const nsIAccessibleSelectable = Components.interfaces.nsIAccessibleSelectable;
+const nsIAccessibleTable = Components.interfaces.nsIAccessibleTable;
+const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue;
+
+const nsIObserverService = Components.interfaces.nsIObserverService;
+
+const nsIDOMNode = Components.interfaces.nsIDOMNode;
+
+////////////////////////////////////////////////////////////////////////////////
+// General
+
+/**
+ * nsIAccessibleRetrieval, initialized when test is loaded.
+ */
+var gAccRetrieval = null;
+
+/**
+ * Return accessible for the given ID attribute or DOM element.
+ *
+ * @param aElmOrID [in] the ID attribute or DOM element to get an accessible
+ * for
+ * @param aInterfaces [in, optional] the accessible interface or the array of
+ * accessible interfaces to query it/them from obtained
+ * accessible
+ * @param aElmObj [out, optional] object to store DOM element which
+ * accessible is created for
+ */
+function getAccessible(aElmOrID, aInterfaces, aElmObj)
+{
+ var elm = null;
+
+ if (aElmOrID instanceof nsIDOMNode) {
+ elm = aElmOrID;
+ } else {
+ var elm = document.getElementById(aElmOrID);
+ if (!elm) {
+ ok(false, "Can't get DOM element for " + aID);
+ return null;
+ }
+ }
+
+ if (aElmObj && (typeof aElmObj == "object"))
+ aElmObj.value = elm;
+
+ var acc = null;
+ try {
+ acc = gAccRetrieval.getAccessibleFor(elm);
+ } catch (e) {
+ }
+
+ if (!acc) {
+ ok(false, "Can't get accessible for " + aID);
+ return null;
+ }
+
+ if (!aInterfaces)
+ return acc;
+
+ if (aInterfaces instanceof Array) {
+ for (var index = 0; index < aInterfaces.length; index++) {
+ try {
+ acc.QueryInterface(aInterfaces[index]);
+ } catch (e) {
+ ok(false, "Can't query " + aInterfaces[index] + " for " + aID);
+ return null;
+ }
+ }
+ return acc;
+ }
+
+ try {
+ acc.QueryInterface(aInterfaces);
+ } catch (e) {
+ ok(false, "Can't query " + aInterfaces + " for " + aID);
+ return null;
+ }
+
+ return acc;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// General
+
+function initialize()
+{
+ gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+ getService(nsIAccessibleRetrieval);
+}
+
+addLoadEvent(initialize);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/longdesc_src.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<title>Mozilla logo</title>
+</head>
+<body>
+<p>This file would contain a longer description of the Mozilla logo, if I knew what it looked like.</p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/nsIAccessibleEditableText.js
@@ -0,0 +1,105 @@
+function nsEditableText(aElmOrID)
+{
+ this.setTextContents = function setTextContents(aStr)
+ {
+ try {
+ this.mAcc.setTextContents(aStr);
+
+ is(this.getValue(), aStr,
+ "setTextContents: Can't set " + aStr +
+ " to element with ID '" + this.mID + "'");
+ } catch (e) {
+ ok(false,
+ "setTextContents: Can't set " + aStr +
+ "to element with ID '" + this.mID +
+ "', value '" + this.getValue() + "', exception" + e);
+ }
+ }
+
+ this.insertText = function insertText(aStr, aPos, aResStr)
+ {
+ try {
+ this.mAcc.insertText(aStr, aPos);
+
+ is(this.getValue(), aResStr,
+ "insertText: Can't insert " + aStr + " at " + aPos +
+ " to element with ID '" + this.mID + "'");
+ } catch (e) {
+ ok(false,
+ "insertText: Can't insert " + aStr + " at " + aPos +
+ " to element with ID '" + this.mID +
+ "', value '" + this.getValue() + "', exception " + e);
+ }
+ }
+
+ this.copyNPasteText = function copyNPasteText(aStartPos, aEndPos,
+ aPos, aResStr)
+ {
+ try {
+ this.mAcc.copyText(aStartPos, aEndPos);
+ this.mAcc.pasteText(aPos);
+
+ is(this.getValue(), aResStr,
+ "copyText & pasteText: Can't copy text from " + aStartPos +
+ " to " + aEndPos + " and paste to " + aPos +
+ " for element with ID '" + this.mID + "'");
+ } catch (e) {
+ ok(false,
+ "copyText & pasteText: Can't copy text from " + aStartPos +
+ " to " + aEndPos + " and paste to " + aPos +
+ " for element with ID '" + this.mID +
+ "', value '" + this.getValue() + "', exception " + e);
+ }
+ }
+
+ this.cutNPasteText = function copyNPasteText(aStartPos, aEndPos,
+ aPos, aResStr)
+ {
+ try {
+ this.mAcc.cutText(aStartPos, aEndPos);
+ this.mAcc.pasteText(aPos);
+
+ is(this.getValue(), aResStr,
+ "cutText & pasteText: Can't cut text from " + aStartPos +
+ " to " + aEndPos + " and paste to " + aPos +
+ " for element with ID '" + this.mID + "'");
+ } catch (e) {
+ ok(false,
+ "cutText & pasteText: Can't cut text from " + aStartPos +
+ " to " + aEndPos + " and paste to " + aPos +
+ " for element with ID '" + this.mID +
+ "', value '" + this.getValue() + "', exception " + e);
+ }
+ }
+
+ this.deleteText = function deleteText(aStartPos, aEndPos, aResStr)
+ {
+ try {
+ this.mAcc.deleteText(aStartPos, aEndPos);
+
+ is(this.getValue(), aResStr,
+ "deleteText: Can't delete text from " + aStartPos +
+ " to " + aEndPos + " for element with ID '" + this.mID + "'");
+ } catch (e) {
+ ok(false,
+ "deleteText: Can't delete text from " + aStartPos +
+ " to " + aEndPos + " for element with ID '" + this.mID +
+ "', value " + this.getValue() + ", exception " + e);
+ }
+ }
+
+ this.getValue = function getValue()
+ {
+ if (this.mElm instanceof Components.interfaces.nsIDOMNSEditableElement)
+ return this.mElm.value;
+ if (this.mElm instanceof Components.interfaces.nsIDOMHTMLDocument)
+ return this.mElm.body.textContent;
+ return this.mElm.textContent;
+ }
+
+ var elmObj = { value: null };
+ this.mAcc = getAccessible(aElmOrID, nsIAccessibleEditableText, elmObj);
+
+ this.mElm = elmObj.value;
+ this.mID = aElmOrID;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_bug434464.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=434464
+-->
+<head>
+ <title>Test NSIAccessNode cache invalidation</title>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript">
+ function doTest()
+ {
+ var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+ getService(Components.interfaces.nsIAccessibleRetrieval);
+
+ var parentElm = document.getElementById("parent");
+ if (!parentElm) {
+ ok(false, "no parent element for paragraph!");
+ SimpleTest.finish();
+ }
+
+ var elm = document.getElementById("para");
+ if (!elm) {
+ ok(false, "no element for paragraph!");
+ SimpleTest.finish();
+ }
+
+ // It's currently hidden. Ask for its parent's nsIAccessNode.
+ var parentElmAccNode = null;
+ try {
+ parentElmAccNode = accRetrieval.getAccessibleFor(parentElm).
+ QueryInterface(Components.interfaces.nsIAccessNode);
+ } catch(e) {}
+
+ if (!parentElmAccNode) {
+ ok(false, "No accessNode for parent of hidden paragraph!");
+ SimpleTest.finish();
+ }
+
+ // Get the paragraph's accessNode.
+ var elmAccNode = null;
+ try {
+ elmAccNode = parentElmAccNode.firstChildNode;
+ } catch(e) {}
+
+ if (!elmAccNode) {
+ ok(false, "No accessNode for hidden paragraph!");
+ SimpleTest.finish();
+ }
+
+ // Now make the paragraph visible. This invalidates the just-retrieved
+ // AccessNode. An nsIAccessible should then be retrievable.
+ elm.style.display = "block";
+
+ // Now, get an accessible for it. Use a timeout so the layout engine can
+ // catch up.
+ window.setTimeout(
+ function()
+ {
+ var elmAcc = null;
+ try {
+ elmAcc = accRetrieval.getAccessibleFor(elm);
+ } catch(e) {}
+
+ ok(elmAcc, "No accessible for paragraph after it became visible!");
+
+ SimpleTest.finish();
+ },
+ 200);
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=434464">Mozilla Bug 434464</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+ <div id="parent"><p style="display: none;" id="para">I'm hidden initially, but then made visible.</p></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleEditableText.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=452161
+-->
+<head>
+ <title>nsIAccessibleEditableText chrome tests</title>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/MochiKit/packed.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/a11y/accessible/nsIAccessibleEditableText.js"></script>
+
+ <script type="application/javascript">
+ var gParagraphAcc;
+
+ function testEditable(aID)
+ {
+ var et = new nsEditableText(aID);
+
+ //////////////////////////////////////////////////////////////////////////
+ // insertText
+ et.insertText("hello", 0, "hello");
+ et.insertText("ma ", 0, "ma hello");
+ et.insertText("ma", 2, "mama hello");
+ et.insertText(" hello", 10, "mama hello hello");
+
+ // XXX: bug 452584
+
+ //////////////////////////////////////////////////////////////////////////
+ // setTextContents
+// et.setTextContents("hello", "hello");
+// et.setTextContents("olleh", "olleh");
+// et.setTextContents("", "");
+
+ //////////////////////////////////////////////////////////////////////////
+ // deleteText
+// et.deleteText(0, 5, "hello hello");
+// et.deleteText(5, 6, "hellohello");
+// et.deleteText(5, 10, "hello");
+// et.deleteText(0, 5, "");
+
+ //////////////////////////////////////////////////////////////////////////
+ // copyNPasteText
+// et.copyNPasteText(0, 0, 0, "");
+// et.insertText("hello", 0, "hello");
+// et.copyNPasteText(0, 1, 0, "hhello");
+// et.copyNPasteText(5, 6, 6, "hhelloo");
+// et.copyNPasteText(3, 4, 1, "hehelloo");
+
+ //////////////////////////////////////////////////////////////////////////
+// // cutNPasteText
+// et.cutNPasteText(0, 1, 1, "ehhelloo");
+// et.cutNPasteText(1, 2, 0, "hehelloo");
+// et.cutNPasteText(7, 8, 8, "hehelloo");
+ }
+
+ function doTest()
+ {
+ testEditable("input");
+ // testEditable("div"); XXX: bug 452599
+
+ var frame = document.getElementById("frame");
+ frame.contentDocument.designMode = "on";
+ testEditable(frame.contentDocument);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank"
+ title="nsIAccessibleEditableText chrome tests"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">Mozilla Bug 452161</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <input id="input"/>
+
+ <div id="div" contentEditable="true"/>
+
+ <iframe id="frame"/>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_nsIAccessibleImage.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleImage.html
@@ -80,17 +80,18 @@ https://bugzilla.mozilla.org/show_bug.cg
}
var width = {}, height = {};
imageAcc.getImageSize(width, height);
is(width.value, aWidth, "Wrong width for " + aID + "!");
is(height.value, aHeight, "wrong height for " + aID + "!");
}
- function testThis(aID, aName, aSRC, aWidth, aHeight)
+ function testThis(aID, aName, aSRC, aWidth, aHeight,
+ aNumActions, aActionNames)
{
var elem = document.getElementById(aID);
var acc;
try {
acc = gAccRetrieval.getAccessibleFor(elem);
} catch(e) {}
ok(acc, "No accessible for " + aID + "!");
@@ -105,16 +106,26 @@ https://bugzilla.mozilla.org/show_bug.cg
// bug 429659: Make sure the SRC attribute is set for any image
var attributes;
try {
attributes = acc.attributes;
} catch(e) {}
ok(attributes, "no attributes on " + aID + "!");
is(attributes.getStringProperty("src"), aSRC,
"no correct src attribute for " + aID + "!");
+
+ if (aNumActions) {
+ is(acc.numActions, aNumActions,
+ "Wrong number of actions for " + aID + "!");
+
+ for (index = 0; index < aActionNames.length; index++) {
+ is(acc.getActionName(index), aActionNames[index],
+ "Wrong action name for " + aID + ", index " + index +"!");
+ }
+ }
}
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(Components.interfaces.nsIAccessibleRetrieval);
// Test non-linked image
@@ -142,16 +153,33 @@ https://bugzilla.mozilla.org/show_bug.cg
testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42);
// Test simple image with empty alt attribute and title
testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38);
// Test linked image with empty alt attribute and title
testThis("linkedImageEmptyAltAndTitle", "Link to Mozilla Foundation", "moz.png", 93, 42);
+ // Image with long desc
+ var actionNamesArray = new Array("showlongdesc");
+ testThis("longdesc", "Image of Mozilla logo", "moz.png", 89, 38, 1,
+ actionNamesArray);
+
+ // Image with click and long desc
+ actionNamesArray = null;
+ actionNamesArray = new Array("click", "showlongdesc");
+ testThis("clickAndLongdesc", "Another image of Mozilla logo", "moz.png",
+ 89, 38, 2, actionNamesArray);
+
+ // Image with click
+ actionNamesArray = null;
+ actionNamesArray = new Array("click");
+ testThis("click", "A third image of Mozilla logo", "moz.png",
+ 89, 38, 1, actionNamesArray);
+
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
@@ -177,10 +205,19 @@ https://bugzilla.mozilla.org/show_bug.cg
<img id="nonLinkedImageEmptyAlt" src="moz.png" alt=""/>
<br>Linked image with empty alt:<br>
<a href="http://www.mozilla.org"><img id="linkedImageEmptyAlt" src="moz.png" alt=""/></a>
<br>Simple image with empty alt and title:<br>
<img id="nonLinkedImageEmptyAltAndTitle" src="moz.png" alt="" title="MozillaFoundation"/>
<br>Linked image with empty alt and title:<br>
<a href="http://www.mozilla.org"><img id="linkedImageEmptyAltAndTitle" src="moz.png" alt=""
title="Link to Mozilla Foundation"/></a>
+ <br>Image with longdesc:<br>
+ <img id="longdesc" src="moz.png" longdesc="longdesc_src.html"
+ alt="Image of Mozilla logo"/>
+ <br>Image with click and longdesc:<br>
+ <img id="clickAndLongdesc" src="moz.png" longdesc="longdesc_src.html"
+ alt="Another image of Mozilla logo" onclick="alert('Clicked!');"/>
+ <br>Image with click:<br>
+ <img id="click" src="moz.png"
+ alt="A third image of Mozilla logo" onclick="alert('Clicked, too!');"/>
</body>
</html>
--- a/accessible/tests/mochitest/test_textattrs.html
+++ b/accessible/tests/mochitest/test_textattrs.html
@@ -23,102 +23,122 @@
*
* @param aID the ID of DOM element having text accessible
* @param aOffset the offset inside text accessible to fetch
* text attributes
* @param aAttrs the map of text attributes (name/value pairs)
* @param aStartOffset the start offset where text attributes are
* applied
* @param aEndOffset the end offset where text attribute are applied
- * @param aDefAttrs the list of default text attributes (name/value
- * pairs)
*/
function testTextAttrs(aID, aOffset,
- aAttrs, aStartOffset, aEndOffset, aDefAttrs)
+ aAttrs, aStartOffset, aEndOffset)
{
- var node = document.getElementById(aID);
- if (!node) {
- ok(false, "Can't get the element with ID " + aID);
+ var accessible = getTextAccessible(aID);
+ if (!accessible)
return;
- }
-
- var accessible = null;
- try {
- accessible = gAccRetrieval.getAccessibleFor(node);
- accessible.QueryInterface(nsIAccessibleText);
- } catch (e) {
- }
-
- if (!accessible) {
- ok(false, "Can't query nsIAccessibleText interface for " + aID);
- return;
- }
var startOffset = { value: -1 };
var endOffset = { value: -1 };
var attrs = null;
try {
attrs = accessible.getTextAttributes(false,
aOffset,
startOffset, endOffset);
} catch (e) {
}
if (!attrs) {
ok(false, "Can't get text attributes for " + aID);
return;
}
- var errorMsg = " for " + aID + "at offset " + aOffset;
+ var errorMsg = " for " + aID + " at offset " + aOffset;
is(startOffset.value, aStartOffset,
"Wrong start offset" + errorMsg);
is(endOffset.value, aEndOffset,
"Wrong end offset" + errorMsg);
compareTextAttrs(errorMsg, attrs, aAttrs);
+ }
+
+ /**
+ * Test default text attributes.
+ *
+ * @param aID the ID of DOM element having text accessible
+ * @param aDefAttrs the list of default text attributes (name/value
+ * pairs)
+ */
+ function testDefaultTextAttrs(aID, aDefAttrs)
+ {
+ var accessible = getTextAccessible(aID);
+ if (!accessible)
+ return;
var defAttrs = null;
try{
defAttrs = accessible.defaultTextAttributes;
} catch (e) {
}
if (!defAttrs) {
ok(false, "Can't get default attributes for " + aID);
return;
}
+ var errorMsg = ". Getting default attributes for " + aID;
compareTextAttrs(errorMsg, defAttrs, aDefAttrs);
}
+ function getTextAccessible(aID)
+ {
+ var node = document.getElementById(aID);
+ if (!node) {
+ ok(false, "Can't get the element with ID " + aID);
+ return;
+ }
+
+ var accessible = null;
+ try {
+ accessible = gAccRetrieval.getAccessibleFor(node);
+ accessible.QueryInterface(nsIAccessibleText);
+ } catch (e) {
+ }
+
+ if (!accessible)
+ ok(false, "Can't query nsIAccessibleText interface for " + aID);
+
+ return accessible;
+ }
+
function compareTextAttrs(aErrorMsg, aAttrs, aExpectedAttrs)
{
var enumerate = aAttrs.enumerate();
while (enumerate.hasMoreElements()) {
var prop = enumerate.getNext().
QueryInterface(Components.interfaces.nsIPropertyElement);
if (!(prop.key in aExpectedAttrs))
ok(false,
- "Unexpected attribute '" + prop.key + "'" + aErrorMsg);
+ "Unexpected attribute '" + prop.key + "' having '" + prop.value + "'" + aErrorMsg);
else
is(prop.value, aExpectedAttrs[prop.key],
- "Attribute '" + prop.key + "' has wrong value" + aErrorMsg);
+ "Attribute '" + prop.key + " 'has wrong value" + aErrorMsg);
}
for (var name in aExpectedAttrs) {
var value = "";
try {
value = aAttrs.getStringProperty(name);
} catch(e) {
}
if (!value)
ok(false,
- "There is no expected attribute '" + name + "'" + aErrorMsg);
+ "There is no expected attribute '" + name + "' " + aErrorMsg);
}
}
var gObserverService = null;
var gA11yEventObserver = null;
function testSpellTextAttrs()
{
@@ -162,26 +182,27 @@
"font-size": "11px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "Lucida Grande",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
- var attrs = { "background-color": "transparent" };
+ var attrs = { };
var misspelledAttrs = {
- "background-color": "transparent",
"invalid": "spelling"
};
- testTextAttrs(ID, 0, attrs, 0, 11, defAttrs);
- testTextAttrs(ID, 11, misspelledAttrs, 11, 17, defAttrs);
- testTextAttrs(ID, 18, misspelledAttrs, 18, 22, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 11);
+ testTextAttrs(ID, 11, misspelledAttrs, 11, 17);
+ testTextAttrs(ID, 17, attrs, 17, 18);
+ testTextAttrs(ID, 18, misspelledAttrs, 18, 22);
is(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
"Wrong count of 'text attribute changed' events for " + ID);
// Remove a11y events listener
gObserverService.removeObserver(gA11yEventObserver,
"accessible-event");
@@ -196,221 +217,238 @@
//////////////////////////////////////////////////////////////////////////
// area1
var ID = "area1";
var defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
var attrs = {};
- testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 7);
attrs = {"font-weight": "401"};
- testTextAttrs(ID, 7, attrs, 7, 11, defAttrs);
+ testTextAttrs(ID, 7, attrs, 7, 11);
attrs = {};
- testTextAttrs(ID, 12, attrs, 11, 18, defAttrs);
+ testTextAttrs(ID, 12, attrs, 11, 18);
//////////////////////////////////////////////////////////////////////////
// area2
ID = "area2";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {};
- testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 7);
attrs = {"font-weight": "401"};
- testTextAttrs(ID, 7, attrs, 7, 12, defAttrs);
+ testTextAttrs(ID, 7, attrs, 7, 12);
attrs = {"font-style": "italic", "font-weight": "401"};
- testTextAttrs(ID, 13, attrs, 12, 19, defAttrs);
+ testTextAttrs(ID, 13, attrs, 12, 19);
attrs = {"font-weight": "401"};
- testTextAttrs(ID, 20, attrs, 19, 23, defAttrs);
+ testTextAttrs(ID, 20, attrs, 19, 23);
attrs = {};
- testTextAttrs(ID, 24, attrs, 23, 30, defAttrs);
+ testTextAttrs(ID, 24, attrs, 23, 30);
//////////////////////////////////////////////////////////////////////////
// area3
ID = "area3";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(0, 0, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {"color": "rgb(0, 128, 0)"};
- testTextAttrs(ID, 0, attrs, 0, 6, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 6);
attrs = {"color": "rgb(255, 0, 0)"};
- testTextAttrs(ID, 6, attrs, 6, 26, defAttrs);
+ testTextAttrs(ID, 6, attrs, 6, 26);
attrs = {"color": "rgb(0, 128, 0)"};
- testTextAttrs(ID, 26, attrs, 26, 50, defAttrs);
+ testTextAttrs(ID, 26, attrs, 26, 27);
+
+ attrs = {"color": "rgb(0, 128, 0)", "background-color": "rgb(255, 255, 0)"};
+ testTextAttrs(ID, 27, attrs, 27, 50);
//////////////////////////////////////////////////////////////////////////
// area4
ID = "area4";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {"color": "rgb(0, 128, 0)"};
- testTextAttrs(ID, 0, attrs, 0, 16, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 16);
attrs = {"color": "rgb(255, 0, 0)"};
- testTextAttrs(ID, 16, attrs, 16, 33, defAttrs);
+ testTextAttrs(ID, 16, attrs, 16, 33);
attrs = {"color": "rgb(0, 128, 0)"};
- testTextAttrs(ID, 34, attrs, 33, 46, defAttrs);
+ testTextAttrs(ID, 34, attrs, 33, 46);
//////////////////////////////////////////////////////////////////////////
// area5
ID = "area5";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {"color": "rgb(0, 128, 0)"};
- testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 5);
attrs = {};
- testTextAttrs(ID, 7, attrs, 5, 8, defAttrs);
+ testTextAttrs(ID, 7, attrs, 5, 8);
attrs = {"color": "rgb(255, 0, 0)"};
- testTextAttrs(ID, 9, attrs, 8, 11, defAttrs);
+ testTextAttrs(ID, 9, attrs, 8, 11);
attrs = {};
- testTextAttrs(ID, 11, attrs, 11, 18, defAttrs);
+ testTextAttrs(ID, 11, attrs, 11, 18);
//////////////////////////////////////////////////////////////////////////
// area6 (CSS vertical-align property, bug 445938)
ID = "area6";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {};
- testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 5);
attrs = {"text-position": "super", "font-size": "13px" };
- testTextAttrs(ID, 5, attrs, 5, 13, defAttrs);
+ testTextAttrs(ID, 5, attrs, 5, 13);
attrs = {};
- testTextAttrs(ID, 13, attrs, 13, 27, defAttrs);
+ testTextAttrs(ID, 13, attrs, 13, 27);
attrs = {"text-position": "super" };
- testTextAttrs(ID, 27, attrs, 27, 35, defAttrs);
+ testTextAttrs(ID, 27, attrs, 27, 35);
attrs = {};
- testTextAttrs(ID, 35, attrs, 35, 39, defAttrs);
+ testTextAttrs(ID, 35, attrs, 35, 39);
attrs = {"text-position": "sub", "font-size": "13px" };
- testTextAttrs(ID, 39, attrs, 39, 50, defAttrs);
+ testTextAttrs(ID, 39, attrs, 39, 50);
attrs = {};
- testTextAttrs(ID, 50, attrs, 50, 55, defAttrs);
+ testTextAttrs(ID, 50, attrs, 50, 55);
attrs = {"text-position": "sub" };
- testTextAttrs(ID, 55, attrs, 55, 64, defAttrs);
+ testTextAttrs(ID, 55, attrs, 55, 64);
//////////////////////////////////////////////////////////////////////////
// area7
ID = "area7";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
- "background-color": "transparent",
+ "background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
+ testDefaultTextAttrs(ID, defAttrs);
+
attrs = {"language": "ru"};
- testTextAttrs(ID, 0, attrs, 0, 12, defAttrs);
+ testTextAttrs(ID, 0, attrs, 0, 12);
attrs = {"language": "en"};
- testTextAttrs(ID, 12, attrs, 12, 13, defAttrs);
+ testTextAttrs(ID, 12, attrs, 12, 13);
attrs = {"language" :"en", "background-color": "rgb(0, 0, 255)"};
- testTextAttrs(ID, 13, attrs, 13, 26, defAttrs);
+ testTextAttrs(ID, 13, attrs, 13, 26);
attrs = {"language": "en" };
- testTextAttrs(ID, 26, attrs, 26, 27, defAttrs);
+ testTextAttrs(ID, 26, attrs, 26, 27);
attrs = {"language": "de"};
- testTextAttrs(ID, 27, attrs, 27, 42, defAttrs);
+ testTextAttrs(ID, 27, attrs, 27, 42);
attrs = {"language": "en"};
- testTextAttrs(ID, 42, attrs, 42, 43, defAttrs);
+ testTextAttrs(ID, 42, attrs, 42, 43);
attrs = {};
- testTextAttrs(ID, 43, attrs, 43, 50, defAttrs);
+ testTextAttrs(ID, 43, attrs, 43, 50);
attrs = {"color": "rgb(255, 0, 255)"};
- testTextAttrs(ID, 50, attrs, 50, 57, defAttrs);
+ testTextAttrs(ID, 50, attrs, 50, 57);
attrs = {"font-weight": "401", "color": "rgb(255, 0, 255)" };
- testTextAttrs(ID, 57, attrs, 57, 61, defAttrs);
+ testTextAttrs(ID, 57, attrs, 57, 61);
attrs = {"color": "rgb(255, 0, 255)"};
- testTextAttrs(ID, 61, attrs, 61, 68, defAttrs);
+ testTextAttrs(ID, 61, attrs, 61, 68);
//////////////////////////////////////////////////////////////////////////
// test spelling text attributes
testSpellTextAttrs(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
@@ -425,21 +463,21 @@
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<p id="area1">Normal <b>Bold</b> Normal</p>
<p id="area2">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p>
- <p id="area3">
- <span style="color: green">
+ <p id="area3" style="background-color: blue;">
+ <span style="color: green; background-color: rgb(0, 0, 255)">
Green
<span style="color: red">but children are red</span>
- </span><span style="color: green">
+ </span><span style="color: green; background-color: rgb(255, 255, 0);">
Another green section.
</span>
</p>
<p id="area4">
<span style="color: green">
Green
</span><span style="color: green">
Green too
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -8,12 +8,15 @@ builtin(include, build/autoconf/gtk.m4)d
builtin(include, build/autoconf/libIDL.m4)dnl
builtin(include, build/autoconf/libIDL-2.m4)dnl
builtin(include, build/autoconf/nspr.m4)dnl
builtin(include, build/autoconf/nss.m4)dnl
builtin(include, build/autoconf/libart.m4)dnl
builtin(include, build/autoconf/pkg.m4)dnl
builtin(include, build/autoconf/freetype2.m4)dnl
builtin(include, build/autoconf/codeset.m4)dnl
-dnl
-define(MOZ_TOPSRCDIR,.)dnl MOZ_TOPSRCDIR is used in altoptions.m4
builtin(include, build/autoconf/altoptions.m4)dnl
+# Read the user's .mozconfig script. We can't do this in
+# configure.in: autoconf puts the argument parsing code above anything
+# expanded from configure.in, and we need to get the configure options
+# from .mozconfig in place before that argument parsing code.
+MOZ_READ_MOZCONFIG(.)
--- a/browser/app/module.ver
+++ b/browser/app/module.ver
@@ -1,8 +1,8 @@
WIN32_MODULE_COMPANYNAME=Mozilla Corporation
WIN32_MODULE_COPYRIGHT=©Firefox and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable.
WIN32_MODULE_PRODUCTVERSION=3,1,0,0
-WIN32_MODULE_PRODUCTVERSION_STRING=3.1a2
+WIN32_MODULE_PRODUCTVERSION_STRING=3.1b1pre
WIN32_MODULE_TRADEMARKS=Firefox is a Trademark of The Mozilla Foundation.
WIN32_MODULE_DESCRIPTION=Firefox
WIN32_MODULE_PRODUCTNAME=Firefox
WIN32_MODULE_NAME=Firefox
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -59,21 +59,19 @@
#endif
static void Output(const char *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE
- char msg[2048];
-
- _vsnprintf(msg, sizeof(msg), fmt, ap);
-
- MessageBox(NULL, msg, "XULRunner", MB_OK | MB_ICONERROR);
+ PRUnichar msg[2048];
+ _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
+ MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
#else
vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
}
/**
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -211,16 +211,17 @@ pref("browser.urlbar.doubleClickSelectsA
#else
pref("browser.urlbar.doubleClickSelectsAll", false);
#endif
pref("browser.urlbar.autoFill", false);
pref("browser.urlbar.matchOnlyTyped", false);
// 0: Match anywhere (e.g., middle of words)
// 1: Match on word boundaries and then try matching anywhere
// 2: Match only on word boundaries (e.g., after / or .)
+// 3: Match at the beginning of the url or title
pref("browser.urlbar.matchBehavior", 1);
pref("browser.urlbar.filter.javascript", true);
// the maximum number of results to show in autocomplete when doing richResults
pref("browser.urlbar.maxRichResults", 12);
// Size of "chunks" affects the number of places to process between each search
// timeout (ms). Too big and the UI will be unresponsive; too small and we'll
// be waiting on the timeout too often without many results.
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1077,17 +1077,19 @@ function delayedStartup()
// Attach a listener to watch for "command" events bubbling up from error
// pages. This lets us fix bugs like 401575 which require error page UI to
// do privileged things, without letting error pages have any privilege
// themselves.
gBrowser.addEventListener("command", BrowserOnCommand, false);
tabPreviews.init();
- if (gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
+ if ((!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") ||
+ !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")) &&
+ gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
ctrlTab.init();
// Delayed initialization of the livemarks update timer.
// Livemark updates don't need to start until after bookmark UI
// such as the toolbar has initialized. Starting 5 seconds after
// delayedStartup in order to stagger this before the download
// manager starts (see below).
setTimeout(function() PlacesUtils.livemarks.start(), 5000);
@@ -5403,24 +5405,18 @@ var OfflineApps = {
getService(Ci.nsIPermissionManager);
pm.add(aURI, "offline-app",
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
},
// XXX: duplicated in preferences/advanced.js
_getOfflineAppUsage: function (host)
{
- var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
- getService(Components.interfaces.nsICacheService);
- var cacheSession = cacheService.createSession("HTTP-offline",
- Components.interfaces.nsICache.STORE_OFFLINE,
- true).
- QueryInterface(Components.interfaces.nsIOfflineCacheSession);
- var usage = cacheSession.getDomainUsage(host);
-
+ // XXX Bug 442810: include offline cache usage.
+ var usage = 0;
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager);
usage += storageManager.getUsage(host);
return usage;
},
_checkUsage: function(aURI) {
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -126,17 +126,26 @@ nsContextMenu.prototype = {
this.initMiscItems();
this.initSpellingItems();
this.initSaveItems();
this.initClipboardItems();
this.initMetadataItems();
},
initOpenItems: function CM_initOpenItems() {
- var shouldShow = this.onSaveableLink ||
+ var isMailtoInternal = false;
+ if (this.onMailtoLink) {
+ var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
+ getService(Ci.nsIExternalProtocolService).
+ getProtocolHandlerInfo("mailto");
+ isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
+ mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
+ (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
+ }
+ var shouldShow = this.onSaveableLink || isMailtoInternal ||
(this.inDirList && this.onLink);
this.showItem("context-openlink", shouldShow);
this.showItem("context-openlinkintab", shouldShow);
this.showItem("context-sep-open", shouldShow);
},
initNavigationItems: function CM_initNavigationItems() {
var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -183,20 +183,16 @@ gImageView.getCellProperties = function(
var gImageHash = { };
// localized strings (will be filled in when the document is loaded)
// this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop
var gStrings = { };
var gBundle;
-const DRAGSERVICE_CONTRACTID = "@mozilla.org/widget/dragservice;1";
-const TRANSFERABLE_CONTRACTID = "@mozilla.org/widget/transferable;1";
-const ARRAY_CONTRACTID = "@mozilla.org/supports-array;1";
-const STRING_CONTRACTID = "@mozilla.org/supports-string;1";
const PERMISSION_CONTRACTID = "@mozilla.org/permissionmanager;1";
const PREFERENCES_CONTRACTID = "@mozilla.org/preferences-service;1";
const ATOM_CONTRACTID = "@mozilla.org/atom-service;1";
// a number of services I'll need later
// the cache services
const nsICacheService = Components.interfaces.nsICacheService;
const ACCESS_READ = Components.interfaces.nsICache.ACCESS_READ;
@@ -658,42 +654,26 @@ function onBeginLinkDrag(event,urlField,
var tree = event.target;
if (!("treeBoxObject" in tree))
tree = tree.parentNode;
var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY);
if (row == -1)
return;
- // Getting drag-system needed services
- var dragService = Components.classes[DRAGSERVICE_CONTRACTID].getService()
- .QueryInterface(Components.interfaces.nsIDragService);
- var transArray = Components.classes[ARRAY_CONTRACTID]
- .createInstance(Components.interfaces.nsISupportsArray);
- if (!transArray)
- return;
-
- var trans = Components.classes[TRANSFERABLE_CONTRACTID]
- .createInstance(Components.interfaces.nsITransferable);
- if (!trans)
- return;
-
// Adding URL flavor
- trans.addDataFlavor("text/x-moz-url");
var col = tree.columns[urlField];
var url = tree.view.getCellText(row, col);
col = tree.columns[descField];
var desc = tree.view.getCellText(row, col);
- var stringURL = Components.classes[STRING_CONTRACTID]
- .createInstance(Components.interfaces.nsISupportsString);
- stringURL.data = url + "\n" + desc;
- trans.setTransferData("text/x-moz-url", stringURL, stringURL.data.length * 2 );
- transArray.AppendElement(trans.QueryInterface(Components.interfaces.nsISupports));
- dragService.invokeDragSession(event.target, transArray, null, dragService.DRAGDROP_ACTION_NONE);
+ var dt = event.dataTransfer;
+ dt.setData("text/x-moz-url", url + "\n" + desc);
+ dt.setData("text/url-list", url);
+ dt.setData("text/plain", url);
}
//******** Image Stuff
function getSelectedImage(tree)
{
if (!gImageView.rowCount)
return null;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1538,17 +1538,17 @@
if (currentIndex > index)
newIndex = currentIndex-1;
else if (currentIndex < index)
newIndex = currentIndex;
else {
if ("owner" in aTab && aTab.owner &&
this.mPrefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
for (var i = 0; i < length; ++i) {
- tab = this.mTabContainer.childNodes[i];
+ var tab = this.mTabContainer.childNodes[i];
if (tab == aTab.owner) {
newIndex = i;
break;
}
}
}
if (newIndex == -1)
newIndex = (index == length) ? index - 1 : index;
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -71,16 +71,24 @@ DistributionCustomizer.prototype = {
__annoSvc: null,
get _annoSvc() {
if (!this.__annoSvc)
this.__annoSvc = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService);
return this.__annoSvc;
},
+ __livemarkSvc: null,
+ get _livemarkSvc() {
+ if (!this.__livemarkSvc)
+ this.__livemarkSvc = Cc["@mozilla.org/browser/livemark-service;2"].
+ getService(Ci.nsILivemarkService);
+ return this.__livemarkSvc;
+ },
+
__dirSvc: null,
get _dirSvc() {
if (!this.__dirSvc)
this.__dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
return this.__dirSvc;
},
@@ -174,16 +182,28 @@ DistributionCustomizer.prototype = {
break;
case "separator":
if (iid < defaultItemId)
index = prependIndex++;
this._bmSvc.insertSeparator(parentId, index);
break;
+ case "livemark":
+ if (iid < defaultItemId)
+ index = prependIndex++;
+
+ newId = this._livemarkSvc.
+ createLivemark(parentId,
+ items[iid]["title"],
+ this._makeURI(items[iid]["siteLink"]),
+ this._makeURI(items[iid]["feedLink"]),
+ index);
+ break;
+
case "bookmark":
default:
if (iid < defaultItemId)
index = prependIndex++;
newId = this._bmSvc.insertBookmark(parentId,
this._makeURI(items[iid]["link"]),
index, items[iid]["title"]);
@@ -213,18 +233,26 @@ DistributionCustomizer.prototype = {
// (we also check here to be consistent with applyPrefDefaults below)
if (!sections["Global"])
return;
let globalPrefs = enumToObject(this._ini.getKeys("Global"));
if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
return;
let bmProcessed = false;
- let bmProcessedPref = "distribution." +
- this._ini.getString("Global", "id") + ".bookmarksProcessed";
+ let bmProcessedPref;
+
+ try {
+ bmProcessedPref = this._ini.getString("Global",
+ "bookmarks.initialized.pref");
+ } catch (e) {
+ bmProcessedPref = "distribution." +
+ this._ini.getString("Global", "id") + ".bookmarksProcessed";
+ }
+
try {
bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
} catch (e) {}
if (!bmProcessed) {
if (sections["BookmarksMenu"])
this._parseBookmarksSection(this._bmSvc.bookmarksMenuFolder,
"BookmarksMenu");
--- a/browser/components/migration/src/nsIEProfileMigrator.cpp
+++ b/browser/components/migration/src/nsIEProfileMigrator.cpp
@@ -862,17 +862,17 @@ static GUID IEPStoreSiteAuthGUID = { 0x5
nsresult
nsIEProfileMigrator::CopyPasswords(PRBool aReplace)
{
HRESULT hr;
nsresult rv;
nsVoidArray signonsFound;
- HMODULE pstoreDLL = ::LoadLibrary("pstorec.dll");
+ HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
if (!pstoreDLL) {
// XXXben TODO
// Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
// and we can just blunder into the registry and use CryptUnprotect to get the data out.
return NS_ERROR_FAILURE;
}
PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
@@ -1186,17 +1186,17 @@ nsIEProfileMigrator::GetUserNameAndPass(
//
// "Quite Easily Done". ;-)
//
nsresult
nsIEProfileMigrator::CopyFormData(PRBool aReplace)
{
HRESULT hr;
- HMODULE pstoreDLL = ::LoadLibrary("pstorec.dll");
+ HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
if (!pstoreDLL) {
// XXXben TODO
// Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
// and we can just blunder into the registry and use CryptUnprotect to get the data out.
return NS_ERROR_FAILURE;
}
PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
@@ -1419,30 +1419,29 @@ nsIEProfileMigrator::CopySmartKeywords(P
return NS_OK;
}
void
nsIEProfileMigrator::ResolveShortcut(const nsString &aFileName, char** aOutURL)
{
HRESULT result;
- IUniformResourceLocator* urlLink = nsnull;
+ IUniformResourceLocatorW* urlLink = nsnull;
result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
- IID_IUniformResourceLocator, (void**)&urlLink);
+ IID_IUniformResourceLocatorW, (void**)&urlLink);
if (SUCCEEDED(result) && urlLink) {
IPersistFile* urlFile = nsnull;
result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile);
if (SUCCEEDED(result) && urlFile) {
result = urlFile->Load(aFileName.get(), STGM_READ);
if (SUCCEEDED(result) ) {
- LPSTR lpTemp = nsnull;
+ LPWSTR lpTemp = nsnull;
result = urlLink->GetURL(&lpTemp);
if (SUCCEEDED(result) && lpTemp) {
- *aOutURL = PL_strdup(lpTemp);
-
+ *aOutURL = (char*)ToNewUTF8String(nsDependentString(lpTemp));
// free the string that GetURL alloc'd
::CoTaskMemFree(lpTemp);
}
}
urlFile->Release();
}
urlLink->Release();
}
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -211,23 +211,18 @@ var gAdvancedPane = {
document.documentElement.openWindow("Browser:Permissions",
"chrome://browser/content/preferences/permissions.xul",
"", params);
},
// XXX: duplicated in browser.js
_getOfflineAppUsage: function (host)
{
- var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
- getService(Components.interfaces.nsICacheService);
- var cacheSession = cacheService.createSession("HTTP-offline",
- Components.interfaces.nsICache.STORE_OFFLINE,
- true).
- QueryInterface(Components.interfaces.nsIOfflineCacheSession);
- var usage = cacheSession.getDomainUsage(host);
+ // XXX Bug 442710: include offline cache usage.
+ var usage = 0;
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager);
usage += storageManager.getUsage(host);
return usage;
},
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -37,13 +37,13 @@
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-DIRS += chrome \
+DIRS += browser \
$(NULL)
include $(topsrcdir)/config/rules.mk
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -40,13 +40,15 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/sessionstore/test/browser
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
+ browser_350525.js \
+ browser_393716.js \
browser_448741.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_350525.js
@@ -0,0 +1,100 @@
+function test() {
+ /** Test for Bug 350525 **/
+
+ function test(aLambda) {
+ try {
+ return aLambda() || true;
+ }
+ catch (ex) { }
+ return false;
+ }
+
+ // test setup
+ let tabbrowser = getBrowser();
+ waitForExplicitFinish();
+
+ // component
+ let ssComponent = test(function() Cc["@mozilla.org/browser/sessionstore;1"]);
+ ok(ssComponent, "reference the sessionstore component");
+
+ // service
+ let ss = test(function() ssComponent.getService(Ci.nsISessionStore));
+ ok(ss, "reference the sessionstore service");
+
+ ////////////////////////////
+ // setWindowValue, et al. //
+ ////////////////////////////
+ let key = "Unique name: " + Date.now();
+ let value = "Unique value: " + Math.random();
+
+ // test adding
+ ok(test(function() ss.setWindowValue(window, key, value)), "set a window value");
+
+ // test retrieving
+ is(ss.getWindowValue(window, key), value, "stored window value matches original");
+
+ // test deleting
+ ok(test(function() ss.deleteWindowValue(window, key)), "delete the window value");
+
+ // value should not exist post-delete
+ is(ss.getWindowValue(window, key), "", "window value was deleted");
+
+ /////////////////////////
+ // setTabValue, et al. //
+ /////////////////////////
+ key = "Unique name: " + Math.random();
+ value = "Unique value: " + Date.now();
+ let tab = tabbrowser.addTab();
+
+ // test adding
+ ok(test(function() ss.setTabValue(tab, key, value)), "store a tab value");
+
+ // test retrieving
+ is(ss.getTabValue(tab, key), value, "stored tab value match original");
+
+ // test deleting
+ ok(test(function() ss.deleteTabValue(tab, key)), "delete the tab value");
+ // value should not exist post-delete
+ is(ss.getTabValue(tab, key), "", "tab value was deleted");
+
+ // clean up
+ tabbrowser.removeTab(tab);
+
+ /////////////////////////////////////
+ // getClosedTabCount, undoCloseTab //
+ /////////////////////////////////////
+
+ // get closed tab count
+ let count = ss.getClosedTabCount(window);
+ let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
+ ok(0 <= count && count <= max_tabs_undo,
+ "getClosedTabCount returns zero or at most max_tabs_undo");
+
+ // create a new tab
+ let testURL = "about:";
+ tab = tabbrowser.addTab(testURL);
+ tab.linkedBrowser.addEventListener("load", function(aEvent) {
+ // make sure that the next closed tab will increase getClosedTabCount
+ gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
+
+ // remove tab
+ tabbrowser.removeTab(tab);
+
+ // getClosedTabCount
+ var newcount = ss.getClosedTabCount(window);
+ ok(newcount > count, "after closing a tab, getClosedTabCount has been incremented");
+
+ // undoCloseTab
+ ok(test(function() ss.undoCloseTab(window, 0)), "undoCloseTab doesn't throw")
+ tab = tabbrowser.selectedTab;
+
+ tab.linkedBrowser.addEventListener("load", function(aEvent) {
+ is(this.currentURI.spec, testURL, "correct tab was reopened");
+
+ // clean up
+ gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo);
+ tabbrowser.removeTab(tab);
+ finish();
+ }, true);
+ }, true);
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_393716.js
@@ -0,0 +1,78 @@
+function test() {
+ /** Test for Bug 393716 **/
+
+ // set up the basics (SessionStore service, tabbrowser)
+ try {
+ var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+ }
+ catch (ex) { }
+ ok(ss, "SessionStore service is available");
+ let tabbrowser = getBrowser();
+ waitForExplicitFinish();
+
+ /////////////////
+ // getTabState //
+ /////////////////
+ let key = "Unique key: " + Date.now();
+ let value = "Unique value: " + Math.random();
+ let testURL = "about:config";
+
+ // create a new tab
+ let tab = tabbrowser.addTab(testURL);
+ ss.setTabValue(tab, key, value);
+ tab.linkedBrowser.addEventListener("load", function(aEvent) {
+ // get the tab's state
+ let state = ss.getTabState(tab);
+ ok(state, "get the tab's state");
+
+ // verify the tab state's integrity
+ state = eval("(" + state + ")");
+ ok(state instanceof Object && state.entries instanceof Array && state.entries.length > 0,
+ "state object seems valid");
+ ok(state.entries.length == 1 && state.entries[0].url == testURL,
+ "Got the expected state object (test URL)");
+ ok(state.extData && state.extData[key] == value,
+ "Got the expected state object (test manually set tab value)");
+
+ // clean up
+ tabbrowser.removeTab(tab);
+ }, true);
+
+ //////////////////////////////////
+ // setTabState and duplicateTab //
+ //////////////////////////////////
+ let key2 = "key2";
+ let value2 = "Value " + Math.random();
+ let value3 = "Another value: " + Date.now();
+ let state = { entries: [{ url: testURL }], extData: { key2: value2 } };
+
+ // create a new tab
+ let tab2 = tabbrowser.addTab();
+ // set the tab's state
+ ss.setTabState(tab2, state.toSource());
+ tab2.linkedBrowser.addEventListener("load", function(aEvent) {
+ // verify the correctness of the restored tab
+ ok(ss.getTabValue(tab2, key2) == value2 && this.currentURI.spec == testURL,
+ "the tab's state was correctly restored");
+
+ // add text data
+ let textbox = this.contentDocument.getElementById("textbox");
+ textbox.wrappedJSObject.value = value3;
+
+ // duplicate the tab
+ let duplicateTab = ss.duplicateTab(window, tab2);
+ tabbrowser.removeTab(tab2);
+
+ duplicateTab.linkedBrowser.addEventListener("load", function(aEvent) {
+ // verify the correctness of the duplicated tab
+ ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL,
+ "correctly duplicated the tab's state");
+ let textbox = this.contentDocument.getElementById("textbox");
+ is(textbox.wrappedJSObject.value, value3, "also duplicated text data");
+
+ // clean up
+ tabbrowser.removeTab(duplicateTab);
+ finish();
+ }, true);
+ }, true);
+}
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/Makefile.in
+++ /dev/null
@@ -1,52 +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 mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2007
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of 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 *****
-
-DEPTH = ../../../../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-relativesrcdir = browser/components/sessionstore/test/chrome
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES = \
- test_bug350525.xul \
- test_bug393716.xul \
- $(NULL)
-
-libs:: $(_TEST_FILES)
- $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/test_bug350525.xul
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=350525
--->
-<window title="Mozilla Bug 350525"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <title>Test for Bug 350525</title>
- <script type="application/javascript"
- src="chrome://mochikit/content/MochiKit/packed.js"></script>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-<body xmlns="http://www.w3.org/1999/xhtml">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=350525">Mozilla Bug 350525</a>
-
- <p id="display"></p>
-
- <pre id="test">
- <script class="testbody" type="application/javascript">
-
- /** Test for Bug 350525 **/
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cr = Components.results;
-
- // component
- try {
- Cc["@mozilla.org/browser/sessionstore;1"];
- ok(1==1, "Able to reference the sessionstore component?");
- } catch(ex) {
- alert(ex);
- ok(1==2, "Able to reference the sessionstore component?");
- }
-
- // service
- try {
- var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
- ok(true, "Able to reference the sessionstore service?");
- } catch(ex) {
- ok(false, "Able to reference the sessionstore service?");
- }
-
- // get current window, tabbrowser
- var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
- var windowEnumerator = wm.getEnumerator("navigator:browser");
- var currentWindow = windowEnumerator.getNext();
- var tabbrowser = currentWindow.getBrowser();
-
- /*****************
- undoCloseTab, getClosedTabCount
- *****************/
-
- // get closed tab count
- var count = ss.getClosedTabCount(currentWindow);
- ok(count > -1, "getClosedTabCount returns zero or more?");
-
- // create a new tab
- var newTab = tabbrowser.addTab("http://www.mozilla.org");
-
- // remove tab
- tabbrowser.removeTab(newTab);
-
- // getClosedTabCount
- var newcount = ss.getClosedTabCount(currentWindow);
- todo(newcount > count, "After closing a tab, getClosedTabCount has been incremented? " + newcount + " > " + count);
-
- // undoCloseTab
- var undid = ss.undoCloseTab(currentWindow, null);
- ok(undid != -1, "undoCloseTab throws?");
-
- // clean up
- tabbrowser.removeAllTabsBut(tabbrowser.selectedTab);
-
- /*****************
- setWindowValue
- *****************/
- var key = "key1";
- var value = "value1";
-
- // create a new tab
- var newTab = tabbrowser.addTab("http://www.mozilla.org");
-
- // test adding
- ok(ss.setWindowValue(currentWindow, key, value) != -1, "Able to set a window value?");
-
- // test retrieving
- var storedValue = ss.getWindowValue(currentWindow, key);
- is(value, storedValue, "Stored window value matches original?");
-
- // test deleting
- ok(ss.deleteWindowValue(currentWindow, key) != -1, "Delete window value?");
-
- // value should not exist post-delete
- is(ss.getWindowValue(currentWindow, key), "", "Fetching deleted window value fails?");
-
- // clean up
- tabbrowser.removeTab(newTab);
-
- /*********************
- tabValues
- *********************/
- key = "key1";
- value = "value1";
-
- // create a new tab
- newTab = tabbrowser.addTab("http://www.mozilla.org");
-
- // test adding
- ok(ss.setTabValue(newTab, key, value) != -1, "Able to store a tab value?");
-
- // test retrieving
- var storedValue = ss.getTabValue(newTab, key);
- ok(value==storedValue, "Stored tab value match original?");
-
- // test deleting
- ok(ss.deleteTabValue(newTab, key) != -1, "Able to delete a tab value?");
- // value should not exist post-delete
- ok(ss.getTabValue(newTab, key) == "", "Unable to retrieve deleted tab value?");
-
- // clean up
- tabbrowser.removeTab(newTab);
-
- </script>
- </pre>
-</body>
-
-</window>
deleted file mode 100644
--- a/browser/components/sessionstore/test/chrome/test_bug393716.xul
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=393716
--->
-<window title="Mozilla Bug 393716"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <title>Test for Bug 393716</title>
- <script type="application/javascript"
- src="chrome://mochikit/content/MochiKit/packed.js"></script>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-<body xmlns="http://www.w3.org/1999/xhtml">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393716">Mozilla Bug 393716</a>
-
- <p id="display"></p>
-
- <pre id="test">
- <script class="testbody" type="application/javascript">
- <![CDATA[
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
-
- // set up the basics (SessionStore service, tabbrowser)
- try {
- var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
- } catch (ex) {
- ok(false, "SessionStore service available?");
- }
- try {
- var windowEnumerator = Cc["@mozilla.org/appshell/window-mediator;1"].
- getService(Ci.nsIWindowMediator).
- getEnumerator("navigator:browser");
- var currentWindow = windowEnumerator.getNext();
- var tabbrowser = currentWindow.getBrowser();
- } catch (ex) {
- ok(false, "tabbrowser available?");
- }
-
- /**************
- * getTabState
- **************/
- var key = "key1", value = "value1";
-
- // create a new tab
- var newTab = tabbrowser.addTab();
- ss.setTabValue(newTab, key, value);
-
- // get the tab's state
- var state = ss.getTabState(newTab);
- ok(state, "Able to get the tab's state?");
-
- // verify the tab state's integrity
- state = eval("(" + state + ")");
- ok(state instanceof Object && state.entries instanceof Array && state.entries.length > 0,
- "Got a valid state object?");
- ok(state.entries.length == 1 && state.entries[0].url == "about:blank",
- "Got the expected state object (test URL)?");
- ok(state.extData && state.extData[key] == value,
- "Got the expected state object (test manually set tab value)?");
-
- // clean up
- tabbrowser.removeTab(newTab);
-
- /*****************************
- * setTabState / duplicateTab
- *****************************/
- key = "key2";
- value = "value2";
- state = { entries: [{ url: "about:blank" }], extData: { key2: value } };
-
- // create a new tab
- newTab = tabbrowser.addTab();
-
- // set the tab's state
- ss.setTabState(newTab, state.toSource());
-
- // verify the correctness of the restored tab
- ok(ss.getTabValue(newTab, key) == value, "Correctly restored the tab's state?");
-
- // duplicate the tab
- var duplicateTab = ss.duplicateTab(currentWindow, newTab);
-
- // verify the correctness of the duplicated tab
- ok(ss.getTabValue(duplicateTab, key) == value, "Correctly duplicated the tab's state?");
-
- // clean up
- tabbrowser.removeTab(newTab);
- tabbrowser.removeTab(duplicateTab);
-
- ]]>
- </script>
- </pre>
-</body>
-
-</window>
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-3.1a2
+3.1b1pre
--- a/browser/installer/unix/packages-static
+++ b/browser/installer/unix/packages-static
@@ -85,16 +85,17 @@ bin/components/cookie.xpt
bin/components/directory.xpt
bin/components/docshell.xpt
bin/components/dom.xpt
bin/components/dom_base.xpt
bin/components/dom_canvas.xpt
bin/components/dom_core.xpt
bin/components/dom_css.xpt
bin/components/dom_events.xpt
+bin/components/dom_geolocation.xpt
bin/components/dom_html.xpt
bin/components/dom_offline.xpt
bin/components/dom_json.xpt
bin/components/dom_range.xpt
bin/components/dom_sidebar.xpt
bin/components/dom_storage.xpt
bin/components/dom_stylesheets.xpt
bin/components/dom_traversal.xpt
@@ -235,16 +236,17 @@ bin/components/nsLivemarkService.js
bin/components/nsTaggingService.js
bin/components/nsDefaultCLH.js
bin/components/nsContentPrefService.js
bin/components/nsContentDispatchChooser.js
bin/components/nsHandlerService.js
bin/components/nsWebHandlerApp.js
bin/components/libdbusservice.so
bin/components/aboutRobots.js
+bin/components/nsBadCertHandler.js
; Modules
bin/modules/*
; Safe Browsing
bin/components/nsSafebrowsingApplication.js
bin/components/nsUrlClassifierListManager.js
bin/components/nsUrlClassifierLib.js
--- a/browser/installer/windows/packages-static
+++ b/browser/installer/windows/packages-static
@@ -92,16 +92,17 @@ bin\components\cookie.xpt
bin\components\directory.xpt
bin\components\docshell_base.xpt
bin\components\dom.xpt
bin\components\dom_base.xpt
bin\components\dom_canvas.xpt
bin\components\dom_core.xpt
bin\components\dom_css.xpt
bin\components\dom_events.xpt
+bin\components\dom_geolocation.xpt
bin\components\dom_html.xpt
bin\components\dom_offline.xpt
bin\components\dom_json.xpt
bin\components\dom_range.xpt
bin\components\dom_sidebar.xpt
bin\components\dom_storage.xpt
bin\components\dom_stylesheets.xpt
bin\components\dom_traversal.xpt
@@ -241,16 +242,17 @@ bin\components\txEXSLTRegExFunctions.js
bin\components\nsLivemarkService.js
bin\components\nsTaggingService.js
bin\components\nsDefaultCLH.js
bin\components\nsContentPrefService.js
bin\components\nsContentDispatchChooser.js
bin\components\nsHandlerService.js
bin\components\nsWebHandlerApp.js
bin\components\aboutRobots.js
+bin\components\nsBadCertHandler.js
; Modules
bin\modules\*
; Safe Browsing
bin\components\nsSafebrowsingApplication.js
bin\components\nsUrlClassifierListManager.js
bin\components\nsUrlClassifierLib.js
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -314,8 +314,28 @@ else
sed -e "s/%AB_CD%/$(AB_CD)/" > $(FINAL_TARGET)/updater.ini
endif
endif
ifdef MOZ_CRASHREPORTER
libs:: $(addprefix $(LOCALE_SRCDIR)/,crashreporter/crashreporter-override.ini)
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
endif
+
+# This variable is to allow the wget-en-US target to know which ftp server to download from
+ifndef EN_US_BINARY_URL
+EN_US_BINARY_URL = $(error You must set EN_US_BINARY_URL)
+endif
+
+# This make target allows us to wget the latest en-US binary from a specified website
+# The make installers-% target needs the en-US binary in dist/
+# and for the windows repackages we need the .installer.exe in dist/sea
+wget-en-US:
+ifndef WGET
+ $(error Wget not installed)
+endif
+ @$(WGET) -nv --output-document $(_ABS_DIST)/$(PACKAGE) $(EN_US_BINARY_URL)/$(PACKAGE)
+ @echo "Downloaded $(EN_US_BINARY_URL)/$(PACKAGE) to $(_ABS_DIST)/$(PACKAGE)"
+ifeq ($(OS_ARCH), WINNT)
+ $(NSINSTALL) -D $(_ABS_DIST)/install/sea
+ @$(WGET) -nv --output-document $(_ABS_DIST)/install/sea/$(PKG_BASENAME).installer.exe $(EN_US_BINARY_URL)/$(PKG_BASENAME).installer.exe
+ @echo "Downloaded $(EN_US_BINARY_URL)/$(PKG_BASENAME).installer.exe to $(_ABS_DIST)/install/sea/$(PKG_BASENAME)"
+endif
--- a/build/autoconf/altoptions.m4
+++ b/build/autoconf/altoptions.m4
@@ -147,11 +147,8 @@ echo "
dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
AC_DEFUN([MOZ_READ_MOZCONFIG],
[AC_REQUIRE([AC_INIT_BINSH])dnl
# Read in '.mozconfig' script to set the initial options.
# See the mozconfig2configure script for more details.
_AUTOCONF_TOOLS_DIR=`dirname [$]0`/[$1]/build/autoconf
. $_AUTOCONF_TOOLS_DIR/mozconfig2configure])
-
-dnl This gets inserted at the top of the configure script
-MOZ_READ_MOZCONFIG(MOZ_TOPSRCDIR)
new file mode 100644
--- /dev/null
+++ b/build/package/mac_osx/installdmg.ex
@@ -0,0 +1,44 @@
+#!/usr/bin/expect
+# ***** 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 Mozilla Corporation Code.
+#
+# The Initial Developer of the Original Code is
+# Clint Talbert.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Armen Zambrano Gasparnian <armenzg@mozilla.com>
+# Axel Hecht <l10n@mozilla.com>
+#
+# 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 *****
+spawn hdiutil attach -readonly -mountroot /tmp -private -noautoopen $argv
+expect {
+"byte" {send "G"; exp_continue}
+"END" {send "\r"; exp_continue}
+"Y/N?" {send "Y\r"; exp_continue}
+}
--- a/build/pgo/automation.py.in
+++ b/build/pgo/automation.py.in
@@ -274,16 +274,17 @@ user_pref("dom.max_script_run_time", 0);
user_pref("signed.applets.codebase_principal_support", true);
user_pref("security.warn_submit_insecure", false);
user_pref("browser.shell.checkDefaultBrowser", false);
user_pref("browser.warnOnQuit", false);
user_pref("accessibility.typeaheadfind.autostart", false);
user_pref("javascript.options.showInConsole", true);
user_pref("layout.debug.enable_data_xbl", true);
user_pref("browser.EULA.override", true);
+user_pref("javascript.options.jit.content", false);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
"""
prefs.append(part)
locations = readLocations()
# Grant God-power to all the privileged servers on which tests run.
--- a/caps/src/Makefile.in
+++ b/caps/src/Makefile.in
@@ -68,16 +68,17 @@ REQUIRES = xpcom \
content \
layout \
$(NULL)
CPPSRCS = \
nsPrincipal.cpp \
nsSystemPrincipal.cpp \
nsNullPrincipal.cpp \
+ nsNullPrincipalURI.cpp \
nsJSPrincipals.cpp \
nsScriptSecurityManager.cpp \
nsSecurityManagerFactory.cpp \
$(NULL)
ifdef XPC_IDISPATCH_SUPPORT
DEFINES += -DXPC_IDISPATCH_SUPPORT
endif
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -38,27 +38,26 @@
/**
* This is the principal that has no rights and can't be accessed by
* anything other than itself and chrome; null principals are not
* same-origin with anything but themselves.
*/
#include "nsNullPrincipal.h"
+#include "nsNullPrincipalURI.h"
#include "nsMemory.h"
#include "nsIUUIDGenerator.h"
#include "nsID.h"
#include "nsNetUtil.h"
#include "nsIClassInfoImpl.h"
#include "nsNetCID.h"
#include "nsDOMError.h"
#include "nsScriptSecurityManager.h"
-static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
-
NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
nsIPrincipal,
nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
nsIPrincipal,
nsISerializable)
NS_IMETHODIMP_(nsrefcnt)
@@ -114,32 +113,24 @@ nsNullPrincipal::Init()
// Use an nsCString so we only do the allocation once here and then share
// with nsJSPrincipals
nsCString str;
str.SetCapacity(prefixLen + suffixLen);
str.Append(NS_NULLPRINCIPAL_PREFIX);
str.Append(chars);
-
+
if (str.Length() != prefixLen + suffixLen) {
NS_WARNING("Out of memory allocating null-principal URI");
return NS_ERROR_OUT_OF_MEMORY;
}
- // Use CID so we're sure we get the impl we want. Note that creating the URI
- // directly is ok because we have our own private URI scheme. In effect,
- // we're being a protocol handler.
- mURI = do_CreateInstance(kSimpleURICID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = mURI->SetSpec(str);
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_TryToSetImmutable(mURI);
+ mURI = new nsNullPrincipalURI(str);
+ NS_ENSURE_TRUE(mURI, NS_ERROR_OUT_OF_MEMORY);
return mJSPrincipals.Init(this, str);
}
/**
* nsIPrincipal implementation
*/
new file mode 100644
--- /dev/null
+++ b/caps/src/nsNullPrincipalURI.cpp
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Shawn Wilsher <me@shawnwilsher.com> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#include "nsNullPrincipalURI.h"
+#include "nsNetUtil.h"
+#include "nsEscape.h"
+#include "nsCRT.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsNullPrincipalURI
+
+nsNullPrincipalURI::nsNullPrincipalURI(const nsCString &aSpec)
+{
+ PRInt32 dividerPosition = aSpec.FindChar(':');
+ NS_ASSERTION(dividerPosition != -1, "Malformed URI!");
+
+ PRInt32 n = aSpec.Left(mScheme, dividerPosition);
+ NS_ASSERTION(n == dividerPosition, "Storing the scheme failed!");
+
+ PRInt32 count = aSpec.Length() - dividerPosition - 1;
+ n = aSpec.Mid(mPath, dividerPosition + 1, count);
+ NS_ASSERTION(n == count, "Storing the path failed!");
+
+ ToLowerCase(mScheme);
+}
+
+static NS_DEFINE_CID(kNullPrincipalURIImplementationCID,
+ NS_NULLPRINCIPALURI_IMPLEMENTATION_CID);
+
+NS_IMPL_THREADSAFE_ADDREF(nsNullPrincipalURI)
+NS_IMPL_THREADSAFE_RELEASE(nsNullPrincipalURI)
+
+NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+ if (aIID.Equals(kNullPrincipalURIImplementationCID))
+ foundInterface = static_cast<nsIURI *>(this);
+ else
+ NS_INTERFACE_MAP_ENTRY(nsIURI)
+NS_INTERFACE_MAP_END
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIURI
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetAsciiHost(nsACString &_host)
+{
+ _host.Truncate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
+{
+ nsCAutoString buffer;
+ (void)GetSpec(buffer);
+ NS_EscapeURL(buffer, esc_OnlyNonASCII | esc_AlwaysCopy, _spec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetHost(nsACString &_host)
+{
+ _host.Truncate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetHost(const nsACString &aHost)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetHostPort(nsACString &_host)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetHostPort(const nsACString &aHost)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetOriginCharset(nsACString &_charset)
+{
+ _charset.Truncate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPassword(nsACString &_password)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPassword(const nsACString &aPassword)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPath(nsACString &_path)
+{
+ // We want to give a full copy of the string and not share a string buffer
+ _path = nsDependentCString(mPath);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPath(const nsACString &aPath)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPrePath(nsACString &_prePath)
+{
+ _prePath = mScheme + NS_LITERAL_CSTRING(":");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetPort(PRInt32 *_port)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetPort(PRInt32 aPort)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetScheme(nsACString &_scheme)
+{
+ // We want to give a full copy of the string and not share a string buffer
+ _scheme = nsDependentCString(mScheme);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetScheme(const nsACString &aScheme)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetSpec(nsACString &_spec)
+{
+ _spec = mScheme + NS_LITERAL_CSTRING(":") + mPath;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetSpec(const nsACString &aSpec)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetUsername(nsACString &_username)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetUsername(const nsACString &aUsername)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::GetUserPass(nsACString &_userPass)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SetUserPass(const nsACString &aUserPass)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Clone(nsIURI **_newURI)
+{
+ nsCOMPtr<nsIURI> uri =
+ new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath);
+ NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
+ uri.forget(_newURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
+{
+ *_equals = PR_FALSE;
+ nsNullPrincipalURI *otherURI;
+ nsresult rv = aOther->QueryInterface(kNullPrincipalURIImplementationCID,
+ (void **)&otherURI);
+ if (NS_SUCCEEDED(rv)) {
+ *_equals = (0 == strcmp(mScheme.get(), otherURI->mScheme.get()) &&
+ 0 == strcmp(mPath.get(), otherURI->mPath.get()));
+ NS_RELEASE(otherURI);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::Resolve(const nsACString &aRelativePath,
+ nsACString &_resolvedURI)
+{
+ _resolvedURI = aRelativePath;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipalURI::SchemeIs(const char *aScheme, PRBool *_schemeIs)
+{
+ *_schemeIs = (0 == nsCRT::strcasecmp(mScheme.get(), aScheme));
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/caps/src/nsNullPrincipalURI.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Shawn Wilsher <me@shawnwilsher.com> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+/**
+ * This wraps nsSimpleURI so that all calls to it are done on the main thread.
+ */
+
+#ifndef __nsNullPrincipalURI_h__
+#define __nsNullPrincipalURI_h__
+
+#include "nsIURI.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+
+// {51fcd543-3b52-41f7-b91b-6b54102236e6}
+#define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \
+ {0x51fcd543, 0x3b52, 0x41f7, \
+ {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
+
+class nsNullPrincipalURI : public nsIURI
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIURI
+
+ nsNullPrincipalURI(const nsCString &aSpec);
+
+private:
+ nsCString mScheme;
+ nsCString mPath;
+};
+
+#endif // __nsNullPrincipalURI_h__
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -311,128 +311,17 @@ nsScriptSecurityManager::GetSafeJSContex
return cx;
}
/* static */
PRBool
nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
nsIURI* aTargetURI)
{
- // Note that this is not an Equals() test on purpose -- for URIs that don't
- // support host/port, we want equality to basically be object identity, for
- // security purposes. Otherwise, for example, two javascript: URIs that
- // are otherwise unrelated could end up "same origin", which would be
- // unfortunate.
- if (aSourceURI && aSourceURI == aTargetURI)
- {
- return PR_TRUE;
- }
-
- if (!aTargetURI || !aSourceURI)
- {
- return PR_FALSE;
- }
-
- // If either URI is a nested URI, get the base URI
- nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
- nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
-
- if (!sourceBaseURI || !targetBaseURI)
- return PR_FALSE;
-
- // Compare schemes
- nsCAutoString targetScheme;
- PRBool sameScheme = PR_FALSE;
- if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) ||
- NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) ||
- !sameScheme)
- {
- // Not same-origin if schemes differ
- return PR_FALSE;
- }
-
- // special handling for file: URIs
- if (targetScheme.EqualsLiteral("file"))
- {
- // in traditional unsafe behavior all files are the same origin
- if (!sStrictFileOriginPolicy)
- return PR_TRUE;
-
- nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
- nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
-
- if (!sourceFileURL || !targetFileURL)
- return PR_FALSE;
-
- nsCOMPtr<nsIFile> sourceFile, targetFile;
-
- sourceFileURL->GetFile(getter_AddRefs(sourceFile));
- targetFileURL->GetFile(getter_AddRefs(targetFile));
-
- if (!sourceFile || !targetFile)
- return PR_FALSE;
-
- // Otherwise they had better match
- PRBool filesAreEqual = PR_FALSE;
- nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual);
- return NS_SUCCEEDED(rv) && filesAreEqual;
- }
-
- // Special handling for mailnews schemes
- if (targetScheme.EqualsLiteral("imap") ||
- targetScheme.EqualsLiteral("mailbox") ||
- targetScheme.EqualsLiteral("news"))
- {
- // Each message is a distinct trust domain; use the
- // whole spec for comparison
- nsCAutoString targetSpec;
- nsCAutoString sourceSpec;
- return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) &&
- NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) &&
- targetSpec.Equals(sourceSpec) );
- }
-
- // Compare hosts
- nsCAutoString targetHost;
- nsCAutoString sourceHost;
- if (NS_FAILED( targetBaseURI->GetHost(targetHost) ) ||
- NS_FAILED( sourceBaseURI->GetHost(sourceHost) ) ||
- !targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator()))
- {
- // Not same-origin if hosts differ
- return PR_FALSE;
- }
-
- // Compare ports
- PRInt32 targetPort;
- nsresult rv = targetBaseURI->GetPort(&targetPort);
- PRInt32 sourcePort;
- if (NS_SUCCEEDED(rv))
- rv = sourceBaseURI->GetPort(&sourcePort);
- PRBool result = NS_SUCCEEDED(rv) && targetPort == sourcePort;
- // If the port comparison failed, see if either URL has a
- // port of -1. If so, replace -1 with the default port
- // for that scheme.
- if (NS_SUCCEEDED(rv) && !result &&
- (sourcePort == -1 || targetPort == -1))
- {
- NS_ENSURE_TRUE(sIOService, PR_FALSE);
-
- PRInt32 defaultPort = NS_GetDefaultPort(targetScheme.get());
- if (defaultPort == -1)
- return PR_FALSE; // No default port for this scheme
-
- if (sourcePort == -1)
- sourcePort = defaultPort;
- else if (targetPort == -1)
- targetPort = defaultPort;
- result = targetPort == sourcePort;
- }
-
- return result;
+ return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
}
NS_IMETHODIMP
nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal)
{
NS_PRECONDITION(aChannel, "Must have channel!");
nsCOMPtr<nsISupports> owner;
--- a/client.mk
+++ b/client.mk
@@ -84,21 +84,19 @@ endif
ifndef TOPSRCDIR
ifeq (,$(wildcard client.mk))
$(error Must run from the client.mk directory, or specify TOPSRCDIR)
endif
TOPSRCDIR = $(CWD)
endif
-ifeq (Darwin,$(shell uname -s))
-AUTOCONF ?= autoconf213
-else
-AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 | head -1)
-endif
+# try to find autoconf 2.13 - discard errors from 'which'
+# MacOS X 10.4 sends "no autoconf*" errors to stdout, discard those via grep
+AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 2>/dev/null | grep -v '^no autoconf' | head -1)
MKDIR := mkdir
SH := /bin/sh
ifndef MAKE
MAKE := gmake
endif
PERL ?= perl
PYTHON ?= python
@@ -159,16 +157,17 @@ ifdef MOZ_OBJDIR
MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
else
OBJDIR := $(TOPSRCDIR)
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
endif
endif # MOZ_BUILD_PROJECTS
+# 'configure' scripts generated by autoconf.
CONFIGURES := $(TOPSRCDIR)/configure
CONFIGURES += $(TOPSRCDIR)/nsprpub/configure
#######################################################################
# Rules
#
# The default rule is build
@@ -271,30 +270,25 @@ CONFIG_STATUS = $(wildcard $(OBJDIR)/con
CONFIG_CACHE = $(wildcard $(OBJDIR)/config.cache)
ifdef RUN_AUTOCONF_LOCALLY
EXTRA_CONFIG_DEPS := \
$(TOPSRCDIR)/aclocal.m4 \
$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
$(NULL)
-$(TOPSRCDIR)/configure: $(TOPSRCDIR)/configure.in $(EXTRA_CONFIG_DEPS)
+$(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS)
@echo Generating $@ using autoconf
- cd $(TOPSRCDIR); $(AUTOCONF)
-
-$(TOPSRCDIR)/nsprpub/configure: $(TOPSRCDIR)/nsprpub/configure.in $(EXTRA_CONFIG_DEPS)
- @echo Generating $@ using autoconf
- cd $(TOPSRCDIR)/nsprpub; $(AUTOCONF)
+ cd $(@D); $(AUTOCONF)
endif
CONFIG_STATUS_DEPS := \
- $(TOPSRCDIR)/configure \
+ $(wildcard $(CONFIGURES)) \
$(TOPSRCDIR)/allmakefiles.sh \
$(TOPSRCDIR)/.mozconfig.mk \
- $(wildcard $(TOPSRCDIR)/nsprpub/configure) \
$(wildcard $(TOPSRCDIR)/directory/c-sdk/configure) \
$(wildcard $(TOPSRCDIR)/config/milestone.txt) \
$(wildcard $(TOPSRCDIR)/config/chrome-versions.sh) \
$(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \
$(NULL)
# configure uses the program name to determine @srcdir@. Calling it without
# $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
@@ -304,17 +298,19 @@ ifeq ($(TOPSRCDIR),$(OBJDIR))
else
CONFIGURE = $(TOPSRCDIR)/configure
endif
ifdef MOZ_TOOLS
CONFIGURE = $(TOPSRCDIR)/configure
endif
-configure:: $(CONFIGURES)
+configure-files: $(CONFIGURES)
+
+configure:: configure-files
ifdef MOZ_BUILD_PROJECTS
@if test ! -d $(MOZ_OBJDIR); then $(MKDIR) $(MOZ_OBJDIR); else true; fi
endif
@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
@echo cd $(OBJDIR);
@echo $(CONFIGURE) $(CONFIGURE_ARGS)
@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
|| ( echo "*** Fix above errors and then restart with\
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -390,16 +390,17 @@ UNZIP = @UNZIP@
ZIP = @ZIP@
XARGS = @XARGS@
STRIP = @STRIP@
DOXYGEN = @DOXYGEN@
MAKE = @MAKE@
PBBUILD_BIN = @PBBUILD@
SDP = @SDP@
NSINSTALL_BIN = @NSINSTALL_BIN@
+WGET = @WGET@
ifdef MOZ_NATIVE_JPEG
JPEG_CFLAGS = @JPEG_CFLAGS@
JPEG_LIBS = @JPEG_LIBS@
JPEG_REQUIRES =
else
JPEG_CFLAGS = @MOZ_JPEG_CFLAGS@
JPEG_LIBS = @MOZ_JPEG_LIBS@
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
# x.x.x.x
# x.x.x+
#
# Referenced by milestone.pl.
# Hopefully I'll be able to automate replacement of *all*
# hardcoded milestones in the tree from these two files.
#--------------------------------------------------------
-1.9.1a2
+1.9.1b1pre
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1128,17 +1128,17 @@ ifeq ($(OS_ARCH),OpenVMS)
fi; \
fi
ifdef IS_COMPONENT
@if test ! -f $(VMS_SYMVEC_FILE); then \
echo Creating generic component options file $(VMS_SYMVEC_FILE); \
cp $(VMS_SYMVEC_FILE_COMP) $(VMS_SYMVEC_FILE); \
fi
endif
-endif
+endif # OpenVMS
ifdef NO_LD_ARCHIVE_FLAGS
ifdef SHARED_LIBRARY_LIBS
@rm -f $(SUB_SHLOBJS)
@for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
ifeq ($(OS_ARCH),Darwin)
@echo Making symlinks to the original object files in the archive libraries $(SHARED_LIBRARY_LIBS)
@for lib in $(SHARED_LIBRARY_LIBS); do \
libdir=`echo $$lib|sed -e 's,/[^/]*\.a,,'`; \
@@ -1166,17 +1166,17 @@ endif
$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
@rm -f $(PROBE_LOBJS)
@rm -f $(DTRACE_PROBE_OBJ)
@for lib in $(MOZILLA_PROBE_LIBS); do \
if [ -L $${lib} ]; then rm -f `readlink $${lib}`; fi; \
done
@rm -f $(MOZILLA_PROBE_LIBS)
-else
+else # ! DTRACE_LIB_DEPENDENT
$(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
endif # DTRACE_LIB_DEPENDENT
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
ifdef MSMANIFEST_TOOL
ifdef EMBED_MANIFEST_AT
@if test -f $@.manifest; then \
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
--- a/configure.in
+++ b/configure.in
@@ -1369,16 +1369,34 @@ if test "$GNU_CXX"; then
*)
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
;;
esac
fi
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h'
_USE_CPP_INCLUDE_FLAG=1
+
+ AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
+ ac_has_wno_invalid_offsetof,
+ [
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ _SAVE_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
+ AC_TRY_COMPILE([],
+ [return(0);],
+ ac_has_wno_invalid_offsetof="yes",
+ ac_has_wno_invalid_offsetof="no")
+ CXXFLAGS="$_SAVE_CXXFLAGS"
+ AC_LANG_RESTORE
+ ])
+ if test "$ac_has_wno_invalid_offsetof" = "yes"; then
+ _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
+ fi
else
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
fi
dnl gcc can come with its own linker so it is better to use the pass-thru calls
dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
dnl files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker to
dnl normal behavior.
@@ -1453,17 +1471,16 @@ AC_CACHE_VAL(ac_cv_static_assertion_macr
ac_cv_static_assertion_macros_work="no",
)
AC_LANG_RESTORE
])
AC_MSG_RESULT("$ac_cv_static_assertion_macros_work")
if test "$ac_cv_static_assertion_macros_work" = "no"; then
AC_MSG_ERROR([Compiler cannot compile macros used in autoconf tests.])
fi
-
fi # COMPILE_ENVIRONMENT
dnl ========================================================
dnl Checking for 64-bit OS
dnl ========================================================
if test "$COMPILE_ENVIRONMENT"; then
AC_LANG_SAVE
AC_LANG_C
@@ -4625,16 +4642,20 @@ content/xslt)
standalone)
MOZ_APP_NAME=mozilla
MOZ_APP_DISPLAYNAME=Mozilla
MOZ_APP_VERSION=$MOZILLA_VERSION
;;
esac
+if test -z "$MOZ_XUL_APP"; then
+ AC_MSG_ERROR([builds with unsetting MOZ_XUL_APP in confvars.sh are not supported.])
+fi
+
AC_SUBST(MOZ_BUILD_APP)
AC_SUBST(MOZ_XUL_APP)
AC_SUBST(MOZ_PHOENIX)
AC_SUBST(MOZ_STANDALONE_COMPOSER)
AC_SUBST(MOZ_XULRUNNER)
AC_DEFINE_UNQUOTED(MOZ_BUILD_APP,$MOZ_BUILD_APP)
@@ -4771,17 +4792,17 @@ cairo-mac|cairo-cocoa)
else
MOZ_WIDGET_TOOLKIT=mac
fi
MOZ_GFX_TOOLKIT=cairo
MOZ_USER_DIR="Mozilla"
AC_DEFINE(XP_MACOSX)
AC_DEFINE(TARGET_CARBON)
AC_DEFINE(TARGET_API_MAC_CARBON)
- TK_LIBS='-framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit'
+ TK_LIBS='-framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook'
TK_CFLAGS="-I${MACOS_SDK_DIR}/Developer/Headers/FlatCarbon"
CFLAGS="$CFLAGS $TK_CFLAGS"
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
;;
esac
if test "$MOZ_ENABLE_XREMOTE"; then
AC_DEFINE(MOZ_ENABLE_XREMOTE)
@@ -5770,16 +5791,21 @@ AC_SUBST(MOZ_INSTALLER)
AC_MSG_CHECKING([for tar archiver])
AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
if test -z "$TAR"; then
AC_MSG_ERROR([no tar archiver found in \$PATH])
fi
AC_MSG_RESULT([$TAR])
AC_SUBST(TAR)
+AC_MSG_CHECKING([for wget])
+AC_CHECK_PROGS(WGET, wget, "")
+AC_MSG_RESULT([$WGET])
+AC_SUBST(WGET)
+
dnl ========================================================
dnl Updater
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(updater,
[ --disable-updater Disable building of updater],
MOZ_UPDATER=,
MOZ_UPDATER=1 )
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -96,16 +96,17 @@ class nsIScriptContext;
class nsIRunnable;
template<class E> class nsCOMArray;
class nsIPref;
class nsVoidArray;
struct JSRuntime;
class nsICaseConversion;
class nsIUGenCategory;
class nsIWidget;
+class nsIDragSession;
class nsPIDOMWindow;
#ifdef MOZ_XTF
class nsIXTFService;
#endif
#ifdef IBMBIDI
class nsIBidiKeyboard;
#endif
@@ -1214,16 +1215,21 @@ public:
/**
* Hide any XUL popups associated with aDocument, including any documents
* displayed in child frames.
*/
static void HidePopupsInDocument(nsIDocument* aDocument);
/**
+ * Retrieve the current drag session, or null if no drag is currently occuring
+ */
+ static already_AddRefed<nsIDragSession> GetDragSession();
+
+ /**
* Return true if aURI is a local file URI (i.e. file://).
*/
static PRBool URIIsLocalFile(nsIURI *aURI);
/**
* If aContent is an HTML element with a DOM level 0 'name', then
* return the name. Otherwise return null.
*/
@@ -1240,16 +1246,21 @@ public:
static void GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI);
/**
* Check whether an application should be allowed to use offline APIs.
*/
static PRBool OfflineAppAllowed(nsIURI *aURI);
/**
+ * Check whether an application should be allowed to use offline APIs.
+ */
+ static PRBool OfflineAppAllowed(nsIPrincipal *aPrincipal);
+
+ /**
* Increases the count of blockers preventing scripts from running.
* NOTE: You might want to use nsAutoScriptBlocker rather than calling
* this directly
*/
static void AddScriptBlocker();
/**
* Decreases the count of blockers preventing scripts from running.
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -92,18 +92,18 @@ class nsIDocumentObserver;
class nsBindingManager;
class nsIDOMNodeList;
class mozAutoSubtreeModified;
struct JSObject;
class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
- { 0x5f0203a8, 0xd926, 0x4adf, \
- { 0xba, 0x96, 0xe6, 0xc3, 0xe6, 0xbb, 0x1b, 0xe5 } }
+ { 0xd5b1e3c5, 0x85dc, 0x403e, \
+ { 0xbb, 0x4a, 0x54, 0x66, 0xdc, 0xbe, 0x15, 0x69 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
//----------------------------------------------------------------------
// Document interface. This is implemented by all document objects in
// Gecko.
@@ -565,16 +565,21 @@ public:
* for event/script handling. Do not process any events/script if the method
* returns null, but aHasHadScriptHandlingObject is true.
*/
virtual nsIScriptGlobalObject*
GetScriptHandlingObject(PRBool& aHasHadScriptHandlingObject) const = 0;
virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject) = 0;
/**
+ * Sets script handling object to null and marks that document has had one.
+ */
+ virtual void ClearScriptHandlingObject() = 0;
+
+ /**
* Get the object that is used as the scope for all of the content
* wrappers whose owner document is this document. Unlike the script global
* object, this will only return null when the global object for this
* document is truly gone. Use this object when you're trying to find a
* content wrapper in XPConnect.
*/
virtual nsIScriptGlobalObject* GetScopeObject() = 0;
@@ -893,16 +898,24 @@ public:
virtual void ClearBoxObjectFor(nsIContent *aContent) = 0;
/**
* Get the compatibility mode for this document
*/
nsCompatibility GetCompatibilityMode() const {
return mCompatMode;
}
+
+ /**
+ * Check whether we've ever fired a DOMTitleChanged event for this
+ * document.
+ */
+ PRBool HaveFiredDOMTitleChange() const {
+ return mHaveFiredTitleChange;
+ }
/**
* See GetXBLChildNodesFor on nsBindingManager
*/
virtual nsresult GetXBLChildNodesFor(nsIContent* aContent,
nsIDOMNodeList** aResult) = 0;
/**
@@ -1055,16 +1068,19 @@ protected:
// True if we're loaded as data and therefor has any dangerous stuff, such
// as scripts and plugins, disabled.
PRPackedBool mLoadedAsData;
// If true, whoever is creating the document has gotten it to the
// point where it's safe to start layout on it.
PRPackedBool mMayStartLayout;
+
+ // True iff we've ever fired a DOMTitleChanged event for this document
+ PRPackedBool mHaveFiredTitleChange;
// The bidi options for this document. What this bitfield means is
// defined in nsBidiUtils.h
PRUint32 mBidiOptions;
nsCString mContentLanguage;
nsCString mContentType;
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -54,16 +54,17 @@ REQUIRES = xpcom \
layout \
widget \
view \
locale \
htmlparser \
js \
webshell \
necko \
+ nkcache \
mimetype \
exthandler \
chardet \
caps \
lwbrk \
uconv \
docshell \
pref \
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -40,24 +40,25 @@
// Local Includes
#include "nsContentAreaDragDrop.h"
// Helper Classes
#include "nsString.h"
// Interfaces needed to be included
+#include "nsIVariant.h"
#include "nsIDOMNSUIEvent.h"
#include "nsIDOMUIEvent.h"
#include "nsISelection.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMEvent.h"
#include "nsIDOMNSEvent.h"
-#include "nsIDOMMouseEvent.h"
+#include "nsIDOMDragEvent.h"
#include "nsIDOMAbstractView.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentRange.h"
#include "nsIDOMRange.h"
#include "nsIDocumentEncoder.h"
#include "nsIFormControl.h"
#include "nsISelectionPrivate.h"
@@ -68,38 +69,38 @@
#include "nsIDragSession.h"
#include "nsComponentManagerUtils.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
#include "nsNetUtil.h"
#include "nsIFile.h"
#include "nsIWebNavigation.h"
-#include "nsIClipboardDragDropHooks.h"
-#include "nsIClipboardDragDropHookList.h"
#include "nsIDocShell.h"
#include "nsIContent.h"
#include "nsIImageLoadingContent.h"
#include "nsINameSpaceManager.h"
#include "nsUnicharUtils.h"
#include "nsIURL.h"
#include "nsIImage.h"
#include "nsIDocument.h"
#include "nsIScriptSecurityManager.h"
+#include "nsIPrincipal.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIDocShellTreeItem.h"
#include "nsIFrame.h"
#include "nsRange.h"
#include "nsIWebBrowserPersist.h"
#include "nsEscape.h"
#include "nsContentUtils.h"
#include "nsIMIMEService.h"
#include "imgIRequest.h"
#include "nsContentCID.h"
+#include "nsDOMDataTransfer.h"
#include "nsISelectionController.h"
#include "nsFrameSelection.h"
#include "nsIDOMEventTarget.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
// private clipboard data flavors for html copy, used by editor when pasting
@@ -109,53 +110,62 @@ static NS_DEFINE_CID(kHTMLConverterCID,
NS_IMPL_ADDREF(nsContentAreaDragDrop)
NS_IMPL_RELEASE(nsContentAreaDragDrop)
NS_INTERFACE_MAP_BEGIN(nsContentAreaDragDrop)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDragListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMDragListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMDragListener)
- NS_INTERFACE_MAP_ENTRY(nsIFlavorDataProvider)
NS_INTERFACE_MAP_ENTRY(nsIDragDropHandler)
NS_INTERFACE_MAP_END
class NS_STACK_CLASS nsTransferableFactory
{
public:
- nsTransferableFactory(nsIDOMEvent* inMouseEvent,
- nsIFlavorDataProvider *inFlavorDataProvider);
- nsresult Produce(PRBool *aDragSelection, nsITransferable** outTrans);
+ nsTransferableFactory(nsIDOMWindow* aWindow,
+ nsIContent* aTarget,
+ nsIContent* aSelectionTargetNode,
+ PRBool aIsAltKeyPressed);
+ nsresult Produce(nsDOMDataTransfer* aDataTransfer,
+ PRBool* aCanDrag,
+ PRBool* aDragSelection,
+ nsIContent** aDragNode);
private:
- nsresult ConvertStringsToTransferable(nsITransferable** outTrans);
+ void AddString(nsDOMDataTransfer* aDataTransfer,
+ const nsAString& aFlavor,
+ const nsAString& aData,
+ nsIPrincipal* aPrincipal);
+ nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
+ nsDOMDataTransfer* aDataTransfer);
static nsresult GetDraggableSelectionData(nsISelection* inSelection,
- nsIDOMNode* inRealTargetNode,
- nsIDOMNode **outImageOrLinkNode,
+ nsIContent* inRealTargetNode,
+ nsIContent **outImageOrLinkNode,
PRBool* outDragSelectedText);
- static already_AddRefed<nsIDOMNode> FindParentLinkNode(nsIDOMNode* inNode);
- static void GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL);
- static void GetNodeString(nsIDOMNode* inNode, nsAString & outNodeString);
+ static already_AddRefed<nsIContent> FindParentLinkNode(nsIContent* inNode);
+ static void GetAnchorURL(nsIContent* inNode, nsAString& outURL);
+ static void GetNodeString(nsIContent* inNode, nsAString & outNodeString);
static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
nsAString& outLinkText);
static void GetSelectedLink(nsISelection* inSelection,
- nsIDOMNode **outLinkNode);
+ nsIContent **outLinkNode);
// if inNode is null, use the selection from the window
static nsresult SerializeNodeOrSelection(nsIDOMWindow* inWindow,
- nsIDOMNode* inNode,
+ nsIContent* inNode,
nsAString& outResultString,
nsAString& outHTMLContext,
nsAString& outHTMLInfo);
- PRBool mInstanceAlreadyUsed;
-
- nsCOMPtr<nsIDOMEvent> mMouseEvent;
- nsCOMPtr<nsIFlavorDataProvider> mFlavorDataProvider;
+ nsCOMPtr<nsIDOMWindow> mWindow;
+ nsCOMPtr<nsIContent> mTarget;
+ nsCOMPtr<nsIContent> mSelectionTargetNode;
+ PRPackedBool mIsAltKeyPressed;
nsString mUrlString;
nsString mImageSourceString;
nsString mImageDestFileName;
nsString mTitleString;
// will be filled automatically if you fill urlstring
nsString mHtmlString;
nsString mContextString;
@@ -287,101 +297,63 @@ nsContentAreaDragDrop::DragOver(nsIDOMEv
nsuiEvent->GetPreventDefault(&preventDefault);
if ( preventDefault )
return NS_OK;
// if the drag originated w/in this content area, bail
// early. This avoids loading a URL dragged from the content
// area into the very same content area (which is almost never
// the desired action).
- nsCOMPtr<nsIDragService> dragService =
- do_GetService("@mozilla.org/widget/dragservice;1");
- if (!dragService)
- return NS_ERROR_FAILURE;
- nsCOMPtr<nsIDragSession> session;
- dragService->GetCurrentSession(getter_AddRefs(session));
+ nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
+ NS_ENSURE_TRUE(session, NS_OK);
+
+ PRBool dropAllowed = PR_TRUE;
- if (session) {
- // if the client has provided an override callback, check if we
- // the drop is allowed. If it allows it, we should still protect
- // against dropping w/in the same document.
- PRBool dropAllowed = PR_TRUE;
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- GetHookEnumeratorFromEvent(inEvent, getter_AddRefs(enumerator));
+ nsCOMPtr<nsIDOMDocument> sourceDoc;
+ session->GetSourceDocument(getter_AddRefs(sourceDoc));
+ nsCOMPtr<nsIDOMDocument> eventDoc;
+ GetEventDocument(inEvent, getter_AddRefs(eventDoc));
+
+ if (sourceDoc == eventDoc) { // common case
+ dropAllowed = PR_FALSE;
+ } else if (sourceDoc && eventDoc) {
+ // dig deeper
+ // XXXbz we need better ways to get from a document to the docshell!
+ nsCOMPtr<nsIDocument> sourceDocument(do_QueryInterface(sourceDoc));
+ nsCOMPtr<nsIDocument> eventDocument(do_QueryInterface(eventDoc));
+ NS_ASSERTION(sourceDocument, "Confused document object");
+ NS_ASSERTION(eventDocument, "Confused document object");
- if (enumerator) {
- PRBool hasMoreHooks = PR_FALSE;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
- && hasMoreHooks) {
- nsCOMPtr<nsISupports> isupp;
- if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
- break;
- }
+ nsPIDOMWindow* sourceWindow = sourceDocument->GetWindow();
+ nsPIDOMWindow* eventWindow = eventDocument->GetWindow();
+
+ if (sourceWindow && eventWindow) {
+ nsCOMPtr<nsIDocShellTreeItem> sourceShell =
+ do_QueryInterface(sourceWindow->GetDocShell());
+ nsCOMPtr<nsIDocShellTreeItem> eventShell =
+ do_QueryInterface(eventWindow->GetDocShell());
- nsCOMPtr<nsIClipboardDragDropHooks> override =
- do_QueryInterface(isupp);
+ if (sourceShell && eventShell) {
+ // Whew. Almost there. Get the roots that are of the same type
+ // (otherwise we'll always end up with the root docshell for the
+ // window, and drag/drop from chrom to content won't work).
+ nsCOMPtr<nsIDocShellTreeItem> sourceRoot;
+ nsCOMPtr<nsIDocShellTreeItem> eventRoot;
+ sourceShell->GetSameTypeRootTreeItem(getter_AddRefs(sourceRoot));
+ eventShell->GetSameTypeRootTreeItem(getter_AddRefs(eventRoot));
- if (override) {
-#ifdef DEBUG
- nsresult hookResult =
-#endif
- override->AllowDrop(inEvent, session, &dropAllowed);
- NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowDrop");
-
- if (!dropAllowed) {
- break;
- }
+ if (sourceRoot && sourceRoot == eventRoot) {
+ dropAllowed = PR_FALSE;
}
}
}
-
- nsCOMPtr<nsIDOMDocument> sourceDoc;
- session->GetSourceDocument(getter_AddRefs(sourceDoc));
- nsCOMPtr<nsIDOMDocument> eventDoc;
- GetEventDocument(inEvent, getter_AddRefs(eventDoc));
-
- if (sourceDoc == eventDoc) { // common case
- dropAllowed = PR_FALSE;
- } else if (sourceDoc && eventDoc) {
- // dig deeper
- // XXXbz we need better ways to get from a document to the docshell!
- nsCOMPtr<nsIDocument> sourceDocument(do_QueryInterface(sourceDoc));
- nsCOMPtr<nsIDocument> eventDocument(do_QueryInterface(eventDoc));
- NS_ASSERTION(sourceDocument, "Confused document object");
- NS_ASSERTION(eventDocument, "Confused document object");
-
- nsPIDOMWindow* sourceWindow = sourceDocument->GetWindow();
- nsPIDOMWindow* eventWindow = eventDocument->GetWindow();
-
- if (sourceWindow && eventWindow) {
- nsCOMPtr<nsIDocShellTreeItem> sourceShell =
- do_QueryInterface(sourceWindow->GetDocShell());
- nsCOMPtr<nsIDocShellTreeItem> eventShell =
- do_QueryInterface(eventWindow->GetDocShell());
-
- if (sourceShell && eventShell) {
- // Whew. Almost there. Get the roots that are of the same type
- // (otherwise we'll always end up with the root docshell for the
- // window, and drag/drop from chrom to content won't work).
- nsCOMPtr<nsIDocShellTreeItem> sourceRoot;
- nsCOMPtr<nsIDocShellTreeItem> eventRoot;
- sourceShell->GetSameTypeRootTreeItem(getter_AddRefs(sourceRoot));
- eventShell->GetSameTypeRootTreeItem(getter_AddRefs(eventRoot));
-
- if (sourceRoot && sourceRoot == eventRoot) {
- dropAllowed = PR_FALSE;
- }
- }
- }
- }
-
- session->SetCanDrop(dropAllowed);
}
+ session->SetCanDrop(dropAllowed);
return NS_OK;
}
//
// DragExit
//
// Called when an OS drag is in process and the mouse is over a gecko
@@ -492,27 +464,18 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEv
if (preventDefault) {
return NS_OK;
}
// pull the transferable out of the drag service. at the moment, we
// only care about the first item of the drag. We don't allow
// dropping multiple items into a content area.
- nsCOMPtr<nsIDragService> dragService =
- do_GetService("@mozilla.org/widget/dragservice;1");
- if (!dragService) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDragSession> session;
- dragService->GetCurrentSession(getter_AddRefs(session));
- if (!session) {
- return NS_ERROR_FAILURE;
- }
+ nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
+ NS_ENSURE_TRUE(session, NS_OK);
nsCOMPtr<nsITransferable> trans =
do_CreateInstance("@mozilla.org/widget/transferable;1");
if (!trans) {
return NS_ERROR_FAILURE;
}
// add the relevant flavors. order is important (highest fidelity to lowest)
@@ -520,45 +483,16 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEv
trans->AddDataFlavor(kURLMime);
trans->AddDataFlavor(kFileMime);
trans->AddDataFlavor(kUnicodeMime);
// again, we only care about the first object
nsresult rv = session->GetData(trans, 0);
if (NS_SUCCEEDED(rv)) {
- // if the client has provided an override callback, call it. It may
- // still return that we should continue processing.
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
-
- if (enumerator) {
- PRBool actionCanceled = PR_TRUE;
- PRBool hasMoreHooks = PR_FALSE;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
- && hasMoreHooks) {
- nsCOMPtr<nsISupports> isupp;
- if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
- break;
- nsCOMPtr<nsIClipboardDragDropHooks> override =
- do_QueryInterface(isupp);
-
- if (override) {
-#ifdef DEBUG
- nsresult hookResult =
-#endif
- override->OnPasteOrDrop(inMouseEvent, trans, &actionCanceled);
- NS_ASSERTION(NS_SUCCEEDED(hookResult),
- "hook failure in OnPasteOrDrop");
- if (!actionCanceled)
- return NS_OK;
- }
- }
- }
-
nsXPIDLCString flavor;
nsCOMPtr<nsISupports> dataWrapper;
PRUint32 dataLen = 0;
rv = trans->GetAnyTransferData(getter_Copies(flavor),
getter_AddRefs(dataWrapper), &dataLen);
if (NS_SUCCEEDED(rv) && dataLen > 0) {
// get the url from one of several possible formats
nsAutoString url;
@@ -660,194 +594,64 @@ nsContentAreaDragDrop::GetEventDocument(
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(view));
if (window) {
window->GetDocument(outDocument);
}
}
}
-nsresult
-nsContentAreaDragDrop::GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
- nsISimpleEnumerator **outEnumerator)
-{
- *outEnumerator = nsnull;
-
- nsCOMPtr<nsIDOMDocument> domdoc;
- GetEventDocument(inEvent, getter_AddRefs(domdoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsISupports> container = doc->GetContainer();
- nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIClipboardDragDropHookList> hookList = do_GetInterface(docShell);
- NS_ENSURE_TRUE(hookList, NS_ERROR_FAILURE);
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- hookList->GetHookEnumerator(getter_AddRefs(enumerator));
- NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
-
- *outEnumerator = enumerator;
- NS_ADDREF(*outEnumerator);
-
- return NS_OK;
-}
-
//
// DragGesture
//
-// Determine if the user has started to drag something and kick off
-// an OS-level drag if it's applicable
-//
NS_IMETHODIMP
nsContentAreaDragDrop::DragGesture(nsIDOMEvent* inMouseEvent)
{
- // first check that someone hasn't already handled this event
- PRBool preventDefault = PR_TRUE;
- nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent(do_QueryInterface(inMouseEvent));
- if (nsuiEvent) {
- nsuiEvent->GetPreventDefault(&preventDefault);
- }
-
- if (preventDefault) {
- return NS_OK;
- }
-
- // if the client has provided an override callback, check if we
- // should continue
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
-
- if (enumerator) {
- PRBool allow = PR_TRUE;
- PRBool hasMoreHooks = PR_FALSE;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
- && hasMoreHooks) {
- nsCOMPtr<nsISupports> isupp;
- if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
- break;
-
- nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
- if (override) {
-#ifdef DEBUG
- nsresult hookResult =
-#endif
- override->AllowStartDrag(inMouseEvent, &allow);
- NS_ASSERTION(NS_SUCCEEDED(hookResult),
- "hook failure in AllowStartDrag");
-
- if (!allow)
- return NS_OK;
- }
- }
- }
-
- PRBool isSelection = PR_FALSE;
- nsCOMPtr<nsITransferable> trans;
- nsTransferableFactory factory(inMouseEvent, static_cast<nsIFlavorDataProvider*>(this));
- factory.Produce(&isSelection, getter_AddRefs(trans));
-
- if (trans) {
- // if the client has provided an override callback, let them manipulate
- // the flavors or drag data
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
- if (enumerator) {
- PRBool hasMoreHooks = PR_FALSE;
- PRBool doContinueDrag = PR_TRUE;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
- && hasMoreHooks) {
- nsCOMPtr<nsISupports> isupp;
- if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
- break;
- nsCOMPtr<nsIClipboardDragDropHooks> override =
- do_QueryInterface(isupp);
+ return NS_OK;
+}
- if (override) {
-#ifdef DEBUG
- nsresult hookResult =
-#endif
- override->OnCopyOrDrag(inMouseEvent, trans, &doContinueDrag);
- NS_ASSERTION(NS_SUCCEEDED(hookResult),
- "hook failure in OnCopyOrDrag");
-
- if (!doContinueDrag) {
- return NS_OK;
- }
- }
- }
- }
-
- nsCOMPtr<nsISupportsArray> transArray =
- do_CreateInstance("@mozilla.org/supports-array;1");
- if (!transArray) {
- return NS_ERROR_FAILURE;
- }
-
- transArray->InsertElementAt(trans, 0);
-
- // kick off the drag
- nsCOMPtr<nsIDOMEventTarget> target;
- inMouseEvent->GetTarget(getter_AddRefs(target));
- nsCOMPtr<nsIDragService> dragService =
- do_GetService("@mozilla.org/widget/dragservice;1");
+nsresult
+nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
+ nsIContent* aTarget,
+ nsIContent* aSelectionTargetNode,
+ PRBool aIsAltKeyPressed,
+ nsDOMDataTransfer* aDataTransfer,
+ PRBool* aCanDrag,
+ PRBool* aDragSelection,
+ nsIContent** aDragNode)
+{
+ NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
- if (!dragService) {
- return NS_ERROR_FAILURE;
- }
-
- PRUint32 action = nsIDragService::DRAGDROP_ACTION_COPY +
- nsIDragService::DRAGDROP_ACTION_MOVE +
- nsIDragService::DRAGDROP_ACTION_LINK;
-
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(inMouseEvent));
+ *aCanDrag = PR_TRUE;
- if (isSelection) {
- nsCOMPtr<nsIContent> targetContent(do_QueryInterface(target));
- nsIDocument* doc = targetContent->GetCurrentDoc();
- if (doc) {
- nsIPresShell* presShell = doc->GetPrimaryShell();
- if (presShell) {
- nsISelection* selection =
- presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
- return dragService->InvokeDragSessionWithSelection(selection,
- transArray,
- action,
- mouseEvent);
- }
- }
- }
-
- nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(target));
- dragService->InvokeDragSessionWithImage(targetNode, transArray, nsnull,
- action, nsnull, 0, 0, mouseEvent);
- }
-
- return NS_OK;
+ nsTransferableFactory
+ factory(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
+ return factory.Produce(aDataTransfer, aCanDrag, aDragSelection, aDragNode);
}
NS_IMETHODIMP
nsContentAreaDragDrop::HandleEvent(nsIDOMEvent *event)
{
return NS_OK;
}
#if 0
#pragma mark -
#endif
+NS_IMPL_ISUPPORTS1(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
+
// SaveURIToFile
// used on platforms where it's possible to drag items (e.g. images)
// into the file system
nsresult
-nsContentAreaDragDrop::SaveURIToFile(nsAString& inSourceURIString,
- nsIFile* inDestFile)
+nsContentAreaDragDropDataProvider::SaveURIToFile(nsAString& inSourceURIString,
+ nsIFile* inDestFile)
{
nsCOMPtr<nsIURI> sourceURI;
nsresult rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
@@ -860,37 +664,37 @@ nsContentAreaDragDrop::SaveURIToFile(nsA
// we rely on the fact that the WPB is refcounted by the channel etc,
// so we don't keep a ref to it. It will die when finished.
nsCOMPtr<nsIWebBrowserPersist> persist =
do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
&rv);
NS_ENSURE_SUCCESS(rv, rv);
- return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull,
- inDestFile);
+ return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, inDestFile);
}
// This is our nsIFlavorDataProvider callback. There are several
// assumptions here that make this work:
//
// 1. Someone put a kFilePromiseURLMime flavor into the transferable
// with the source URI of the file to save (as a string). We did
-// that above.
+// that in AddStringsToDataTransfer.
//
// 2. Someone put a kFilePromiseDirectoryMime flavor into the
// transferable with an nsILocalFile for the directory we are to
// save in. That has to be done by platform-specific code (in
-// widget), // which gets the destination directory from
-// OS-specific drag // information.
+// widget), which gets the destination directory from
+// OS-specific drag information.
//
NS_IMETHODIMP
-nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
- const char *aFlavor, nsISupports **aData,
- PRUint32 *aDataLen)
+nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
+ const char *aFlavor,
+ nsISupports **aData,
+ PRUint32 *aDataLen)
{
NS_ENSURE_ARG_POINTER(aData && aDataLen);
*aData = nsnull;
*aDataLen = 0;
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
if (strcmp(aFlavor, kFilePromiseMime) == 0) {
@@ -932,75 +736,74 @@ nsContentAreaDragDrop::GetFlavorData(nsI
return NS_ERROR_FAILURE;
nsCOMPtr<nsIFile> file;
rv = destDirectory->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
file->Append(targetFilename);
- // now save the file
rv = SaveURIToFile(sourceURLString, file);
-
// send back an nsILocalFile
if (NS_SUCCEEDED(rv)) {
CallQueryInterface(file, aData);
*aDataLen = sizeof(nsIFile*);
}
}
return rv;
}
-nsTransferableFactory::nsTransferableFactory(nsIDOMEvent* inMouseEvent,
- nsIFlavorDataProvider *dataProvider)
- : mInstanceAlreadyUsed(PR_FALSE),
- mMouseEvent(inMouseEvent),
- mFlavorDataProvider(dataProvider)
+nsTransferableFactory::nsTransferableFactory(nsIDOMWindow* aWindow,
+ nsIContent* aTarget,
+ nsIContent* aSelectionTargetNode,
+ PRBool aIsAltKeyPressed)
+ : mWindow(aWindow),
+ mTarget(aTarget),
+ mSelectionTargetNode(aSelectionTargetNode),
+ mIsAltKeyPressed(aIsAltKeyPressed)
{
}
//
// FindParentLinkNode
//
// Finds the parent with the given link tag starting at |inNode|. If
// it gets up to the root without finding it, we stop looking and
// return null.
//
-already_AddRefed<nsIDOMNode>
-nsTransferableFactory::FindParentLinkNode(nsIDOMNode* inNode)
+already_AddRefed<nsIContent>
+nsTransferableFactory::FindParentLinkNode(nsIContent* inNode)
{
- nsCOMPtr<nsIContent> content(do_QueryInterface(inNode));
+ nsIContent* content = inNode;
if (!content) {
// That must have been the document node; nothing else to do here;
return nsnull;
}
for (; content; content = content->GetParent()) {
if (nsContentUtils::IsDraggableLink(content)) {
- nsIDOMNode* node = nsnull;
- CallQueryInterface(content, &node);
- return node;
+ NS_ADDREF(content);
+ return content;
}
}
return nsnull;
}
//
// GetAnchorURL
//
void
-nsTransferableFactory::GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL)
+nsTransferableFactory::GetAnchorURL(nsIContent* inNode, nsAString& outURL)
{
nsCOMPtr<nsIURI> linkURI;
- nsCOMPtr<nsIContent> content = do_QueryInterface(inNode);
- if (!content || !content->IsLink(getter_AddRefs(linkURI))) {
+ if (!inNode || !inNode->IsLink(getter_AddRefs(linkURI))) {
// Not a link
outURL.Truncate();
return;
}
nsCAutoString spec;
linkURI->GetSpec(spec);
CopyUTF8toUTF16(spec, outURL);
@@ -1032,190 +835,166 @@ nsTransferableFactory::CreateLinkText(co
//
// GetNodeString
//
// Gets the text associated with a node
//
void
-nsTransferableFactory::GetNodeString(nsIDOMNode* inNode,
+nsTransferableFactory::GetNodeString(nsIContent* inNode,
nsAString & outNodeString)
{
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
+
outNodeString.Truncate();
// use a range to get the text-equivalent of the node
nsCOMPtr<nsIDOMDocument> doc;
- inNode->GetOwnerDocument(getter_AddRefs(doc));
+ node->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocumentRange> docRange(do_QueryInterface(doc));
if (docRange) {
nsCOMPtr<nsIDOMRange> range;
docRange->CreateRange(getter_AddRefs(range));
if (range) {
- range->SelectNode(inNode);
+ range->SelectNode(node);
range->ToString(outNodeString);
}
}
}
nsresult
-nsTransferableFactory::Produce(PRBool* aDragSelection,
- nsITransferable** outTrans)
+nsTransferableFactory::Produce(nsDOMDataTransfer* aDataTransfer,
+ PRBool* aCanDrag,
+ PRBool* aDragSelection,
+ nsIContent** aDragNode)
{
- if (mInstanceAlreadyUsed) {
- return NS_ERROR_FAILURE;
- }
+ NS_PRECONDITION(aCanDrag && aDragSelection && aDataTransfer && aDragNode,
+ "null pointer passed to Produce");
+ NS_ASSERTION(mWindow, "window not set");
+ NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
- if (!outTrans || !mMouseEvent || !mFlavorDataProvider) {
- return NS_ERROR_FAILURE;
- }
+ *aDragNode = nsnull;
- mInstanceAlreadyUsed = PR_TRUE;
- *outTrans = nsnull;
+ nsIContent* dragNode = nsnull;
- nsCOMPtr<nsIDOMWindow> window;
- PRBool isAltKeyDown = PR_FALSE;
mIsAnchor = PR_FALSE;
- {
- nsCOMPtr<nsIDOMUIEvent> uiEvent(do_QueryInterface(mMouseEvent));
- if (!uiEvent) {
- return NS_OK;
- }
-
- // find the selection to see what we could be dragging and if
- // what we're dragging is in what is selected.
- nsCOMPtr<nsIDOMAbstractView> view;
- uiEvent->GetView(getter_AddRefs(view));
- window = do_QueryInterface(view);
- if (!window) {
- return NS_OK;
- }
- }
-
- {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(mMouseEvent));
- if (mouseEvent) {
- mouseEvent->GetAltKey(&isAltKeyDown);
- }
- }
-
+ // find the selection to see what we could be dragging and if
+ // what we're dragging is in what is selected.
nsCOMPtr<nsISelection> selection;
- window->GetSelection(getter_AddRefs(selection));
+ mWindow->GetSelection(getter_AddRefs(selection));
if (!selection) {
return NS_OK;
}
+ // check if the node is inside a form control. If so, dragging will be
+ // handled in editor code (nsPlaintextDataTransfer::DoDrag). Don't set
+ // aCanDrag to false however, as we still want to allow the drag.
+ nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
+ nsIContent* findFormParent = findFormNode->GetParent();
+ while (findFormParent) {
+ nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
+ if (form && form->GetType() != NS_FORM_OBJECT)
+ return NS_OK;
+ findFormParent = findFormParent->GetParent();
+ }
+
// if set, serialize the content under this node
- nsCOMPtr<nsIDOMNode> nodeToSerialize;
- PRBool useSelectedText = PR_FALSE;
+ nsCOMPtr<nsIContent> nodeToSerialize;
*aDragSelection = PR_FALSE;
{
PRBool haveSelectedContent = PR_FALSE;
// possible parent link node
- nsCOMPtr<nsIDOMNode> parentLink;
- nsCOMPtr<nsIDOMNode> draggedNode;
+ nsCOMPtr<nsIContent> parentLink;
+ nsCOMPtr<nsIContent> draggedNode;
{
- nsCOMPtr<nsIDOMEventTarget> target;
- mMouseEvent->GetTarget(getter_AddRefs(target));
-
// only drag form elements by using the alt key,
// otherwise buttons and select widgets are hard to use
// Note that while <object> elements implement nsIFormControl, we should
// really allow dragging them if they happen to be images.
- nsCOMPtr<nsIFormControl> form(do_QueryInterface(target));
- if (form && !isAltKeyDown && form->GetType() != NS_FORM_OBJECT) {
+ nsCOMPtr<nsIFormControl> form(do_QueryInterface(mTarget));
+ if (form && !mIsAltKeyPressed && form->GetType() != NS_FORM_OBJECT) {
+ *aCanDrag = PR_FALSE;
return NS_OK;
}
- draggedNode = do_QueryInterface(target);
+ draggedNode = mTarget;
}
nsCOMPtr<nsIDOMHTMLAreaElement> area; // client-side image map
nsCOMPtr<nsIImageLoadingContent> image;
nsCOMPtr<nsIDOMHTMLAnchorElement> link;
- {
- // Get the real target and see if it is in the selection
- nsCOMPtr<nsIDOMNode> realTargetNode;
+ nsCOMPtr<nsIContent> selectedImageOrLinkNode;
+ GetDraggableSelectionData(selection, mSelectionTargetNode,
+ getter_AddRefs(selectedImageOrLinkNode),
+ &haveSelectedContent);
- {
- nsCOMPtr<nsIDOMNSEvent> internalEvent = do_QueryInterface(mMouseEvent);
- if (internalEvent) {
- nsCOMPtr<nsIDOMEventTarget> realTarget;
- internalEvent->GetExplicitOriginalTarget(getter_AddRefs(realTarget));
- realTargetNode = do_QueryInterface(realTarget);
- }
+ // either plain text or anchor text is selected
+ if (haveSelectedContent) {
+ link = do_QueryInterface(selectedImageOrLinkNode);
+ if (link && mIsAltKeyPressed) {
+ // if alt is pressed, select the link text instead of drag the link
+ *aCanDrag = PR_FALSE;
+ return NS_OK;
}
- {
- nsCOMPtr<nsIDOMNode> selectedImageOrLinkNode;
- GetDraggableSelectionData(selection, realTargetNode,
- getter_AddRefs(selectedImageOrLinkNode),
- &haveSelectedContent);
-
- // either plain text or anchor text is selected
- if (haveSelectedContent) {
- link = do_QueryInterface(selectedImageOrLinkNode);
- if (link && isAltKeyDown) {
- return NS_OK;
- }
+ *aDragSelection = PR_TRUE;
+ } else if (selectedImageOrLinkNode) {
+ // an image is selected
+ image = do_QueryInterface(selectedImageOrLinkNode);
+ } else {
+ // nothing is selected -
+ //
+ // look for draggable elements under the mouse
+ //
+ // if the alt key is down, don't start a drag if we're in an
+ // anchor because we want to do selection.
+ parentLink = FindParentLinkNode(draggedNode);
+ if (parentLink && mIsAltKeyPressed) {
+ *aCanDrag = PR_FALSE;
+ return NS_OK;
+ }
- useSelectedText = PR_TRUE;
- *aDragSelection = PR_TRUE;
- } else if (selectedImageOrLinkNode) {
- // an image is selected
- image = do_QueryInterface(selectedImageOrLinkNode);
- } else {
- // nothing is selected -
- //
- // look for draggable elements under the mouse
- //
- // if the alt key is down, don't start a drag if we're in an
- // anchor because we want to do selection.
- parentLink = FindParentLinkNode(draggedNode);
- if (parentLink && isAltKeyDown) {
- return NS_OK;
- }
-
- area = do_QueryInterface(draggedNode);
- image = do_QueryInterface(draggedNode);
- link = do_QueryInterface(draggedNode);
- }
- }
+ area = do_QueryInterface(draggedNode);
+ image = do_QueryInterface(draggedNode);
+ link = do_QueryInterface(draggedNode);
}
{
// set for linked images, and links
- nsCOMPtr<nsIDOMNode> linkNode;
+ nsCOMPtr<nsIContent> linkNode;
if (area) {
// use the alt text (or, if missing, the href) as the title
area->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
if (mTitleString.IsEmpty()) {
// this can be a relative link
area->GetAttribute(NS_LITERAL_STRING("href"), mTitleString);
}
// we'll generate HTML like <a href="absurl">alt text</a>
mIsAnchor = PR_TRUE;
// gives an absolute link
- GetAnchorURL(area, mUrlString);
+ GetAnchorURL(draggedNode, mUrlString);
mHtmlString.AssignLiteral("<a href=\"");
mHtmlString.Append(mUrlString);
mHtmlString.AppendLiteral("\">");
mHtmlString.Append(mTitleString);
mHtmlString.AppendLiteral("</a>");
+
+ dragNode = draggedNode;
} else if (image) {
mIsAnchor = PR_TRUE;
// grab the href as the url, use alt text as the title of the
// area if it's there. the drag data is the image tag and src
// attribute.
nsCOMPtr<nsIURI> imageURI;
image->GetCurrentURI(getter_AddRefs(imageURI));
if (imageURI) {
@@ -1305,45 +1084,47 @@ nsTransferableFactory::Produce(PRBool* a
}
if (parentLink) {
// If we are dragging around an image in an anchor, then we
// are dragging the entire anchor
linkNode = parentLink;
nodeToSerialize = linkNode;
} else {
- nodeToSerialize = draggedNode;
+ nodeToSerialize = do_QueryInterface(draggedNode);
}
+ dragNode = nodeToSerialize;
} else if (link) {
// set linkNode. The code below will handle this
- linkNode = link; // XXX test this
+ linkNode = do_QueryInterface(link); // XXX test this
GetNodeString(draggedNode, mTitleString);
} else if (parentLink) {
// parentLink will always be null if there's selected content
linkNode = parentLink;
nodeToSerialize = linkNode;
} else if (!haveSelectedContent) {
// nothing draggable
return NS_OK;
}
if (linkNode) {
mIsAnchor = PR_TRUE;
GetAnchorURL(linkNode, mUrlString);
+ dragNode = linkNode;
}
}
}
- if (nodeToSerialize || useSelectedText) {
+ if (nodeToSerialize || *aDragSelection) {
// if we have selected text, use it in preference to the node
- if (useSelectedText) {
+ if (*aDragSelection) {
nodeToSerialize = nsnull;
}
- SerializeNodeOrSelection(window, nodeToSerialize,
+ SerializeNodeOrSelection(mWindow, nodeToSerialize,
mHtmlString, mContextString, mInfoString);
nsCOMPtr<nsIFormatConverter> htmlConverter =
do_CreateInstance(kHTMLConverterCID);
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
nsCOMPtr<nsISupportsString> html =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
@@ -1369,173 +1150,141 @@ nsTransferableFactory::Produce(PRBool* a
if (mTitleString.IsEmpty()) {
mTitleString = mUrlString;
}
// if we haven't constructed a html version, make one now
if (mHtmlString.IsEmpty() && !mUrlString.IsEmpty())
CreateLinkText(mUrlString, mTitleString, mHtmlString);
- return ConvertStringsToTransferable(outTrans);
+ // if there is no drag node, which will be the case for a selection, just
+ // use the selection target node.
+ nsresult rv = AddStringsToDataTransfer(
+ dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_IF_ADDREF(*aDragNode = dragNode);
+ return NS_OK;
+}
+
+void
+nsTransferableFactory::AddString(nsDOMDataTransfer* aDataTransfer,
+ const nsAString& aFlavor,
+ const nsAString& aData,
+ nsIPrincipal* aPrincipal)
+{
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+ if (variant) {
+ variant->SetAsAString(aData);
+ aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
+ }
}
nsresult
-nsTransferableFactory::ConvertStringsToTransferable(nsITransferable** outTrans)
+nsTransferableFactory::AddStringsToDataTransfer(nsIContent* aDragNode,
+ nsDOMDataTransfer* aDataTransfer)
{
- // now create the transferable and stuff data into it.
- nsCOMPtr<nsITransferable> trans =
- do_CreateInstance("@mozilla.org/widget/transferable;1");
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
+ NS_ASSERTION(aDragNode, "adding strings for null node");
+
+ // set all of the data to have the principal of the node where the data came from
+ nsIPrincipal* principal = aDragNode->NodePrincipal();
// add a special flavor if we're an anchor to indicate that we have
// a URL in the drag data
if (!mUrlString.IsEmpty() && mIsAnchor) {
nsAutoString dragData(mUrlString);
dragData.AppendLiteral("\n");
dragData += mTitleString;
- nsCOMPtr<nsISupportsString> urlPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(urlPrimitive, NS_ERROR_FAILURE);
-
- urlPrimitive->SetData(dragData);
- trans->SetTransferData(kURLMime, urlPrimitive,
- dragData.Length() * sizeof(PRUnichar));
-
- nsCOMPtr<nsISupportsString> urlDataPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(urlDataPrimitive, NS_ERROR_FAILURE);
-
- urlDataPrimitive->SetData(mUrlString);
- trans->SetTransferData(kURLDataMime, urlDataPrimitive,
- mUrlString.Length() * sizeof(PRUnichar));
-
- nsCOMPtr<nsISupportsString> urlDescPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(urlDescPrimitive, NS_ERROR_FAILURE);
-
- urlDescPrimitive->SetData(mTitleString);
- trans->SetTransferData(kURLDescriptionMime, urlDescPrimitive,
- mTitleString.Length() * sizeof(PRUnichar));
+ AddString(aDataTransfer, NS_LITERAL_STRING(kURLMime), dragData, principal);
+ AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
+ AddString(aDataTransfer, NS_LITERAL_STRING(kURLDescriptionMime), mTitleString, principal);
+ AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
}
// add a special flavor, even if we don't have html context data
- nsCOMPtr<nsISupportsString> context =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
-
- nsAutoString contextData(mContextString);
- context->SetData(contextData);
- trans->SetTransferData(kHTMLContext, context, contextData.Length() * 2);
+ AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
// add a special flavor if we have html info data
- if (!mInfoString.IsEmpty()) {
- nsCOMPtr<nsISupportsString> info =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(info, NS_ERROR_FAILURE);
-
- nsAutoString infoData(mInfoString);
- info->SetData(infoData);
- trans->SetTransferData(kHTMLInfo, info, infoData.Length() * 2);
- }
+ if (!mInfoString.IsEmpty())
+ AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
// add the full html
- nsCOMPtr<nsISupportsString> htmlPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(htmlPrimitive, NS_ERROR_FAILURE);
-
- htmlPrimitive->SetData(mHtmlString);
- trans->SetTransferData(kHTMLMime, htmlPrimitive,
- mHtmlString.Length() * sizeof(PRUnichar));
+ AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
- // add the plain (unicode) text. we use the url for text/unicode
- // data if an anchor is being dragged, rather than the title text of
- // the link or the alt text for an anchor image.
- nsCOMPtr<nsISupportsString> textPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(textPrimitive, NS_ERROR_FAILURE);
-
- textPrimitive->SetData(mIsAnchor ? mUrlString : mTitleString);
- trans->SetTransferData(kUnicodeMime, textPrimitive,
- (mIsAnchor ? mUrlString.Length() :
- mTitleString.Length()) * sizeof(PRUnichar));
+ // add the plain text. we use the url for text/plain data if an anchor is
+ // being dragged, rather than the title text of the link or the alt text for
+ // an anchor image.
+ AddString(aDataTransfer, NS_LITERAL_STRING(kTextMime),
+ mIsAnchor ? mUrlString : mTitleString, principal);
// add image data, if present. For now, all we're going to do with
// this is turn it into a native data flavor, so indicate that with
// a new flavor so as not to confuse anyone who is really registered
// for image/gif or image/jpg.
if (mImage) {
- nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive =
- do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
- NS_ENSURE_TRUE(ptrPrimitive, NS_ERROR_FAILURE);
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+ if (variant) {
+ variant->SetAsISupports(mImage);
+ aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
+ variant, 0, principal);
+ }
- ptrPrimitive->SetData(mImage);
- trans->SetTransferData(kNativeImageMime, ptrPrimitive,
- sizeof(nsISupportsInterfacePointer*));
// assume the image comes from a file, and add a file promise. We
// register ourselves as a nsIFlavorDataProvider, and will use the
// GetFlavorData callback to save the image to disk.
- trans->SetTransferData(kFilePromiseMime, mFlavorDataProvider,
- nsITransferable::kFlavorHasDataProvider);
-
- nsCOMPtr<nsISupportsString> imageUrlPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(imageUrlPrimitive, NS_ERROR_FAILURE);
- imageUrlPrimitive->SetData(mImageSourceString);
- trans->SetTransferData(kFilePromiseURLMime, imageUrlPrimitive,
- mImageSourceString.Length() * sizeof(PRUnichar));
+ nsCOMPtr<nsIFlavorDataProvider> dataProvider =
+ new nsContentAreaDragDropDataProvider();
+ if (dataProvider) {
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+ if (variant) {
+ variant->SetAsISupports(dataProvider);
+ aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
+ variant, 0, principal);
+ }
+ }
- nsCOMPtr<nsISupportsString> imageFileNamePrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(imageFileNamePrimitive, NS_ERROR_FAILURE);
-
- imageFileNamePrimitive->SetData(mImageDestFileName);
- trans->SetTransferData(kFilePromiseDestFilename, imageFileNamePrimitive,
- mImageDestFileName.Length() * sizeof(PRUnichar));
+ AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseURLMime),
+ mImageSourceString, principal);
+ AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseDestFilename),
+ mImageDestFileName, principal);
// if not an anchor, add the image url
if (!mIsAnchor) {
- nsCOMPtr<nsISupportsString> urlDataPrimitive =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(urlDataPrimitive, NS_ERROR_FAILURE);
-
- urlDataPrimitive->SetData(mUrlString);
- trans->SetTransferData(kURLDataMime, urlDataPrimitive,
- mUrlString.Length() * sizeof(PRUnichar));
+ AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
+ AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
}
}
- *outTrans = trans;
- NS_IF_ADDREF(*outTrans);
-
return NS_OK;
}
// note that this can return NS_OK, but a null out param (by design)
// static
nsresult
nsTransferableFactory::GetDraggableSelectionData(nsISelection* inSelection,
- nsIDOMNode* inRealTargetNode,
- nsIDOMNode **outImageOrLinkNode,
+ nsIContent* inRealTargetNode,
+ nsIContent **outImageOrLinkNode,
PRBool* outDragSelectedText)
{
NS_ENSURE_ARG(inSelection);
NS_ENSURE_ARG(inRealTargetNode);
NS_ENSURE_ARG_POINTER(outImageOrLinkNode);
*outImageOrLinkNode = nsnull;
*outDragSelectedText = PR_FALSE;
PRBool selectionContainsTarget = PR_FALSE;
PRBool isCollapsed = PR_FALSE;
inSelection->GetIsCollapsed(&isCollapsed);
if (!isCollapsed) {
- inSelection->ContainsNode(inRealTargetNode, PR_FALSE,
+ nsCOMPtr<nsIDOMNode> realTargetNode = do_QueryInterface(inRealTargetNode);
+ inSelection->ContainsNode(realTargetNode, PR_FALSE,
&selectionContainsTarget);
if (selectionContainsTarget) {
// track down the anchor node, if any, for the url
nsCOMPtr<nsIDOMNode> selectionStart;
inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
nsCOMPtr<nsIDOMNode> selectionEnd;
@@ -1559,18 +1308,17 @@ nsTransferableFactory::GetDraggableSelec
if (selStartContent) {
PRInt32 childOffset =
(anchorOffset < focusOffset) ? anchorOffset : focusOffset;
nsIContent *childContent =
selStartContent->GetChildAt(childOffset);
// if we find an image, we'll fall into the node-dragging code,
// rather the the selection-dragging code
if (nsContentUtils::IsDraggableImage(childContent)) {
- CallQueryInterface(childContent, outImageOrLinkNode);
-
+ NS_ADDREF(*outImageOrLinkNode = childContent);
return NS_OK;
}
}
}
}
}
// see if the selection is a link; if so, its node will be returned
@@ -1581,30 +1329,31 @@ nsTransferableFactory::GetDraggableSelec
}
}
return NS_OK;
}
// static
void nsTransferableFactory::GetSelectedLink(nsISelection* inSelection,
- nsIDOMNode **outLinkNode)
+ nsIContent **outLinkNode)
{
*outLinkNode = nsnull;
- nsCOMPtr<nsIDOMNode> selectionStart;
- inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
- nsCOMPtr<nsIDOMNode> selectionEnd;
- inSelection->GetFocusNode(getter_AddRefs(selectionEnd));
+ nsCOMPtr<nsIDOMNode> selectionStartNode;
+ inSelection->GetAnchorNode(getter_AddRefs(selectionStartNode));
+ nsCOMPtr<nsIDOMNode> selectionEndNode;
+ inSelection->GetFocusNode(getter_AddRefs(selectionEndNode));
// simple case: only one node is selected
// see if it or its parent is an anchor, then exit
- if (selectionStart == selectionEnd) {
- nsCOMPtr<nsIDOMNode> link = FindParentLinkNode(selectionStart);
+ if (selectionStartNode == selectionEndNode) {
+ nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
+ nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
if (link) {
link.swap(*outLinkNode);
}
return;
}
// more complicated case: multiple nodes are selected
@@ -1622,87 +1371,89 @@ void nsTransferableFactory::GetSelectedL
nsCOMPtr<nsIDOMRange> range;
inSelection->GetRangeAt(0, getter_AddRefs(range));
if (!range) {
return;
}
nsCOMPtr<nsIDOMNode> tempNode;
range->GetStartContainer( getter_AddRefs(tempNode));
- if (tempNode != selectionStart) {
- selectionEnd = selectionStart;
- selectionStart = tempNode;
+ if (tempNode != selectionStartNode) {
+ selectionEndNode = selectionStartNode;
+ selectionStartNode = tempNode;
inSelection->GetAnchorOffset(&endOffset);
inSelection->GetFocusOffset(&startOffset);
} else {
inSelection->GetAnchorOffset(&startOffset);
inSelection->GetFocusOffset(&endOffset);
}
}
// trim leading node if the string is empty or
// the selection starts at the end of the text
nsAutoString nodeStr;
- selectionStart->GetNodeValue(nodeStr);
+ selectionStartNode->GetNodeValue(nodeStr);
if (nodeStr.IsEmpty() ||
startOffset+1 >= static_cast<PRInt32>(nodeStr.Length())) {
- nsCOMPtr<nsIDOMNode> curr = selectionStart;
+ nsCOMPtr<nsIDOMNode> curr = selectionStartNode;
nsIDOMNode* next;
while (curr) {
curr->GetNextSibling(&next);
if (next) {
- selectionStart = dont_AddRef(next);
+ selectionStartNode = dont_AddRef(next);
break;
}
curr->GetParentNode(&next);
curr = dont_AddRef(next);
}
}
// trim trailing node if the selection ends before its text begins
if (endOffset == 0) {
- nsCOMPtr<nsIDOMNode> curr = selectionEnd;
+ nsCOMPtr<nsIDOMNode> curr = selectionEndNode;
nsIDOMNode* next;
while (curr) {
curr->GetPreviousSibling(&next);
if (next){
- selectionEnd = dont_AddRef(next);
+ selectionEndNode = dont_AddRef(next);
break;
}
curr->GetParentNode(&next);
curr = dont_AddRef(next);
}
}
// see if the leading & trailing nodes are part of the
// same anchor - if so, return the anchor node
- nsCOMPtr<nsIDOMNode> link = FindParentLinkNode(selectionStart);
+ nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
+ nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
if (link) {
- nsCOMPtr<nsIDOMNode> link2 = FindParentLinkNode(selectionEnd);
+ nsCOMPtr<nsIContent> selectionEnd = do_QueryInterface(selectionEndNode);
+ nsCOMPtr<nsIContent> link2 = FindParentLinkNode(selectionEnd);
if (link == link2) {
NS_IF_ADDREF(*outLinkNode = link);
}
}
return;
}
// static
nsresult
nsTransferableFactory::SerializeNodeOrSelection(nsIDOMWindow* inWindow,
- nsIDOMNode* inNode,
+ nsIContent* inNode,
nsAString& outResultString,
nsAString& outContext,
nsAString& outInfo)
{
NS_ENSURE_ARG_POINTER(inWindow);
nsresult rv;
nsCOMPtr<nsIDocumentEncoder> encoder =
@@ -1712,21 +1463,22 @@ nsTransferableFactory::SerializeNodeOrSe
nsCOMPtr<nsIDOMDocument> domDoc;
inWindow->GetDocument(getter_AddRefs(domDoc));
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
PRUint32 flags = nsIDocumentEncoder::OutputAbsoluteLinks |
nsIDocumentEncoder::OutputEncodeHTMLEntities;
nsCOMPtr<nsIDOMRange> range;
nsCOMPtr<nsISelection> selection;
- if (inNode) {
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
+ if (node) {
// make a range around this node
rv = NS_NewRange(getter_AddRefs(range));
NS_ENSURE_SUCCESS(rv, rv);
- rv = range->SelectNode(inNode);
+ rv = range->SelectNode(node);
NS_ENSURE_SUCCESS(rv, rv);
} else {
inWindow->GetSelection(getter_AddRefs(selection));
flags |= nsIDocumentEncoder::OutputSelectionOnly;
}
rv = encoder->Init(domDoc, NS_LITERAL_STRING(kHTMLMime), flags);
NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsContentAreaDragDrop.h
+++ b/content/base/src/nsContentAreaDragDrop.h
@@ -53,16 +53,17 @@ class nsITransferable;
class nsIImage;
class nsIPresShell;
class nsPresContext;
class nsIContent;
class nsIDocument;
class nsIURI;
class nsIFile;
class nsISimpleEnumerator;
+class nsDOMDataTransfer;
// {1f34bc80-1bc7-11d6-a384-d705dd0746fc}
#define NS_CONTENTAREADRAGDROP_CID \
{ 0x1f34bc80, 0x1bc7, 0x11d6, \
{ 0xa3, 0x84, 0xd7, 0x05, 0xdd, 0x07, 0x46, 0xfc } }
#define NS_CONTENTAREADRAGDROP_CONTRACTID "@mozilla.org:/content/content-area-dragdrop;1"
@@ -71,64 +72,98 @@ class nsISimpleEnumerator;
// class nsContentAreaDragDrop
//
// The class that listens to the chrome events handles anything
// related to drag and drop. Registers itself with the DOM with
// AddChromeListeners() and removes itself with
// RemoveChromeListeners().
//
class nsContentAreaDragDrop : public nsIDOMDragListener,
- public nsIDragDropHandler,
- public nsIFlavorDataProvider
+ public nsIDragDropHandler
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDRAGDROPHANDLER
- NS_DECL_NSIFLAVORDATAPROVIDER
nsContentAreaDragDrop();
virtual ~nsContentAreaDragDrop();
// nsIDOMDragListener
NS_IMETHOD DragEnter(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragExit(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragDrop(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragGesture(nsIDOMEvent* aMouseEvent);
NS_IMETHOD Drag(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragEnd(nsIDOMEvent* aMouseEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent *event);
+ /**
+ * Determine what data in the content area, if any, is being dragged.
+ *
+ * aWindow - the window containing the target node
+ * aTarget - the mousedown event target that started the drag
+ * aSelectionTargetNode - the node where the drag event should be fired
+ * aIsAltKeyPressed - true if the Alt key is pressed. In some cases, this
+ * will prevent the drag from occuring. For example,
+ * holding down Alt over a link should select the text,
+ * not drag the link.
+ * aDataTransfer - the dataTransfer for the drag event.
+ * aCanDrag - [out] set to true if the drag may proceed, false to stop the
+ * drag entirely
+ * aDragSelection - [out] set to true to indicate that a selection is being
+ * dragged, rather than a specific node
+ * aDragNode - [out] the link, image or area being dragged, or null if the
+ * drag occured on another element.
+ */
+ static nsresult GetDragData(nsIDOMWindow* aWindow,
+ nsIContent* aTarget,
+ nsIContent* aSelectionTargetNode,
+ PRBool aIsAltKeyPressed,
+ nsDOMDataTransfer* aDataTransfer,
+ PRBool* aCanDrag,
+ PRBool* aDragSelection,
+ nsIContent** aDragNode);
+
private:
// Add/remove the relevant listeners
nsresult AddDragListener();
nsresult RemoveDragListener();
// utility routines
static void NormalizeSelection(nsIDOMNode* inBaseNode,
nsISelection* inSelection);
static void GetEventDocument(nsIDOMEvent* inEvent,
nsIDOMDocument** outDocument);
- static nsresult SaveURIToFile(nsAString& inSourceURIString,
- nsIFile* inDestFile);
-
- void ExtractURLFromData(const nsACString & inFlavor,
- nsISupports* inDataWrapper, PRUint32 inDataLen,
- nsAString & outURL);
- nsresult GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
- nsISimpleEnumerator** outEnumerator);
+ static void ExtractURLFromData(const nsACString & inFlavor,
+ nsISupports* inDataWrapper, PRUint32 inDataLen,
+ nsAString & outURL);
PRPackedBool mListenerInstalled;
nsCOMPtr<nsPIDOMEventTarget> mEventTarget;
// weak ref, this is probably my owning webshell
// FIXME: we set this and never null it out. That's bad! See bug 332187.
nsIWebNavigation* mNavigator;
};
+// this is used to save images to disk lazily when the image data is asked for
+// during the drop instead of when it is added to the drag data transfer. This
+// ensures that the image data is only created when an image drop is allowed.
+class nsContentAreaDragDropDataProvider : public nsIFlavorDataProvider
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFLAVORDATAPROVIDER
+
+ virtual ~nsContentAreaDragDropDataProvider() {}
+
+ nsresult SaveURIToFile(nsAString& inSourceURIString,
+ nsIFile* inDestFile);
+};
#endif /* nsContentAreaDragDrop_h__ */
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -66,16 +66,19 @@
#include "nsIContentViewer.h"
#include "nsIAtom.h"
#include "nsGkAtoms.h"
#include "nsIDOMWindowInternal.h"
#include "nsIPrincipal.h"
#include "nsIScriptGlobalObject.h"
#include "nsNetCID.h"
#include "nsIOfflineCacheUpdate.h"
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheContainer.h"
+#include "nsIApplicationCacheService.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMLoadStatus.h"
#include "nsICookieService.h"
#include "nsIPrompt.h"
#include "nsServiceManagerUtils.h"
#include "nsContentUtils.h"
#include "nsParserUtils.h"
#include "nsCRT.h"
@@ -89,16 +92,20 @@
#include "nsIDOMNSDocument.h"
#include "nsIRequest.h"
#include "nsNodeUtils.h"
#include "nsIDOMNode.h"
#include "nsThreadUtils.h"
#include "nsPresShellIterator.h"
#include "nsPIDOMWindow.h"
#include "mozAutoDocUpdate.h"
+#include "nsIWebNavigation.h"
+#include "nsIDocumentLoader.h"
+#include "nsICachingChannel.h"
+#include "nsICacheEntryDescriptor.h"
PRLogModuleInfo* gContentSinkLogModuleInfo;
class nsScriptLoaderObserverProxy : public nsIScriptLoaderObserver
{
public:
nsScriptLoaderObserverProxy(nsIScriptLoaderObserver* aInner)
: mInner(do_GetWeakReference(aInner))
@@ -840,71 +847,314 @@ nsContentSink::PrefetchHref(const nsAStr
mDocumentBaseURI);
if (uri) {
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aSource);
prefetchService->PrefetchURI(uri, mDocumentURI, domNode, aExplicit);
}
}
}
+nsresult
+nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey)
+{
+ aCacheKey.Truncate();
+
+ nsresult rv;
+ nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aChannel, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISupports> token;
+ rv = cachingChannel->GetCacheToken(getter_AddRefs(token));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsICacheEntryDescriptor> descriptor = do_QueryInterface(token, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = descriptor->GetKey(aCacheKey);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+nsresult
+nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
+ nsIURI *aManifestURI,
+ PRBool aIsTopDocument,
+ PRBool aFetchedWithHTTPGetOrEquiv,
+ CacheSelectionAction *aAction)
+{
+ *aAction = CACHE_SELECTION_NONE;
+
+ nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
+ do_QueryInterface(mDocument);
+ NS_ASSERTION(applicationCacheDocument,
+ "mDocument must implement nsIApplicationCacheContainer.");
+
+ nsresult rv;
+
+ // We might decide on a new application cache...
+ nsCOMPtr<nsIApplicationCache> applicationCache = aLoadApplicationCache;
+
+ if (applicationCache) {
+ nsCAutoString groupID;
+ rv = applicationCache->GetGroupID(groupID);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIURI> groupURI;
+ rv = NS_NewURI(getter_AddRefs(groupURI), groupID);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool equal = PR_FALSE;
+ rv = groupURI->Equals(aManifestURI, &equal);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!equal) {
+ // This is a foreign entry, mark it as such. If this is a
+ // toplevel load, force a reload to avoid loading the foreign
+ // entry. The next attempt will not choose this cache entry
+ // (because it has been marked foreign).
+
+ nsCAutoString cachekey;
+ rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = applicationCache->MarkEntry(cachekey,
+ nsIApplicationCache::ITEM_FOREIGN);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aIsTopDocument) {
+ *aAction = CACHE_SELECTION_RELOAD;
+ }
+
+ return NS_OK;
+ }
+
+ if (aIsTopDocument) {
+ // This is a top level document and the http manifest attribute
+ // URI is equal to the manifest URI of the cache the document
+ // was loaded from - associate the document with that cache and
+ // invoke the cache update process.
+ rv = applicationCacheDocument->SetApplicationCache(applicationCache);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aAction = CACHE_SELECTION_UPDATE;
+ }
+ }
+ else {
+ // The document was not loaded from an application cache
+ // Here we know the manifest has the same origin as the
+ // document. There is call to CheckMayLoad() on it above.
+
+ if (!aFetchedWithHTTPGetOrEquiv) {
+ // The document was not loaded using HTTP GET or equivalent
+ // method. The spec says to run the cache selection algorithm w/o
+ // the manifest specified but we can just do return NS_OK here.
+
+ return NS_OK;
+ }
+
+ // If there is an existing application cache for this manifest,
+ // associate it with the document.
+ nsCAutoString manifestURISpec;
+ rv = aManifestURI->GetAsciiSpec(manifestURISpec);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIApplicationCacheService> appCacheService =
+ do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
+ if (!appCacheService) {
+ // No application cache service, nothing to do here.
+ return NS_OK;
+ }
+
+ rv = appCacheService->GetActiveCache(manifestURISpec,
+ getter_AddRefs(applicationCache));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (applicationCache) {
+ rv = applicationCacheDocument->SetApplicationCache(applicationCache);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ // XXX bug 443023: if there is already a scheduled update or
+ // update in progress we have to add this document as
+ // an implicit entry.
+ }
+
+ // Always do an update in this case
+ *aAction = CACHE_SELECTION_UPDATE;
+ }
+
+ if (applicationCache) {
+ // We are now associated with an application cache. This item
+ // should be marked as an implicit entry.
+ nsCAutoString cachekey;
+ rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
+ if (NS_SUCCEEDED(rv)) {
+ rv = applicationCache->MarkEntry(cachekey,
+ nsIApplicationCache::ITEM_IMPLICIT);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
+ PRBool aIsTopDocument,
+ nsIURI **aManifestURI,
+ CacheSelectionAction *aAction)
+{
+ *aManifestURI = nsnull;
+ *aAction = CACHE_SELECTION_NONE;
+
+ if (!aIsTopDocument || !aLoadApplicationCache) {
+ return NS_OK;
+ }
+
+ nsresult rv;
+
+ // The document was loaded from an application cache, use that
+ // application cache as the document's application cache.
+ nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
+ do_QueryInterface(mDocument);
+ NS_ASSERTION(applicationCacheDocument,
+ "mDocument must implement nsIApplicationCacheContainer.");
+
+ rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Return the uri and invoke the update process for the selected
+ // application cache.
+ nsCAutoString groupID;
+ rv = aLoadApplicationCache->GetGroupID(groupID);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_NewURI(aManifestURI, groupID);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aAction = CACHE_SELECTION_UPDATE;
+
+ return NS_OK;
+}
+
void
nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
{
+ // Only check the manifest for root document nodes.
+ if (aElement != mDocument->GetRootContent()) {
+ return;
+ }
+
+ nsresult rv;
+
// Check for a manifest= attribute.
nsAutoString manifestSpec;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
- if (manifestSpec.IsEmpty() ||
- manifestSpec.FindChar('#') != kNotFound) {
- return;
+ // Grab the application cache the document was loaded from, if any.
+ nsCOMPtr<nsIApplicationCache> applicationCache;
+
+ nsCOMPtr<nsIApplicationCacheContainer> applicationCacheChannel =
+ do_QueryInterface(mDocument->GetChannel());
+ if (applicationCacheChannel) {
+ rv = applicationCacheChannel->GetApplicationCache(
+ getter_AddRefs(applicationCache));
+ if (NS_FAILED(rv)) {
+ return;
+ }
}
- // We only care about manifests in toplevel windows.
- nsCOMPtr<nsPIDOMWindow> pwindow =
- do_QueryInterface(mDocument->GetScriptGlobalObject());
- if (!pwindow) {
- return;
- }
-
- nsCOMPtr<nsIDOMWindow> window =
- do_QueryInterface(pwindow->GetOuterWindow());
- if (!window) {
- return;
- }
-
- nsCOMPtr<nsIDOMWindow> parent;
- window->GetParent(getter_AddRefs(parent));
- if (parent.get() != window.get()) {
+ if (manifestSpec.IsEmpty() && !applicationCache) {
+ // Not loaded from an application cache, and no manifest
+ // attribute. Nothing to do here.
return;
}
- // Only update if the document has permission to use offline APIs.
- if (!nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
+ // The manifest attribute is handled differently if the document is
+ // not toplevel.
+ nsCOMPtr<nsIDOMWindow> window = mDocument->GetWindow();
+ if (!window)
return;
+ nsCOMPtr<nsIDOMWindow> parent;
+ window->GetParent(getter_AddRefs(parent));
+ PRBool isTop = (parent == window);
+
+ CacheSelectionAction action = CACHE_SELECTION_NONE;
+ nsCOMPtr<nsIURI> manifestURI;
+
+ if (manifestSpec.IsEmpty()) {
+ rv = SelectDocAppCacheNoManifest(applicationCache,
+ isTop,
+ getter_AddRefs(manifestURI),
+ &action);
+ if (NS_FAILED(rv)) {
+ return;
+ }
+ }
+ else {
+ nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
+ manifestSpec, mDocument,
+ mDocumentURI);
+ if (!manifestURI) {
+ return;
+ }
+
+ // Documents must list a manifest from the same origin
+ rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
+ if (NS_FAILED(rv)) {
+ return;
+ }
+
+ // Only continue if the document has permission to use offline APIs.
+ if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
+ return;
+ }
+
+ PRBool fetchedWithHTTPGetOrEquiv = PR_FALSE;
+ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mDocument->GetChannel()));
+ if (httpChannel) {
+ nsCAutoString method;
+ rv = httpChannel->GetRequestMethod(method);
+ if (NS_SUCCEEDED(rv))
+ fetchedWithHTTPGetOrEquiv = method.Equals("GET");
+ }
+
+ rv = SelectDocAppCache(applicationCache, manifestURI, isTop,
+ fetchedWithHTTPGetOrEquiv, &action);
+ if (NS_FAILED(rv)) {
+ return;
+ }
}
- nsCOMPtr<nsIURI> manifestURI;
- nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
- manifestSpec, mDocument,
- mDocumentURI);
- if (!manifestURI) {
+ switch (action)
+ {
+ case CACHE_SELECTION_NONE:
return;
- }
+ case CACHE_SELECTION_UPDATE: {
+ nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
+ do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
- // Documents must list a manifest from the same origin
- nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
- if (NS_FAILED(rv)) {
- return;
+ if (updateService) {
+ nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
+ updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
+ }
+ break;
}
+ case CACHE_SELECTION_RELOAD: {
+ // This situation occurs only for toplevel documents, see bottom
+ // of SelectDocAppCache method.
+ NS_ASSERTION(isTop, "Should only reload toplevel documents!");
+ nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
- // Start the update
- nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
- nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
- do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
- updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
+ webNav->Stop(nsIWebNavigation::STOP_ALL);
+ webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
+ break;
+ }
+ }
}
void
nsContentSink::ScrollToRef()
{
if (mRef.IsEmpty()) {
return;
}
@@ -1414,16 +1664,20 @@ nsContentSink::EndUpdate(nsIDocument *aD
if (aUpdateType != UPDATE_CONTENT_STATE && !--mInNotification) {
UpdateChildCounts();
}
}
void
nsContentSink::DidBuildModelImpl(void)
{
+ if (!mDocument->HaveFiredDOMTitleChange()) {
+ mDocument->NotifyPossibleTitleChange(PR_FALSE);
+ }
+
// Cancel a timer if we had one out there
if (mNotificationTimer) {
SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_REFLOW,
("nsContentSink::DidBuildModel: canceling notification "
"timeout"));
mNotificationTimer->Cancel();
mNotificationTimer = 0;
}
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -71,16 +71,17 @@ class nsIDocShell;
class nsICSSLoader;
class nsIParser;
class nsIAtom;
class nsIChannel;
class nsIContent;
class nsIViewManager;
class nsNodeInfoManager;
class nsScriptLoader;
+class nsIApplicationCache;
#ifdef NS_DEBUG
extern PRLogModuleInfo* gContentSinkLogModuleInfo;
#define SINK_TRACE_CALLS 0x1
#define SINK_TRACE_REFLOW 0x2
#define SINK_ALWAYS_REFLOW 0x4
@@ -145,16 +146,35 @@ class nsContentSink : public nsICSSLoade
virtual void EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType);
virtual void UpdateChildCounts() = 0;
protected:
nsContentSink();
virtual ~nsContentSink();
+ enum CacheSelectionAction {
+ // There is no offline cache manifest specified by the document,
+ // or the document was loaded from a cache other than the one it
+ // specifies via its manifest attribute and IS NOT a top-level
+ // document, or an error occurred during the cache selection
+ // algorithm.
+ CACHE_SELECTION_NONE = 0,
+
+ // The offline cache manifest must be updated.
+ CACHE_SELECTION_UPDATE = 1,
+
+ // The document was loaded from a cache other than the one it
+ // specifies via its manifest attribute and IS a top-level
+ // document. In this case, the document is marked as foreign in
+ // the cache it was loaded from and must be reloaded from the
+ // correct cache (the one it specifies).
+ CACHE_SELECTION_RELOAD = 2
+ };
+
nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
nsISupports* aContainer, nsIChannel* aChannel);
nsresult ProcessHTTPHeaders(nsIChannel* aChannel);
nsresult ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
nsIContent* aContent = nsnull);
nsresult ProcessLinkHeader(nsIContent* aElement,
const nsAString& aLinkData);
@@ -166,16 +186,70 @@ protected:
const nsSubstring& aHref,
PRBool aAlternate,
const nsSubstring& aTitle,
const nsSubstring& aType,
const nsSubstring& aMedia);
void PrefetchHref(const nsAString &aHref, nsIContent *aSource,
PRBool aExplicit);
+
+ // Gets the cache key (used to identify items in a cache) of the channel.
+ nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
+
+ // There is an offline cache manifest attribute specified and the
+ // document is allowed to use the offline cache. Process the cache
+ // selection algorithm for this document and the manifest. Result is
+ // an action that must be taken on the manifest, see
+ // CacheSelectionAction enum above.
+ //
+ // @param aLoadApplicationCache
+ // The application cache from which the load originated, if
+ // any.
+ // @param aManifestURI
+ // The manifest URI listed in the document.
+ // @param aIsTopDocument
+ // TRUE if this is a toplevel document.
+ // @param aFetchedWithHTTPGetOrEquiv
+ // TRUE if this was fetched using the HTTP GET method.
+ // @param aAction
+ // Out parameter, returns the action that should be performed
+ // by the calling function.
+ nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
+ nsIURI *aManifestURI,
+ PRBool aIsTopDocument,
+ PRBool aFetchedWithHTTPGetOrEquiv,
+ CacheSelectionAction *aAction);
+
+ // There is no offline cache manifest attribute specified. Process
+ // the cache selection algorithm w/o the manifest. Result is an
+ // action that must be taken, see CacheSelectionAction enum
+ // above. In case the offline cache manifest has to be updated the
+ // manifest URI is returned in aManifestURI.
+ //
+ // @param aLoadApplicationCache
+ // The application cache from which the load originated, if
+ // any.
+ // @param aIsTopDocument
+ // TRUE if this is a toplevel document.
+ // @param aManifestURI
+ // Out parameter, returns the manifest URI of the cache that
+ // was selected.
+ // @param aAction
+ // Out parameter, returns the action that should be performed
+ // by the calling function.
+ nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
+ PRBool aIsTopDocument,
+ nsIURI **aManifestURI,
+ CacheSelectionAction *aAction);
+
+ // Searches for the offline cache manifest attribute and calls one
+ // of the above defined methods to select the document's application
+ // cache, let it be associated with the document and eventually
+ // schedule the cache update process.
void ProcessOfflineManifest(nsIContent *aElement);
// Tries to scroll to the URI's named anchor. Once we've successfully
// done that, further calls to this method will be ignored.
void ScrollToRef();
nsresult RefreshIfEnabled(nsIViewManager* vm);
// Start layout. If aIgnorePendingSheets is true, this will happen even if
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -149,16 +149,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
#include "nsIPermissionManager.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIRunnable.h"
#include "nsDOMJSUtils.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValue.h"
#include "nsReferencedElement.h"
#include "nsIUGenCategory.h"
+#include "nsIDragService.h"
#ifdef IBMBIDI
#include "nsIBidiKeyboard.h"
#endif
#include "nsCycleCollectionParticipant.h"
// for ReportToConsole
#include "nsIStringBundle.h"
@@ -412,23 +413,26 @@ nsContentUtils::InitializeEventTable() {
{ &nsGkAtoms::onclose, { NS_XUL_CLOSE, EventNameType_XUL }},
{ &nsGkAtoms::onpopupshowing, { NS_XUL_POPUP_SHOWING, EventNameType_XUL }},
{ &nsGkAtoms::onpopupshown, { NS_XUL_POPUP_SHOWN, EventNameType_XUL }},
{ &nsGkAtoms::onpopuphiding, { NS_XUL_POPUP_HIDING, EventNameType_XUL }},
{ &nsGkAtoms::onpopuphidden, { NS_XUL_POPUP_HIDDEN, EventNameType_XUL }},
{ &nsGkAtoms::oncommand, { NS_XUL_COMMAND, EventNameType_XUL }},
{ &nsGkAtoms::onbroadcast, { NS_XUL_BROADCAST, EventNameType_XUL }},
{ &nsGkAtoms::oncommandupdate, { NS_XUL_COMMAND_UPDATE, EventNameType_XUL }},
- { &nsGkAtoms::ondragenter, { NS_DRAGDROP_ENTER, EventNameType_XUL }},
- { &nsGkAtoms::ondragover, { NS_DRAGDROP_OVER_SYNTH, EventNameType_XUL }},
+ { &nsGkAtoms::ondragenter, { NS_DRAGDROP_ENTER, EventNameType_HTMLXUL }},
+ { &nsGkAtoms::ondragover, { NS_DRAGDROP_OVER_SYNTH, EventNameType_HTMLXUL }},
{ &nsGkAtoms::ondragexit, { NS_DRAGDROP_EXIT_SYNTH, EventNameType_XUL }},
- { &nsGkAtoms::ondragdrop, { NS_DRAGDROP_DROP, EventNameType_XUL }},
+ { &nsGkAtoms::ondragdrop, { NS_DRAGDROP_DRAGDROP, EventNameType_XUL }},
{ &nsGkAtoms::ondraggesture, { NS_DRAGDROP_GESTURE, EventNameType_XUL }},
- { &nsGkAtoms::ondrag, { NS_DRAGDROP_DRAG, EventNameType_XUL }},
- { &nsGkAtoms::ondragend, { NS_DRAGDROP_END, EventNameType_XUL }},
+ { &nsGkAtoms::ondrag, { NS_DRAGDROP_DRAG, EventNameType_HTMLXUL }},
+ { &nsGkAtoms::ondragend, { NS_DRAGDROP_END, EventNameType_HTMLXUL }},
+ { &nsGkAtoms::ondragstart, { NS_DRAGDROP_START, EventNameType_HTMLXUL }},
+ { &nsGkAtoms::ondragleave, { NS_DRAGDROP_LEAVE_SYNTH, EventNameType_HTMLXUL }},
+ { &nsGkAtoms::ondrop, { NS_DRAGDROP_DROP, EventNameType_HTMLXUL }},
{ &nsGkAtoms::onoverflow, { NS_SCROLLPORT_OVERFLOW, EventNameType_XUL }},
{ &nsGkAtoms::onunderflow, { NS_SCROLLPORT_UNDERFLOW, EventNameType_XUL }}
#ifdef MOZ_SVG
,{ &nsGkAtoms::onSVGLoad, { NS_SVG_LOAD, EventNameType_None }},
{ &nsGkAtoms::onSVGUnload, { NS_SVG_UNLOAD, EventNameType_None }},
{ &nsGkAtoms::onSVGAbort, { NS_SVG_ABORT, EventNameType_None }},
{ &nsGkAtoms::onSVGError, { NS_SVG_ERROR, EventNameType_None }},
{ &nsGkAtoms::onSVGResize, { NS_SVG_RESIZE, EventNameType_None }},
@@ -799,51 +803,27 @@ nsContentUtils::GetOfflineAppManifest(ns
nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
topDoc, topDoc->GetBaseURI());
}
/* static */
PRBool
nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
{
- nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
- if (!innerURI)
- return PR_FALSE;
-
- // only http and https applications can use offline APIs.
- PRBool match;
- nsresult rv = innerURI->SchemeIs("http", &match);
- NS_ENSURE_SUCCESS(rv, PR_FALSE);
-
- if (!match) {
- rv = innerURI->SchemeIs("https", &match);
- NS_ENSURE_SUCCESS(rv, PR_FALSE);
- if (!match) {
- return PR_FALSE;
- }
- }
-
- nsCOMPtr<nsIPermissionManager> permissionManager =
- do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
- if (!permissionManager) {
- return PR_FALSE;
- }
-
- PRUint32 perm;
- permissionManager->TestExactPermission(innerURI, "offline-app", &perm);
-
- if (perm == nsIPermissionManager::UNKNOWN_ACTION) {
- return GetBoolPref("offline-apps.allow_by_default");
- }
-
- if (perm == nsIPermissionManager::DENY_ACTION) {
- return PR_FALSE;
- }
-
- return PR_TRUE;
+ return NS_OfflineAppAllowed(aURI, sPrefBranch);
+}
+
+/* static */
+PRBool
+nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
+{
+ nsCOMPtr<nsIURI> codebaseURI;
+ aPrincipal->GetURI(getter_AddRefs(codebaseURI));
+
+ return OfflineAppAllowed(codebaseURI);
}
// static
void
nsContentUtils::Shutdown()
{
sInitialized = PR_FALSE;
@@ -4303,16 +4283,28 @@ nsContentUtils::HidePopupsInDocument(nsI
nsCOMPtr<nsIDocShellTreeItem> docShellToHide = do_QueryInterface(container);
if (docShellToHide)
pm->HidePopupsInDocShell(docShellToHide);
}
#endif
}
/* static */
+already_AddRefed<nsIDragSession>
+nsContentUtils::GetDragSession()
+{
+ nsIDragSession* dragSession = nsnull;
+ nsCOMPtr<nsIDragService> dragService =
+ do_GetService("@mozilla.org/widget/dragservice;1");
+ if (dragService)
+ dragService->GetCurrentSession(&dragSession);
+ return dragSession;
+}
+
+/* static */
PRBool
nsContentUtils::URIIsLocalFile(nsIURI *aURI)
{
PRBool isFile;
nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
nsIProtocolHandler::URI_IS_LOCAL_FILE,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1138,16 +1138,17 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsPIDOMEventTarget)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOM3Node)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOM3Document)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNodeSelector)
+ NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
// nsNodeSH::PreCreate() depends on the identity pointer being the
// same as nsINode (which nsIDocument inherits), so if you change
// the below line, make sure nsNodeSH::PreCreate() still does the
// right thing!
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsDocument, nsISupports, nsIDocument)
NS_INTERFACE_TABLE_END
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
@@ -1949,16 +1950,32 @@ nsDocument::GetPrincipal()
void
nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
{
mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
}
NS_IMETHODIMP
+nsDocument::GetApplicationCache(nsIApplicationCache **aApplicationCache)
+{
+ NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache)
+{
+ mApplicationCache = aApplicationCache;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsDocument::GetContentType(nsAString& aContentType)
{
CopyUTF8toUTF16(mContentType, aContentType);
return NS_OK;
}
void
@@ -3020,16 +3037,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
}
}
}
mScriptGlobalObject = aScriptGlobalObject;
if (aScriptGlobalObject) {
+ mScriptObject = nsnull;
mHasHadScriptHandlingObject = PR_TRUE;
// Go back to using the docshell for the layout history state
mLayoutHistoryState = nsnull;
mScopeObject = do_GetWeakReference(aScriptGlobalObject);
}
// Remember the pointer to our window (or lack there of), to avoid
// having to QI every time it's asked for.
@@ -4457,16 +4475,17 @@ nsDocument::NotifyPossibleTitleChange(PR
mPendingTitleChangeEvent = event;
}
}
void
nsDocument::DoNotifyPossibleTitleChange()
{
mPendingTitleChangeEvent.Forget();
+ mHaveFiredTitleChange = PR_TRUE;
nsAutoString title;
GetTitle(title);
nsPresShellIterator iter(this);
nsCOMPtr<nsIPresShell> shell;
while ((shell = iter.GetNextShell())) {
nsCOMPtr<nsISupports> container = shell->GetPresContext()->GetContainer();
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -88,16 +88,18 @@
#include "nsIRequest.h"
#include "nsILoadGroup.h"
#include "nsTObserverArray.h"
#include "nsStubMutationObserver.h"
#include "nsIChannel.h"
#include "nsCycleCollectionParticipant.h"
#include "nsContentList.h"
#include "nsGkAtoms.h"
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheContainer.h"
// Put these here so all document impls get them automatically
#include "nsHTMLStyleSheet.h"
#include "nsIHTMLCSSStyleSheet.h"
#include "nsStyleSet.h"
#include "nsXMLEventsManager.h"
#include "pldhash.h"
@@ -403,16 +405,17 @@ class nsDocument : public nsIDocument,
public nsIDOM3Document,
public nsSupportsWeakReference,
public nsIDOMEventTarget,
public nsIDOM3EventTarget,
public nsIDOMNSEventTarget,
public nsIScriptObjectPrincipal,
public nsIRadioGroupContainer,
public nsIDOMNodeSelector,
+ public nsIApplicationCacheContainer,
public nsStubMutationObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup);
virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
nsIPrincipal* aPrincipal);
@@ -556,16 +559,22 @@ public:
*/
virtual nsIScriptGlobalObject* GetScriptGlobalObject() const;
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject);
virtual nsIScriptGlobalObject*
GetScriptHandlingObject(PRBool& aHasHadScriptHandlingObject) const;
virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject);
+ virtual void ClearScriptHandlingObject()
+ {
+ mScriptObject = nsnull;
+ mHasHadScriptHandlingObject = PR_TRUE;
+ }
+
virtual nsIScriptGlobalObject* GetScopeObject();
/**
* Return the window containing the document (the outer window).
*/
virtual nsPIDOMWindow *GetWindow();
/**
@@ -747,16 +756,19 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
// nsIScriptObjectPrincipal
virtual nsIPrincipal* GetPrincipal();
+ // nsIApplicationCacheContainer
+ NS_DECL_NSIAPPLICATIONCACHECONTAINER
+
virtual nsresult Init();
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID,
PRBool aDocumentDefaultType,
nsIContent **aResult);
@@ -1016,16 +1028,20 @@ protected:
nsCOMPtr<nsIScriptEventManager> mScriptEventManager;
nsString mBaseTarget;
// Our update nesting level
PRUint32 mUpdateNestLevel;
+ // The application cache that this document is associated with, if
+ // any. This can change during the lifetime of the document.
+ nsCOMPtr<nsIApplicationCache> mApplicationCache;
+
private:
friend class nsUnblockOnloadEvent;
void PostUnblockOnloadEvent();
void DoUnblockOnload();
/**
* See if aDocument is a child of this. If so, return the frame element in
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2786,19 +2786,21 @@ nsGenericElement::doPreHandleEvent(nsICo
//FIXME! Document how this event retargeting works, Bug 329124.
aVisitor.mCanHandle = PR_TRUE;
// Don't propagate mouseover and mouseout events when mouse is moving
// inside native anonymous content.
PRBool isAnonForEvents = aContent->IsRootOfNativeAnonymousSubtree();
if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
- // This is an optimization - try to stop event propagation when
- // event has just possibly been retargeted.
- static_cast<nsISupports*>(aContent) == aVisitor.mEvent->target) {
+ // Check if we should stop event propagation when event has just been
+ // dispatched or when we're about to propagate from
+ // native anonymous subtree.
+ ((static_cast<nsISupports*>(aContent) == aVisitor.mEvent->originalTarget &&
+ !aContent->IsInNativeAnonymousSubtree()) || isAnonForEvents)) {
nsCOMPtr<nsIContent> relatedTarget =
do_QueryInterface(static_cast<nsMouseEvent*>
(aVisitor.mEvent)->relatedTarget);
if (relatedTarget &&
relatedTarget->GetOwnerDoc() == aContent->GetOwnerDoc()) {
// If current target is anonymous for events or we know that related
// target is descendant of an element which is anonymous for events,
@@ -2818,29 +2820,47 @@ nsGenericElement::doPreHandleEvent(nsICo
// native anonymous subtree. The case where anonOwner is still
// inside native anonymous subtree will be handled when event
// propagates up in the DOM tree.
while (anonOwner != anonOwnerRelated &&
anonOwnerRelated->IsInNativeAnonymousSubtree()) {
anonOwnerRelated = FindNativeAnonymousSubtreeOwner(anonOwnerRelated);
}
if (anonOwner == anonOwnerRelated) {
- nsCOMPtr<nsIContent> target =
+#ifdef DEBUG_smaug
+ nsCOMPtr<nsIContent> originalTarget =
do_QueryInterface(aVisitor.mEvent->originalTarget);
- // Because XBL and native anon content both do event re-targeting,
- // static_cast<nsISupports*>(aContent) == aVisitor.mEvent->target
- // optimization may not always work. So be paranoid and make
- // sure we never stop event propagation when we shouldn't!
- if (relatedTarget->FindFirstNonNativeAnonymous() ==
- target->FindFirstNonNativeAnonymous()) {
- aVisitor.mParentTarget = nsnull;
- // Event should not propagate to non-anon content.
- aVisitor.mCanHandle = isAnonForEvents;
- return NS_OK;
+ nsAutoString ot, ct, rt;
+ if (originalTarget) {
+ originalTarget->Tag()->ToString(ot);
}
+ aContent->Tag()->ToString(ct);
+ relatedTarget->Tag()->ToString(rt);
+ printf("Stopping %s propagation:"
+ "\n\toriginalTarget=%s \n\tcurrentTarget=%s %s"
+ "\n\trelatedTarget=%s %s \n%s",
+ (aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH)
+ ? "mouseover" : "mouseout",
+ NS_ConvertUTF16toUTF8(ot).get(),
+ NS_ConvertUTF16toUTF8(ct).get(),
+ isAnonForEvents
+ ? "(is native anonymous)"
+ : (aContent->IsInNativeAnonymousSubtree()
+ ? "(is in native anonymous subtree)" : ""),
+ NS_ConvertUTF16toUTF8(rt).get(),
+ relatedTarget->IsInNativeAnonymousSubtree()
+ ? "(is in native anonymous subtree)" : "",
+ (originalTarget && relatedTarget->FindFirstNonNativeAnonymous() ==
+ originalTarget->FindFirstNonNativeAnonymous())
+ ? "" : "Wrong event propagation!?!\n");
+#endif
+ aVisitor.mParentTarget = nsnull;
+ // Event should not propagate to non-anon content.
+ aVisitor.mCanHandle = isAnonForEvents;
+ return NS_OK;
}
}
}
}
}
}
nsCOMPtr<nsIContent> parent = aContent->GetParent();
@@ -4126,19 +4146,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
// nsNodeSH::PreCreate() depends on the identity pointer being the
// same as nsINode (which nsIContent inherits), so if you change the
// below line, make sure nsNodeSH::PreCreate() still does the right
// thing!
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericElement, nsIContent)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement,
- nsIContent,
- nsNodeUtils::LastRelease(this))
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement,
+ nsIContent,
+ nsNodeUtils::LastRelease(this))
nsresult
nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
{
nsIDocument *document = GetOwnerDoc();
if (document) {
return document->BindingManager()->GetBindingImplementation(this, aIID,
aInstancePtr);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -399,18 +399,16 @@ class nsNSElementTearoff;
class nsGenericElement : public nsIContent
{
public:
nsGenericElement(nsINodeInfo *aNodeInfo);
virtual ~nsGenericElement();
friend class nsNSElementTearoff;
- friend class nsNSElementTearoff;
-
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
/**
* Called during QueryInterface to give the binding manager a chance to
* get an interface for this element.
*/
nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -306,20 +306,24 @@ GK_ATOM(DOMNodeRemovedFromDocument, "DOM
GK_ATOM(DOMSubtreeModified, "DOMSubtreeModified")
GK_ATOM(double_, "double")
GK_ATOM(drag, "drag")
GK_ATOM(dragdrop, "dragdrop")
GK_ATOM(dragend, "dragend")
GK_ATOM(dragenter, "dragenter")
GK_ATOM(dragevent, "dragevent")
GK_ATOM(dragexit, "dragexit")
+GK_ATOM(draggable, "draggable")
GK_ATOM(draggesture, "draggesture")
GK_ATOM(dragging, "dragging")
+GK_ATOM(dragleave, "dragleave")
GK_ATOM(dragover, "dragover")
GK_ATOM(dragSession, "dragSession")
+GK_ATOM(dragstart, "dragstart")
+GK_ATOM(drop, "drop")
GK_ATOM(dropAfter, "dropAfter")
GK_ATOM(dropBefore, "dropBefore")
GK_ATOM(dropOn, "dropOn")
GK_ATOM(dt, "dt")
GK_ATOM(editable, "editable")
GK_ATOM(editing, "editing")
GK_ATOM(editor, "editor")
GK_ATOM(editorDisplayList, "EditorDisplay-List")
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -393,17 +393,17 @@ nsRange::ComparePoint(nsIDOMNode* aParen
PRInt32 cmp;
if ((cmp = nsContentUtils::ComparePoints(parent, aOffset,
mStartParent, mStartOffset)) <= 0) {
*aResult = cmp;
}
else if (nsContentUtils::ComparePoints(mEndParent, mEndOffset,
- parent, aOffset) == -1) {
+ parent, aOffset) <= 0) {
*aResult = 1;
}
else {
*aResult = 0;
}
return NS_OK;
}
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -880,25 +880,19 @@ nsXMLHttpRequest::ConvertBodyToText(nsAS
PRInt32 dataLen = mResponseBody.Length();
if (!dataLen)
return NS_OK;
nsresult rv = NS_OK;
nsCAutoString dataCharset;
- nsCOMPtr<nsIDOM3Document> document(do_QueryInterface(mDocument));
+ nsCOMPtr<nsIDocument> document(do_QueryInterface(mDocument));
if (document) {
- nsAutoString inputEncoding;
- document->GetInputEncoding(inputEncoding);
- if (DOMStringIsNull(inputEncoding)) {
- dataCharset.AssignLiteral("UTF-8");
- } else {
- CopyUTF16toUTF8(inputEncoding, dataCharset);
- }
+ dataCharset = document->GetDocumentCharacterSet();
} else {
if (NS_FAILED(DetectCharset(dataCharset)) || dataCharset.IsEmpty()) {
// MS documentation states UTF-8 is default for responseText
dataCharset.AssignLiteral("UTF-8");
}
}
if (dataCharset.EqualsLiteral("ASCII")) {
@@ -1059,16 +1053,18 @@ nsXMLHttpRequest::Abort()
// The ChangeState call above calls onreadystatechange handlers which
// if they load a new url will cause nsXMLHttpRequest::OpenRequest to clear
// the abort state bit. If this occurs we're not uninitialized (bug 361773).
if (mState & XML_HTTP_REQUEST_ABORTED) {
ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE); // IE seems to do it
}
+ mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
+
return NS_OK;
}
/* string getAllResponseHeaders (); */
NS_IMETHODIMP
nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
@@ -1933,19 +1929,25 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
nsMemory::Free(iid);
// document?
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(supports));
if (doc) {
nsCOMPtr<nsIDOMSerializer> serializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
- nsCOMPtr<nsIDocument> baseDoc(do_QueryInterface(doc));
- if (baseDoc) {
- charset = baseDoc->GetDocumentCharacterSet();
+ nsCOMPtr<nsIDOM3Document> dom3doc(do_QueryInterface(doc));
+ if (dom3doc) {
+ nsAutoString inputEncoding;
+ dom3doc->GetInputEncoding(inputEncoding);
+ if (DOMStringIsNull(inputEncoding)) {
+ charset.AssignLiteral("UTF-8");
+ } else {
+ CopyUTF16toUTF8(inputEncoding, charset);
+ }
}
// Serialize to a stream so that the encoding used will
// match the document's.
nsCOMPtr<nsIStorageStream> storStream;
rv = NS_NewStorageStream(4096, PR_UINT32_MAX, getter_AddRefs(storStream));
NS_ENSURE_SUCCESS(rv, rv);
@@ -2337,18 +2339,16 @@ nsXMLHttpRequest::BeforeUnload(nsIDOMEve
return NS_OK;
}
nsresult
nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
{
Abort();
- mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
-
return NS_OK;
}
nsresult
nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
{
mDocument = nsnull;
ChangeState(XML_HTTP_REQUEST_COMPLETED);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -179,22 +179,24 @@ include $(topsrcdir)/config/rules.mk
file_XHR_pass3.txt \
file_XHR_pass3.txt^headers^ \
file_XHR_fail1.txt \
file_XHR_fail1.txt^headers^ \
test_bug428847.html \
file_bug428847-1.xhtml \
file_bug428847-2.xhtml \
test_bug425201.html \
+ test_bug431701.html \
test_bug431833.html \
test_bug435425.html \
bug435425.sjs \
bug435425_redirect.sjs \
test_bug438519.html \
test_bug444722.html \
+ test_bug451376.html \
test_text_replaceWholeText.html \
test_text_wholeText.html \
wholeTexty-helper.xml \
test_bug444030.xhtml \
test_NodeIterator_basics_filters.xhtml \
test_NodeIterator_mutations_1.xhtml \
test_NodeIterator_mutations_2.html \
test_bug28293.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug431701.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=431701
+-->
+<head>
+ <title>Test for Bug 431701</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=431701">Mozilla Bug 431701</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe id="one"></iframe>
+ <iframe id="two"></iframe>
+ <iframe id="three"></iframe>
+ <iframe id="four"></iframe>
+ <iframe id="five"></iframe>
+ <iframe id="six"></iframe>
+ <iframe id="seven"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 431701 **/
+SimpleTest.waitForExplicitFinish();
+
+var docSources = [
+ "data:text/html,<html></html>",
+ "data:text/html;charset=UTF-8,<html></html>",
+ "data:text/html;charset=ISO-8859-1,<html></html>",
+ "data:text/xml,<html></html>",
+ "data:text/xml,<?xml version='1.0'?><html></html>",
+ "data:text/xml,<?xml version='1.0' encoding='UTF-8'?><html></html>",
+ "data:text/xml,<?xml version='1.0' encoding='ISO-8859-1'?><html></html>",
+];
+
+for (var i = 0; i < docSources.length; ++i) {
+ document.getElementsByTagName("iframe")[i].src = docSources[i];
+}
+
+function frameDoc(id) {
+ return function() { return $(id).contentDocument; };
+}
+
+function createDoc() {
+ return document.implementation.createDocument('', 'html', null);
+}
+
+function xhrDoc(idx) {
+ return function() {
+ // Defy same-origin restrictions!
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", docSources[idx], false);
+ xhr.send();
+ return xhr.responseXML;
+ };
+}
+
+// Each row has the document getter function, then the characterSet,
+// inputEncoding, xmlEncoding expected for that document.
+
+var tests = [
+ [ frameDoc("one"), "ISO-8859-1", "ISO-8859-1", null ],
+ [ frameDoc("two"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("three"), "ISO-8859-1", "ISO-8859-1", null ],
+ [ frameDoc("four"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("five"), "UTF-8", "UTF-8", null ],
+ [ frameDoc("six"), "UTF-8", "UTF-8", "UTF-8"],
+ [ frameDoc("seven"), "ISO-8859-1", "ISO-8859-1", "ISO-8859-1" ],
+ [ createDoc, "UTF-8", null, null ],
+ [ xhrDoc(4), "UTF-8", "UTF-8", null ],
+ [ xhrDoc(5), "UTF-8", "UTF-8", "UTF-8" ],
+ [ xhrDoc(6), "ISO-8859-1", "ISO-8859-1", "ISO-8859-1" ],
+];
+
+function doTest(idx) {
+ var [docGetter, expectedCharacterSet,
+ expectedInputEncoding, expectedXMLEncoding] = tests[idx];
+ var doc = docGetter();
+
+ // Have to be careful here to catch null vs ""
+ is(doc.characterSet, expectedCharacterSet, "Test " + idx + " characterSet");
+ is(doc.inputEncoding, expectedInputEncoding,
+ "Test " + idx + " inputEncoding");
+ is(doc.xmlEncoding, expectedXMLEncoding, "Test " + idx + " xmlEncoding");
+}
+
+addLoadEvent(function() {
+ // sanity check
+ isnot("", null, "Shouldn't be equal!");
+
+ for (var i = 0; i < tests.length; ++i) {
+ doTest(i);
+ }
+
+ // Now check what xhr does
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", document.location.href);
+ xhr.send(createDoc());
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ is(xhr.channel.QueryInterface(Components.interfaces.nsIHttpChannel)
+ .getRequestHeader("Content-Type"),
+ "application/xml; charset=UTF-8", "Testing correct type on the wire");
+ xhr.abort();
+
+ SimpleTest.finish();
+});
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/base/test/test_bug435425.html
+++ b/content/base/test/test_bug435425.html
@@ -30,17 +30,18 @@ function logEvent(evt) {
while ((currentEvents.length != i) &&
currentEvents[i].optional &&
((currentEvents[i].type != evt.type) ||
(!evt.target instanceof currentEvents[i].target))) {
++i;
}
ok(i != currentEvents.length, "Extra or wrong event?");
is(evt.type, currentEvents[i].type, "Wrong event!")
- ok(evt.target instanceof currentEvents[i].target, "Wrong event target [" + evt.type + "]!");
+ ok(evt.target instanceof currentEvents[i].target,
+ "Wrong event target [" + evt.target + "," + evt.type + "]!");
// If we handled non-optional event, remove all optional events before the
// handled event and then the non-optional event from the list.
if (!currentEvents[i].optional) {
for (;i != -1; --i) {
currentEvents.shift();
}
}
}
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug451376.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=451376
+-->
+<head>
+ <title>Test for Bug 451376</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 onload="doTest()">
+ <a target="_blank"
+ title="IAccessibleText::attributes provides incorrect info after a mis-spelled word"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=451376">Mozilla Bug 451376</a>
+ <p id="display"></p>
+ <div id="content" style="display:none">
+ </div>
+ <pre id="test">
+
+ <div id="area"><button>btn1</button>text<button>btn2</button></div>
+
+ <script class="testbody" type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ function testRange(aRangeID,
+ aStartNode, aStartOffset,
+ aEndNode, aEndOffset,
+ aBeforeRangeNode, aBeforeRangeOffset,
+ aInRangeNode, aInRangeOffset,
+ aAfterRangeNode, aAfterRangeOffset)
+ {
+ var range = document.createRange().
+ QueryInterface(Components.interfaces.nsIDOMNSRange);
+
+ range.setStart(aStartNode, aStartOffset);
+ range.setEnd(aEndNode, aEndOffset);
+
+ if (aBeforeRangeNode)
+ is(range.comparePoint(aBeforeRangeNode, aBeforeRangeOffset), -1,
+ "Wrong result for the point before the range '" + aRangeID + "'");
+ if (aInRangeNode)
+ is(range.comparePoint(aInRangeNode, aInRangeOffset), 0,
+ "Wrong result for the point inside the range '" + aRangeID + "'");
+ if (aAfterRangeNode)
+ is(range.comparePoint(aAfterRangeNode, aAfterRangeOffset), 1,
+ "Wrong result for the point after the range '" + aRangeID + "'");
+ }
+
+ function doTest()
+ {
+ var area = document.getElementById("area");
+ var btn1 = area.firstChild;
+ var text = btn1.nextSibling;
+ var btn2 = area.lastChild;
+
+ testRange("range1", area, 0, area, 1,
+ null, 0,
+ area, 0,
+ area, 1);
+
+ testRange("range2", text, 2, text, 4,
+ text, 0,
+ text, 3,
+ text, 4);
+
+ testRange("range3", text, 4, area, 2,
+ text, 0,
+ text, 4,
+ area, 2);
+
+ SimpleTest.finish();
+ }
+ </script>
+</pre>
+</body>
+</html>
+
--- a/content/base/test/test_title.html
+++ b/content/base/test/test_title.html
@@ -71,16 +71,17 @@ function testDynamics() {
var t = doc.getElementById("t"); t.textContent = "Hello";
});
testDynamic("html2", "Foo", "Removing HTML <title>", function(doc){
var t = doc.getElementById("t"); t.parentNode.removeChild(t);
});
testDynamic("html3", "Hello", "Appending HTML <title> element to root element", function(doc){
var t = doc.createElement("title"); t.textContent = "Hello"; doc.documentElement.appendChild(t);
});
+
testDynamic("xhtml3", "Hello", "Setting 'title' clears existing <title> contents", function(doc){
doc.title = "Hello";
}, function(doc, desc) {
is(doc.documentElement.firstChild.data, "Hello", desc);
is(doc.documentElement.firstChild.nextSibling, null, desc);
});
// This one does nothing and won't fire an event
document.getElementById("xhtml4").contentDocument.title = "Hello";
@@ -128,35 +129,17 @@ function testDynamics() {
for (description in inProgress) {
ok(!inProgress[description], description + ": DOMTitleChange not fired");
}
SimpleTest.finish();
}
setTimeout(end, 500);
}
-function acid() {
- var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
- is(doctype.ownerDocument, null, "doctype's ownerDocument was wrong after creation");
- var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype);
- doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "head"));
- doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "body"));
- var t = doc.createElementNS("http://www.w3.org/1999/xhtml", "title");
- doc.documentElement.firstChild.appendChild(t);
- // ok we have a conforming XHTML1 doc in |doc| now.
- is(doctype.ownerDocument, doc, "doctype's ownerDocument didn't change when it was assigned to another document");
- is(doc.title, "", "document had unexpected title");
- t.textContent = "Sparrow";
- is(doc.title, "Sparrow", "document.title did not update dynamically");
- doc.body.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "form"));
- is(doc.forms.length, 1, "document.forms not updated after inserting a form");
-}
-
function runTests() {
testStatics();
- // acid();
testDynamics();
}
</script>
</pre>
</body>
</html>
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3141,16 +3141,23 @@ nsCanvasRenderingContext2D::GetImageData
jsval *retvalPtr;
ncc->GetRetValPtr(&retvalPtr);
*retvalPtr = OBJECT_TO_JSVAL(result);
ncc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}
+extern "C" {
+#include "jstypes.h"
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint8 *dest);
+}
+
// void putImageData (in ImageData d, in float x, in float y);
NS_IMETHODIMP
nsCanvasRenderingContext2D::PutImageData()
{
nsresult rv;
if (!mValid)
return NS_ERROR_FAILURE;
@@ -3211,59 +3218,85 @@ nsCanvasRenderingContext2D::PutImageData
arrayLen < (jsuint)(w * h * 4))
return NS_ERROR_DOM_SYNTAX_ERR;
nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[w * h * 4]);
if (!imageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8 *imgPtr = imageBuffer.get();
- jsval vr, vg, vb, va;
- PRUint8 ir, ig, ib, ia;
- for (int32 j = 0; j < h; j++) {
- for (int32 i = 0; i < w; i++) {
- if (!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 0, &vr) ||
- !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 1, &vg) ||
- !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 2, &vb) ||
- !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 3, &va))
- return NS_ERROR_DOM_SYNTAX_ERR;
-
- if (JSVAL_IS_INT(vr)) ir = (PRUint8) JSVAL_TO_INT(vr);
- else if (JSVAL_IS_DOUBLE(vr)) ir = (PRUint8) (*JSVAL_TO_DOUBLE(vr));
- else return NS_ERROR_DOM_SYNTAX_ERR;
-
-
- if (JSVAL_IS_INT(vg)) ig = (PRUint8) JSVAL_TO_INT(vg);
- else if (JSVAL_IS_DOUBLE(vg)) ig = (PRUint8) (*JSVAL_TO_DOUBLE(vg));
- else return NS_ERROR_DOM_SYNTAX_ERR;
-
- if (JSVAL_IS_INT(vb)) ib = (PRUint8) JSVAL_TO_INT(vb);
- else if (JSVAL_IS_DOUBLE(vb)) ib = (PRUint8) (*JSVAL_TO_DOUBLE(vb));
- else return NS_ERROR_DOM_SYNTAX_ERR;
-
- if (JSVAL_IS_INT(va)) ia = (PRUint8) JSVAL_TO_INT(va);
- else if (JSVAL_IS_DOUBLE(va)) ia = (PRUint8) (*JSVAL_TO_DOUBLE(va));
- else return NS_ERROR_DOM_SYNTAX_ERR;
-
- // Convert to premultiplied color (losslessly if the input came from getImageData)
- ir = (ir*ia + 254) / 255;
- ig = (ig*ia + 254) / 255;
- ib = (ib*ia + 254) / 255;
+
+ JSBool ok = js_ArrayToJSUint8Buffer(ctx, dataArray, 0, w*h*4, imageBuffer);
+
+ // no fast path? go slow.
+ if (!ok) {
+ jsval vr, vg, vb, va;
+ PRUint8 ir, ig, ib, ia;
+ for (int32 j = 0; j < h; j++) {
+ for (int32 i = 0; i < w; i++) {
+ if (!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 0, &vr) ||
+ !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 1, &vg) ||
+ !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 2, &vb) ||
+ !JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 3, &va))
+ return NS_ERROR_DOM_SYNTAX_ERR;
+
+ if (JSVAL_IS_INT(vr)) ir = (PRUint8) JSVAL_TO_INT(vr);
+ else if (JSVAL_IS_DOUBLE(vr)) ir = (PRUint8) (*JSVAL_TO_DOUBLE(vr));
+ else return NS_ERROR_DOM_SYNTAX_ERR;
+
+ if (JSVAL_IS_INT(vg)) ig = (PRUint8) JSVAL_TO_INT(vg);
+ else if (JSVAL_IS_DOUBLE(vg)) ig = (PRUint8) (*JSVAL_TO_DOUBLE(vg));
+ else return NS_ERROR_DOM_SYNTAX_ERR;
+
+ if (JSVAL_IS_INT(vb)) ib = (PRUint8) JSVAL_TO_INT(vb);
+ else if (JSVAL_IS_DOUBLE(vb)) ib = (PRUint8) (*JSVAL_TO_DOUBLE(vb));
+ else return NS_ERROR_DOM_SYNTAX_ERR;
+
+ if (JSVAL_IS_INT(va)) ia = (PRUint8) JSVAL_TO_INT(va);
+ else if (JSVAL_IS_DOUBLE(va)) ia = (PRUint8) (*JSVAL_TO_DOUBLE(va));
+ else return NS_ERROR_DOM_SYNTAX_ERR;
+
+ // Convert to premultiplied color (losslessly if the input came from getImageData)
+ ir = (ir*ia + 254) / 255;
+ ig = (ig*ia + 254) / 255;
+ ib = (ib*ia + 254) / 255;
#ifdef IS_LITTLE_ENDIAN
- *imgPtr++ = ib;
- *imgPtr++ = ig;
- *imgPtr++ = ir;
- *imgPtr++ = ia;
+ *imgPtr++ = ib;
+ *imgPtr++ = ig;
+ *imgPtr++ = ir;
+ *imgPtr++ = ia;
#else
- *imgPtr++ = ia;
- *imgPtr++ = ir;
- *imgPtr++ = ig;
- *imgPtr++ = ib;
+ *imgPtr++ = ia;
+ *imgPtr++ = ir;
+ *imgPtr++ = ig;
+ *imgPtr++ = ib;
#endif
+ }
+ }
+ } else {
+ /* Walk through and premultiply and swap rgba */
+ /* XXX SSE me */
+ PRUint8 ir, ig, ib, ia;
+ PRUint8 *ptr = imgPtr;
+ for (int32 i = 0; i < w*h; i++) {
+#ifdef IS_LITTLE_ENDIAN
+ ir = ptr[0];
+ ig = ptr[1];
+ ib = ptr[2];
+ ia = ptr[3];
+ ptr[0] = (ib*ia + 254) / 255;
+ ptr[1] = (ig*ia + 254) / 255;
+ ptr[2] = (ir*ia + 254) / 255;
+#else
+ ptr[0] = (ptr[0]*ptr[3] + 254) / 255;
+ ptr[1] = (ptr[1]*ptr[3] + 254) / 255;
+ ptr[2] = (ptr[2]*ptr[3] + 254) / 255;
+#endif
+ ptr += 4;
}
}
nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
gfxIntSize(w, h),
w * 4,
gfxASurface::ImageFormatARGB32);
if (!imgsurf || imgsurf->CairoStatus())
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -78,16 +78,18 @@ nsresult
NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent *aEvent);
nsresult
NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsGUIEvent *aEvent);
nsresult
NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
nsresult
NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
nsresult
+NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsDragEvent *aEvent);
+nsresult
NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsKeyEvent *aEvent);
nsresult
NS_NewDOMMutationEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsMutationEvent* aEvent);
nsresult
NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsPopupBlockedEvent* aEvent);
nsresult
NS_NewDOMTextEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsTextEvent* aEvent);
nsresult
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -71,32 +71,34 @@ CPPSRCS = \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMDataContainerEvent.cpp \
nsDOMUIEvent.cpp \
nsDOMKeyboardEvent.cpp \
nsDOMTextEvent.cpp \
nsDOMMouseEvent.cpp \
nsDOMMouseScrollEvent.cpp \
+ nsDOMDragEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMPopupBlockedEvent.cpp \
nsDOMBeforeUnloadEvent.cpp \
nsDOMPageTransitionEvent.cpp \
nsDOMXULCommandEvent.cpp \
nsDOMCommandEvent.cpp \
nsDOMMessageEvent.cpp \
nsPrivateTextRange.cpp \
nsDOMEventGroup.cpp \
nsXMLEventsManager.cpp \
nsXMLEventsElement.cpp \
nsPLDOMEvent.cpp \
nsEventDispatcher.cpp \
nsIMEStateManager.cpp \
nsQueryContentEventHandler.cpp \
nsDOMProgressEvent.cpp \
+ nsDOMDataTransfer.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -0,0 +1,768 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Neil Deakin <enndeakin@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#include "nsDOMDataTransfer.h"
+
+#include "prlog.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+#include "nsIServiceManager.h"
+#include "nsIVariant.h"
+#include "nsISupportsPrimitives.h"
+#include "nsDOMClassInfo.h"
+#include "nsDOMLists.h"
+#include "nsGUIEvent.h"
+#include "nsDOMError.h"
+#include "nsIDragService.h"
+#include "nsIScriptableRegion.h"
+#include "nsContentUtils.h"
+
+NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMNSDataTransfer)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDataTransfer)
+ NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(DataTransfer)
+NS_INTERFACE_MAP_END
+
+// the size of the array
+const char nsDOMDataTransfer::sEffects[8][9] = {
+ "none", "copy", "move", "copyMove", "link", "copyLink", "linkMove", "all"
+};
+
+nsDOMDataTransfer::nsDOMDataTransfer()
+ : mEventType(NS_DRAGDROP_START),
+ mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+ mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED),
+ mReadOnly(PR_FALSE),
+ mIsExternal(PR_FALSE),
+ mDragImageX(0),
+ mDragImageY(0)
+{
+}
+
+nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction)
+ : mEventType(aEventType),
+ mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+ mReadOnly(PR_TRUE),
+ mIsExternal(PR_TRUE),
+ mDragImageX(0),
+ mDragImageY(0)
+{
+ mEffectAllowed = aAction &
+ (nsIDragService::DRAGDROP_ACTION_COPY |
+ nsIDragService::DRAGDROP_ACTION_LINK |
+ nsIDragService::DRAGDROP_ACTION_MOVE);
+
+ CacheExternalFormats();
+}
+
+nsDOMDataTransfer::nsDOMDataTransfer(PRUint32 aEventType,
+ const PRUint32 aEffectAllowed,
+ PRBool aIsExternal,
+ nsTArray<nsTArray<TransferItem> >& aItems,
+ nsIDOMElement* aDragImage,
+ PRUint32 aDragImageX,
+ PRUint32 aDragImageY)
+ : mEventType(aEventType),
+ mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE),
+ mEffectAllowed(aEffectAllowed),
+ mReadOnly(PR_TRUE),
+ mIsExternal(aIsExternal),
+ mItems(aItems),
+ mDragImage(aDragImage),
+ mDragImageX(aDragImageX),
+ mDragImageY(aDragImageY)
+{
+ // The items are copied from aItems into mItems. There is no need to copy
+ // the actual data in the items as the data transfer will be read only. The
+ // draggesture and dragstart events are the only times when items are
+ // modifiable, but those events should have been using the first constructor
+ // above.
+ NS_ASSERTION(aEventType != NS_DRAGDROP_GESTURE &&
+ aEventType != NS_DRAGDROP_START,
+ "invalid event type for nsDOMDataTransfer constructor");
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetDropEffect(nsAString& aDropEffect)
+{
+ aDropEffect.AssignASCII(sEffects[mDropEffect]);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDropEffect(const nsAString& aDropEffect)
+{
+ // the drop effect can only be 'none', 'copy', 'move' or 'link'.
+ for (PRUint32 e = 0; e <= nsIDragService::DRAGDROP_ACTION_LINK; e++) {
+ if (aDropEffect.EqualsASCII(sEffects[e])) {
+ // don't allow copyMove
+ if (e != (nsIDragService::DRAGDROP_ACTION_COPY |
+ nsIDragService::DRAGDROP_ACTION_MOVE))
+ mDropEffect = e;
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetEffectAllowed(nsAString& aEffectAllowed)
+{
+ if (mEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
+ aEffectAllowed.AssignLiteral("uninitialized");
+ else
+ aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetEffectAllowed(const nsAString& aEffectAllowed)
+{
+ if (aEffectAllowed.EqualsLiteral("uninitialized")) {
+ mEffectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
+ return NS_OK;
+ }
+
+ PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_NONE == 0);
+ PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_COPY == 1);
+ PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_MOVE == 2);
+ PR_STATIC_ASSERT(nsIDragService::DRAGDROP_ACTION_LINK == 4);
+
+ for (PRUint32 e = 0; e < NS_ARRAY_LENGTH(sEffects); e++) {
+ if (aEffectAllowed.EqualsASCII(sEffects[e])) {
+ mEffectAllowed = e;
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetDropEffectInt(PRUint32* aDropEffect)
+{
+ *aDropEffect = mDropEffect;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDropEffectInt(PRUint32 aDropEffect)
+{
+ mDropEffect = aDropEffect;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetEffectAllowedInt(PRUint32* aEffectAllowed)
+{
+ *aEffectAllowed = mEffectAllowed;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetEffectAllowedInt(PRUint32 aEffectAllowed)
+{
+ mEffectAllowed = aEffectAllowed;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetTypes(nsIDOMDOMStringList** aTypes)
+{
+ return MozTypesAt(0, aTypes);
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
+{
+ // return an empty string if data for the format was not found
+ aData.Truncate();
+
+ nsCOMPtr<nsIVariant> data;
+ nsresult rv = MozGetDataAt(aFormat, 0, getter_AddRefs(data));
+ if (rv == NS_ERROR_DOM_INDEX_SIZE_ERR)
+ return NS_OK;
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (data) {
+ nsAutoString stringdata;
+ data->GetAsAString(stringdata);
+
+ // for the URL type, parse out the first URI from the list. The URIs are
+ // separated by newlines
+ if (aFormat.EqualsLiteral("URL")) {
+ PRInt32 lastidx = 0, idx;
+ PRInt32 length = stringdata.Length();
+ while (lastidx < length) {
+ idx = stringdata.FindChar('\n', lastidx);
+ // lines beginning with # are comments
+ if (stringdata[lastidx] == '#') {
+ if (idx == -1)
+ break;
+ }
+ else {
+ if (idx == -1)
+ aData.Assign(Substring(stringdata, lastidx));
+ else
+ aData.Assign(Substring(stringdata, lastidx, idx - lastidx));
+ aData = nsContentUtils::TrimWhitespace(aData, PR_TRUE);
+ return NS_OK;
+ }
+ lastidx = idx + 1;
+ }
+ }
+ else {
+ aData = stringdata;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
+{
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+ NS_ENSURE_TRUE(variant, NS_ERROR_OUT_OF_MEMORY);
+
+ variant->SetAsAString(aData);
+
+ return MozSetDataAt(aFormat, variant, 0);
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::ClearData(const nsAString& aFormat)
+{
+ nsresult rv = MozClearDataAt(aFormat, 0);
+ return (rv == NS_ERROR_DOM_INDEX_SIZE_ERR) ? NS_OK : rv;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::GetMozItemCount(PRUint32* aCount)
+{
+ *aCount = mItems.Length();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozTypesAt(PRUint32 aIndex, nsIDOMDOMStringList** aTypes)
+{
+ *aTypes = nsnull;
+
+ nsRefPtr<nsDOMStringList> types = new nsDOMStringList();
+ NS_ENSURE_TRUE(types, NS_ERROR_OUT_OF_MEMORY);
+
+ if (aIndex < mItems.Length()) {
+ // note that you can retrieve the types regardless of their principal
+ nsTArray<TransferItem>& item = mItems[aIndex];
+ for (PRUint32 i = 0; i < item.Length(); i++)
+ types->Add(item[i].mFormat);
+ }
+
+ *aTypes = types;
+ NS_ADDREF(*aTypes);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozGetDataAt(const nsAString& aFormat,
+ PRUint32 aIndex,
+ nsIVariant** aData)
+{
+ *aData = nsnull;
+
+ if (aFormat.IsEmpty())
+ return NS_OK;
+
+ if (aIndex >= mItems.Length())
+ return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+ nsAutoString format;
+ GetRealFormat(aFormat, format);
+
+ nsTArray<TransferItem>& item = mItems[aIndex];
+
+ // allow access to any data in the drop and dragdrop events, or if the
+ // UniversalBrowserRead privilege is set, otherwise only allow access to
+ // data from the same principal.
+ nsIPrincipal* principal = nsnull;
+ if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
+ !nsContentUtils::IsCallerTrustedForCapability("UniversalBrowserRead"))
+ principal = GetCurrentPrincipal();
+
+ PRUint32 count = item.Length();
+ for (PRUint32 i = 0; i < count; i++) {
+ TransferItem& formatitem = item[i];
+ if (formatitem.mFormat.Equals(format)) {
+ PRBool subsumes;
+ if (formatitem.mPrincipal && principal &&
+ (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
+ return NS_ERROR_DOM_SECURITY_ERR;
+
+ if (!formatitem.mData)
+ FillInExternalDragData(formatitem, aIndex);
+ *aData = formatitem.mData;
+ NS_IF_ADDREF(*aData);
+ return NS_OK;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozSetDataAt(const nsAString& aFormat,
+ nsIVariant* aData,
+ PRUint32 aIndex)
+{
+ NS_ENSURE_TRUE(aData, NS_ERROR_NULL_POINTER);
+
+ if (aFormat.IsEmpty())
+ return NS_OK;
+
+ if (mReadOnly)
+ return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ // Specifying an index less than the current length will replace an existing
+ // item. Specifying an index equal to the current length will add a new item.
+ if (aIndex > mItems.Length())
+ return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+ // don't allow non-chrome to add file data
+ // XXX perhaps this should also limit any non-string type as well
+ if ((aFormat.EqualsLiteral("application/x-moz-file-promise") ||
+ aFormat.EqualsLiteral("application/x-moz-file")) &&
+ !nsContentUtils::IsCallerChrome()) {
+ return NS_ERROR_DOM_SECURITY_ERR;
+ }
+
+ return SetDataWithPrincipal(aFormat, aData, aIndex, GetCurrentPrincipal());
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::MozClearDataAt(const nsAString& aFormat, PRUint32 aIndex)
+{
+ if (mReadOnly)
+ return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ if (aIndex >= mItems.Length())
+ return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+ nsAutoString format;
+ GetRealFormat(aFormat, format);
+
+ nsIPrincipal* principal = GetCurrentPrincipal();
+
+ // if the format is empty, clear all formats
+ PRBool clearall = format.IsEmpty();
+
+ nsTArray<TransferItem>& item = mItems[aIndex];
+ // count backwards so that the count and index don't have to be adjusted
+ // after removing an element
+ for (PRInt32 i = item.Length() - 1; i >= 0; i--) {
+ TransferItem& formatitem = item[i];
+ if (clearall || formatitem.mFormat.Equals(format)) {
+ // don't allow removing data that has a stronger principal
+ PRBool subsumes;
+ if (formatitem.mPrincipal && principal &&
+ (NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
+ return NS_ERROR_DOM_SECURITY_ERR;
+
+ item.RemoveElementAt(i);
+
+ // if a format was specified, break out. Otherwise, loop around until
+ // all formats have been removed
+ if (!clearall)
+ break;
+ }
+ }
+
+ // if the last format for an item is removed, remove the entire item
+ if (!item.Length())
+ mItems.RemoveElementAt(aIndex);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::SetDragImage(nsIDOMElement* aImage, PRInt32 aX, PRInt32 aY)
+{
+ if (mReadOnly)
+ return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ mDragImage = aImage;
+ mDragImageX = aX;
+ mDragImageY = aY;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMDataTransfer::AddElement(nsIDOMElement* aElement)
+{
+ NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
+
+ if (mReadOnly)
+ return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ mDragTarget = do_QueryInterface(aElement);
+
+ return NS_OK;
+}
+
+nsresult
+nsDOMDataTransfer::Clone(PRUint32 aEventType,
+ nsIDOMDataTransfer** aNewDataTransfer)
+{
+ nsDOMDataTransfer* newDataTransfer =
+ new nsDOMDataTransfer(aEventType, mEffectAllowed, mIsExternal,
+ mItems, mDragImage, mDragImageX, mDragImageY);
+ NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_OUT_OF_MEMORY);
+
+ *aNewDataTransfer = newDataTransfer;
+ NS_ADDREF(*aNewDataTransfer);
+ return NS_OK;
+}
+
+void
+nsDOMDataTransfer::GetTransferables(nsISupportsArray** aArray)
+{
+ *aArray = nsnull;
+
+ nsCOMPtr<nsISupportsArray> transArray =
+ do_CreateInstance("@mozilla.org/supports-array;1");
+ if (!transArray)
+ return;
+
+ PRBool added = PR_FALSE;
+ PRUint32 count = mItems.Length();
+ for (PRUint32 i = 0; i < count; i++) {
+
+ nsTArray<TransferItem>& item = mItems[i];
+ PRUint32 count = item.Length();
+ if (!count)
+ continue;
+
+ nsCOMPtr<nsITransferable> transferable =
+ do_CreateInstance("@mozilla.org/widget/transferable;1");
+ if (!transferable)
+ return;
+
+ for (PRUint32 f = 0; f < count; f++) {
+ TransferItem& formatitem = item[f];
+ if (!formatitem.mData) // skip empty items
+ continue;
+
+ PRUint32 length;
+ nsCOMPtr<nsISupports> convertedData;
+ if (!ConvertFromVariant(formatitem.mData, getter_AddRefs(convertedData), &length))
+ continue;
+
+ // the underlying drag code uses text/unicode, so use that instead of text/plain
+ const char* format;
+ NS_ConvertUTF16toUTF8 utf8format(formatitem.mFormat);
+ if (utf8format.EqualsLiteral("text/plain"))
+ format = kUnicodeMime;
+ else
+ format = utf8format.get();
+
+ // if a converter is set for a format, set the converter for the
+ // transferable and don't add the item
+ nsCOMPtr<nsIFormatConverter> converter = do_QueryInterface(convertedData);
+ if (converter) {
+ transferable->AddDataFlavor(format);
+ transferable->SetConverter(converter);
+ continue;
+ }
+
+ nsresult rv = transferable->SetTransferData(format, convertedData, length);
+ if (NS_FAILED(rv))
+ return;
+
+ added = PR_TRUE;
+ }
+
+ // only append the transferable if data was successfully added to it
+ if (added)
+ transArray->AppendElement(transferable);
+ }
+
+ NS_ADDREF(*aArray = transArray);
+}
+
+PRBool
+nsDOMDataTransfer::ConvertFromVariant(nsIVariant* aVariant,
+ nsISupports** aSupports,
+ PRUint32* aLength)
+{
+ *aSupports = nsnull;
+ *aLength = 0;
+
+ PRUint16 type;
+ aVariant->GetDataType(&type);
+ if (type == nsIDataType::VTYPE_INTERFACE ||
+ type == nsIDataType::VTYPE_INTERFACE_IS) {
+ if (NS_FAILED(aVariant->GetAsISupports(aSupports)))
+ return PR_FALSE;
+
+ // for flavour data providers, use kFlavorHasDataProvider (which has the
+ // value 0) as the length.
+ nsCOMPtr<nsIFlavorDataProvider> fdp = do_QueryInterface(*aSupports);
+ *aLength = fdp ? sizeof(nsISupports) : nsITransferable::kFlavorHasDataProvider;
+ }
+
+ PRUnichar* chrs;
+ nsresult rv = aVariant->GetAsWString(&chrs);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+
+ nsCOMPtr<nsISupportsString>
+ strSupports(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
+ if (!strSupports)
+ return PR_FALSE;
+
+ nsAutoString str(chrs);
+ strSupports->SetData(str);
+
+ *aSupports = strSupports;
+ NS_ADDREF(*aSupports);
+
+ // each character is two bytes
+ *aLength = str.Length() << 1;
+
+ return PR_TRUE;
+}
+
+void
+nsDOMDataTransfer::ClearAll()
+{
+ mItems.Clear();
+}
+
+nsresult
+nsDOMDataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
+ nsIVariant* aData,
+ PRUint32 aIndex,
+ nsIPrincipal* aPrincipal)
+{
+ nsAutoString format;
+ GetRealFormat(aFormat, format);
+
+ // check if the item for the format already exists. In that case,
+ // just replace it.
+ TransferItem* formatitem;
+ if (aIndex < mItems.Length()) {
+ nsTArray<TransferItem>& item = mItems[aIndex];
+ PRUint32 count = item.Length();
+ for (PRUint32 i = 0; i < count; i++) {
+ TransferItem& itemformat = item[i];
+ if (itemformat.mFormat.Equals(format)) {
+ // don't allow replacing data that has a stronger principal
+ PRBool subsumes;
+ if (itemformat.mPrincipal && aPrincipal &&
+ (NS_FAILED(aPrincipal->Subsumes(itemformat.mPrincipal, &subsumes)) || !subsumes))
+ return NS_ERROR_DOM_SECURITY_ERR;
+
+ itemformat.mPrincipal = aPrincipal;
+ itemformat.mData = aData;
+ return NS_OK;
+ }
+ }
+
+ // add a new format
+ formatitem = item.AppendElement();
+ }
+ else {
+ NS_ASSERTION(aIndex == mItems.Length(), "Index out of range");
+
+ // add a new index
+ nsTArray<TransferItem>* item = mItems.AppendElement();
+ NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
+
+ formatitem = item->AppendElement();
+ }
+
+ NS_ENSURE_TRUE(formatitem, NS_ERROR_OUT_OF_MEMORY);
+
+ formatitem->mFormat = format;
+ formatitem->mPrincipal = aPrincipal;
+ formatitem->mData = aData;
+
+ return NS_OK;
+}
+
+nsIPrincipal*
+nsDOMDataTransfer::GetCurrentPrincipal()
+{
+ nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+
+ nsCOMPtr<nsIPrincipal> currentPrincipal;
+ ssm->GetSubjectPrincipal(getter_AddRefs(currentPrincipal));
+ if (!currentPrincipal)
+ ssm->GetSystemPrincipal(getter_AddRefs(currentPrincipal));
+
+ return currentPrincipal.get();
+}
+
+void
+nsDOMDataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
+{
+ // treat text/unicode as equivalent to text/plain
+ if (aInFormat.EqualsLiteral("Text") || aInFormat.EqualsLiteral("text/unicode"))
+ aOutFormat.AssignLiteral("text/plain");
+ else if (aInFormat.EqualsLiteral("URL"))
+ aOutFormat.AssignLiteral("text/uri-list");
+ else
+ aOutFormat.Assign(aInFormat);
+}
+
+void
+nsDOMDataTransfer::CacheExternalFormats()
+{
+ // Called during the constructor to cache the formats available from an
+ // external drag. The data associated with each format will be set to null.
+ // This data will instead only be retrieved in FillInExternalDragData when
+ // asked for, as it may be time consuming for the source application to
+ // generate it.
+
+ nsCOMPtr<nsIDragService> dragService =
+ do_GetService("@mozilla.org/widget/dragservice;1");
+ if (!dragService)
+ return;
+
+ nsCOMPtr<nsIDragSession> dragSession;
+ dragService->GetCurrentSession(getter_AddRefs(dragSession));
+ if (!dragSession)
+ return;
+
+ // make sure that the system principal is used for external drags
+ nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+ nsCOMPtr<nsIPrincipal> sysPrincipal;
+ ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal));
+
+ // there isn't a way to get a list of the formats that might be available on
+ // all platforms, so just check for the types that can actually be imported
+ // XXXndeakin there are some other formats but those are platform specific.
+ const char* formats[] = { kFileMime, kHTMLMime, kURLMime, kURLDataMime, kUnicodeMime };
+
+ PRUint32 count;
+ dragSession->GetNumDropItems(&count);
+ for (PRUint32 c = 0; c < count; c++) {
+ for (PRUint32 f = 0; f < NS_ARRAY_LENGTH(formats); f++) {
+ // IsDataFlavorSupported doesn't take an index as an argument and just
+ // checks if any of the items support a particular flavor, even though
+ // the GetData method does take an index. Here, we just assume that
+ // every item being dragged has the same set of flavors.
+ PRBool supported;
+ dragSession->IsDataFlavorSupported(formats[f], &supported);
+ // if the format is supported, add an item to the array with null as
+ // the data. When retrieved, GetRealData will read the data.
+ if (supported) {
+ if (formats[f] == kUnicodeMime) {
+ SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nsnull, c, sysPrincipal);
+ }
+ else {
+ if (formats[f] == kURLDataMime)
+ SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nsnull, c, sysPrincipal);
+ SetDataWithPrincipal(NS_ConvertUTF8toUTF16(formats[f]), nsnull, c, sysPrincipal);
+ }
+ }
+ }
+ }
+}
+
+void
+nsDOMDataTransfer::FillInExternalDragData(TransferItem& aItem, PRUint32 aIndex)
+{
+ NS_PRECONDITION(mIsExternal, "Not an external drag");
+
+ if (!aItem.mData) {
+ nsCOMPtr<nsITransferable> trans =
+ do_CreateInstance("@mozilla.org/widget/transferable;1");
+ if (!trans)
+ return;
+
+ NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
+ const char* format = utf8format.get();
+ if (strcmp(format, "text/plain") == 0)
+ format = kUnicodeMime;
+ else if (strcmp(format, "text/uri-list") == 0)
+ format = kURLDataMime;
+
+ nsCOMPtr<nsIDragService> dragService =
+ do_GetService("@mozilla.org/widget/dragservice;1");
+ if (!dragService)
+ return;
+
+ nsCOMPtr<nsIDragSession> dragSession;
+ dragService->GetCurrentSession(getter_AddRefs(dragSession));
+ if (!dragSession)
+ return;
+
+ trans->AddDataFlavor(format);
+ dragSession->GetData(trans, aIndex);
+
+ PRUint32 length = 0;
+ nsCOMPtr<nsISupports> data;
+ trans->GetTransferData(format, getter_AddRefs(data), &length);
+ if (!data)
+ return;
+
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
+ if (!variant)
+ return;
+
+ nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
+ if (supportsstr) {
+ nsAutoString str;
+ supportsstr->GetData(str);
+ variant->SetAsAString(str);
+ }
+ else {
+ variant->SetAsISupports(data);
+ }
+ aItem.mData = variant;
+ }
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMDataTransfer.h
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Neil Deakin <enndeakin@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#ifndef nsDOMDataTransfer_h__
+#define nsDOMDataTransfer_h__
+
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsIVariant.h"
+#include "nsIPrincipal.h"
+#include "nsIDOMDataTransfer.h"
+#include "nsIDragService.h"
+#include "nsIDOMElement.h"
+#include "nsCycleCollectionParticipant.h"
+
+class nsITransferable;
+
+/**
+ * TransferItem is used to hold data for a particular format. Each piece of
+ * data has a principal set from the caller which added it. This allows a
+ * caller that wishes to retrieve the data to only be able to access the data
+ * it is allowed to, yet still allow a chrome caller to retrieve any of the
+ * data.
+ */
+struct TransferItem {
+ nsString mFormat;
+ nsCOMPtr<nsIPrincipal> mPrincipal;
+ nsCOMPtr<nsIVariant> mData;
+};
+
+class nsDOMDataTransfer : public nsIDOMDataTransfer,
+ public nsIDOMNSDataTransfer
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_NSIDOMDATATRANSFER
+ NS_DECL_NSIDOMNSDATATRANSFER
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMDataTransfer, nsIDOMDataTransfer)
+
+ friend class nsDOMDragEvent;
+ friend class nsEventStateManager;
+
+protected:
+
+ // the constructors are protected so only our friends can call them
+
+ // default constructor used for the dragstart/draggesture event and
+ // synthetic events
+ nsDOMDataTransfer();
+
+ // this constructor must only be used to create a dataTransfer for a drag
+ // that was started without using a data transfer, either an external drag,
+ // that is, a drag where the source is another application, or a drag
+ // started by calling the drag service directly.
+ nsDOMDataTransfer(PRUint32 aEventType, PRUint32 aAction);
+
+ // this constructor is used only by the Clone method to copy the fields as
+ // needed to a new data transfer.
+ nsDOMDataTransfer(PRUint32 aEventType,
+ const PRUint32 aEffectAllowed,
+ PRBool aIsExternal,
+ nsTArray<nsTArray<TransferItem> >& aItems,
+ nsIDOMElement* aDragImage,
+ PRUint32 aDragImageX,
+ PRUint32 aDragImageY);
+
+ static const char sEffects[8][9];
+
+public:
+
+ void GetDragTarget(nsIDOMElement** aDragTarget)
+ {
+ *aDragTarget = mDragTarget;
+ NS_IF_ADDREF(*aDragTarget);
+ }
+
+ // a readonly dataTransfer cannot have new data added or existing data removed.
+ // Only the dropEffect and effectAllowed may be modified.
+ void SetReadOnly() { mReadOnly = PR_TRUE; }
+
+ // converts the data into an array of nsITransferable objects to be used for
+ // drag and drop or clipboard operations.
+ void GetTransferables(nsISupportsArray** transferables);
+
+ // converts the data in the variant to an nsISupportString if possible or
+ // an nsISupports or null otherwise.
+ PRBool ConvertFromVariant(nsIVariant* aVariant,
+ nsISupports** aSupports,
+ PRUint32* aLength);
+
+ // clears all of the data
+ void ClearAll();
+
+ // Similar to SetData except also specifies the principal to store.
+ // aData may be null when called from CacheExternalFormats.
+ nsresult SetDataWithPrincipal(const nsAString& aFormat,
+ nsIVariant* aData,
+ PRUint32 aIndex,
+ nsIPrincipal* aPrincipal);
+
+protected:
+
+ // returns a weak reference to the drag image
+ nsIDOMElement* GetDragImage(PRInt32* aX, PRInt32* aY)
+ {
+ *aX = mDragImageX;
+ *aY = mDragImageY;
+ return mDragImage;
+ }
+
+ // returns a weak reference to the current principal
+ nsIPrincipal* GetCurrentPrincipal();
+
+ // converts some formats used for compatibility in aInFormat into aOutFormat.
+ // Text and text/unicode become text/plain, and URL becomes text/uri-list
+ void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat);
+
+ // caches the formats that exist in the drag service that were added by an
+ // external drag
+ void CacheExternalFormats();
+
+ // fills in the data field of aItem with the data from the drag service for
+ // a given index.
+ void FillInExternalDragData(TransferItem& aItem, PRUint32 aIndex);
+
+ // the event type this data transfer is for. This will correspond to an
+ // event->message value.
+ PRUint32 mEventType;
+
+ // the drop effect and effect allowed
+ PRUint32 mDropEffect;
+ PRUint32 mEffectAllowed;
+
+ // readonly data transfers may not be modified except the drop effect and
+ // effect allowed.
+ PRPackedBool mReadOnly;
+
+ // true for drags started without a data transfer, for example, those from
+ // another application.
+ PRPackedBool mIsExternal;
+
+ // array of items, each containing an array of format->data pairs
+ nsTArray<nsTArray<TransferItem> > mItems;
+
+ // the target of the drag. The drag and dragend events will fire at this.
+ nsCOMPtr<nsIDOMElement> mDragTarget;
+