This commit is contained in:
Andreas Gal 2008-09-21 12:44:24 -07:00
Родитель 4b03acd64e 2d807d6426
Коммит ccf766cf50
1010 изменённых файлов: 26925 добавлений и 26331 удалений

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

@ -58,7 +58,7 @@ interface nsIAccessibleRelation;
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(004b6882-2df1-49df-bb5f-0fb81a5b1edf)]
[scriptable, uuid(c7520419-87ec-42bc-98cc-04c0bf173530)]
interface nsIAccessible : nsISupports
{
/**
@ -199,9 +199,25 @@ interface nsIAccessible : nsISupports
* current accessible will be returned.
* If the point is in neither the current accessible or a child, then
* null will be returned.
*
* @param x screen's x coordinate
* @param y screen's y coordinate
* @return the deepest accessible child containing the given point
*/
nsIAccessible getChildAtPoint(in long x, in long y);
/**
* Deepest accessible child which contains the coordinate at (x, y) in screen
* pixels. If the point is in the current accessible but not in a child, the
* current accessible will be returned. If the point is in neither the current
* accessible or a child, then null will be returned.
*
* @param x screen's x coordinate
* @param y screen's y coordinate
* @return the deepest accessible child containing the given point
*/
nsIAccessible getDeepestChildAtPoint(in long x, in long y);
/**
* Nth accessible child using zero-based index or last child if index less than zero
*/

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

@ -608,16 +608,17 @@ nsAccessNode::GetChildNodeAt(PRInt32 aChildNum, nsIAccessNode **aAccessNode)
}
NS_IMETHODIMP
nsAccessNode::GetComputedStyleValue(const nsAString& aPseudoElt, const nsAString& aPropertyName, nsAString& aValue)
nsAccessNode::GetComputedStyleValue(const nsAString& aPseudoElt,
const nsAString& aPropertyName,
nsAString& aValue)
{
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
if (!domElement) {
if (IsDefunct())
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl;
GetComputedStyleDeclaration(aPseudoElt, domElement, getter_AddRefs(styleDecl));
GetComputedStyleDeclaration(aPseudoElt, mDOMNode, getter_AddRefs(styleDecl));
NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
return styleDecl->GetPropertyValue(aPropertyName, aValue);
}
@ -627,15 +628,13 @@ nsAccessNode::GetComputedStyleCSSValue(const nsAString& aPseudoElt,
nsIDOMCSSPrimitiveValue **aCSSValue)
{
NS_ENSURE_ARG_POINTER(aCSSValue);
*aCSSValue = nsnull;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
if (!domElement)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl;
GetComputedStyleDeclaration(aPseudoElt, domElement,
GetComputedStyleDeclaration(aPseudoElt, mDOMNode,
getter_AddRefs(styleDecl));
NS_ENSURE_STATE(styleDecl);
@ -646,28 +645,29 @@ nsAccessNode::GetComputedStyleCSSValue(const nsAString& aPseudoElt,
return CallQueryInterface(cssValue, aCSSValue);
}
void nsAccessNode::GetComputedStyleDeclaration(const nsAString& aPseudoElt,
nsIDOMElement *aElement,
nsIDOMCSSStyleDeclaration **aCssDecl)
void
nsAccessNode::GetComputedStyleDeclaration(const nsAString& aPseudoElt,
nsIDOMNode *aNode,
nsIDOMCSSStyleDeclaration **aCssDecl)
{
*aCssDecl = nsnull;
nsCOMPtr<nsIDOMElement> domElement = nsAccUtils::GetDOMElementFor(aNode);
if (!domElement)
return;
// Returns number of items in style declaration
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (!content) {
return;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(domElement);
nsCOMPtr<nsIDocument> doc = content->GetDocument();
if (!doc) {
if (!doc)
return;
}
nsCOMPtr<nsIDOMViewCSS> viewCSS(do_QueryInterface(doc->GetWindow()));
if (!viewCSS) {
if (!viewCSS)
return;
}
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
viewCSS->GetComputedStyle(aElement, aPseudoElt, getter_AddRefs(cssDecl));
viewCSS->GetComputedStyle(domElement, aPseudoElt, getter_AddRefs(cssDecl));
NS_IF_ADDREF(*aCssDecl = cssDecl);
}

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

@ -114,7 +114,7 @@ class nsAccessNode: public nsIAccessNode,
static already_AddRefed<nsIPresShell> GetPresShellFor(nsIDOMNode *aStartNode);
static void GetComputedStyleDeclaration(const nsAString& aPseudoElt,
nsIDOMElement *aElement,
nsIDOMNode *aNode,
nsIDOMCSSStyleDeclaration **aCssDecl);
already_AddRefed<nsRootAccessible> GetRootAccessible();

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

@ -1104,10 +1104,10 @@ NS_IMETHODIMP nsAccessible::GetFocusedChild(nsIAccessible **aFocusedChild)
return NS_OK;
}
/* nsIAccessible getChildAtPoint (in long x, in long y); */
// nsIAccessible getDeepestChildAtPoint(in long x, in long y)
NS_IMETHODIMP
nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
nsAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
@ -1205,29 +1205,52 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
// Fall through -- the point is in this accessible but not in a child
// We are allowed to return |this| as the answer
}
else {
nsCOMPtr<nsIAccessible> parent;
while (PR_TRUE) {
accessible->GetParent(getter_AddRefs(parent));
if (!parent) {
// Reached the top of the hierarchy
// these bounds were inside an accessible that is not a descendant of this one
NS_IF_ADDREF(*aAccessible = fallbackAnswer);
return NS_OK;
}
if (parent == this) {
// We reached |this|, so |accessible| is the
// child we want to return
break;
}
accessible.swap(parent);
}
}
NS_IF_ADDREF(*aAccessible = accessible);
return NS_OK;
}
// nsIAccessible getChildAtPoint(in long x, in long y)
NS_IMETHODIMP
nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
{
nsresult rv = GetDeepestChildAtPoint(aX, aY, aAccessible);
NS_ENSURE_SUCCESS(rv, rv);
if (!*aAccessible)
return NS_OK;
nsCOMPtr<nsIAccessible> parent, accessible(*aAccessible);
while (PR_TRUE) {
accessible->GetParent(getter_AddRefs(parent));
if (!parent) {
NS_ASSERTION(PR_FALSE,
"Obtained accessible isn't a child of this accessible.");
// Reached the top of the hierarchy. These bounds were inside an
// accessible that is not a descendant of this one.
// If we can't find the point in a child, we will return the fallback
// answer: we return |this| if the point is within it, otherwise nsnull.
PRInt32 x, y, width, height;
GetBounds(&x, &y, &width, &height);
if (aX >= x && aX < x + width && aY >= y && aY < y + height)
NS_ADDREF(*aAccessible = this);
return NS_OK;
}
if (parent == this) {
// We reached |this|, so |accessible| is the child we want to return.
NS_ADDREF(*aAccessible = accessible);
return NS_OK;
}
accessible.swap(parent);
}
return NS_OK;
}
void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
{
/*

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

@ -247,8 +247,17 @@ nsCaretAccessible::NormalSelectionChanged(nsIDOMDocument *aDoc,
return NS_OK; // Don't fire caret moves until doc loaded
}
nsCOMPtr<nsIDOMNode> nodeWithCaret = focusNode;
// Get focused node.
nsCOMPtr<nsIContent> focusContainer(do_QueryInterface(focusNode));
if (focusContainer && focusContainer->IsNodeOfType(nsINode::eELEMENT)) {
PRInt32 focusOffset = 0;
aSel->GetFocusOffset(&focusOffset);
nsCOMPtr<nsIContent> focusContent = focusContainer->GetChildAt(focusOffset);
focusNode = do_QueryInterface(focusContent);
}
// Get relevant accessible for the focused node.
nsCOMPtr<nsIAccessibleText> textAcc;
while (focusNode) {
// Make sure to get the correct starting node for selection events inside XBL content trees
@ -307,6 +316,16 @@ nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
if (!targetNode)
return NS_OK;
// Get focused node.
nsCOMPtr<nsIContent> focusContainer(do_QueryInterface(targetNode));
if (focusContainer && focusContainer->IsNodeOfType(nsINode::eELEMENT)) {
PRInt32 focusOffset = 0;
aSel->GetFocusOffset(&focusOffset);
nsCOMPtr<nsIContent> focusContent = focusContainer->GetChildAt(focusOffset);
targetNode = do_QueryInterface(focusContent);
}
nsCOMPtr<nsIAccessibleDocument> docAccessible =
nsAccessNode::GetDocAccessibleFor(targetNode);
NS_ENSURE_STATE(docAccessible);

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

@ -67,6 +67,7 @@ nsOuterDocAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
return NS_OK;
}
// nsIAccessible::getChildAtPoint(in long x, in long y)
NS_IMETHODIMP
nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
@ -85,6 +86,23 @@ nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
return GetFirstChild(aAccessible); // Always return the inner doc unless bounds outside of it
}
// nsIAccessible::getDeepestChildAtPoint(in long x, in long y)
NS_IMETHODIMP
nsOuterDocAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
{
// Call getDeepestChildAtPoint on the fist child accessible of the outer
// document accessible if the given point is inside of outer document.
nsCOMPtr<nsIAccessible> childAcc;
nsresult rv = GetChildAtPoint(aX, aY, getter_AddRefs(childAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (!childAcc)
return NS_OK;
return childAcc->GetDeepestChildAtPoint(aX, aY, aAccessible);
}
void nsOuterDocAccessible::CacheChildren()
{
// An outer doc accessible usually has 1 nsDocAccessible child,

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

@ -54,8 +54,12 @@ class nsOuterDocAccessible : public nsAccessibleWrap
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible);
NS_IMETHOD GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible);
void CacheChildren();
nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
NS_IMETHOD GetNumActions(PRUint8 *aNumActions);

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

@ -1138,10 +1138,12 @@ NS_IMETHODIMP nsHTMLTableAccessible::IsProbablyForLayout(PRBool *aIsProbablyForL
for (PRInt32 rowCount = 0; rowCount < rows; rowCount ++) {
nsCOMPtr<nsIDOMNode> rowNode;
nodeList->Item(rowCount, getter_AddRefs(rowNode));
nsCOMPtr<nsIDOMElement> rowElement = do_QueryInterface(rowNode);
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl;
GetComputedStyleDeclaration(EmptyString(), rowElement, getter_AddRefs(styleDecl));
GetComputedStyleDeclaration(EmptyString(), rowNode,
getter_AddRefs(styleDecl));
NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
lastRowColor = color;
styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"), color);
if (rowCount > 0 && PR_FALSE == lastRowColor.Equals(color)) {

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

@ -104,7 +104,7 @@ nsHTMLTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes
GetRole(&role);
if (role == nsIAccessibleRole::ROLE_STATICTEXT) {
nsAutoString oldValueUnused;
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("static"),
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("auto-generated"),
NS_LITERAL_STRING("true"), oldValueUnused);
}

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

@ -293,22 +293,17 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
if (mIsExpired)
return nil;
// Convert from cocoa's coordinate system to gecko's. According to the docs
// the point we're given is guaranteed to be bottom-left screen coordinates.
nsPoint geckoPoint;
ConvertCocoaToGeckoPoint (point, geckoPoint);
// start iterating as deep down as we can on this point, with the current accessible as the root.
// as soon as GetChildAtPoint() returns null, or can't descend further (without getting the same accessible again)
// we stop.
nsCOMPtr<nsIAccessible> deepestFoundChild, newChild(mGeckoAccessible);
do {
deepestFoundChild = newChild;
deepestFoundChild->GetChildAtPoint((PRInt32)geckoPoint.x, (PRInt32)geckoPoint.y, getter_AddRefs(newChild));
} while (newChild && newChild.get() != deepestFoundChild.get());
nsCOMPtr<nsIAccessible> deepestFoundChild;
mGeckoAccessible->GetDeepestChildAtPoint((PRInt32)geckoPoint.x,
(PRInt32)geckoPoint.y,
getter_AddRefs(deepestFoundChild));
// if we found something, return its native accessible.
if (deepestFoundChild) {
mozAccessible *nativeChild = GetNativeFromGeckoAccessible(deepestFoundChild);

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

@ -310,13 +310,13 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
/* [out] */ unsigned short __RPC_FAR *aNumStyleProperties)
{
__try{
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
if (!domElement)
return E_FAIL;
*aNumStyleProperties = 0;
if (IsDefunct())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
GetComputedStyleDeclaration(EmptyString(), domElement, getter_AddRefs(cssDecl));
GetComputedStyleDeclaration(EmptyString(), mDOMNode, getter_AddRefs(cssDecl));
NS_ENSURE_TRUE(cssDecl, E_FAIL);
PRUint32 length;
@ -347,12 +347,11 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
/* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
{
__try {
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
if (!domElement)
if (IsDefunct())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
GetComputedStyleDeclaration(EmptyString(), domElement, getter_AddRefs(cssDecl));
GetComputedStyleDeclaration(EmptyString(), mDOMNode, getter_AddRefs(cssDecl));
NS_ENSURE_TRUE(cssDecl, E_FAIL);
PRUint32 index;

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

@ -355,6 +355,15 @@ nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
return GetCachedTreeitemAccessible(row, column, aAccessible);
}
// nsIAccessible::getDeepestChildAtPoint(in long x, in long y)
NS_IMETHODIMP
nsXULTreeAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible)
{
// Call getChildAtPoint until tree doesn't support complex content.
return GetChildAtPoint(aX, aY, aAccessible);
}
// Ask treeselection to get all selected children
NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval)
{

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

@ -71,8 +71,11 @@ public:
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
NS_IMETHOD GetChildCount(PRInt32 *_retval);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible);
NS_IMETHOD GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible);
static void GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
static nsresult GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32 *aCount);

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

@ -53,18 +53,21 @@ _TEST_FILES =\
nsIAccessible_name.css \
nsIAccessible_name.js \
nsIAccessible_name.xbl \
nsIAccessible_selects.js \
nsIAccessibleEditableText.js \
test_aria_activedescendant.html \
test_aria_role_article.html \
test_bug368835.xul \
test_bug420863.html \
test_cssattrs.html \
test_events_caretmove.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_nsIAccessible_selects.html \
test_nsIAccessible_focus.html \
test_nsIAccessibleDocument.html \
test_nsIAccessibleEditableText.html \
@ -77,6 +80,7 @@ _TEST_FILES =\
test_nsIAccessibleTable_3.html \
test_nsIAccessibleTable_4.html \
test_nsIAccessibleTable_listboxes.xul \
test_nsIAccessNode_utils.html \
test_nsOuterDocAccessible.html \
test_textattrs.html \
test_textboxes.html \

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

@ -30,6 +30,28 @@ const nsIObserverService = Components.interfaces.nsIObserverService;
const nsIDOMNode = Components.interfaces.nsIDOMNode;
////////////////////////////////////////////////////////////////////////////////
// Roles
const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
////////////////////////////////////////////////////////////////////////////////
// States
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
////////////////////////////////////////////////////////////////////////////////
// Accessible general
@ -77,16 +99,16 @@ function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj)
acc = gAccRetrieval.getAccessibleFor(elm);
} catch (e) {
}
if (!acc) {
ok(false, "Can't get accessible for " + aID);
ok(false, "Can't get accessible for " + aAccOrElmOrID);
return null;
}
}
if (!aInterfaces)
return acc;
if (aInterfaces instanceof Array) {
for (var index = 0; index < aInterfaces.length; index++) {
try {

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

@ -0,0 +1,111 @@
/**
* Tests an accessible and its children.
* The accessible is one of the following:
* - HTML:select (ROLE_COMBOBOX)
* - HTML:select @size (ROLE_LIST)
* - HTML:label containing either of the above (ROLE_LABEL)
*
* @param aID The ID of the base element to test.
* @param aNames The array of expected names for the accessible and
* its children.
* @param aRoles The array of expected roles for the accessible and
* its children.
* @param aStates The array of states to test for on each accessible.
* @param aUndesiredStates Array of states we don't want to have for each
* accessible.
*
* @note Each of the three arrays must have an equal number of elements. The
* order of elements corresponds to the order in which the tree is walked from
* the base accessible downwards.
*/
function testSelect(aID, aNames, aRoles, aStates, aUndesiredStates)
{
// used to walk the tree starting at the aID's accessible.
var acc = getAccessible(aID);
if (!acc) {
return;
}
testThis(aID, acc, aNames, aRoles, aStates, aUndesiredStates, 0);
}
/**
* Tests a single accessible.
* Recursively calls itself until it reaches the last option item.
* Called first time from the testSelect function.
*
* @param aID @see testSelect
* @param aAcc The accessible to test.
* @param aNames @see testSelect
* @param aRoles @see testSelect
* @param aStates @see testSelect
* @param aUndesiredStates @see testSelect
* @param aIndex The index in the three arrays to use. Used for both
* the error message and for walking the tree downwards
* from the base accessible.
*/
function testThis(aID, aAcc, aNames, aRoles, aStates, aUndesiredStates, aIndex)
{
if (aIndex >= aNames.length)
return; // End of test
else if (!aAcc) {
ok(false, "No accessible for " + aID + " at index " + aIndex + "!");
return;
}
is(aAcc.name, aNames[aIndex],
"wrong name for " + aID + " at index " + aIndex + "!");
var role = aAcc.role;
is(role, aRoles[aIndex],
"Wrong role for " + aID + " at index " + aIndex + "!");
testStates(aID, aAcc, aStates, aUndesiredStates, aIndex);
switch(role) {
case ROLE_COMBOBOX:
case ROLE_COMBOBOX_LIST:
case ROLE_LABEL:
case ROLE_LIST:
// All of these expect the next item to be the first child of the current
// accessible.
var acc = null;
try {
acc = aAcc.firstChild;
} catch(e) {}
testThis(aID, acc, aNames, aRoles, aStates, aUndesiredStates, ++aIndex);
break;
case ROLE_COMBOBOX_OPTION:
case ROLE_OPTION:
case ROLE_TEXT_LEAF:
// All of these expect the next item's accessible to be the next sibling.
var acc = null;
try {
acc = aAcc.nextSibling;
} catch(e) {}
testThis(aID, acc, aNames, aRoles, aStates, aUndesiredStates, ++aIndex);
break;
default:
break;
}
}
/**
* Tests the states for the given accessible.
* Does not test for extraStates since we don't need these.
*
* @param aID the ID of the base element.
* @param aAcc the current accessible from the recursive algorithm.
* @param aStates the states array passed down from the testThis function.
* @param aUndesiredStates the array of states we don't want to see, if any.
* @param aIndex the index of the item to test, determined and passed in from
* the testThis function.
*/
function testStates(aID, aAcc, aStates, aUndesiredStates, aIndex)
{
var state = {}, extraState = {};
aAcc.getFinalState(state, extraState);
if (aStates[aIndex] != 0)
is(state.value & aStates[aIndex], aStates[aIndex],
"Wrong state bits for " + aID + " at index " + aIndex + "!");
if (aUndesiredStates[aIndex] != 0)
is(state.value & aUndesiredStates[aIndex], 0,
"Wrong undesired state bits for " + aID + " at index " + aIndex + "!");
}

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

@ -1,28 +1,16 @@
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
// Mapping needed state flags for easier handling.
const state_focusable =
Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
const state_focused =
Components.interfaces.nsIAccessibleStates.STATE_FOCUSED;
const state_readonly =
Components.interfaces.nsIAccessibleStates.STATE_READONLY;
const state_focusable = nsIAccessibleStates.STATE_FOCUSABLE;
const state_focused = nsIAccessibleStates.STATE_FOCUSED;
const state_readonly = nsIAccessibleStates.STATE_READONLY;
const ext_state_multi_line =
Components.interfaces.nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const ext_state_editable =
Components.interfaces.nsIAccessibleStates.EXT_STATE_EDITABLE;
const ext_state_required =
Components.interfaces.nsIAccessibleStates.STATE_REQUIRED;
const ext_state_invalid =
Components.interfaces.nsIAccessibleStates.STATE_INVALID;
const ext_state_multi_line = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const ext_state_editable = nsIAccessibleStates.EXT_STATE_EDITABLE;
const ext_state_required = nsIAccessibleStates.STATE_REQUIRED;
const ext_state_invalid = nsIAccessibleStates.STATE_INVALID;
// Mapping needed final roles
const role_entry = Components.interfaces.nsIAccessibleRole.ROLE_ENTRY;
const role_password_text =
Components.interfaces.nsIAccessibleRole.ROLE_PASSWORD_TEXT;
var gAccRetrieval = null;
const role_entry = nsIAccessibleRole.ROLE_ENTRY;
const role_password_text = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
function testValue(aID, aAcc, aValue, aRole)
{

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

@ -105,13 +105,13 @@
"nsITreeBoxObject::rowCountChanged");
break;
case 2:
TreeInvalidatedHandlerHelper(aEvent, null, null, 0, 0,
"nsITreeBoxObject::invalidateColumn");
// XXX see bug 454647 TreeInvalidatedHandlerHelper(aEvent, null, null, 0, 0,
// "nsITreeBoxObject::invalidateColumn");
gTreeColumnInvalidated = true;
break;
case 3:
TreeInvalidatedHandlerHelper(aEvent, 1, 1, null, null,
"nsITreeBoxObject::invalidateRow");
// XXX see bug 454647 TreeInvalidatedHandlerHelper(aEvent, 1, 1, null, null,
// "nsITreeBoxObject::invalidateRow");
gTreeRowInvalidated = true;
break;
}

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

@ -0,0 +1,130 @@
<html>
<head>
<title>Accessible caret move events testing</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/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript">
function synthMouseTest(aNode)
{
this.node = aNode;
this.testFunc = function testFunc()
{
synthesizeMouse(this.node, 1, 1, {});
}
}
function synthKeyTest(aNode, aKey)
{
this.node = aNode;
this.testFunc = function testFunc()
{
synthesizeKey(aKey, {});
}
}
function synthTabTest(aNode, aBackTab)
{
this.node = aNode;
this.testFunc = function testFunc()
{
synthesizeKey("VK_TAB", {shiftKey: aBackTab});
}
}
var gTestsArray = [];
var gTestIdx = -1;
var gCaretMoveHandler =
{
handleEvent: function handleEvent(aEvent)
{
if (aEvent.DOMNode == gTestsArray[gTestIdx].node)
gTestsArray[gTestIdx].wasCaught = true;
}
};
function doTest()
{
window.setTimeout(
function()
{
if (gTestIdx == gTestsArray.length - 1) {
unregisterA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED,
gCaretMoveHandler);
for (var idx = 0; idx < gTestsArray.length; idx++)
ok(gTestsArray[idx].wasCaught, "test " + idx + " failed");
SimpleTest.finish();
return;
}
gTestsArray[++gTestIdx].testFunc();
doTest();
},
100
);
}
function doTests()
{
var textbox = document.getElementById("textbox");
gTestsArray.push(new synthMouseTest(textbox));
gTestsArray.push(new synthKeyTest(textbox, "VK_RIGHT"));
var textarea = document.getElementById("textarea");
gTestsArray.push(new synthMouseTest(textarea));
gTestsArray.push(new synthKeyTest(textarea, "VK_RIGHT"));
gTestsArray.push(new synthKeyTest(textarea, "VK_DOWN"));
var p = document.getElementById("p");
gTestsArray.push(new synthMouseTest(p));
gTestsArray.push(new synthKeyTest(p, "VK_RIGHT"));
gTestsArray.push(new synthKeyTest(p, "VK_DOWN"));
gTestsArray.push(new synthTabTest(textarea, true));
gTestsArray.push(new synthTabTest(p));
registerA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED,
gCaretMoveHandler);
doTest();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=454377"
title="Accessible caret move events testing">
Mozilla Bug 454377
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="textbox" value="hello"/>
<textarea id="textarea">text<br>text</textarea>
<p id="p" contentEditable="true"><span>text</span><br/>text</p>
</body>
</html>

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

@ -0,0 +1,55 @@
<html>
<head>
<title>nsIAccessNode util methods testing</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">
function doTest()
{
var elmObj = {};
var acc = getAccessible("span", [nsIAccessNode], elmObj);
computedStyle = document.defaultView.getComputedStyle(elmObj.value, "");
// html:span element
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
"Wrong color for element with ID 'span'");
// text child of html:span element
acc = getAccessible(acc.firstChild, [nsIAccessNode]);
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
"Wrong color for text child of element with ID 'span'");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=454211"
title="nsIAccessNode util methods testing">
Mozilla Bug 454211
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<span role="description" style="color: red" id="span">text</span>
</body>
</html>

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

@ -56,7 +56,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
testThis("imgmap", 78, 3, "b");
// empty hyperlink
testThis("emptyLink", 93, 4, "");
// XXX see bug 434636 testThis("emptyLink", 93, 4, "");
// normal hyperlink with embedded span
testThis("LinkWithSpan", 119, 5, "Heise Online");

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

@ -98,8 +98,14 @@
var states = {}, extraStates = {};
aFocusMgr.mAcc.getFinalState(states, extraStates);
ok(states.value & nsIAccessibleStates.STATE_FOCUSED,
"No focused state for element with ID " + aFocusMgr.mName + ".");
// XXX see bug 455840. Only fails on aria-link, the other two are OK.
// When fixing this bug, remove the if statement and else block and "todo" statement.
if (states.value & nsIAccessibleStates.STATE_FOCUSED)
ok(states.value & nsIAccessibleStates.STATE_FOCUSED,
"No focused state for element with ID " + aFocusMgr.mName + ".");
else
todo(states.value & nsIAccessibleStates.STATE_FOCUSED,
"No focused state for element with ID " + aFocusMgr.mName + ".");
aFocusMgr.mCallback();
}, 0, this);

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

@ -0,0 +1,210 @@
<html>
<head>
<title>nsIAccessible selects 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/nsIAccessible_selects.js"></script>
<script type="application/javascript">
function doTest()
{
// Label and combo, separate tags
var names = [
"Foo:", // combobox
"Foo:", // combobox list
"item 1", // first item
"item 2" // second item
];
var roles = [
ROLE_COMBOBOX, // root
ROLE_COMBOBOX_LIST, // list accessible
ROLE_COMBOBOX_OPTION, // first option
ROLE_COMBOBOX_OPTION // second option
];
var states = [
(STATE_FOCUSABLE | STATE_HASPOPUP | STATE_COLLAPSED), // combobox
(0), // combobox_list
(STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE | STATE_FOCUSED),
(STATE_SELECTABLE | STATE_FOCUSABLE) // second item, not focused
];
var undesiredStates = [
(STATE_FOCUSED), // combobox
(STATE_FOCUSED), // combobox_list
(0), // first item
(STATE_SELECTED | STATE_FOCUSED) // second, not currently focused, item
];
testSelect("combo1", names, roles, states, undesiredStates);
// Select nested within label element.
// XXX see bug 455482: The accName for the label, combobox, and
// combobox_list contains the label text and the names of each option.
// When fixing bug 455482, please fix below names and remove this comment.
names = [
"Search in: Newsticker Entire site", // label
"Search in:", // text leaf
"Search in: Newsticker Entire site", // combobox
"Search in: Newsticker Entire site", // combobox_list
"Newsticker", // option 1
"Entire site" // Option 2
];
roles = [
ROLE_LABEL, // root
ROLE_TEXT_LEAF, // inner text
ROLE_COMBOBOX, // combobox accessible
ROLE_COMBOBOX_LIST, // list accessible
ROLE_COMBOBOX_OPTION, // first option
ROLE_COMBOBOX_OPTION // second option
];
states = [
(0), // label
(0), // text leaf
(STATE_FOCUSABLE | STATE_HASPOPUP | STATE_COLLAPSED), // combobox
(0), // combobox_list
(STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE | STATE_FOCUSED),
(STATE_SELECTABLE | STATE_FOCUSABLE) // second item, not focused
];
undesiredStates = [
(0), // label
(0), // text leaf
(STATE_FOCUSED), // combobox
(STATE_FOCUSED), // combobox_list
(0), // first item
(STATE_SELECTED | STATE_FOCUSED) // second, not currently focused, item
];
testSelect("combo2", names, roles, states, undesiredStates);
// select @size with label as separate tags.
names = [
"Component:", // list
"Build", // item 1
"Disability Access APIs", // item 2
"General", // item 3
"UI" // item 4
];
roles = [
ROLE_LIST, // root
ROLE_OPTION, // item 1
ROLE_OPTION, // item 2
ROLE_OPTION, // item 4
ROLE_OPTION // item 4
];
states = [
(STATE_FOCUSABLE), // list
(STATE_SELECTABLE | STATE_FOCUSABLE | STATE_FOCUSED),
(STATE_SELECTABLE | STATE_FOCUSABLE), // second item, not focused
(STATE_SELECTABLE | STATE_FOCUSABLE), // third item, not focused
(STATE_SELECTABLE | STATE_FOCUSABLE) // fourth item, not focused
];
undesiredStates = [
(STATE_FOCUSED), // listbox
(STATE_SELECTED), // first item
(STATE_SELECTED | STATE_FOCUSED), // second, not currently focused, item
(STATE_SELECTED | STATE_FOCUSED), // third, not currently focused, item
(STATE_SELECTED | STATE_FOCUSED) // fourth, not currently focused, item
];
testSelect("list1", names, roles, states, undesiredStates);
// Select @size nested within label element.
// XXX see bug 455482: The accName for the label and listbox
// contains the label text and the names of each option.
// When fixing bug 455482, please fix below names and remove this comment.
names = [
"Version: 2.0 3.0 3.1 trunk", // label
"Version:", // text leaf
"Version: 2.0 3.0 3.1 trunk", // list
"2.0", // option 1
"3.0", // Option 2
"3.1", // Option 3
"trunk" // Option 4
];
roles = [
ROLE_LABEL, // root
ROLE_TEXT_LEAF, // inner text
ROLE_LIST, // listbox accessible
ROLE_OPTION, // first option
ROLE_OPTION, // second option
ROLE_OPTION, // third option
ROLE_OPTION // fourth option
];
states = [
(0), // label
(0), // text leaf
(STATE_FOCUSABLE), // listbox
(STATE_SELECTABLE | STATE_FOCUSABLE | STATE_FOCUSED), // Option 1
(STATE_SELECTABLE | STATE_FOCUSABLE), // second item, not focused
(STATE_SELECTABLE | STATE_FOCUSABLE), // third item, not focused
(STATE_SELECTABLE | STATE_FOCUSABLE) // fourth item, not focused
];
undesiredStates = [
(0), // label
(0), // text leaf
(STATE_FOCUSED | STATE_HASPOPUP | STATE_COLLAPSED), // listbox
(STATE_SELECTED), // first item
(STATE_SELECTED | STATE_FOCUSED), // second, not currently focused, item
(STATE_SELECTED | STATE_FOCUSED), // third, not currently focused, item
(STATE_SELECTED | STATE_FOCUSED) // fourth, not currently focused, item
];
testSelect("list2", names, roles, states, undesiredStates);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=443889"
title="mochitest for selects and lists">
Mozilla Bug 443889
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<form action="post.php" method="post">
<!-- Label and select separate tags -->
<label for="combo1">Foo:</label>
<select id="combo1" name="combo1">
<option>item 1</option>
<option>item 2</option>
</select><br />
<!-- Select embedded in label -->
<label id="combo2">Search in:<select name="search">
<option>Newsticker</option>
<option>Entire site</option>
</select></label><br />
<!-- Label and select @size -->
<label for="list1">Component:</label>
<select id="list1" name="component" size="3">
<option>Build</option>
<option>Disability Access APIs</option>
<option>General</option>
<option>UI</option>
</select><br />
<!-- Select @size nested within label -->
<label id="list2">Version:<select name="version" size="3">
<option>2.0</option>
<option>3.0</option>
<option>3.1</option>
<option>trunk</option>
</select></label><br />
</form>
</body>
</html>

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

@ -52,7 +52,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=441519
"Wrong focusable state bit for internal frame!");
// see bug 428954: No name wanted for internal frame
is(outerDocAcc.name, "", "Wrong name for internal frame!");
// xxx see bug 454636 is(outerDocAcc.name, "", "Wrong name for internal frame!");
// see bug 440770, no actions wanted on outer doc
is(outerDocAcc.numActions, 0,

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

@ -17,6 +17,7 @@
const nsIObserverService = Components.interfaces.nsIObserverService;
var gAccRetrieval = null;
var gComputedStyle = null;
/**
* Test text attributes.
@ -176,16 +177,17 @@
window.setTimeout(function()
{
gComputedStyle = document.defaultView.getComputedStyle(node, "");
var defAttrs = {
"font-style": "normal",
"text-align": "start",
"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"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": gComputedStyle.backgroundColor,
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
@ -218,16 +220,18 @@
//////////////////////////////////////////////////////////////////////////
// area1
var ID = "area1";
var tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
var defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
@ -235,7 +239,9 @@
var attrs = {};
testTextAttrs(ID, 0, attrs, 0, 7);
attrs = {"font-weight": "401"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"font-weight": gComputedStyle.fontWeight};
testTextAttrs(ID, 7, attrs, 7, 11);
attrs = {};
@ -244,16 +250,18 @@
//////////////////////////////////////////////////////////////////////////
// area2
ID = "area2";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX bug 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
@ -261,12 +269,19 @@
attrs = {};
testTextAttrs(ID, 0, attrs, 0, 7);
attrs = {"font-weight": "401"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"font-weight": gComputedStyle.fontWeight};
testTextAttrs(ID, 7, attrs, 7, 12);
attrs = {"font-style": "italic", "font-weight": "401"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"font-style": gComputedStyle.fontStyle,
"font-weight": gComputedStyle.fontWeight};
testTextAttrs(ID, 13, attrs, 12, 19);
tempElem = tempElem.parentNode;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"font-weight": "401"};
testTextAttrs(ID, 20, attrs, 19, 23);
@ -276,82 +291,107 @@
//////////////////////////////////////////////////////////////////////////
// area3
ID = "area3";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(0, 0, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": gComputedStyle.backgroundColor,
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
attrs = {"color": "rgb(0, 128, 0)"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, 0, 6);
attrs = {"color": "rgb(255, 0, 0)"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 6, attrs, 6, 26);
attrs = {"color": "rgb(0, 128, 0)"};
tempElem = tempElem.parentNode;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 26, attrs, 26, 27);
attrs = {"color": "rgb(0, 128, 0)", "background-color": "rgb(255, 255, 0)"};
tempElem = tempElem.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color,
"background-color": gComputedStyle.backgroundColor};
testTextAttrs(ID, 27, attrs, 27, 50);
//////////////////////////////////////////////////////////////////////////
// area4
ID = "area4";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX bug 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
attrs = {"color": "rgb(0, 128, 0)"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, 0, 16);
attrs = {"color": "rgb(255, 0, 0)"};
tempElem = tempElem.nextSibling.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 16, attrs, 16, 33);
attrs = {"color": "rgb(0, 128, 0)"};
tempElem = tempElem.parentNode;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 34, attrs, 33, 46);
//////////////////////////////////////////////////////////////////////////
// area5
ID = "area5";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX bug 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
attrs = {"color": "rgb(0, 128, 0)"};
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 0, attrs, 0, 5);
attrs = {};
testTextAttrs(ID, 7, attrs, 5, 8);
attrs = {"color": "rgb(255, 0, 0)"};
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 9, attrs, 8, 11);
attrs = {};
@ -360,16 +400,18 @@
//////////////////////////////////////////////////////////////////////////
// area6 (CSS vertical-align property, bug 445938)
ID = "area6";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX bug 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
@ -377,40 +419,52 @@
attrs = {};
testTextAttrs(ID, 0, attrs, 0, 5);
attrs = {"text-position": "super", "font-size": "13px" };
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"text-position": gComputedStyle.verticalAlign,
"font-size": gComputedStyle.fontSize};
testTextAttrs(ID, 5, attrs, 5, 13);
attrs = {};
testTextAttrs(ID, 13, attrs, 13, 27);
attrs = {"text-position": "super" };
tempElem = tempElem.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"text-position": gComputedStyle.verticalAlign};
testTextAttrs(ID, 27, attrs, 27, 35);
attrs = {};
testTextAttrs(ID, 35, attrs, 35, 39);
attrs = {"text-position": "sub", "font-size": "13px" };
tempElem = tempElem.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"text-position": gComputedStyle.verticalAlign,
"font-size": gComputedStyle.fontSize};
testTextAttrs(ID, 39, attrs, 39, 50);
attrs = {};
testTextAttrs(ID, 50, attrs, 50, 55);
attrs = {"text-position": "sub" };
tempElem = tempElem.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"text-position": gComputedStyle.verticalAlign};
testTextAttrs(ID, 55, attrs, 55, 64);
//////////////////////////////////////////////////////////////////////////
// area7
ID = "area7";
tempElem = document.getElementById(ID);
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
"font-style": gComputedStyle.fontStyle,
"text-align": gComputedStyle.textAlign,
"font-size": gComputedStyle.fontSize,
"background-color": "rgb(0, 0, 0)", // XXX 455834
"font-weight": gComputedStyle.fontWeight,
"text-indent": gComputedStyle.textIndent,
"color": gComputedStyle.color,
"font-family": gComputedStyle.fontFamily,
"text-position": gComputedStyle.verticalAlign
};
testDefaultTextAttrs(ID, defAttrs);
@ -421,7 +475,10 @@
attrs = {"language": "en"};
testTextAttrs(ID, 12, attrs, 12, 13);
attrs = {"language" :"en", "background-color": "rgb(0, 0, 255)"};
tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"language" :"en",
"background-color": gComputedStyle.backgroundColor};
testTextAttrs(ID, 13, attrs, 13, 26);
attrs = {"language": "en" };
@ -436,13 +493,20 @@
attrs = {};
testTextAttrs(ID, 43, attrs, 43, 50);
attrs = {"color": "rgb(255, 0, 255)"};
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 50, attrs, 50, 57);
attrs = {"font-weight": "401", "color": "rgb(255, 0, 255)" };
tempElem = tempElem.firstChild.nextSibling;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"font-weight": gComputedStyle.fontWeight,
"color": gComputedStyle.color};
testTextAttrs(ID, 57, attrs, 57, 61);
attrs = {"color": "rgb(255, 0, 255)"};
tempElem = tempElem.parentNode;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 61, attrs, 61, 68);
//////////////////////////////////////////////////////////////////////////

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

@ -7,17 +7,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
<title>nsIAccessible textboxes 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/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/testTextboxes.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/testTextboxes.js"></script>
<script type="application/javascript">
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
//////////////////////////////////////////////////////////////////////////
// normal textbox without content and with no proper label
testThis("unlabelled_Textbox", // ID

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

@ -12,15 +12,14 @@
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/testTextboxes.js"></script>
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/testTextboxes.js" />
<script type="application/javascript">
<![CDATA[
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
//////////////////////////////////////////////////////////////////////////
// normal textbox without content and with no proper label
testThis("unlabelled_Textbox", // ID

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

@ -72,12 +72,18 @@ GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBX
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
ifdef MOZ_MEMORY
ifneq ($(OS_ARCH),WINNT)
LIBS += -ljemalloc
SOURCE_STAMP := $(shell hg identify -i $(topsrcdir) 2>/dev/null)
ifdef SOURCE_STAMP
DEFINES += -DMOZ_SOURCE_STAMP="$(SOURCE_STAMP)"
endif
SOURCE_REPO := $(shell hg -R $(topsrcdir) showconfig paths.default 2>/dev/null | sed s/^ssh:/http:/)
ifdef SOURCE_REPO
DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
endif
LIBS += $(JEMALLOC_LIBS)
ifdef LIBXUL_SDK
include $(topsrcdir)/config/rules.mk
else
@ -117,11 +123,18 @@ ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
TK_LIBS := $(TK_LIBS)
endif
ifdef MOZ_ENABLE_LIBXUL
APP_XPCOM_LIBS = $(XPCOM_GLUE_LDOPTS)
else
MOZILLA_INTERNAL_API = 1
APP_XPCOM_LIBS = $(XPCOM_LIBS)
endif
LIBS += \
$(STATIC_COMPONENTS_LINKER_PATH) \
$(EXTRA_DSO_LIBS) \
$(MOZ_JS_LIBS) \
$(XPCOM_GLUE_LDOPTS) \
$(APP_XPCOM_LIBS) \
$(NSPR_LIBS) \
$(TK_LIBS) \
$(NULL)

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

@ -41,6 +41,12 @@ Vendor=Mozilla
Name=Firefox
Version=@APP_VERSION@
BuildID=@GRE_BUILDID@
#ifdef MOZ_SOURCE_REPO
SourceRepository=@MOZ_SOURCE_REPO@
#endif
#ifdef MOZ_SOURCE_STAMP
SourceStamp=@MOZ_SOURCE_STAMP@
#endif
Copyright=Copyright (c) 1998 - 2008 mozilla.org
ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}

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

@ -309,8 +309,7 @@ pref("browser.link.open_newwindow", 3);
pref("browser.link.open_newwindow.restriction", 2);
// Tabbed browser
pref("browser.tabs.autoHide", true);
pref("browser.tabs.forceHide", false);
pref("browser.tabs.autoHide", false);
pref("browser.tabs.warnOnClose", true);
pref("browser.tabs.warnOnOpen", true);
pref("browser.tabs.maxOpenBeforeWarn", 15);
@ -338,6 +337,7 @@ pref("browser.tabs.closeButtons", 1);
pref("browser.tabs.selectOwnerOnClose", true);
pref("browser.ctrlTab.mostRecentlyUsed", true);
pref("browser.ctrlTab.recentlyUsedLimit", 7);
pref("browser.ctrlTab.smoothScroll", true);
// Default bookmark sorting
@ -695,15 +695,6 @@ pref("browser.sessionstore.max_tabs_undo", 10);
// allow META refresh by default
pref("accessibility.blockautorefresh", false);
// If true, will migrate uri post-data annotations to
// bookmark post-data annotations (bug 398914)
// XXX to be removed after beta 2 (bug 391419)
pref("browser.places.migratePostDataAnnotations", true);
// If true, will update the Smart Bookmarks uri for
// recent tags (bug 385245). Useful just for FX3 beta users.
pref("browser.places.updateRecentTagsUri", true);
// the (maximum) number of the recent visits to sample
// when calculating frecency
pref("places.frecency.numVisits", 10);

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

@ -384,7 +384,7 @@
key="showAllHistoryKb"
#endif
command="Browser:ShowAllHistory"/>
<menuseparator id="startHistorySeparator" builder="start"/>
<menuseparator id="startHistorySeparator"/>
<menuseparator id="endHistorySeparator" builder="end"/>
<menu id="historyUndoMenu" label="&historyUndoMenu.label;" disabled="true">
<menupopup id="historyUndoPopup" onpopupshowing="HistoryMenu.populateUndoSubmenu();"/>
@ -396,7 +396,8 @@
label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;"
ondragenter="PlacesMenuDNDController.onBookmarksMenuDragEnter(event);"
ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDropHandler);"
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDropHandler);">
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDropHandler);"
ondragexit="nsDragAndDrop.dragExit(event, BookmarksMenuDropHandler);">
<menupopup id="bookmarksMenuPopup"
type="places"
place="place:folder=BOOKMARKS_MENU"
@ -437,7 +438,7 @@
context="placesContext"
onpopupshowing="BookmarksEventHandler.onPopupShowing(event);"/>
</menu>
<menuseparator builder="start"/>
<menuseparator/>
</menupopup>
</menu>

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

@ -711,7 +711,6 @@ var BookmarksEventHandler = {
if (!target._endOptSeparator) {
// create a separator before options
target._endOptSeparator = document.createElement("menuseparator");
target._endOptSeparator.setAttribute("builder", "end");
target._endMarker = target.childNodes.length;
target.appendChild(target._endOptSeparator);
}
@ -789,7 +788,8 @@ var BookmarksMenuDropHandler = {
* state.
*/
onDragOver: function BMDH_onDragOver(event, flavor, session) {
session.canDrop = this.canDrop(event, session);
if (!this.canDrop(event, session))
event.dataTransfer.effectAllowed = "none";
},
/**
@ -812,6 +812,8 @@ var BookmarksMenuDropHandler = {
* otherwise.
*/
canDrop: function BMDH_canDrop(event, session) {
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, -1);
return ip && PlacesControllerDragHelper.canDrop(ip);
},
@ -826,9 +828,21 @@ var BookmarksMenuDropHandler = {
* The active DragSession
*/
onDrop: function BMDH_onDrop(event, data, session) {
// Put the item at the end of bookmark menu
var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, -1);
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
// Put the item at the end of bookmark menu
var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, -1,
Ci.nsITreeView.DROP_ON);
PlacesControllerDragHelper.onDrop(ip);
},
/**
* Called when drop target leaves the menu or after a drop.
* @param aEvent
* A drop event
*/
onDragExit: function BMDH_onDragExit(event, session) {
PlacesControllerDragHelper.currentDataTransfer = null;
}
};
@ -903,8 +917,9 @@ var PlacesMenuDNDController = {
*` menu-toolbarbutton), false otherwise.
*/
_isContainer: function PMDC__isContainer(node) {
return node.localName == "menu" ||
node.localName == "toolbarbutton" && node.getAttribute("type") == "menu";
return node.localName == "menu" ||
(node.localName == "toolbarbutton" &&
node.getAttribute("type") == "menu");
},
/**
@ -1009,62 +1024,3 @@ var PlacesStarButton = {
onItemVisited: function() { },
onItemMoved: function() { }
};
/**
* Various migration tasks.
*/
function placesMigrationTasks() {
// bug 398914 - move all post-data annotations from URIs to bookmarks
// XXX - REMOVE ME FOR BETA 3 (bug 391419)
if (gPrefService.getBoolPref("browser.places.migratePostDataAnnotations")) {
const annosvc = PlacesUtils.annotations;
var bmsvc = PlacesUtils.bookmarks;
const oldPostDataAnno = "URIProperties/POSTData";
var pages = annosvc.getPagesWithAnnotation(oldPostDataAnno, {});
for (let i = 0; i < pages.length; i++) {
try {
let uri = pages[i];
var postData = annosvc.getPageAnnotation(uri, oldPostDataAnno);
// We can't know which URI+keyword combo this postdata was for, but
// it's very likely that if this URI is bookmarked and has a keyword
// *and* the URI has postdata, then this bookmark was using the
// postdata. Propagate the annotation to all bookmarks for this URI
// just to be safe.
let bookmarks = bmsvc.getBookmarkIdsForURI(uri, {});
for (let i = 0; i < bookmarks.length; i++) {
var keyword = bmsvc.getKeywordForBookmark(bookmarks[i]);
if (keyword)
annosvc.setItemAnnotation(bookmarks[i], POST_DATA_ANNO, postData, 0, annosvc.EXPIRE_NEVER);
}
// Remove the old annotation.
annosvc.removePageAnnotation(uri, oldPostDataAnno);
} catch(ex) {}
}
gPrefService.setBoolPref("browser.places.migratePostDataAnnotations", false);
}
if (gPrefService.getBoolPref("browser.places.updateRecentTagsUri")) {
var oldUriSpec = "place:folder=TAGS&group=3&queryType=1" +
"&applyOptionsToContainers=1&sort=12&maxResults=10";
var maxResults = 10;
var newUriSpec = "place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
"&maxResults=" + maxResults;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var oldUri = ios.newURI(oldUriSpec, null, null);
var newUri = ios.newURI(newUriSpec, null, null);
let bmsvc = PlacesUtils.bookmarks;
let bookmarks = bmsvc.getBookmarkIdsForURI( oldUri, {});
for (let i = 0; i < bookmarks.length; i++) {
bmsvc.changeBookmarkURI( bookmarks[i], newUri);
}
gPrefService.setBoolPref("browser.places.updateRecentTagsUri", false);
}
}

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

@ -42,9 +42,9 @@
* Tab previews utility, produces thumbnails
*/
var tabPreviews = {
aspectRatio: 0.6875, // 16:11
aspectRatio: 0.5625, // 16:9
init: function () {
this.width = Math.ceil(screen.availWidth / 7);
this.width = Math.ceil(screen.availWidth / 5);
this.height = Math.round(this.width * this.aspectRatio);
gBrowser.tabContainer.addEventListener("TabSelect", this, false);
@ -64,16 +64,19 @@ var tabPreviews = {
return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy"));
},
capture: function (aTab, aStore) {
var win = aTab.linkedBrowser.contentWindow;
var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
thumbnail.mozOpaque = true;
thumbnail.height = this.height;
thumbnail.width = this.width;
var ctx = thumbnail.getContext("2d");
var widthScale = this.width / win.innerWidth;
ctx.scale(widthScale, widthScale);
var win = aTab.linkedBrowser.contentWindow;
var snippetWidth = win.innerWidth * .6;
var scale = this.width / snippetWidth;
ctx.scale(scale, scale);
ctx.drawWindow(win, win.scrollX, win.scrollY,
win.innerWidth, win.innerWidth * this.aspectRatio, "rgb(255,255,255)");
snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)");
var data = thumbnail.toDataURL("image/jpeg", "quality=60");
if (aStore) {
aTab.__thumbnail = data;
@ -111,7 +114,6 @@ var tabPreviews = {
* Ctrl-Tab panel
*/
var ctrlTab = {
tabs: null,
visibleCount: 3,
_uniqid: 0,
get panel () {
@ -152,10 +154,17 @@ var ctrlTab = {
.getAttribute("key")
.toLowerCase().charCodeAt(0);
},
get recentlyUsedLimit () {
delete this.recentlyUsedLimit;
return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit");
},
get smoothScroll () {
delete this.smoothScroll;
return this.smoothScroll = gPrefService.getBoolPref("browser.ctrlTab.smoothScroll");
},
get tabCount () {
return gBrowser.mTabs.length;
},
get offscreenStart () {
return Array.indexOf(this.container.childNodes, this.selected) - 1;
},
@ -169,16 +178,11 @@ var ctrlTab = {
return this.panel.state == "open" || this.panel.state == "showing";
},
init: function () {
if (this.tabs)
if (this._recentlyUsedTabs)
return;
this._recentlyUsedTabs = [gBrowser.selectedTab];
var tabContainer = gBrowser.tabContainer;
this.tabs = [];
Array.forEach(tabContainer.childNodes, function (tab) {
this.attachTab(tab, tab == gBrowser.selectedTab);
}, this);
tabContainer.addEventListener("TabOpen", this, false);
tabContainer.addEventListener("TabSelect", this, false);
tabContainer.addEventListener("TabClose", this, false);
@ -187,7 +191,7 @@ var ctrlTab = {
document.addEventListener("keypress", this, false);
},
uninit: function () {
this.tabs = null;
this._recentlyUsedTabs = null;
var tabContainer = gBrowser.tabContainer;
tabContainer.removeEventListener("TabOpen", this, false);
@ -348,12 +352,12 @@ var ctrlTab = {
advanceSelected: function () {
// regardless of visibleCount, the new highlighted tab will be
// the first or third-visible tab, depending on whether Shift is pressed
var index = ((this.invertDirection ? 0 : 2) + this.offscreenStart + this.tabs.length)
% this.tabs.length;
var index = ((this.invertDirection ? 0 : 2) + this.offscreenStart + this.tabCount)
% this.tabCount;
if (index < 2)
index += this.tabs.length;
index += this.tabCount;
if (index > this.container.childNodes.length - this.visibleCount + 1)
index -= this.tabs.length;
index -= this.tabCount;
this.selected = this.container.childNodes[index];
},
arrangeBoxes: function () {
@ -372,13 +376,14 @@ var ctrlTab = {
this.arrange(i);
},
addOffscreenBox: function (aAtStart) {
if (this.container.childNodes.length < this.tabs.length + this.visibleCount + 1 &&
if (this.container.childNodes.length < this.tabCount + this.visibleCount + 1 &&
!(aAtStart ? this.offscreenStart : this.offscreenEnd)) {
let tabs = this.getTabList();
let i = aAtStart ?
this.tabs.indexOf(this.container.firstChild._tab) - 1:
this.tabs.indexOf(this.container.lastChild._tab) + 1;
i = (i + this.tabs.length) % this.tabs.length;
this.addPreview(this.addBox(aAtStart), this.tabs[i]);
tabs.indexOf(this.container.firstChild._tab) - 1:
tabs.indexOf(this.container.lastChild._tab) + 1;
i = (i + tabs.length) % tabs.length;
this.addPreview(this.addBox(aAtStart), tabs[i]);
}
},
arrange: function (aIndex) {
@ -422,19 +427,36 @@ var ctrlTab = {
}
XULBrowserWindow.setOverLink(value, null);
},
attachTab: function (aTab, aSelected) {
if (aSelected)
this.tabs.unshift(aTab);
getTabList: function () {
var list = Array.slice(gBrowser.mTabs);
for (let i = 0; i < gBrowser.tabContainer.selectedIndex; i++)
list.push(list.shift());
if (!this._useTabBarOrder && this.recentlyUsedLimit > 0) {
let recentlyUsedTabs = this._recentlyUsedTabs.slice(0, this.recentlyUsedLimit);
for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) {
list.splice(list.indexOf(recentlyUsedTabs[i]), 1);
list.unshift(recentlyUsedTabs[i]);
}
}
return list;
},
attachTab: function (aTab, aPos) {
if (aPos == 0)
this._recentlyUsedTabs.unshift(aTab);
else if (aPos)
this._recentlyUsedTabs.splice(aPos, 0, aTab);
else
this.tabs.push(aTab);
this._recentlyUsedTabs.push(aTab);
},
detachTab: function (aTab) {
var i = this.tabs.indexOf(aTab);
var i = this._recentlyUsedTabs.indexOf(aTab);
if (i >= 0)
this.tabs.splice(i, 1);
this._recentlyUsedTabs.splice(i, 1);
},
open: function () {
this._deferOnTabSelect = [];
if (this.invertDirection)
this._useTabBarOrder = true;
document.addEventListener("keyup", this, false);
document.addEventListener("keydown", this, false);
@ -447,9 +469,12 @@ var ctrlTab = {
// display $visibleCount tabs, starting with the first or
// the second to the last tab, depending on whether Shift is pressed
for (let index = this.invertDirection ? this.tabs.length - 2 : 0,
i = this.visibleCount; i > 0; i--)
this.addPreview(this.addBox(), this.tabs[index++ % this.tabs.length]);
{
let tabs = this.getTabList();
let index = this.invertDirection ? tabs.length - 2 : 0;
for (let i = this.visibleCount; i > 0; i--)
this.addPreview(this.addBox(), tabs[index++ % tabs.length]);
}
// regardless of visibleCount, highlight the second-visible tab
this.selected = this.container.childNodes[1];
@ -465,9 +490,9 @@ var ctrlTab = {
this.invertDirection = event.shiftKey;
if (isOpen)
this.scroll();
else if (this.tabs.length == 2)
gBrowser.selectedTab = this.tabs[1];
else if (this.tabs.length > 2)
else if (this.tabCount == 2)
gBrowser.selectedTab = this.getTabList()[1];
else if (this.tabCount > 2)
this.open();
}
break;
@ -494,6 +519,7 @@ var ctrlTab = {
this.removeBox(this.container.lastChild);
this.selected = null;
this.invertDirection = false;
this._useTabBarOrder = false;
this._uniqid = 0;
this.label.value = "";
this.setStatusbarValue();
@ -506,7 +532,7 @@ var ctrlTab = {
onTabSelect: function (aTab) {
if (aTab.parentNode) {
this.detachTab(aTab);
this.attachTab(aTab, true);
this.attachTab(aTab, 0);
}
},
handleEvent: function (event) {
@ -522,11 +548,11 @@ var ctrlTab = {
this.onTabSelect(event.target);
break;
case "TabOpen":
this.attachTab(event.target);
this.attachTab(event.target, 1);
break;
case "TabClose":
if (this.isOpen) {
if (this.tabs.length == 2) {
if (this.tabCount == 2) {
// we have two tabs, one is being closed, so the panel isn't needed anymore
this.panel.hidePopup();
} else {

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

@ -69,7 +69,6 @@ const MAX_HISTORY_MENU_ITEMS = 15;
// We use this once, for Clear Private Data
const GLUE_CID = "@mozilla.org/browser/browserglue;1";
var gURIFixup = null;
var gCharsetMenu = null;
var gLastBrowserCharset = null;
var gPrevCharset = null;
@ -986,10 +985,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
UpdateUrlbarSearchSplitterState();
try {
placesMigrationTasks();
} catch(ex) {}
PlacesStarButton.init();
// called when we go into full screen, even if it is
@ -1318,7 +1313,6 @@ AutoHideTabbarPrefListener.prototype =
catch (e) {
}
gBrowser.setStripVisibilityTo(aVisible);
gPrefService.setBoolPref("browser.tabs.forceHide", false);
}
}
}
@ -1641,8 +1635,7 @@ function BrowserOpenFileWindow()
}
}
function BrowserCloseTabOrWindow()
{
function BrowserCloseTabOrWindow() {
#ifdef XP_MACOSX
// If we're not a browser window, just close the window
if (window.location.href != getBrowserURL()) {
@ -1651,23 +1644,8 @@ function BrowserCloseTabOrWindow()
}
#endif
if (gBrowser.tabContainer.childNodes.length > 1) {
gBrowser.removeCurrentTab();
return;
}
#ifndef XP_MACOSX
if (gBrowser.localName == "tabbrowser" && window.toolbar.visible &&
!gPrefService.getBoolPref("browser.tabs.autoHide")) {
// Replace the remaining tab with a blank one and focus the address bar
gBrowser.removeCurrentTab();
if (gURLBar)
setTimeout(function() { gURLBar.focus(); }, 0);
return;
}
#endif
closeWindow(true);
// If the current tab is the last one, this will close the window.
gBrowser.removeCurrentTab();
}
function BrowserTryToCloseWindow()
@ -1970,37 +1948,25 @@ function checkForDirectoryListing()
}
}
function URLBarSetURI(aURI) {
function URLBarSetURI(aURI, aValid) {
var value = gBrowser.userTypedValue;
var state = "invalid";
var valid = false;
if (!value) {
if (aURI) {
// If the url has "wyciwyg://" as the protocol, strip it off.
// Nobody wants to see it on the urlbar for dynamically generated
// pages.
if (!gURIFixup)
gURIFixup = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup);
try {
aURI = gURIFixup.createExposableURI(aURI);
} catch (ex) {}
} else {
aURI = getWebNavigation().currentURI;
}
let uri = aURI || getWebNavigation().currentURI;
if (aURI.spec == "about:blank") {
// Replace "about:blank" with an empty string
// only if there's no opener (bug 370555).
value = content.opener ? aURI.spec : "";
} else {
value = losslessDecodeURI(aURI);
state = "valid";
}
// Replace "about:blank" with an empty string
// only if there's no opener (bug 370555).
if (uri.spec == "about:blank")
value = content.opener ? "about:blank" : "";
else
value = losslessDecodeURI(uri);
valid = value && (!aURI || aValid);
}
gURLBar.value = value;
SetPageProxyState(state);
SetPageProxyState(valid ? "valid" : "invalid");
}
function losslessDecodeURI(aURI) {
@ -3760,6 +3726,11 @@ var XULBrowserWindow = {
delete this.isImage;
return this.isImage = document.getElementById("isImage");
},
get _uriFixup () {
delete this._uriFixup;
return this._uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup);
},
init: function () {
this.throbberElement = document.getElementById("navigator-throbber");
@ -3892,9 +3863,10 @@ var XULBrowserWindow = {
// and progress bars and such
if (aRequest) {
let msg = "";
let location;
// Get the URI either from a channel or a pseudo-object
if (aRequest instanceof nsIChannel || "URI" in aRequest) {
let location = aRequest.URI;
location = aRequest.URI;
// For keyword URIs clear the user typed value since they will be changed into real URIs
if (location.scheme == "keyword" && aWebProgress.DOMWindow == content)
@ -4017,8 +3989,15 @@ var XULBrowserWindow = {
gBrowser.setIcon(gBrowser.mCurrentTab, null);
if (gURLBar) {
URLBarSetURI(aLocationURI);
PlacesStarButton.updateState(); // Update starring UI
// Strip off "wyciwyg://" and passwords for the location bar
let uri = aLocationURI;
try {
uri = this._uriFixup.createExposableURI(uri);
} catch (e) {}
URLBarSetURI(uri, true);
// Update starring UI
PlacesStarButton.updateState();
}
FullZoom.onLocationChange(aLocationURI);
@ -4225,22 +4204,26 @@ var XULBrowserWindow = {
// clear out search-engine data
gBrowser.mCurrentBrowser.engines = null;
const nsIChannel = Components.interfaces.nsIChannel;
var urlStr = aRequest.QueryInterface(nsIChannel).URI.spec;
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
var uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
if (gURLBar &&
gURLBar.value == "" &&
getWebNavigation().currentURI.spec == "about:blank")
URLBarSetURI(uri);
try {
observerService.notifyObservers(content, "StartDocumentLoad", urlStr);
observerService.notifyObservers(content, "StartDocumentLoad", uri.spec);
} catch (e) {
}
},
endDocumentLoad: function (aRequest, aStatus) {
const nsIChannel = Components.interfaces.nsIChannel;
var urlStr = aRequest.QueryInterface(nsIChannel).originalURI.spec;
var urlStr = aRequest.QueryInterface(Ci.nsIChannel).originalURI.spec;
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
var notification = Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad";
try {

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

@ -99,10 +99,10 @@
<tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
<!-- for search and content formfill/pw manager -->
<panel type="autocomplete" chromedir="&locale.dir;" id="PopupAutoComplete" noautofocus="true" hidden="true" level="top"/>
<panel type="autocomplete" chromedir="&locale.dir;" id="PopupAutoComplete" noautofocus="true" hidden="true"/>
<!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox" chromedir="&locale.dir;" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true" level="top"/>
<panel type="autocomplete-richlistbox" chromedir="&locale.dir;" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
<panel id="editBookmarkPanel"
orient="vertical"

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

@ -1106,7 +1106,7 @@ function formatNumber(number)
function formatDate(datestr, unknown)
{
// scriptable date formater, for pretty printing dates
// scriptable date formatter, for pretty printing dates
var dateService = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Components.interfaces.nsIScriptableDateFormat);

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

@ -201,8 +201,8 @@
<description id="general-security-identity" class="header"/>
<description id="general-security-privacy" class="header"/>
<hbox align="right">
<button id="security-view-more" label="&generalSecurityMore;"
accesskey="&generalSecurityMore.accesskey;"
<button id="security-view-details" label="&generalSecurityDetails;"
accesskey="&generalSecurityDetails.accesskey;"
oncommand="onClickMore();"/>
</hbox>
</groupbox>

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

@ -179,10 +179,10 @@ Sanitizer.prototype = {
formdata: {
clear: function ()
{
//Clear undo history of all searchBars
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var windows = windowManagerInterface.getEnumerator("navigator:browser");
// Clear undo history of all searchBars
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var windows = windowManager.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
var searchBar = windows.getNext().document.getElementById("searchbar");
if (searchBar) {
@ -195,9 +195,23 @@ Sanitizer.prototype = {
.getService(Components.interfaces.nsIFormHistory2);
formHistory.removeAllEntries();
},
get canClear()
{
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var windows = windowManager.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
var searchBar = windows.getNext().document.getElementById("searchbar");
if (searchBar) {
var transactionMgr = searchBar.textbox.editor.transactionManager;
if (searchBar.value ||
transactionMgr.numberOfUndoItems ||
transactionMgr.numberOfRedoItems)
return true;
}
}
var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory2);
return formHistory.hasEntries;

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

@ -1217,8 +1217,6 @@
if (this.mStrip.collapsed)
this.setStripVisibilityTo(true);
this.mPrefs.setBoolPref("browser.tabs.forceHide", false);
// wire up a progress listener for the new browser object.
var position = this.mTabContainer.childNodes.length-1;
var tabListener = this.mTabProgressListener(t, b, blank);
@ -1404,40 +1402,31 @@
if (aTab.localName != "tab")
aTab = this.mCurrentTab;
var l = this.mTabContainer.childNodes.length;
if (l == 1 && this.mPrefs.getBoolPref("browser.tabs.autoHide")) {
// hide the tab bar
this.mPrefs.setBoolPref("browser.tabs.forceHide", true);
this.setStripVisibilityTo(false);
return;
}
if (aFireBeforeUnload) {
var ds = this.getBrowserForTab(aTab).docShell;
let ds = this.getBrowserForTab(aTab).docShell;
if (ds.contentViewer && !ds.contentViewer.permitUnload())
return;
return null;
}
// see notes in addTab
var _delayedUpdate = function(aTabContainer) {
aTabContainer.adjustTabstrip();
aTabContainer.mTabstrip._updateScrollButtonsDisabledState();
}
setTimeout(_delayedUpdate, 0, this.mTabContainer);
var l = this.mTabContainer.childNodes.length;
if (l == 1) {
// add a new blank tab to replace the one we're about to close
// (this ensures that the remaining tab is as good as new)
this.addTab("about:blank");
l++;
closeWindow(true);
return null;
}
else if (l == 2) {
if (l == 2) {
var autohide = this.mPrefs.getBoolPref("browser.tabs.autoHide");
var tabStripHide = !window.toolbar.visible;
if (autohide || tabStripHide)
this.setStripVisibilityTo(false);
}
// see notes in addTab
var _delayedUpdate = function (aTabContainer) {
aTabContainer.adjustTabstrip();
aTabContainer.mTabstrip._updateScrollButtonsDisabledState();
};
setTimeout(_delayedUpdate, 0, this.mTabContainer);
// We're committed to closing the tab now.
// Dispatch a notification.
// We dispatch it before any teardown so that event listeners can
@ -1479,6 +1468,9 @@
<parameter name="aTab"/>
<body>
<![CDATA[
if (!aTab)
return null;
var browser = this.getBrowserForTab(aTab);
var length = this.mTabs.length;
@ -1668,9 +1660,8 @@
if (!this.mAddProgressListenerWasCalled) {
this.mAddProgressListenerWasCalled = true;
var autoHide = this.mPrefs.getBoolPref("browser.tabs.autoHide");
var forceHide = this.mPrefs.getBoolPref("browser.tabs.forceHide");
var tabStripHide = !window.toolbar.visible;
if (!autoHide && !forceHide && !tabStripHide)
if (!autoHide && !tabStripHide)
this.setStripVisibilityTo(true);
}
@ -1927,20 +1918,16 @@
<parameter name="aDragSession"/>
<body>
<![CDATA[
#ifndef XP_MACOSX
var accelKeyPressed = aEvent.ctrlKey;
#else
var accelKeyPressed = aEvent.metaKey;
#endif
var isCopy = aEvent.dataTransfer.dropEffect == "copy";
var draggedTab;
if (aDragSession.sourceNode && aDragSession.sourceNode.localName == "tab" &&
(aDragSession.sourceNode.parentNode == this.mTabContainer ||
aDragSession.sourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
aDragSession.sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser"))
draggedTab = aDragSession.sourceNode;
if (draggedTab && (accelKeyPressed || draggedTab.parentNode == this.mTabContainer)) {
if (draggedTab && (isCopy || draggedTab.parentNode == this.mTabContainer)) {
var newIndex = this.getNewIndex(aEvent);
if (accelKeyPressed) {
if (isCopy) {
// copy the dropped tab (wherever it's from)
var newTab = this.duplicateTab(draggedTab);
this.moveTabTo(newTab, newIndex);
@ -1997,7 +1984,7 @@
if (aEvent.shiftKey)
bgLoad = !bgLoad;
if (document.getBindingParent(aEvent.originalTarget).localName != "tab" || accelKeyPressed) {
if (document.getBindingParent(aEvent.originalTarget).localName != "tab" || isCopy) {
// We're adding a new tab.
newIndex = this.getNewIndex(aEvent);
newTab = this.loadOneTab(getShortcutOrURI(url), null, null, null, bgLoad, false);

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

@ -49,7 +49,7 @@ function test() {
}
assertTabs(2);
ctrlTabTest([1] , 1, 0);
//ctrlTabTest([1], 1, 0);
gBrowser.removeTab(gBrowser.tabContainer.lastChild);

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

@ -62,8 +62,16 @@ install::
ifdef ENABLE_TESTS
# Implemented in testing/testsuite-targets.mk
# Browser tests live in a slightly different location, so we correct the path
ifdef TEST_PATH
BROWSER_TEST_PATH = --test-path=../browser/$(TEST_PATH)
else
BROWSER_TEST_PATH =
endif
mochitest-browser-chrome:
$(RUN_MOCHITEST) --browser-chrome
$(RUN_MOCHITEST) --browser-chrome $(BROWSER_TEST_PATH)
$(CHECK_TEST_ERROR)
mochitest:: mochitest-browser-chrome

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

@ -166,7 +166,10 @@ ServiceInfo.prototype = {
}
};
function WebContentConverterRegistrar() {}
function WebContentConverterRegistrar() {
this._contentTypes = { };
this._autoHandleContentTypes = { };
}
WebContentConverterRegistrar.prototype = {
get stringBundle() {
@ -185,14 +188,6 @@ WebContentConverterRegistrar.prototype = {
return this.stringBundle.GetStringFromName(key);
},
_contentTypes: { },
/**
* Track auto handlers for various content types using a content-type to
* handler map.
*/
_autoHandleContentTypes: { },
/**
* See nsIWebContentConverterService
*/

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

@ -177,10 +177,9 @@ BrowserGlue.prototype = {
{
// Check to see if the EULA must be shown on startup
// Global override for tinderbox machines
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var mustDisplayEULA = true;
var mustDisplayEULA = false;
try {
mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA.override");
} catch (e) {

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

@ -22,7 +22,7 @@
* Ben Goodger <beng@google.com>
* Myk Melez <myk@mozilla.org>
* Asaf Romano <mano@mozilla.com>
* Marco Bonardo <mak77@supereva.it>
* Marco Bonardo <mak77@bonardo.net>
*
* 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
@ -298,7 +298,7 @@ PlacesController.prototype = {
return false;
if (PlacesUtils.nodeIsFolder(nodes[i]) &&
!PlacesControllerDragHelper.canMoveContainerNode(nodes[i]))
!PlacesControllerDragHelper.canMoveNode(nodes[i]))
return false;
// We don't call nodeIsReadOnly here, because nodeIsReadOnly means that
@ -351,7 +351,7 @@ PlacesController.prototype = {
// if the clipboard contains TYPE_X_MOZ_PLACE_* data, it is definitely
// pasteable, with no need to unwrap all the nodes.
var flavors = PlacesUIUtils.placesFlavors;
var flavors = PlacesControllerDragHelper.placesFlavors;
var clipboard = PlacesUIUtils.clipboard;
var hasPlacesData =
clipboard.hasDataMatchingFlavors(flavors, flavors.length,
@ -863,11 +863,13 @@ PlacesController.prototype = {
* An array of nodes to remove. Should all be adjacent.
* @param [out] transactions
* An array of transactions.
* @param [optional] removedFolders
* An array of folder nodes that have already been removed.
*/
_removeRange: function PC__removeRange(range, transactions) {
_removeRange: function PC__removeRange(range, transactions, removedFolders) {
NS_ASSERT(transactions instanceof Array, "Must pass a transactions array");
var removedFolders = [];
if (!removedFolders)
removedFolders = [];
for (var i = 0; i < range.length; ++i) {
var node = range[i];
@ -906,10 +908,11 @@ PlacesController.prototype = {
_removeRowsFromBookmarks: function PC__removeRowsFromBookmarks(txnName) {
var ranges = this._view.getRemovableSelectionRanges();
var transactions = [];
// Delete the selected rows. Do this by walking the selection backward, so
// that when undo is performed they are re-inserted in the correct order.
for (var i = ranges.length - 1; i >= 0 ; --i)
this._removeRange(ranges[i], transactions);
var removedFolders = [];
for (var i = 0; i < ranges.length; i++)
this._removeRange(ranges[i], transactions, removedFolders);
if (transactions.length > 0) {
var txn = PlacesUIUtils.ptm.aggregateTransactions(txnName, transactions);
PlacesUIUtils.ptm.doTransaction(txn);
@ -1012,62 +1015,50 @@ PlacesController.prototype = {
},
/**
* Get a TransferDataSet containing the content of the selection that can be
* dropped elsewhere.
* @param dragAction
* The action to happen when dragging, i.e. copy
* @returns A TransferDataSet object that can be dragged and dropped
* elsewhere.
* Fills a DataTransfer object with the content of the selection that can be
* dropped elsewhere.
* @param aEvent
* The dragstart event.
*/
getTransferData: function PC_getTransferData(dragAction) {
var copy = dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY;
setDataTransfer: function PC_setDataTransfer(aEvent) {
var dt = aEvent.dataTransfer;
var doCopy = dt.effectAllowed == "copyLink" || dt.effectAllowed == "copy";
var result = this._view.getResult();
var oldViewer = result.viewer;
try {
result.viewer = null;
var nodes = this._view.getDragableSelection();
if (dragAction == Ci.nsIDragService.DRAGDROP_ACTION_MOVE) {
nodes = nodes.filter(function(node) {
var parent = node.parent;
return parent && !PlacesUtils.nodeIsReadOnly(parent);
});
}
var dataSet = new TransferDataSet();
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var data = new TransferData();
function addData(type, overrideURI) {
data.addDataForFlavour(type, PlacesUIUtils._wrapString(
PlacesUtils.wrapNode(node, type, overrideURI, copy)));
function addData(type, index, overrideURI) {
var wrapNode = PlacesUtils.wrapNode(node, type, overrideURI, doCopy);
dt.mozSetDataAt(type, wrapNode, index);
}
function addURIData(overrideURI) {
addData(PlacesUtils.TYPE_X_MOZ_URL, overrideURI);
addData(PlacesUtils.TYPE_UNICODE, overrideURI);
addData(PlacesUtils.TYPE_HTML, overrideURI);
function addURIData(index, overrideURI) {
addData(PlacesUtils.TYPE_X_MOZ_URL, index, overrideURI);
addData(PlacesUtils.TYPE_UNICODE, index, overrideURI);
addData(PlacesUtils.TYPE_HTML, index, overrideURI);
}
// This order is _important_! It controls how this and other
// applications select data to be inserted based on type.
addData(PlacesUtils.TYPE_X_MOZ_PLACE);
var uri;
// Allow dropping the feed uri of live-bookmark folders
addData(PlacesUtils.TYPE_X_MOZ_PLACE, i);
// Drop the feed uri for livemark containers
if (PlacesUtils.nodeIsLivemarkContainer(node))
uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec;
addURIData(uri);
dataSet.push(data);
addURIData(i, PlacesUtils.livemarks.getFeedURI(node.itemId).spec);
else if (node.uri)
addURIData(i);
}
}
finally {
if (oldViewer)
result.viewer = oldViewer;
}
return dataSet;
},
/**
@ -1108,7 +1099,7 @@ PlacesController.prototype = {
uri) + suffix);
var placeSuffix = i < (nodes.length - 1) ? "," : "";
var resolveShortcuts = !PlacesControllerDragHelper.canMoveContainerNode(node);
var resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
return PlacesUtils.wrapNode(node, type, overrideURI, resolveShortcuts) + placeSuffix;
}
@ -1245,6 +1236,18 @@ PlacesController.prototype = {
* Drop functions are passed the view that is being dropped on.
*/
var PlacesControllerDragHelper = {
/**
* DOM Element currently being dragged over
*/
currentDropTarget: null,
/**
* Current nsIDOMDataTransfer
* We need to cache this because we don't have access to the event in the
* treeView's canDrop or drop methods, and session.dataTransfer would not be
* filled for drag and drop from external sources (eg. the OS).
*/
currentDataTransfer: null,
/**
* Determines if the mouse is currently being dragged over a child node of
@ -1265,11 +1268,6 @@ var PlacesControllerDragHelper = {
return false;
},
/**
* DOM Element currently being dragged over
*/
currentDropTarget: null,
/**
* @returns The current active drag session. Returns null if there is none.
*/
@ -1279,6 +1277,19 @@ var PlacesControllerDragHelper = {
return dragService.getCurrentSession();
},
/**
* Extract the first accepted flavor from a flavors array.
* @param aFlavors
* The flavors array.
*/
getFirstValidFlavor: function PCDH_getFirstValidFlavor(aFlavors) {
for (var i = 0; i < aFlavors.length; i++) {
if (this.GENERIC_VIEW_DROP_TYPES.indexOf(aFlavors[i]) != -1)
return aFlavors[i];
}
return null;
},
/**
* Determines whether or not the data currently being dragged can be dropped
* on a places view.
@ -1286,35 +1297,28 @@ var PlacesControllerDragHelper = {
* The insertion point where the items should be dropped
*/
canDrop: function PCDH_canDrop(ip) {
var session = this.getSession();
if (!session)
return false;
var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
var foundType = false;
for (var i = 0; i < types.length && !foundType; ++i) {
if (session.isDataFlavorSupported(types[i]))
foundType = true;
}
if (!foundType)
return false;
var dt = this.currentDataTransfer;
var dropCount = dt.mozItemCount;
// Check every dragged item
var xferable = this._initTransferable(session);
var dropCount = session.numDropItems;
for (i = 0; i < dropCount; i++) {
// Get the information of the dragged item
session.getData(xferable, i);
var data = { }, flavor = { };
xferable.getAnyTransferData(flavor, data, { });
data.value.QueryInterface(Ci.nsISupportsString);
var dragged = PlacesUtils.unwrapNodes(data.value.data, flavor.value)[0];
for (var i = 0; i < dropCount; i++) {
var flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
if (!flavor)
return false;
var data = dt.mozGetDataAt(flavor, i);
try {
var dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
} catch (e) {
return false;
}
// Only bookmarks and urls can be dropped into tag containers
if (ip.isTag && dragged.type != PlacesUtils.TYPE_X_MOZ_URL &&
(dragged.type != PlacesUtils.TYPE_X_MOZ_PLACE ||
/^place:/.test(dragged.uri)))
if (ip.isTag && ip.orientation == Ci.nsITreeView.DROP_ON &&
dragged.type != PlacesUtils.TYPE_X_MOZ_URL &&
(dragged.type != PlacesUtils.TYPE_X_MOZ_PLACE ||
/^place:/.test(dragged.uri)))
return false;
// The following loop disallows the dropping of a folder on itself or
@ -1329,39 +1333,36 @@ var PlacesControllerDragHelper = {
}
}
}
return true;
},
/**
* Determines if a container node can be moved.
* Determines if a node can be moved.
*
* @param aNode
* A bookmark folder node.
* @param [optional] aInsertionPoint
* The insertion point of the drop target.
* @returns True if the container can be moved.
* A nsINavHistoryResultNode node.
* @returns True if the node can be moved, false otherwise.
*/
canMoveContainerNode:
function PCDH_canMoveContainerNode(aNode, aInsertionPoint) {
canMoveNode:
function PCDH_canMoveNode(aNode) {
// can't move query root
if (!aNode.parent)
return false;
var targetId = aInsertionPoint ? aInsertionPoint.itemId : -1;
var parentId = PlacesUtils.getConcreteItemId(aNode.parent);
var concreteId = PlacesUtils.getConcreteItemId(aNode);
// can't move tag containers
if (PlacesUtils.nodeIsTagQuery(aNode))
// can't move children of tag containers
if (PlacesUtils.nodeIsTagQuery(aNode.parent))
return false;
// check is child of a read-only container
// can't move children of read-only containers
if (PlacesUtils.nodeIsReadOnly(aNode.parent))
return false;
// check for special folders, etc
if (!this.canMoveContainer(aNode.itemId, parentId))
if (PlacesUtils.nodeIsContainer(aNode) &&
!this.canMoveContainer(aNode.itemId, parentId))
return false;
return true;
@ -1392,89 +1393,95 @@ var PlacesControllerDragHelper = {
if (aParentId == null || aParentId == -1)
aParentId = PlacesUtils.bookmarks.getFolderIdForItem(aId);
if(PlacesUtils.bookmarks.getFolderReadonly(aParentId))
if (PlacesUtils.bookmarks.getFolderReadonly(aParentId))
return false;
return true;
},
/**
* Creates a Transferable object that can be filled with data of types
* supported by a view.
* @param session
* The active drag session
* @returns An object implementing nsITransferable that can receive data
* dropped onto a view.
*/
_initTransferable: function PCDH__initTransferable(session) {
var xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i) {
if (session.isDataFlavorSupported(types[i]))
xferable.addDataFlavor(types[i]);
}
return xferable;
},
/**
* Handles the drop of one or more items onto a view.
* @param insertionPoint
* The insertion point where the items should be dropped
*/
onDrop: function PCDH_onDrop(insertionPoint) {
var session = this.getSession();
// XXX dragAction is not valid, so we also set copy below by checking
// whether the dropped item is moveable, before creating the transaction
var copy = session.dragAction & Ci.nsIDragService.DRAGDROP_ACTION_COPY;
var dt = this.currentDataTransfer;
var doCopy = dt.dropEffect == "copy";
var transactions = [];
var xferable = this._initTransferable(session);
var dropCount = session.numDropItems;
var dropCount = dt.mozItemCount;
var movedCount = 0;
for (var i = 0; i < dropCount; ++i) {
session.getData(xferable, i);
var flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
if (!flavor)
return false;
var data = { }, flavor = { };
xferable.getAnyTransferData(flavor, data, { });
data.value.QueryInterface(Ci.nsISupportsString);
// There's only ever one in the D&D case.
var unwrapped = PlacesUtils.unwrapNodes(data.value.data,
flavor.value)[0];
var data = dt.mozGetDataAt(flavor, i);
// There's only ever one in the D&D case.
var unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0];
var index = insertionPoint.index;
// Adjust insertion index to prevent reversal of dragged items. When you
// drag multiple elts upward: need to increment index or each successive
// elt will be inserted at the same index, each above the previous.
if (index != -1 && index < unwrapped.index) {
index = index + movedCount;
movedCount++;
}
var dragginUp = insertionPoint.itemId == unwrapped.parent &&
index < PlacesUtils.bookmarks.getItemIndex(unwrapped.id);
if (index != -1 && dragginUp)
index+= movedCount++;
// if dragging over a tag container we should tag the item
if (insertionPoint.isTag) {
if (insertionPoint.isTag &&
insertionPoint.orientation == Ci.nsITreeView.DROP_ON) {
var uri = PlacesUtils._uri(unwrapped.uri);
var tagItemId = insertionPoint.itemId;
transactions.push(PlacesUIUtils.ptm.tagURI(uri,[tagItemId]));
}
else {
if (unwrapped.id && !this.canMoveContainer(unwrapped.id, null))
copy = true;
else if (unwrapped.concreteId &&
!this.canMoveContainer(unwrapped.concreteId, null))
copy = true;
transactions.push(PlacesUIUtils.makeTransaction(unwrapped,
flavor.value, insertionPoint.itemId,
index, copy));
flavor, insertionPoint.itemId,
index, doCopy));
}
}
var txn = PlacesUIUtils.ptm.aggregateTransactions("DropItems", transactions);
PlacesUIUtils.ptm.doTransaction(txn);
},
/**
* Checks if we can insert into a container.
* @param aContainer
* The container were we are want to drop
*/
disallowInsertion: function(aContainer) {
NS_ASSERT(aContainer, "empty container");
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
},
placesFlavors: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
PlacesUtils.TYPE_X_MOZ_PLACE],
GENERIC_VIEW_DROP_TYPES: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE],
/**
* Returns our flavourSet
*/
get flavourSet() {
delete this.flavourSet;
var flavourSet = new FlavourSet();
var acceptedDropFlavours = this.GENERIC_VIEW_DROP_TYPES;
acceptedDropFlavours.forEach(flavourSet.appendFlavour, flavourSet);
return this.flavourSet = flavourSet;
}
};

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

@ -24,7 +24,7 @@
# Ben Goodger <beng@google.com>
# Asaf Romano <mano@mozilla.com>
# Simon Bünzli <zeniko@gmail.com>
# Marco Bonardo <mak77@supereva.it>
# Marco Bonardo <mak77@bonardo.net>
#
# 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
@ -88,8 +88,11 @@
PlacesControllerDragHelper.currentDropTarget = aEvent.target;
// check if we have a valid dropPoint
var dropPoint = this._getDropPoint(aEvent);
if (!dropPoint)
if (!dropPoint || !dropPoint.ip ||
!PlacesControllerDragHelper.canDrop(dropPoint.ip)) {
aEvent.dataTransfer.effectAllowed = "none";
return;
}
// add a dragover attribute to this popup
this.setAttribute("dragover", "true");
@ -109,7 +112,7 @@
.setTimer(this._overFolder.hoverTime);
}
// since we are dropping into a folder set the corresponding style
dropPoint.folderNode.setAttribute("dragover-into", "true");
dropPoint.folderNode.setAttribute("_moz-menuactive", true);
}
else {
// We are not dragging over a folder
@ -117,6 +120,14 @@
this._overFolder.clear();
}
// Autoscroll the popup strip if we drag over the scroll buttons
var anonid = aEvent.originalTarget.getAttribute('anonid');
var scrollDir = anonid == "scrollbutton-up" ? -1 :
anonid == "scrollbutton-down" ? 1 : 0;
if (scrollDir != 0) {
this._scrollBox.scrollByIndex(scrollDir);
}
// Check if we should hide the drop indicator for this target
if (!aDragSession.canDrop ||
!dropPoint || dropPoint.folderNode ||
@ -125,29 +136,22 @@
return;
}
var scrollBoxObject = this._scrollBox.scrollBoxObject;
// Autoscroll the popup strip if we drag over the scroll buttons
var anonid = aEvent.originalTarget.getAttribute("anonid");
var scrollDir = anonid == "scrollbutton-up" ? -1 :
anonid == "scrollbutton-down" ? 1 : 0;
if (scrollDir != 0)
this._scrollBox.scrollByIndex(scrollDir);
// We should display the drop indicator relative to the arrowscrollbox
var sbo = this._scrollBox.scrollBoxObject;
var newMarginTop = 0;
if (scrollDir == 0) {
var node = this.firstChild;
while (node && aEvent.screenY > node.boxObject.screenY +
node.boxObject.height / 2)
node = node.nextSibling;
newMarginTop = node ? node.boxObject.screenY - scrollBoxObject.screenY :
scrollBoxObject.height;
newMarginTop = node ? node.boxObject.screenY - sbo.screenY :
sbo.height;
}
else if (scrollDir == 1)
newMarginTop = scrollBoxObject.height;
newMarginTop = sbo.height;
// set the new marginTop based on arrowscrollbox
newMarginTop += scrollBoxObject.y - this._scrollBox.boxObject.y;
newMarginTop += sbo.y - this._scrollBox.boxObject.y;
this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px";
this._indicatorBar.hidden = false;
]]></body>
@ -158,9 +162,8 @@
<parameter name="aDragSession"/>
<body><![CDATA[
PlacesControllerDragHelper.currentDropTarget = null;
PlacesControllerDragHelper.currentDataTransfer = null;
this.removeAttribute("dragover");
// remove dragover-into style from previous target
aEvent.target.removeAttribute("dragover-into");
// if we have not moved to a valid new target clear the drop indicator
// this happens when moving out of the popup
@ -177,7 +180,10 @@
// The autoopened attribute is set when this folder was automatically
// opened after the user dragged over it. If this attribute is set,
// auto-close the folder on drag exit.
if (this.hasAttribute("autoopened")) {
// We should also try to close this popup if the drag has started
// from here, the timer will check if we are dragging over a child.
if (this.hasAttribute("autoopened") ||
this.hasAttribute("dragstart")) {
this._overFolder.closeMenuTimer = this._overFolder
.setTimer(this._overFolder.hoverTime);
}
@ -191,26 +197,32 @@
<parameter name="aXferData"/>
<parameter name="aDragAction"/>
<body><![CDATA[
// Force a copy action if parent node is a query or not-removable
if (aEvent.ctrlKey ||
PlacesUtils.nodeIsQuery(aEvent.target.node.parent) ||
!PlacesControllerDragHelper.canMoveContainerNode(aEvent.target.node))
aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
var draggedNode = aEvent.target.node;
// Force a copy action if parent node is a query or we are dragging a
// not-removable node
if (!PlacesControllerDragHelper.canMoveNode(draggedNode))
aEvent.dataTransfer.effectAllowed = "copyLink";
// activate the view and cache the dragged node
this._rootView._draggedNode = aEvent.target.node;
this._rootView._draggedNode = draggedNode;
this._rootView.focus();
aXferData.data = this._rootView.controller
.getTransferData(aDragAction.action);
// Fill the dataTransfer
this._rootView._controller.setDataTransfer(aEvent);
this.setAttribute("dragstart", "true");
]]></body>
</method>
<method name="onDrop">
<parameter name="aEvent"/>
<parameter name="aDropData"/>
<parameter name="aDropData"/>
<parameter name="aSession"/>
<body><![CDATA[
// Cache the dataTransfer
PlacesControllerDragHelper.currentDataTransfer = aEvent.dataTransfer;
var dropPoint = this._getDropPoint(aEvent);
if (!dropPoint)
return;
@ -222,10 +234,7 @@
<!-- This returns the FavourSet accepted by this popup -->
<method name="getSupportedFlavours">
<body><![CDATA[
var flavourSet = new FlavourSet();
var acceptedDropFlavours = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
acceptedDropFlavours.forEach(flavourSet.appendFlavour, flavourSet);
return flavourSet;
return PlacesControllerDragHelper.flavourSet;
]]></body>
</method>
@ -246,7 +255,8 @@
betweenMarkers = false;
// hide the dropmarker if current node is not a places bookmark item
return !(target && target.node && betweenMarkers && this.canDrop());
return !(target && target.node && betweenMarkers &&
this.canDrop(aEvent));
]]></body>
</method>
@ -257,71 +267,87 @@
<body><![CDATA[
// Can't drop if the menu isn't a folder
var resultNode = this._resultNode;
if (!PlacesUtils.nodeIsFolder(resultNode))
if (!PlacesUtils.nodeIsFolder(resultNode) ||
PlacesControllerDragHelper.disallowInsertion(resultNode)) {
aEvent.dataTransfer.effectAllowed = "none";
return null;
}
var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
var dropPoint = { ip: null, folderNode: null };
// set the limits for valid items
var start = 0;
var popup = this;
var end = popup.childNodes.length;
if (this._startMarker != -1)
start = this._startMarker + 1;
if (this._endMarker != -1)
end = this._endMarker;
// The node we are dragging over
var xulNode = aEvent.target;
// Loop through all the nodes to find the correct dropPoint
var popupY = popup.boxObject.y;
// we should add the scrollBox button height if visible
popupY += this._scrollBox.scrollBoxObject.y - popup.boxObject.y;
for (var i = start; i < end; i++) {
var xulNode = popup.childNodes[i];
var nodeY = xulNode.boxObject.y - popupY;
var nodeHeight = xulNode.boxObject.height;
if (xulNode.node &&
(PlacesUtils.nodeIsFolder(xulNode.node) ||
PlacesUtils.nodeIsTagQuery(xulNode.node)) &&
!PlacesUtils.nodeIsReadOnly(xulNode.node)) {
// This is a folder. If the mouse is in the top 25% of the
// node, drop above the folder. If it's in the middle
// 50%, drop into the folder. If it's past that, drop below.
if (aEvent.layerY < nodeY + (nodeHeight * 0.25)) {
// Drop above this folder.
dropPoint.ip = new InsertionPoint(resultNode.itemId,
i - start, -1);
dropPoint.beforeIndex = i;
return dropPoint;
}
else if (aEvent.layerY < nodeY + (nodeHeight * 0.75)) {
// Drop inside this folder.
dropPoint.ip = new InsertionPoint(xulNode.node.itemId, -1, 1);
dropPoint.beforeIndex = i;
dropPoint.folderNode = xulNode;
return dropPoint;
}
// Calculate positions taking care of arrowscrollbox
var sbo = this._scrollBox.scrollBoxObject;
var eventY = aEvent.layerY;
var nodeY = xulNode.boxObject.y - sbo.y;
var nodeHeight = xulNode.boxObject.height;
if (!xulNode.node) {
// if we are dragging over a non places node drop at the end
dropPoint.ip = new InsertionPoint(resultNode.itemId,
-1,
Ci.nsITreeView.DROP_ON);
return dropPoint;
}
else if ((PlacesUtils.nodeIsFolder(xulNode.node) ||
PlacesUtils.nodeIsTagQuery(xulNode.node)) &&
!PlacesUtils.nodeIsReadOnly(xulNode.node)) {
// This is a folder or a tag container.
if (eventY - nodeY < nodeHeight * 0.25) {
// If the mouse is in the top 25% of the node,
// drop above the folder.
dropPoint.ip = new InsertionPoint(
resultNode.itemId,
-1,
Ci.nsITreeView.DROP_BEFORE,
PlacesUtils.nodeIsTagQuery(xulNode.node),
xulNode.node.itemId);
return dropPoint;
}
else {
// This is a non-folder node. If the mouse is above the middle,
// drop above the folder. Otherwise, drop below.
if (aEvent.layerY <= nodeY + (nodeHeight / 2)) {
// Drop above this bookmark.
dropPoint.ip = new InsertionPoint(resultNode.itemId,
i - start, -1);
dropPoint.beforeIndex = i;
return dropPoint;
}
else if (eventY - nodeY < nodeHeight * 0.75) {
// If the mouse is before the 75 % of the node drop
// inside this folder.
dropPoint.ip = new InsertionPoint(
PlacesUtils.getConcreteItemId(xulNode.node),
-1,
Ci.nsITreeView.DROP_ON,
PlacesUtils.nodeIsTagQuery(xulNode.node));
dropPoint.folderNode = xulNode;
return dropPoint;
}
}
// Should drop below the last node.
dropPoint.ip = new InsertionPoint(resultNode.itemId, -1, 1);
dropPoint.beforeIndex = -1;
else if (eventY - nodeY <= nodeHeight / 2) {
// This is a non-folder node or a readonly folder.
// If the mouse is above the middle, drop above this item.
dropPoint.ip = new InsertionPoint(
resultNode.itemId,
-1,
Ci.nsITreeView.DROP_BEFORE,
PlacesUtils.nodeIsTagQuery(xulNode.node),
xulNode.node.itemId);
return dropPoint;
}
// Drop below the item.
dropPoint.ip = new InsertionPoint(
resultNode.itemId,
-1,
Ci.nsITreeView.DROP_AFTER,
PlacesUtils.nodeIsTagQuery(xulNode.node),
xulNode.node.itemId);
return dropPoint;
]]></body>
</method>
<method name="canDrop">
<parameter name="aEvent"/>
<body><![CDATA[
// Cache the dataTransfer
PlacesControllerDragHelper.currentDataTransfer = aEvent.dataTransfer;
var ip = this._rootView.insertionPoint;
return ip && PlacesControllerDragHelper.canDrop(ip);
]]></body>
@ -332,7 +358,10 @@
closing of folders when the mouse hovers. -->
<field name="_overFolder"><![CDATA[({
_self: this,
_folder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
_folder: {node: null,
openTimer: null,
hoverTime: 350,
closeTimer: null},
_closeMenuTimer: null,
get node() {
@ -406,13 +435,17 @@
else if (aTimer == this.closeMenuTimer) {
// Timer to close this menu after the drag exit.
var popup = this._self;
if (!PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
// if we are no more dragging we can leave the menu open to allow
// for better D&D bookmark organization
if (PlacesControllerDragHelper.getSession() &&
!PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
popup.hidePopup();
// Close any parent menus that aren't being dragged over;
// otherwise they'll stay open because they couldn't close
// while this menu was being dragged over.
this.closeParentMenus();
}
this._closeMenuTimer = null;
}
},
@ -439,8 +472,8 @@
if (this._folder.node && this._folder.node.lastChild) {
if (!this._folder.node.lastChild.hasAttribute("dragover"))
this._folder.node.lastChild.hidePopup();
// remove dragover-into style
this._folder.node.removeAttribute("dragover-into");
// remove menuactive style
this._folder.node.removeAttribute("_moz-menuactive");
this._folder.node = null;
}
if (this._folder.openTimer) {
@ -574,6 +607,9 @@
if (document.popupNode == child)
document.popupNode = null;
child.parentNode.removeChild(child);
if (this._endMarker != -1)
this._endMarker--;
]]></body>
</method>
@ -591,12 +627,16 @@
// Add the new element to the menu. If there is static content at
// the end of the menu, add the element before that. Otherwise,
// just add to the end.
if (aParentPopup._endMarker != -1)
if (aParentPopup._endMarker != -1) {
aParentPopup.insertBefore(element,
aParentPopup.childNodes[aParentPopup._endMarker++]);
aParentPopup.childNodes[aParentPopup._endMarker]);
}
else
aParentPopup.appendChild(element);
}
if (aParentPopup._endMarker != -1)
aParentPopup._endMarker++;
]]></body>
</method>
@ -702,6 +742,7 @@
popup.firstChild == popup._emptyMenuItem)) {
this._self._showEmptyMenuItem(popup);
}
return;
}
}
},
@ -900,15 +941,23 @@
<!-- nsIPlacesView -->
<property name="insertionPoint">
<getter><![CDATA[
// there is no insertion point for history queries
// so bail out now and save a lot of work when updating commands
var resultNode = this._resultNode;
if (PlacesUtils.nodeIsQuery(resultNode) &&
asQuery(resultNode).queryOptions.queryType ==
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
return null;
// By default, the insertion point is at the top level, at the end.
var index = PlacesUtils.bookmarks.DEFAULT_INDEX;
var container = null;
var orientation = Ci.nsITreeView.DROP_BEFORE;
var isTag = false;
if (PlacesUtils.nodeIsFolder(this._resultNode)) {
container = this._resultNode;
isTag = PlacesUtils.nodeIsTagQuery(this._resultNode);
if (PlacesUtils.nodeIsFolder(resultNode)) {
container = resultNode;
isTag = PlacesUtils.nodeIsTagQuery(resultNode);
}
var selectedNode = this.selectedNode;
@ -928,7 +977,7 @@
}
}
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
@ -936,18 +985,6 @@
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
]]></body>
</method>
<!-- nsIPlacesView -->
<method name="selectAll">
<body/>
@ -965,6 +1002,10 @@
this._ensureInitialized();
this._contextMenuShown = true;
this.focus();
// The above call to focus activates the controller, but it may not
// always fire a consumable event for commandUpdater, so we force a
// command update.
window.updateCommands("focus");
var show = this.controller.buildContextMenu(aPopup);
if (show) {
// disable the Delete command if the selection isn't explicit
@ -1013,6 +1054,7 @@
// automatically opened when dragged over. Turn off this attribute
// when the folder closes because it is no longer applicable.
popup.removeAttribute("autoopened");
popup.removeAttribute("dragstart");
]]></handler>
</handlers>
</binding>

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

@ -23,6 +23,7 @@
# Annie Sullivan <annie.sullivan@gmail.com>
# Ben Goodger <beng@google.com>
# Myk Melez <myk@mozilla.org>
# Marco Bonardo <mak77@bonardo.net>
#
# 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
@ -307,6 +308,14 @@
popup.setAttribute("type", "places");
}
}
// We rebuild the chevron on popupShowing, so if it is open
// we must force a rebuild
if (this._chevron.open) {
var popup = this._chevron.firstChild;
for (var i = 0; i < popup.childNodes.length; i++)
popup.childNodes[i].hidden = !this.childNodes[i].collapsed;
}
]]></body>
</method>
@ -406,7 +415,7 @@
}
}
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
@ -414,18 +423,6 @@
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
]]></body>
</method>
<!-- nsIPlacesView -->
<method name="selectAll">
<body><![CDATA[
@ -520,6 +517,9 @@
popup.firstChild == popup._emptyMenuItem)) {
this._self._showEmptyMenuItem(popup);
}
if (popup._endMarker != -1)
popup._endMarker--;
return;
}
}
}
@ -534,11 +534,19 @@
if (aNewParent == this._self.getResultNode()) {
var children = this._self.childNodes;
var chevronPopup = this._self._chevron.firstChild;
for (var i = 0; i < children.length; i++) {
var button = children[i];
if (button.node == aItem) {
this._self.removeChild(button);
this._self.insertBefore(button, children[aNewIndex]);
if (chevronPopup) {
// Maintain chevron in sync
menuitem = chevronPopup.childNodes[i];
chevronPopup.removeChild(menuitem);
chevronPopup.insertBefore(menuitem,
chevronPopup.childNodes[aNewIndex]);
}
this._self.updateChevron();
return;
}
@ -697,7 +705,10 @@
// Menu buttons should be opened when the mouse drags over them, and closed
// when the mouse drags off. The overFolder object manages opening and closing
// of folders when the mouse hovers.
_overFolder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
_overFolder: {node: null,
openTimer: null,
hoverTime: 350,
closeTimer: null},
// timer for turning of indicator bar, to get rid of flicker
_ibTimer: null,
@ -794,8 +805,10 @@
// node (or 25% of the right, in RTL UI), drop before the folder.
// If it's in the middle 50%, drop into the folder. If it's past
// that, drop after.
if ((isRTL && event.clientX > xulNode.boxObject.x + (xulNode.boxObject.width * 0.75)) ||
(!isRTL && event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width * 0.25))) {
if ((isRTL && event.clientX > xulNode.boxObject.x +
(xulNode.boxObject.width * 0.75)) ||
(!isRTL && event.clientX < xulNode.boxObject.x +
(xulNode.boxObject.width * 0.25))) {
// Drop to the left of this folder.
dropPoint.ip =
new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
@ -803,12 +816,15 @@
dropPoint.beforeIndex = i;
return dropPoint;
}
else if ((isRTL && event.clientX > xulNode.boxObject.x + (xulNode.boxObject.width * 0.25)) ||
(!isRTL && event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width * 0.75))) {
else if ((isRTL && event.clientX > xulNode.boxObject.x +
(xulNode.boxObject.width * 0.25)) ||
(!isRTL && event.clientX < xulNode.boxObject.x +
(xulNode.boxObject.width * 0.75))) {
// Drop inside this folder.
dropPoint.ip =
new InsertionPoint(PlacesUtils.getConcreteItemId(xulNode.node),
-1, 1);
-1, 1,
PlacesUtils.nodeIsTagQuery(xulNode.node));
dropPoint.beforeIndex = i;
dropPoint.folderNode = xulNode;
return dropPoint;
@ -836,39 +852,43 @@
dropPoint.beforeIndex = -1;
return dropPoint;
},
onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
onDragStart: function TBV_DO_onDragStart(aEvent, aXferData, aDragAction) {
var draggedXulNode = aEvent.target;
// sub menus have their own d&d handlers
if (event.target.parentNode != this._self)
if (draggedXulNode.parentNode != this._self)
return false;
if (event.target.localName == "toolbarbutton" &&
event.target.getAttribute("type") == "menu") {
if (draggedXulNode.localName == "toolbarbutton" &&
draggedXulNode.getAttribute("type") == "menu") {
#ifdef XP_WIN
// Support folder dragging on the personal toolbar when the user
// holds the "alt" key while they drag (Ctrl+drag has another
// meaning - Copy). This does not appear to work at all on Linux.
if (!event.shiftKey && !event.altKey && !event.ctrlKey)
// Support folder dragging on the personal toolbar when the user
// holds the "alt" or "shift" key while dragging.
// Ctrl+drag is Copy
if (!aEvent.shiftKey && !aEvent.altKey && !aEvent.ctrlKey)
return false;
event.target.firstChild.hidePopup();
#else
return;
// Support folder dragging on the personal toolbar when the user
// holds the "shift" key while dragging
// Ctrl+drag is Copy
if (!aEvent.shiftKey && !aEvent.ctrlKey)
return false;
#endif
draggedXulNode.firstChild.hidePopup();
}
if (event.ctrlKey)
dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
// activate the view and cache the dragged node
this._self._draggedNode = event.target.node;
this._self._draggedNode = draggedXulNode.node;
this._self.focus();
xferData.data = this._self._controller.getTransferData(dragAction.action);
#ifdef XP_WIN
this._self._controller.setDataTransfer(aEvent);
return true;
#endif
},
canDrop: function TBV_DO_canDrop(event, session) {
canDrop: function TBV_DO_canDrop(aEvent, aDragSession) {
// Cache the dataTransfer
PlacesControllerDragHelper.currentDataTransfer = aEvent.dataTransfer;
var ip = this._self.insertionPoint;
return ip && PlacesControllerDragHelper.canDrop(ip);
},
@ -939,13 +959,19 @@
},
onDrop: function TBV_DO_onDrop(event, dropData, session) {
// Cache the dataTransfer
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
var dropPoint = this._getDropPoint(event);
if (dropPoint == null)
if (!dropPoint)
return;
PlacesControllerDragHelper.onDrop(dropPoint.ip);
},
onDragExit: function TBV_DO_onDragExit(event, session) {
PlacesControllerDragHelper.currentDropTarget = null;
PlacesControllerDragHelper.currentDataTransfer = null;
// Set timer to turn off indicator bar (if we turn it off
// here, dragenter might be called immediately after, creating
// flicker.)
@ -955,17 +981,12 @@
// Close any folder being hovered over
if (this._overFolder.node)
this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
PlacesControllerDragHelper.currentDropTarget = null;
this._self._draggedNode = null;
},
getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
var flavorSet = new FlavourSet();
var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i)
flavorSet.appendFlavour(types[i]);
return flavorSet;
return PlacesControllerDragHelper.flavourSet;
}
})]]></field>
@ -1000,6 +1021,10 @@
<body><![CDATA[
this._contextMenuShown = true;
this.focus();
// The above call to focus activates the controller, but it may not
// always fire a consumable event for commandUpdater, so we force a
// command update.
window.updateCommands("focus");
var show = this.controller.buildContextMenu(aPopup);
if (show) {
// disable the Delete command if the selection isn't explicit
@ -1052,11 +1077,14 @@
// just add to the end.
if (aParentPopup._endMarker != -1) {
aParentPopup.insertBefore(element,
aParentPopup.childNodes[aParentPopup._endMarker++]);
aParentPopup.childNodes[aParentPopup._endMarker]);
}
else
aParentPopup.appendChild(element);
}
if (aParentPopup._endMarker != -1)
aParentPopup._endMarker++;
]]></body>
</method>
@ -1126,6 +1154,17 @@
nsDragAndDrop.dragExit(event, this._DNDObserver);
]]></handler>
<handler event="popupshowing" phase="capturing"><![CDATA[
// Don't show the popup if we are dragging a container.
if (this._draggingContainer) {
this._draggingContainer = false;
#ifdef MOZ_WIDGET_GTK2
// Allow drag and drop of folders in Linux.
// We must prevent popupshowing event from firing when shift is pressed.
event.preventDefault();
return false;
#endif
}
var popup = event.originalTarget;
// Avoid handling popupshowing of inner views
@ -1154,8 +1193,18 @@
this._openedMenuButton = null;
]]></handler>
<handler event="mousedown"><![CDATA[
// Allow drag and drop of folders in Linux.
// We must prevent popupshowing event from firing when shift is pressed.
var target = event.originalTarget;
if (event.button == 1 && event.shiftKey &&
target.localName == "toolbarbutton" && target.type == "menu")
this._draggingContainer = true;
]]></handler>
<handler event="mousemove"><![CDATA[
if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
if (this._openedMenuButton == null ||
PlacesControllerDragHelper.getSession())
return;
var target = event.originalTarget;

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

@ -22,6 +22,7 @@
# Contributor(s):
# Ben Goodger <beng@google.com>
# Annie Sullivan <annie.sullivan@gmail.com>
# Marco Bonardo <mak77@bonardo.net>
#
# 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
@ -434,11 +435,10 @@
// there is no insertion point for history queries
// so bail out now and save a lot of work when updating commands
var resultNode = this.getResultNode();
if (PlacesUtils.nodeIsQuery(resultNode)) {
var options = asQuery(resultNode).queryOptions;
if (options.queryType == options.QUERY_TYPE_HISTORY)
if (PlacesUtils.nodeIsQuery(resultNode) &&
asQuery(resultNode).queryOptions.queryType ==
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
return this._cachedInsertionPoint = null;
}
var orientation = Ci.nsITreeView.DROP_BEFORE;
// If there is no selection, insert at the end of the container.
@ -488,18 +488,6 @@
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
]]></body>
</method>
<method name="_getInsertionPoint">
<parameter name="index"/>
<parameter name="orientation"/>
@ -519,14 +507,13 @@
container = lastSelected;
index = -1;
}
else if (!this._disallowInsertion(lastSelected) &&
lastSelected.containerOpen &&
else if (lastSelected.containerOpen &&
orientation == Ci.nsITreeView.DROP_AFTER &&
lastSelected.hasChildren) {
// If the last selected item is an open container and the user is
// trying to drag into it as a first item, really insert into it.
container = lastSelected;
orientation = Ci.nsITreeView.DROP_BEFORE;
orientation = Ci.nsITreeView.DROP_ON;
index = 0;
}
else {
@ -537,7 +524,7 @@
// avoid the potentially expensive call to getIndexOfNode()
// if we know this container doesn't allow insertion
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
var queryOptions = asQuery(result.root).queryOptions;
@ -562,7 +549,7 @@
}
}
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
@ -675,14 +662,10 @@
<!-- nsDragAndDrop -->
<method name="onDragStart">
<parameter name="event"/>
<parameter name="xferData"/>
<parameter name="dragAction"/>
<parameter name="aEvent"/>
<parameter name="aXferData"/>
<parameter name="aDragAction"/>
<body><![CDATA[
// Drag and Drop does not work while a tree view is sorted.
if (this.getAttribute("sortActive") == "true")
throw Cr.NS_OK;
var nodes = this.getSelectionNodes();
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
@ -690,61 +673,83 @@
// Disallow dragging the root node of a tree
var parent = node.parent;
if (!parent)
throw Cr.NS_OK;
return;
// If this node is part of a readonly container (e.g. a livemark) it
// cannot be moved, only copied, so we must change the action used
// by the drag session.
if (PlacesUtils.nodeIsTagQuery(parent) ||
!PlacesControllerDragHelper.canMoveContainerNode(node)) {
// XXX DOES NOTHING! dragAction doesn't persist
dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
// If this node is child of a readonly container (e.g. a livemark)
// or cannot be moved, we must force a copy.
if (!PlacesControllerDragHelper.canMoveNode(node)) {
aEvent.dataTransfer.effectAllowed = "copyLink";
break;
}
}
// XXXben - the drag wrapper should do this automatically.
if (event.ctrlKey)
dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
// Stuff the encoded selection into the transferable data object
xferData.data = this._controller.getTransferData(dragAction.action);
this._controller.setDataTransfer(aEvent);
]]></body>
</method>
<!-- nsDragAndDrop -->
<method name="canDrop">
<parameter name="event"/>
<parameter name="session"/>
<body><![CDATA[
<parameter name="aEvent"/>
<parameter name="aDragSession"/>
<body><![CDATA[
// Cache the dataTransfer for the view
PlacesControllerDragHelper.currentDataTransfer = aEvent.dataTransfer;
var row = { }, col = { }, child = { };
this.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col,
child);
return this.view.canDrop(row.value, -1);
this.treeBoxObject.getCellAt(aEvent.clientX, aEvent.clientY,
row, col, child);
var node = row.value != -1 ?
this.getResultView().nodeForTreeIndex(row.value) :
this.getResultNode();
// cache the dropTarget for the view
PlacesControllerDragHelper.currentDropTarget = node;
// We have to calculate the orientation since view.canDrop will use
// it and we want to be consistent with the dropfeedback
var tbo = this.treeBoxObject;
var rowHeight = tbo.rowHeight;
var eventY = aEvent.clientY - tbo.treeBody.boxObject.y -
rowHeight * (row.value - tbo.getFirstVisibleRow());
var orientation = Ci.nsITreeView.DROP_BEFORE;
if (row.value == -1) {
// If the row is not valid we try to insert inside the resultNode.
orientation = Ci.nsITreeView.DROP_ON;
}
else if (PlacesUtils.nodeIsContainer(node) &&
eventY > rowHeight * 0.75) {
// If we are below the 75% of a container the treeview we try
// to drop after the node.
orientation = Ci.nsITreeView.DROP_AFTER;
}
else if (PlacesUtils.nodeIsContainer(node) &&
eventY > rowHeight * 0.25) {
// If we are below the 25% of a container the treeview we try
// to drop inside the node.
orientation = Ci.nsITreeView.DROP_ON;
}
return this.view.canDrop(row.value, orientation);
]]></body>
</method>
<!-- nsDragAndDrop -->
<method name="onDragOver">
<parameter name="event"/>
<parameter name="flavor"/>
<parameter name="session"/>
<body><![CDATA[
var dragService =
Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService);
var dragSession = dragService.getCurrentSession();
dragSession.canDrop = this.canDrop(event, session);
<parameter name="aEvent"/>
<parameter name="aFlavour"/>
<parameter name="aDragSession"/>
<body><![CDATA[
if (!this.canDrop(aEvent, aDragSession))
aEvent.dataTransfer.effectAllowed = "none";
]]></body>
</method>
<!-- nsDragAndDrop -->
<method name="getSupportedFlavours">
<body><![CDATA[
var flavorSet = new FlavourSet();
var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i)
flavorSet.appendFlavour(types[i]);
return flavorSet;
return PlacesControllerDragHelper.flavourSet;
]]></body>
</method>
@ -782,7 +787,6 @@
}
]]></handler>
<handler event="draggesture"><![CDATA[
// XXXben ew.
if (event.target.localName == "treechildren")
nsDragAndDrop.startDrag(event, this);
]]></handler>
@ -790,6 +794,13 @@
if (event.target.localName == "treechildren")
nsDragAndDrop.dragOver(event, this);
]]></handler>
<handler event="drop"><![CDATA[
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
]]></handler>
<handler event="dragexit"><![CDATA[
PlacesControllerDragHelper.currentDataTransfer = null;
PlacesControllerDragHelper.currentDropTarget = null;
]]></handler>
</handlers>
</binding>

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

@ -996,35 +996,14 @@ PlacesTreeView.prototype = {
if (!this._result)
throw Cr.NS_ERROR_UNEXPECTED;
var node = aRow != -1 ? this.nodeForTreeIndex(aRow) : this._result.root;
// drop position into a sorted treeview would be wrong
if (this.isSorted())
return false;
if (aOrientation == Ci.nsITreeView.DROP_ON) {
// The user cannot drop an item into itself or a read-only container
var dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService);
var dragSession = dragService.getCurrentSession();
var elt = dragSession.sourceNode.parentNode;
if (elt.localName == "tree" && elt.view == this &&
this.selection.isSelected(aRow))
return false;
}
var ip = this._getInsertionPoint(aRow, aOrientation);
return ip && PlacesControllerDragHelper.canDrop(ip);
},
// XXXmano: these two are copied over from tree.xml, to fix this we need to
// either add a helper to PlacesUtils or keep it here and add insertionPoint
// to the view interface.
_disallowInsertion: function PTV__disallowInsertion(aContainer) {
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
},
_getInsertionPoint: function PTV__getInsertionPoint(index, orientation) {
var container = this._result.root;
var dropNearItemId = -1;
@ -1038,14 +1017,13 @@ PlacesTreeView.prototype = {
container = lastSelected;
index = -1;
}
else if (!this._disallowInsertion(lastSelected) &&
lastSelected.containerOpen &&
else if (lastSelected.containerOpen &&
orientation == Ci.nsITreeView.DROP_AFTER &&
lastSelected.hasChildren) {
// If the last selected item is an open container and the user is
// trying to drag into it as a first item, really insert into it.
container = lastSelected;
orientation = Ci.nsITreeView.DROP_BEFORE;
orientation = Ci.nsITreeView.DROP_ON;
index = 0;
}
else {
@ -1056,12 +1034,13 @@ PlacesTreeView.prototype = {
// avoid the potentially expensive call to getIndexOfNode()
// if we know this container doesn't allow insertion
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
var queryOptions = asQuery(this._result.root).queryOptions;
if (queryOptions.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
// If we are within a sorted view, insert at the end
if (queryOptions.sortingMode !=
Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
// If we are within a sorted view, insert at the ends
index = -1;
}
else if (queryOptions.excludeItems ||
@ -1080,7 +1059,7 @@ PlacesTreeView.prototype = {
}
}
if (this._disallowInsertion(container))
if (PlacesControllerDragHelper.disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
@ -1095,7 +1074,7 @@ PlacesTreeView.prototype = {
// since this information is specific to the tree view.
var ip = this._getInsertionPoint(aRow, aOrientation);
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
return;
PlacesControllerDragHelper.onDrop(ip);
},

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

@ -24,6 +24,7 @@
* Asaf Romano <mano@mozilla.com>
* Sungjoon Steve Won <stevewon@gmail.com>
* Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
*
* 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
@ -377,10 +378,12 @@ var PlacesUIUtils = {
return this.ptm.moveItem(data.id, container, index);
break;
default:
if (type == PlacesUtils.TYPE_X_MOZ_URL || type == PlacesUtils.TYPE_UNICODE) {
var title = (type == PlacesUtils.TYPE_X_MOZ_URL) ? data.title : data.uri;
return this.ptm.createItem(PlacesUtils._uri(data.uri), container, index,
title);
if (type == PlacesUtils.TYPE_X_MOZ_URL ||
type == PlacesUtils.TYPE_UNICODE) {
var title = (type == PlacesUtils.TYPE_X_MOZ_URL) ? data.title :
data.uri;
return this.ptm.createItem(PlacesUtils._uri(data.uri),
container, index, title);
}
}
return null;
@ -1035,51 +1038,45 @@ var PlacesUIUtils = {
},
cleanPlacesPopup: function PU_cleanPlacesPopup(aPopup) {
// Find static menuitems at the start and at the end of the menupopup,
// marked by builder="start" and builder="end" attributes, and set
// markers to keep track of their indices.
// Remove places popup children and update markers to keep track of
// their indices.
var start = aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0;
var end = aPopup._endMarker != -1 ? aPopup._endMarker :
aPopup.childNodes.length;
var items = [];
aPopup._startMarker = -1;
aPopup._endMarker = -1;
for (var i = 0; i < aPopup.childNodes.length; ++i) {
var placesNodeFound = false;
for (var i = start; i < end; ++i) {
var item = aPopup.childNodes[i];
if (item.getAttribute("builder") == "start") {
aPopup._startMarker = i;
continue;
}
if (item.getAttribute("builder") == "end") {
// we need to do this for menus that have static content at the end but
// are initially empty, eg. the history menu, we need to know where to
// start inserting new items.
aPopup._endMarker = i;
continue;
break;
}
if ((aPopup._startMarker != -1) && (aPopup._endMarker == -1))
if (item.node) {
items.push(item);
}
// If static items at the beginning were found, remove all items between
// them and the static content at the end.
for (var i = 0; i < items.length; ++i) {
// skip the empty menu item
if (aPopup._emptyMenuItem != items[i]) {
aPopup.removeChild(items[i]);
if (aPopup._endMarker > 0)
--aPopup._endMarker;
placesNodeFound = true;
}
}
// If no static items were found at the beginning, remove all items before
// the static items at the end.
if (aPopup._startMarker == -1) {
var end = aPopup._endMarker == -1 ?
aPopup.childNodes.length - 1 : aPopup._endMarker - 1;
for (var i = end; i >= 0; i--) {
// skip the empty menu item
if (aPopup._emptyMenuItem != aPopup.childNodes[i]) {
aPopup.removeChild(aPopup.childNodes[i]);
if (aPopup._endMarker > 0)
--aPopup._endMarker;
else {
// This is static content...
if (!placesNodeFound)
// ...at the start of the popup
// Initialized in menu.xml, in the base binding
aPopup._startMarker++;
else {
// ...after places nodes
aPopup._endMarker = i;
break;
}
}
}
for (var i = 0; i < items.length; ++i) {
aPopup.removeChild(items[i]);
if (aPopup._endMarker != -1)
aPopup._endMarker--;
}
},
getBestTitle: function PU_getBestTitle(aNode) {
@ -1232,13 +1229,3 @@ var PlacesUIUtils = {
return this.allBookmarksFolderId = this.leftPaneQueries["AllBookmarks"];
}
};
PlacesUIUtils.placesFlavors = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
PlacesUtils.TYPE_X_MOZ_PLACE];
PlacesUIUtils.GENERIC_VIEW_DROP_TYPES = [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE];

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

@ -296,8 +296,11 @@ placesAggregateTransactions.prototype = {
},
commit: function PAT_commit(aUndo) {
for (var i=0; i < this._transactions.length; ++i) {
var txn = this._transactions[i];
var transactions = this._transactions;
if (aUndo)
transactions.reverse();
for (var i = 0; i < transactions.length; i++) {
var txn = transactions[i];
if (this.container > -1)
txn.wrappedJSObject.container = this.container;
if (aUndo)
@ -397,6 +400,7 @@ function placesCreateSeparatorTransactions(aContainer, aIndex) {
this._container = aContainer;
this._index = typeof(aIndex) == "number" ? aIndex : -1;
this._id = null;
this.redoTransaction = this.doTransaction;
}
placesCreateSeparatorTransactions.prototype = {
@ -450,7 +454,6 @@ placesCreateLivemarkTransactions.prototype = {
function placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex) {
this._id = aItemId;
this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id);
this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
this._newContainer = aNewContainer;
this._newIndex = aNewIndex;
this.redoTransaction = this.doTransaction;
@ -460,17 +463,16 @@ placesMoveItemTransactions.prototype = {
__proto__: placesBaseTransaction.prototype,
doTransaction: function PMIT_doTransaction() {
this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
PlacesUtils.bookmarks.moveItem(this._id, this._newContainer, this._newIndex);
// if newIndex == DEFAULT_INDEX we append, so get correct index for undo
if (this._newIndex == PlacesUtils.bookmarks.DEFAULT_INDEX)
this._newIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
this._undoIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
},
undoTransaction: function PMIT_undoTransaction() {
// moving down in the same container takes in count removal of the item
// so to revert positions we must move to oldIndex + 1
if (this._newContainer == this._oldContainer &&
this._oldIndex > this._newIndex)
this._oldIndex > this._undoIndex)
PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex + 1);
else
PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex);
@ -541,7 +543,7 @@ placesRemoveItemTransaction.prototype = {
this._transactions[i].undoTransaction();
}
else // TYPE_SEPARATOR
PlacesUtils.bookmarks.insertSeparator(this._oldContainer, this._oldIndex);
this._id = PlacesUtils.bookmarks.insertSeparator(this._oldContainer, this._oldIndex);
if (this._annotations.length > 0)
PlacesUtils.setAnnotationsForItem(this._id, this._annotations);

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

@ -61,7 +61,7 @@ function test() {
"populate added data to the test root");
is(PlacesControllerDragHelper.canMoveContainer(this.id),
true, "can move regular folder id");
is(PlacesControllerDragHelper.canMoveContainerNode(rootNode.getChild(0)),
is(PlacesControllerDragHelper.canMoveNode(rootNode.getChild(0)),
true, "can move regular folder node");
}
});
@ -92,7 +92,7 @@ function test() {
is(PlacesControllerDragHelper.canMoveContainer(this.shortcutId),
true, "can move folder shortcut id");
is(PlacesControllerDragHelper.canMoveContainerNode(shortcutNode),
is(PlacesControllerDragHelper.canMoveNode(shortcutNode),
true, "can move folder shortcut node");
}
});
@ -118,7 +118,7 @@ function test() {
is(PlacesControllerDragHelper.canMoveContainer(this.queryId),
true, "can move query id");
is(PlacesControllerDragHelper.canMoveContainerNode(queryNode),
is(PlacesControllerDragHelper.canMoveNode(queryNode),
true, "can move query node");
}
});
@ -159,7 +159,7 @@ function test() {
//var node = PlacesUtils.getFolderContents(id, false, true).root;
var node = getRootChildNode(id);
is(PlacesControllerDragHelper.canMoveContainerNode(node),
is(PlacesControllerDragHelper.canMoveNode(node),
false, "shouldn't be able to move special folder node");
var shortcutId = this.shortcuts[id];
@ -172,7 +172,7 @@ function test() {
true, "should be able to move special folder shortcut id");
LOG("can move shortcut node?");
is(PlacesControllerDragHelper.canMoveContainerNode(shortcutNode),
is(PlacesControllerDragHelper.canMoveNode(shortcutNode),
true, "should be able to move special folder shortcut node");
}
}
@ -197,7 +197,7 @@ function test() {
var tagNode = tagsNode.getChild(0);
is(PlacesControllerDragHelper.canMoveContainerNode(tagNode),
is(PlacesControllerDragHelper.canMoveNode(tagNode),
false, "should not be able to move tag container node");
}
});
@ -218,7 +218,7 @@ function test() {
// test that we can move the read-only folder
is(PlacesControllerDragHelper.canMoveContainer(this.id),
true, "can move read-only folder id");
is(PlacesControllerDragHelper.canMoveContainerNode(readOnlyFolder),
is(PlacesControllerDragHelper.canMoveNode(readOnlyFolder),
true, "can move read-only folder node");
// test that we cannot move the child of a read-only folder
@ -228,7 +228,7 @@ function test() {
is(PlacesControllerDragHelper.canMoveContainer(childFolder.itemId),
false, "cannot move a child of a read-only folder");
is(PlacesControllerDragHelper.canMoveContainerNode(childFolder),
is(PlacesControllerDragHelper.canMoveNode(childFolder),
false, "cannot move a child node of a read-only folder node");
}
});

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

@ -151,6 +151,14 @@ function run_test() {
do_check_eq(observer._itemRemovedId, folderId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
txn1.redoTransaction();
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedId, folderId);
txn1.undoTransaction();
do_check_eq(observer._itemRemovedId, folderId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Test creating an item
// Create to Root
@ -163,8 +171,19 @@ function run_test() {
txn2.undoTransaction();
do_check_eq(observer._itemRemovedId, b);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
do_check_false(bmsvc.isBookmarked(uri("http://www.example.com")));
txn2.redoTransaction();
do_check_true(bmsvc.isBookmarked(uri("http://www.example.com")));
var newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example.com"), {}))[0];
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedId, newId);
txn2.undoTransaction();
do_check_eq(observer._itemRemovedId, newId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Create to a folder
// Create item to a folder
var txn2a = ptSvc.createFolder("Folder", root, bmStartIndex);
ptSvc.doTransaction(txn2a);
var fldrId = bmsvc.getChildFolder(root, "Folder");
@ -177,10 +196,19 @@ function run_test() {
txn2b.undoTransaction();
do_check_eq(observer._itemRemovedId, b2);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
txn2b.redoTransaction();
newId = (bmsvc.getBookmarkIdsForURI(uri("http://www.example2.com"), {}))[0];
do_check_eq(observer._itemAddedIndex, bmStartIndex);
do_check_eq(observer._itemAddedParent, fldrId);
do_check_eq(observer._itemAddedId, newId);
txn2b.undoTransaction();
do_check_eq(observer._itemRemovedId, newId);
do_check_eq(observer._itemRemovedFolder, fldrId);
do_check_eq(observer._itemRemovedIndex, bmStartIndex);
// Testing moving an item
ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), root, -1, "Testing2"));
ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), root, -1, "Testing3"));
ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), root, -1, "Testing3"));
ptSvc.doTransaction(ptSvc.createItem(uri("http://www.example3.com"), fldrId, -1, "Testing4"));
var bkmkIds = bmsvc.getBookmarkIdsForURI(uri("http://www.example3.com"), {});
bkmkIds.sort();
@ -202,6 +230,18 @@ function run_test() {
do_check_eq(observer._itemMovedOldIndex, 2);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
txn3.redoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 2);
txn3.undoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 2);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
// Moving items between different folders
var txn3b = ptSvc.moveItem(bkmk1Id, fldrId, -1);
@ -217,6 +257,18 @@ function run_test() {
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
txn3b.redoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, root);
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, fldrId);
do_check_eq(observer._itemMovedNewIndex, 1);
txn3.undoTransaction();
do_check_eq(observer._itemMovedId, bkmk1Id);
do_check_eq(observer._itemMovedOldParent, fldrId);
do_check_eq(observer._itemMovedOldIndex, 1);
do_check_eq(observer._itemMovedNewParent, root);
do_check_eq(observer._itemMovedNewIndex, 1);
// Test Removing a Folder
ptSvc.doTransaction(ptSvc.createFolder("Folder2", root, -1));
@ -230,6 +282,14 @@ function run_test() {
do_check_eq(observer._itemAddedId, fldrId2);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 3);
txn4.redoTransaction();
do_check_eq(observer._itemRemovedId, fldrId2);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 3);
txn4.undoTransaction();
do_check_eq(observer._itemAddedId, fldrId2);
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 3);
// Test removing an item
var txn5 = ptSvc.removeItem(bkmk2Id);
@ -238,6 +298,14 @@ function run_test() {
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 2);
txn5.undoTransaction();
var newbkmk2Id = observer._itemAddedId;
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 2);
txn5.redoTransaction();
do_check_eq(observer._itemRemovedId, newbkmk2Id);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 2);
txn5.undoTransaction();
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 2);
@ -251,6 +319,14 @@ function run_test() {
do_check_eq(observer._itemRemovedId, sepId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
txn6.redoTransaction();
var newSepId = observer._itemAddedId;
do_check_eq(observer._itemAddedIndex, 1);
do_check_eq(observer._itemAddedParent, root);
txn6.undoTransaction();
do_check_eq(observer._itemRemovedId, newSepId);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
// Test removing a separator
ptSvc.doTransaction(ptSvc.createSeparator(root, 1));
@ -264,6 +340,14 @@ function run_test() {
do_check_eq(observer._itemAddedId, sepId2); //New separator created
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 1);
txn7.redoTransaction();
do_check_eq(observer._itemRemovedId, sepId2);
do_check_eq(observer._itemRemovedFolder, root);
do_check_eq(observer._itemRemovedIndex, 1);
txn7.undoTransaction();
do_check_eq(observer._itemAddedId, sepId2); //New separator created
do_check_eq(observer._itemAddedParent, root);
do_check_eq(observer._itemAddedIndex, 1);
// Test editing item title
var txn8 = ptSvc.editItemTitle(bkmk1Id, "Testing2_mod");
@ -275,6 +359,14 @@ function run_test() {
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "title");
do_check_eq(observer._itemChangedValue, "Testing2");
txn8.redoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "title");
do_check_eq(observer._itemChangedValue, "Testing2_mod");
txn8.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "title");
do_check_eq(observer._itemChangedValue, "Testing2");
// Test editing item uri
var txn9 = ptSvc.editBookmarkURI(bkmk1Id, uri("http://newuri.com"));
@ -286,6 +378,14 @@ function run_test() {
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "uri");
do_check_eq(observer._itemChangedValue, "http://www.example3.com/");
txn9.redoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "uri");
do_check_eq(observer._itemChangedValue, "http://newuri.com/");
txn9.undoTransaction();
do_check_eq(observer._itemChangedId, bkmk1Id);
do_check_eq(observer._itemChangedProperty, "uri");
do_check_eq(observer._itemChangedValue, "http://www.example3.com/");
// Test edit item description
var txn10 = ptSvc.editItemDescription(bkmk1Id, "Description1");
@ -371,6 +471,14 @@ function run_test() {
do_check_eq(0, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(2, bmsvc.getItemIndex(b3));
txn17.redoTransaction();
do_check_eq(2, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(0, bmsvc.getItemIndex(b3));
txn17.undoTransaction();
do_check_eq(0, bmsvc.getItemIndex(b1));
do_check_eq(1, bmsvc.getItemIndex(b2));
do_check_eq(2, bmsvc.getItemIndex(b3));
// editBookmarkMicrosummary
var tmpMs = mss.createMicrosummary(uri("http://testmicro.com"),
@ -436,4 +544,76 @@ function run_test() {
do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["bar","foo"]));
untagTxn.redoTransaction();
do_check_eq(uneval(tagssvc.getTagsForURI(tagURI, { })), uneval(["foo"]));
// Test aggregate removeItem transaction
var bkmk1Id = bmsvc.insertBookmark(root, uri("http://www.mozilla.org/"), 0, "Mozilla");
var bkmk2Id = bmsvc.insertSeparator(root, 1);
var bkmk3Id = bmsvc.createFolder(root, "folder", 2);
var bkmk3_1Id = bmsvc.insertBookmark(bkmk3Id, uri("http://www.mozilla.org/"), 0, "Mozilla");
var bkmk3_2Id = bmsvc.insertSeparator(bkmk3Id, 1);
var bkmk3_3Id = bmsvc.createFolder(bkmk3Id, "folder", 2);
var transactions = [];
transactions.push(ptSvc.removeItem(bkmk1Id));
transactions.push(ptSvc.removeItem(bkmk2Id));
transactions.push(ptSvc.removeItem(bkmk3Id));
var txn = ptSvc.aggregateTransactions("RemoveItems", transactions);
txn.doTransaction();
do_check_eq(bmsvc.getItemIndex(bkmk1Id), -1);
do_check_eq(bmsvc.getItemIndex(bkmk2Id), -1);
do_check_eq(bmsvc.getItemIndex(bkmk3Id), -1);
do_check_eq(bmsvc.getItemIndex(bkmk3_1Id), -1);
do_check_eq(bmsvc.getItemIndex(bkmk3_2Id), -1);
do_check_eq(bmsvc.getItemIndex(bkmk3_3Id), -1);
txn.undoTransaction();
var newBkmk1Id = bmsvc.getIdForItemAt(root, 0);
var newBkmk2Id = bmsvc.getIdForItemAt(root, 1);
var newBkmk3Id = bmsvc.getIdForItemAt(root, 2);
var newBkmk3_1Id = bmsvc.getIdForItemAt(newBkmk3Id, 0);
var newBkmk3_2Id = bmsvc.getIdForItemAt(newBkmk3Id, 1);
var newBkmk3_3Id = bmsvc.getIdForItemAt(newBkmk3Id, 2);
do_check_eq(bmsvc.getItemType(newBkmk1Id), bmsvc.TYPE_BOOKMARK);
do_check_eq(bmsvc.getBookmarkURI(newBkmk1Id).spec, "http://www.mozilla.org/");
do_check_eq(bmsvc.getItemType(newBkmk2Id), bmsvc.TYPE_SEPARATOR);
do_check_eq(bmsvc.getItemType(newBkmk3Id), bmsvc.TYPE_FOLDER);
do_check_eq(bmsvc.getItemTitle(newBkmk3Id), "folder");
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_1Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_1Id), bmsvc.TYPE_BOOKMARK);
do_check_eq(bmsvc.getBookmarkURI(newBkmk3_1Id).spec, "http://www.mozilla.org/");
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_2Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_2Id), bmsvc.TYPE_SEPARATOR);
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_3Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_3Id), bmsvc.TYPE_FOLDER);
do_check_eq(bmsvc.getItemTitle(newBkmk3_3Id), "folder");
txn.redoTransaction();
do_check_eq(bmsvc.getItemIndex(newBkmk1Id), -1);
do_check_eq(bmsvc.getItemIndex(newBkmk2Id), -1);
do_check_eq(bmsvc.getItemIndex(newBkmk3Id), -1);
do_check_eq(bmsvc.getItemIndex(newBkmk3_1Id), -1);
do_check_eq(bmsvc.getItemIndex(newBkmk3_2Id), -1);
do_check_eq(bmsvc.getItemIndex(newBkmk3_3Id), -1);
txn.undoTransaction();
newBkmk1Id = bmsvc.getIdForItemAt(root, 0);
newBkmk2Id = bmsvc.getIdForItemAt(root, 1);
newBkmk3Id = bmsvc.getIdForItemAt(root, 2);
newBkmk3_1Id = bmsvc.getIdForItemAt(newBkmk3Id, 0);
newBkmk3_2Id = bmsvc.getIdForItemAt(newBkmk3Id, 1);
newBkmk3_3Id = bmsvc.getIdForItemAt(newBkmk3Id, 2);
do_check_eq(bmsvc.getItemType(newBkmk1Id), bmsvc.TYPE_BOOKMARK);
do_check_eq(bmsvc.getBookmarkURI(newBkmk1Id).spec, "http://www.mozilla.org/");
do_check_eq(bmsvc.getItemType(newBkmk2Id), bmsvc.TYPE_SEPARATOR);
do_check_eq(bmsvc.getItemType(newBkmk3Id), bmsvc.TYPE_FOLDER);
do_check_eq(bmsvc.getItemTitle(newBkmk3Id), "folder");
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_1Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_1Id), bmsvc.TYPE_BOOKMARK);
do_check_eq(bmsvc.getBookmarkURI(newBkmk3_1Id).spec, "http://www.mozilla.org/");
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_2Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_2Id), bmsvc.TYPE_SEPARATOR);
do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_3Id), newBkmk3Id);
do_check_eq(bmsvc.getItemType(newBkmk3_3Id), bmsvc.TYPE_FOLDER);
do_check_eq(bmsvc.getItemTitle(newBkmk3_3Id), "folder");
}

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

@ -66,7 +66,7 @@
<vbox class="contentPane" flex="1">
<description id="permissionsText" control="url"/>
<separator class="thin"/>
<label id="urlLabel" control="url" value="&address.label;"/>
<label id="urlLabel" control="url" value="&address.label;" accesskey="&address.accesskey;"/>
<hbox align="start">
<textbox id="url" flex="1"
oninput="gPermissionManager.onHostInput(event.target);"

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

@ -97,11 +97,11 @@
<separator class="thin"/>
<checkbox id="tellMaybeAttackSite"
label="&tellMaybeAttackSite.label;"
label="&tellMaybeAttackSite2.label;"
accesskey="&tellMaybeAttackSite.accesskey;"
preference="browser.safebrowsing.malware.enabled" />
<checkbox id="tellMaybeForgery"
label="&tellMaybeForgery.label;"
label="&tellMaybeForgery2.label;"
accesskey="&tellMaybeForgery.accesskey;"
preference="browser.safebrowsing.enabled" />
</groupbox>

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

@ -1,7 +1,7 @@
function test() {
waitForExplicitFinish();
// setup a phony hander to ensure the app pane will be populated.
// Setup a phony handler to ensure the app pane will be populated.
var handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
createInstance(Ci.nsIWebHandlerApp);
handler.name = "App pane alive test";
@ -23,8 +23,9 @@ function test() {
observe: function(win, topic, data) {
if (topic != "app-handler-pane-loaded")
return;
runTest(win);
obs.removeObserver(observer, "app-handler-pane-loaded");
runTest(win);
}
};
obs.addObserver(observer, "app-handler-pane-loaded", false);

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

@ -47,18 +47,4 @@ ifdef ENABLE_TESTS
DIRS = test
endif
MODULE = browsersearch
XPIDL_MODULE = browsersearch
XPIDLSRCS = nsIBrowserSearchService.idl
EXTRA_PP_COMPONENTS = nsSearchService.js \
nsSearchSuggestions.js
ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
DEFINES += -DOFFICIAL_BUILD=1
endif
DEFINES += -DMOZ_DISTRIBUTION_ID=$(MOZ_DISTRIBUTION_ID)
include $(topsrcdir)/config/rules.mk

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

@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_346337.js \
browser_346337_sample.html \
browser_350525.js \
browser_367052.js \
browser_393716.js \

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

@ -38,15 +38,20 @@ function test() {
/** Test for Bug 346337 **/
let fieldList = {
"//input[@name='testinput']": Date.now().toString(),
"//input[@name='bad name']": Math.random().toString(),
"//input[@name='input']": Date.now().toString(),
"//input[@name='spaced 1']": Math.random().toString(),
"//input[3]": "three",
"//input[@type='checkbox']": true,
"//input[@name='uncheck']": false,
"//input[@type='radio'][1]": false,
"//input[@type='radio'][2]": true,
"//input[@type='radio'][3]": false,
"//select": 2,
"//select[@multiple]": [1, 3],
"//textarea[1]": "",
"//textarea[3]": "Some more test\n" + new Date()
"//textarea[2]": "Some text... " + Math.random(),
"//textarea[3]": "Some more text\n" + new Date(),
"//input[@type='file']": "/dev/null"
};
function getElementByXPath(aTab, aQuery) {
@ -91,8 +96,9 @@ function test() {
let privacy_level = gPrefService.getIntPref("browser.sessionstore.privacy_level");
gPrefService.setIntPref("browser.sessionstore.privacy_level", 2);
todo(false, "test doesn't run from the harness's http server");
let tab = tabbrowser.addTab("https://bugzilla.mozilla.org/attachment.cgi?id=328502");
let testURL = "chrome://mochikit/content/browser/" +
"browser/components/sessionstore/test/browser/browser_346337_sample.html";
let tab = tabbrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
for (let xpath in fieldList)
setFormValue(tab, xpath, fieldList[xpath]);

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

@ -0,0 +1,36 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Test for bug 346337</title>
<h3>Text Fields</h3>
<input type="text" name="input">
<input type="text" name="spaced 1">
<input>
<h3>Checkboxes and Radio buttons</h3>
<input type="checkbox" name="check"> Check 1
<input type="checkbox" name="uncheck" checked> Check 2
<p>
<input type="radio" name="group" value="1"> Radio 1
<input type="radio" name="group" value="some"> Radio 2
<input type="radio" name="group" checked> Radio 3
<h3>Selects</h3>
<select name="any">
<option value="1"> Select 1
<option value="some"> Select 2
<option>Select 3
</select>
<select multiple="multiple">
<option value=1> Multi-select 1
<option value=2> Multi-select 2
<option value=3> Multi-select 3
<option value=4> Multi-select 4
</select>
<h3>Text Areas</h3>
<textarea name="testarea"></textarea>
<textarea name="sized one" rows="5" cols="25"></textarea>
<textarea></textarea>
<h3>File Selector</h3>
<input type="file">

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

@ -152,7 +152,7 @@ function (engineURL, iconURL)
debug(ex);
Components.utils.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex);
var searchBundle = srGetStrBundle("chrome://browser/locale/search.properties");
var searchBundle = srGetStrBundle("chrome://global/locale/search/search.properties");
var brandBundle = srGetStrBundle("chrome://branding/locale/brand.properties");
var brandName = brandBundle.GetStringFromName("brandShortName");
var title = searchBundle.GetStringFromName("error_invalid_engine_title");

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

@ -66,7 +66,6 @@ bin/components/autocomplete.xpt
bin/components/autoconfig.xpt
bin/components/browsercompsbase.xpt
bin/components/browserplaces.xpt
bin/components/browsersearch.xpt
bin/components/browser-feeds.xpt
bin/components/caps.xpt
bin/components/chardet.xpt
@ -167,6 +166,7 @@ bin/components/spellchecker.xpt
bin/components/storage.xpt
bin/components/profile.xpt
bin/components/toolkitprofile.xpt
bin/components/toolkitsearch.xpt
bin/components/txtsvc.xpt
bin/components/txmgr.xpt
bin/components/uconv.xpt

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

@ -69,6 +69,7 @@ BRANDING_FILES = \
DEFINES += \
-DAB_CD=$(AB_CD) \
-DPKG_BASENAME=$(PKG_BASENAME) \
-DPKG_INST_BASENAME=$(PKG_INST_BASENAME) \
-DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
-DMOZ_APP_DISPLAYNAME=${MOZ_APP_DISPLAYNAME} \

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

@ -2,8 +2,8 @@
!define AppVersion "@MOZ_APP_VERSION@"
!define GREVersion @MOZILLA_VERSION@
!define AB_CD "@AB_CD@"
!define FileInstallerEXE "@PKG_BASENAME@.installer.exe"
!define FileInstallerMSI "@PKG_BASENAME@.installer.msi"
!define FileInstallerEXE "@PKG_INST_BASENAME@.exe"
!define FileInstallerMSI "@PKG_INST_BASENAME@.msi"
!define FileInstallerNETRoot "@PKG_BASENAME@.net-installer"
!define FileMainEXE "@MOZ_APP_NAME@.exe"

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

@ -73,7 +73,6 @@ bin\components\autocomplete.xpt
bin\components\autoconfig.xpt
bin\components\browsercompsbase.xpt
bin\components\browserplaces.xpt
bin\components\browsersearch.xpt
bin\components\browser-feeds.xpt
bin\components\caps.xpt
bin\components\chardet.xpt
@ -171,6 +170,7 @@ bin\components\saxparser.xpt
bin\components\shistory.xpt
bin\components\storage.xpt
bin\components\toolkitprofile.xpt
bin\components\toolkitsearch.xpt
bin\components\txtsvc.xpt
bin\components\txmgr.xpt
#ifdef MOZ_USE_NATIVE_UCONV

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

@ -74,6 +74,7 @@ DEFINES += \
-DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
-DLOCALE_SRCDIR=$(call core_abspath,$(LOCALE_SRCDIR)) \
-DPKG_BASENAME=$(PKG_BASENAME) \
-DPKG_INST_BASENAME=$(PKG_INST_BASENAME) \
$(NULL)
ifndef MOZ_BRANDING_DIRECTORY
@ -192,7 +193,7 @@ PACKAGER_NO_LIBS = 1
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
include $(call EXPAND_LOCALE_SRCDIR,toolkit/locales)/installer/windows/charset.mk
repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/install/sea/$(PKG_BASENAME).installer.exe
repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
repackage-win32-installer: $(WIN32_INSTALLER_IN) $(SUBMAKEFILES)
ifneq (en-US,$(AB_CD))
@echo "Verifying $(AB_CD) installer variable usage"
@ -227,7 +228,7 @@ endif
app.7z > $(WIN32_INSTALLER_OUT)
chmod 0755 $(WIN32_INSTALLER_OUT)
repackage-win32-installer-%: WIN32_INSTALLER_IN=$(_ABS_DIST)/install/sea/$(PKG_BASENAME).installer.exe
repackage-win32-installer-%: WIN32_INSTALLER_IN=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
repackage-win32-installer-%: $(WIN32_INSTALLER_IN)
@$(MAKE) repackage-win32-installer AB_CD=$* WIN32_INSTALLER_IN=$(WIN32_INSTALLER_IN)
@ -267,20 +268,22 @@ ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
mv $(_ABS_DIST)/l10n-stage/$(MOZ_PKG_APPNAME)/$(_APPNAME)/Contents/Resources/en.lproj $(_ABS_DIST)/l10n-stage/$(MOZ_PKG_APPNAME)/$(_APPNAME)/Contents/Resources/$(AB).lproj
endif
endif
$(NSINSTALL) -D $(DIST)/l10n-stage/$(PKG_PATH)
cd $(DIST)/l10n-stage; \
$(MAKE_PACKAGE)
mv -f $(DIST)/l10n-stage/$(PACKAGE) $(DIST)
$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
mv -f $(DIST)/l10n-stage/$(PACKAGE) $(DIST)/$(PACKAGE)
repackage-zip-%: ZIP_IN=$(_ABS_DIST)/$(PACKAGE)
repackage-zip-%: $(ZIP_IN)
@$(MAKE) repackage-zip AB_CD=$* ZIP_IN=$(ZIP_IN)
langpack-%: LANGPACK_FILE=$(_ABS_DIST)/install/firefox-$(MOZ_APP_VERSION).$(AB_CD).langpack.xpi
langpack-%: LANGPACK_FILE=$(_ABS_DIST)/$(PKG_LANGPACK_PATH)$(PKG_LANGPACK_BASENAME).xpi
langpack-%: AB_CD=$*
langpack-%: XPI_NAME=locale-$*
langpack-%:
@echo "Making langpack $(LANGPACK_FILE)"
$(NSINSTALL) -D $(DIST)/install
$(NSINSTALL) -D $(DIST)/$(PKG_LANGPACK_PATH)
@$(RM) -rf $(DIST)/xpi-stage/locale-$(AB_CD)
@$(MAKE) libs-$(AB_CD) USE_EXTENSION_MANIFEST=1
$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) -I$(call EXPAND_LOCALE_SRCDIR,toolkit/locales)/defines.inc -I$(LOCALE_SRCDIR)/defines.inc $(srcdir)/generic/install.rdf > $(FINAL_TARGET)/install.rdf
@ -335,7 +338,53 @@ 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)"
$(NSINSTALL) -D $(_ABS_DIST)/$(PKG_INST_PATH)
@$(WGET) -nv --output-document $(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe $(EN_US_BINARY_URL)/$(PKG_PATH)$(PKG_INST_BASENAME).exe
@echo "Downloaded $(EN_US_BINARY_URL)/$(PKG_PATH)$(PKG_INST_BASENAME).exe to $(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME)"
endif
#These make targets call prepare-repackages by setting different UPLOAD_DIR
prepare-upload-latest-%:
@$(MAKE) prepare-repackages-$* UPLOAD_DIR=$(DIST)/upload/latest
prepare-upload-dated-%:
@$(MAKE) prepare-repackages-$* UPLOAD_DIR=$(DIST)/upload/`date "+%Y-%m-%d-%H"`-$(MOZ_PKG_APPNAME)$(MOZ_APP_VERSION)-l10n
#Each platform uploads their xpi files to different folders
ifeq (Linux, $(OS_ARCH))
XPI_DESTINATION = linux-xpi
endif
ifeq (Darwin, $(OS_ARCH))
XPI_DESTINATION = mac-xpi
endif
ifeq (WINNT, $(OS_ARCH))
XPI_DESTINATION = windows-xpi
endif
# This target will generate a UPLOAD_DIR folder with
# l10n repackages in the way that we offer l10n nightlies
# 1) ./ the binary
# 2) ./{linux,mac,windows}-xpi/locale.xpi
prepare-repackages-%:
ifndef XPI_DESTINATION
$(error XPI_DESTINATION not defined; \
This is the folder where the xpi files will be moved to)
endif
ifndef UPLOAD_DIR
$(error UPLOAD_DIR not defined)
endif
$(NSINSTALL) -D $(UPLOAD_DIR)
$(NSINSTALL) -D $(UPLOAD_DIR)/$(XPI_DESTINATION)
# Move the langpack
mv $(DIST)/install/firefox-$(MOZ_APP_VERSION).$*.langpack.xpi \
$(UPLOAD_DIR)/$(XPI_DESTINATION)/$*.xpi
# Move the repackage
mv $(DIST)/firefox-$(MOZ_APP_VERSION).$*.* \
$(UPLOAD_DIR)/.
# Move the windows installer
ifeq (WINNT, $(OS_ARCH))
mv $(DIST)/install/sea/firefox-$(MOZ_APP_VERSION).$*.win32.installer.exe \
$(UPLOAD_DIR)/.
endif
# Set the permissions that the folders will have in ftp once uploaded
chmod -vR 775 $(UPLOAD_DIR)

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

@ -1,45 +1,60 @@
af
ar
as
be
bg
ca
cs
cy
da
de
el
en-GB
eo
es-AR
es-ES
et
eu
fi
fr
fy-NL
ga-IE
gl
gu-IN
he
hi-IN
hu
id
is
it
ja
ja-JP-mac
ka
kn
ko
ku
lt
mk
mn
mr
nb-NO
nl
nn-NO
oc
pa-IN
pl
pt-BR
pt-PT
ro
ru
si
sk
sq
sr
sv-SE
ta
te
th
tr
uk
zh-CN

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

@ -60,8 +60,8 @@
<!ENTITY generalEncoding "Encoding:">
<!ENTITY generalMetaName "Name">
<!ENTITY generalMetaContent "Content">
<!ENTITY generalSecurityMore "More">
<!ENTITY generalSecurityMore.accesskey "o">
<!ENTITY generalSecurityDetails "Details">
<!ENTITY generalSecurityDetails.accesskey "D">
<!ENTITY mediaTab "Media">
<!ENTITY mediaTab.accesskey "M">

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

@ -8,6 +8,7 @@
<!ENTITY removeallpermissions.label "Remove All Sites">
<!ENTITY removeallpermissions.accesskey "e">
<!ENTITY address.label "Address of web site:">
<!ENTITY address.accesskey "d">
<!ENTITY block.label "Block">
<!ENTITY block.accesskey "B">
<!ENTITY session.label "Allow for Session">

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

@ -5,14 +5,14 @@
The methods by which forged (phished) and attack sites will be detected by
phishing providers will vary from human review to machine-based heuristics to a
combination of both, so it's important that these strings and
useDownloadedList.label convey the meaning "suspected" (and not something like
useDownloadedList.label convey the meaning "reported" (and not something like
"known").
-->
<!ENTITY tellMaybeAttackSite.label "Tell me if the site I'm visiting is a suspected attack site">
<!ENTITY tellMaybeAttackSite2.label "Block reported attack sites">
<!ENTITY tellMaybeAttackSite.accesskey "k">
<!ENTITY tellMaybeForgery.label "Tell me if the site I'm visiting is a suspected forgery">
<!ENTITY tellMaybeForgery.accesskey "T">
<!ENTITY tellMaybeForgery2.label "Block reported web forgeries">
<!ENTITY tellMaybeForgery.accesskey "B">
<!ENTITY addonExceptions.label "Exceptions…">
<!ENTITY addonExceptions.accesskey "E">

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

@ -6,20 +6,5 @@ cmd_clearHistory_accesskey=C
cmd_showSuggestions=Show Suggestions
cmd_showSuggestions_accesskey=S
addEngineConfirmTitle=Add Search Engine
addEngineConfirmation=Add "%S" to the list of engines available in the search bar?\n\nFrom: %S
addEngineUseNowText=Start &using it right away
addEngineAddButtonLabel=Add
error_loading_engine_title=Download Error
# LOCALIZATION NOTE (error_loading_engine_msg2): %1$S = brandShortName, %2$S = location
error_loading_engine_msg2=%S could not download the search plugin from:\n%S
error_duplicate_engine_msg=%S could not install the search plugin from "%S" because an engine with the same name already exists.
error_invalid_engine_title=Install Error
# LOCALIZATION NOTE (error_invalid_engine_msg): %S = brandShortName
error_invalid_engine_msg=This search engine isn't supported by %S and can't be installed.
cmd_addFoundEngine=Add "%S"
suggestion_label=Suggestions

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

@ -3,15 +3,8 @@
<Description>eBay - Online actions</Description>
<InputEncoding>ISO-8859-1</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAADAAAAA/wAAAABAAABAQAAAgEAAAMBAAAD/QAAAAIAAAECAAACAgAAAwIAAAP+AAAAAwAAAQMAAAIDAAADAwAAA/8AAAAD/AABA/wAAgP8AAMD/AAD//wAAAABAAEAAQACAAEAAwABAAP8AQAAAQEAAQEBAAIBAQADAQEAA/0BAAACAQABAgEAAgIBAAMCAQAD/gEAAAMBAAEDAQACAwEAAwMBAAP/AQAAA/0AAQP9AAID/QADA/0AA//9AAAAAgABAAIAAgACAAMAAgAD/AIAAAECAAEBAgACAQIAAwECAAP9AgAAAgIAAQICAAICAgADAgIAA/4CAAADAgABAwIAAgMCAAMDAgAD/wIAAAP+AAED/gACA/4AAwP+AAP//gAAAAMAAQADAAIAAwADAAMAA/wDAAABAwABAQMAAgEDAAMBAwAD/QMAAAIDAAECAwACAgMAAwIDAAP+AwAAAwMAAQMDAAIDAwADAwMAA/8DAAAD/wABA/8AAgP/AAMD/wAD//8AAAAD/AEAA/wCAAP8AwAD/AP8A/wAAQP8AQED/AIBA/wDAQP8A/0D/AACA/wBAgP8AgID/AMCA/wD/gP8AAMD/AEDA/wCAwP8AwMD/AP/A/wAA//8AQP//AID//wDA//8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8fHx8fHx8fHx8fHx8AAB8cGRkUFAcHBx8fBUKfAAAfFBkfHxNHF4cb29vCnwAAHxkZFBQUBx8HG98bwp8fAB8ZGR8UGQcXhxvb28KFXx8fHZkZGRNHBwcfG8jCgoQfAB8fHx8HBx8b29vCnwPCnwAAAB8fBwcfHx8EBB8Dwp8AAAAAHx8fHwAfHx8AHx8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA//8AAP//AACAAwAAAAMAAAADAAAAAQAAAAAAAAAAAACAAAAA4AAAAPCIAAD//wAA//8AAP//AAA=</Image>
<Url type="text/html" method="GET" template="http://search.ebay.com/search/search.dll">
<Param name="query" value="{searchTerms}"/>
<Param name="MfcISAPICommand" value="GetResult"/>
<Param name="ht" value="1"/>
<Param name="ebaytag1" value="ebayreg"/>
<Param name="srchdesc" value="n"/>
<Param name="maxRecordsReturned" value="300"/>
<Param name="maxRecordsPerPage" value="50"/>
<Param name="SortProperty" value="MetaEndSort"/>
<Url type="text/html" method="GET" template="http://rover.ebay.com/rover/1/711-47294-18009-3/4">
<Param name="satitle" value="{searchTerms}"/>
</Url>
<SearchForm>http://search.ebay.com/</SearchForm>
</SearchPlugin>

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

@ -1,27 +0,0 @@
<?xml version="1.0"?>
#filter substitution
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the locales being supplied by this package -->
<RDF:Seq about="urn:mozilla:locale:root">
<RDF:li resource="urn:mozilla:locale:@AB_CD@"/>
</RDF:Seq>
<!-- locale information -->
<RDF:Description about="urn:mozilla:locale:@AB_CD@">
<chrome:packages>
<RDF:Seq about="urn:mozilla:locale:@AB_CD@:packages">
<RDF:li resource="urn:mozilla:locale:@AB_CD@:inspector"/>
</RDF:Seq>
</chrome:packages>
</RDF:Description>
<!-- Version Information. State that we work only with major version of this
package. -->
<RDF:Description about="urn:mozilla:locale:@AB_CD@:inspector"
chrome:localeVersion="@MOZILLA_LOCALE_VERSION@" />
</RDF:RDF>

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

@ -157,10 +157,10 @@ Sanitizer.prototype = {
formdata: {
clear: function ()
{
//Clear undo history of all searchBars
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var windows = windowManagerInterface.getEnumerator("navigator:browser");
// Clear undo history of all searchBars
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var windows = windowManager.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
var searchBar = windows.getNext().document.getElementById("searchbar");
if (searchBar) {
@ -173,9 +173,23 @@ Sanitizer.prototype = {
.getService(Components.interfaces.nsIFormHistory2);
formHistory.removeAllEntries();
},
get canClear()
{
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var windows = windowManager.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
var searchBar = windows.getNext().document.getElementById("searchbar");
if (searchBar) {
var transactionMgr = searchBar.textbox.editor.transactionManager;
if (searchBar.value ||
transactionMgr.numberOfUndoItems ||
transactionMgr.numberOfRedoItems)
return true;
}
}
var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory2);
return formHistory.hasEntries;

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

@ -126,10 +126,6 @@ textbox[disabled] {
#generalPanel > #titletext {
-moz-margin-start: 5px;
}
#metaTags > .groupbox-body {
-moz-margin-start: 5px;
-moz-margin-end: 1px;
}
groupbox.collapsable caption .caption-icon {
width: 9px;
@ -155,6 +151,8 @@ groupbox tree {
}
groupbox.treebox .groupbox-body {
-moz-margin-start: 5px;
-moz-margin-end: 1px;
padding-top: 0;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 156 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 211 B

Двоичные данные
browser/themes/pinstripe/browser/bookmark_toolbar_background.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 403 B

78
browser/themes/pinstripe/browser/browser.css Executable file → Normal file
Просмотреть файл

@ -47,10 +47,6 @@
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace svg url("http://www.w3.org/2000/svg");
#main-window {
-moz-binding: url("chrome://global/skin/globalBindings.xml#unifiedWindow");
}
#main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
border-top: 1px solid rgba(0,0,0,0.65);
-moz-appearance: none;
@ -59,18 +55,12 @@
/* ----- INACTIVE WINDOW ----- */
#main-window:not([active="true"]) > #navigator-toolbox > toolbar {
border-top-color: rgba(255,255,255,0.45);
border-bottom-color: rgba(0,0,0,0.35);
background-color: #cfcfcf;
}
#main-window:not([active="true"]) > #navigator-toolbox > #nav-bar {
background-image: url("chrome://global/skin/toolbar/toolbar-background-inactive.png");
}
#main-window:not([active="true"]) > #navigator-toolbox > #PersonalToolbar {
background-image: url("chrome://browser/skin/bookmark_toolbar_background-inactive.png");
background-color: -moz-mac-chrome-inactive;
}
#main-window:not([active="true"]) > #navigator-toolbox > toolbar > toolbaritem,
@ -92,20 +82,8 @@
color: #575757;
}
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] > .tab-image-middle,
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] > .tab-closebutton,
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] > .tab-close-button {
background-image: url("chrome://browser/skin/tabbrowser/tab-middle-inactive.png");
}
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] > .tab-image-left,
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"][chromedir="rtl"] > .tab-image-right {
background: url("chrome://browser/skin/tabbrowser/tab-left-inactive.png") no-repeat;
}
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] > .tab-image-right,
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"][chromedir="rtl"] > .tab-image-left {
background: url("chrome://browser/skin/tabbrowser/tab-right-inactive.png") no-repeat;
#main-window:not([active="true"]) .tabbrowser-tab[selected="true"] {
background-color: -moz-mac-chrome-inactive;
}
/* ----- SEARCH FIELD ----- */
@ -117,7 +95,7 @@
/* ----- BOOKMARK TOOLBAR ----- */
#PersonalToolbar {
background: url("chrome://browser/skin/bookmark_toolbar_background.gif") repeat-x center center;
background: url("chrome://browser/skin/bookmark_toolbar_background.png") repeat-x center center -moz-mac-chrome-active;
border-top: 1px solid rgba(255,255,255,0.25);
border-bottom: 2px solid;
-moz-border-bottom-colors: rgba(0,0,0,0.35) transparent;
@ -1597,8 +1575,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
#nav-bar {
background-color: #9e9e9e;
border-top: none;
border-bottom: 1px solid rgba(0,0,0,0.35);
background-image: url("chrome://global/skin/toolbar/toolbar-background.gif");
background-repeat: repeat-x;
background-position: top right;
@ -1627,7 +1603,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
}
.tab-icon {
margin: 0 0 4px 0;
margin: 0 0 3px 0;
opacity: 0.6;
}
@ -1654,17 +1630,20 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
.tabbrowser-tab {
-moz-binding: url("chrome://browser/skin/browser.xml#tabbrowser-tab") !important;
-moz-appearance: none;
-moz-border-radius: 0 0 3px 3px;
color: #222;
-moz-box-pack: center;
margin: 0 3px 3px 2px;
padding: 0px;
border: none !important;
min-width: 1px !important;
text-align: center;
height: 27px;
height: 22px;
}
.tabbrowser-tab[selected="true"] {
-moz-user-focus: normal;
background-color: -moz-mac-chrome-active;
}
.tabbrowser-tab[selected="true"]:focus > .tab-image-middle > .tab-text-stack > .tab-text {
@ -1685,8 +1664,17 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
padding: 0px;
}
.tab-image-left,
.tab-image-right,
.tabbrowser-tab > .tab-image-middle,
.tabbrowser-tab > .tab-close-button {
margin-bottom: -3px;
padding-top: 1px;
}
.tabbrowser-tab > .tab-image-right,
.tabbrowser-tab[chromedir="rtl"] > .tab-image-left {
margin-right: -3px;
background: url("chrome://browser/skin/tabbrowser/tab-right.png") no-repeat;
}
@ -1697,6 +1685,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
.tabbrowser-tab > .tab-image-left,
.tabbrowser-tab[chromedir="rtl"] > .tab-image-right {
margin-left: -2px;
background: url("chrome://browser/skin/tabbrowser/tab-left.png") no-repeat;
}
@ -1706,7 +1695,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
}
.tabbrowser-tab > .tab-image-middle,
.tabbrowser-tab > .tab-closebutton {
.tabbrowser-tab > .tab-close-button {
background: url("chrome://browser/skin/tabbrowser/tab-middle.png") repeat-x;
-moz-box-pack: center;
}
@ -1720,16 +1709,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url("chrome://global/skin/tree/item-grayscale.png");
}
.tabs-closebutton {
margin: 0;
list-style-image: url("chrome://global/skin/icons/closetab.png") !important;
}
.tabs-closebutton:hover:active {
list-style-image: url("chrome://global/skin/icons/closetab-active.png") !important;
border: none !important;
}
.tabbrowser-strip {
margin-top: -1px;
border-bottom: 1px solid #404040;
@ -1741,7 +1720,8 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
-moz-box-pack: center;
-moz-box-align: center;
background: url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
height: 27px;
height: 25px;
margin-bottom: 0;
}
.tabs-left {
@ -1790,7 +1770,7 @@ tabbrowser > tabbox > tabpanels {
list-style-image: url("chrome://global/skin/icons/closetab.png");
-moz-appearance: none;
border: none !important;
padding: 0 0 4px 0;
padding: 0 0 3px 0;
margin: 0;
background: inherit;
cursor: default;
@ -1806,21 +1786,12 @@ tabbrowser > tabbox > tabpanels {
list-style-image: url("chrome://global/skin/icons/closetab-active.png");
}
.tabbrowser-tab > .tab-close-button {
background-image: url("chrome://browser/skin/tabbrowser/tab-middle.png");
background-repeat: repeat-x;
}
.tabbrowser-tab[selected="true"] > .tab-close-button {
/* Make this button focusable so clicking on it will not focus the tab while
it's getting closed */
-moz-user-focus: normal;
}
.tabbrowser-tab:not([selected="true"]) > .tab-close-button {
background-image: url("chrome://browser/skin/tabbrowser/tab-middle-bkgnd.png");
}
.tabbrowser-arrowscrollbox > .scrollbutton-up,
.tabbrowser-arrowscrollbox > .scrollbutton-down-stack > .scrollbutton-down[chromedir="rtl"] {
border: 0;
@ -1897,8 +1868,7 @@ tabbrowser > tabbox > tabpanels {
-moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
-moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
margin: 0;
padding-left: 0;
padding-right: 0;
padding: 2px 0 0 0;
}
.tabs-alltabs-button:hover {
background-color: rgba(0,0,0,0.10);

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

@ -1,7 +1,6 @@
classic.jar:
% skin browser classic/1.0 %skin/classic/browser/
skin/classic/browser/bookmark_toolbar_background.gif
skin/classic/browser/bookmark_toolbar_background-inactive.png
skin/classic/browser/bookmark_toolbar_background.png
skin/classic/browser/bookmark-open-left.png
skin/classic/browser/bookmark-open-mid.png
skin/classic/browser/bookmark-open-right.png
@ -129,16 +128,10 @@ classic.jar:
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
skin/classic/browser/tabbrowser/tab-left.png (tabbrowser/tab-left.png)
skin/classic/browser/tabbrowser/tab-left-bkgnd.png (tabbrowser/tab-left-bkgnd.png)
skin/classic/browser/tabbrowser/tab-left-hover.png (tabbrowser/tab-left-hover.png)
skin/classic/browser/tabbrowser/tab-left-inactive.png (tabbrowser/tab-left-inactive.png)
skin/classic/browser/tabbrowser/tab-middle.png (tabbrowser/tab-middle.png)
skin/classic/browser/tabbrowser/tab-middle-bkgnd.png (tabbrowser/tab-middle-bkgnd.png)
skin/classic/browser/tabbrowser/tab-middle-hover.png (tabbrowser/tab-middle-hover.png)
skin/classic/browser/tabbrowser/tab-middle-inactive.png (tabbrowser/tab-middle-inactive.png)
skin/classic/browser/tabbrowser/tab-right.png (tabbrowser/tab-right.png)
skin/classic/browser/tabbrowser/tab-right-bkgnd.png (tabbrowser/tab-right-bkgnd.png)
skin/classic/browser/tabbrowser/tab-right-hover.png (tabbrowser/tab-right-hover.png)
skin/classic/browser/tabbrowser/tab-right-inactive.png (tabbrowser/tab-right-inactive.png)
skin/classic/browser/tabbrowser/tabs-bottom-bg.png (tabbrowser/tabs-bottom-bg.png)
skin/classic/browser/urlbar/endcap.png (urlbar/endcap.png)
skin/classic/browser/urlbar/endcap-rtl.png (urlbar/endcap-rtl.png)

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

@ -39,27 +39,13 @@
@import "chrome://global/skin/";
#main-window {
-moz-binding: url("chrome://global/skin/globalBindings.xml#unifiedWindow");
}
#main-window:not([active="true"]) > #topStackBar {
background-image: url("chrome://global/skin/toolbar/toolbar-background-inactive.png");
background-color: #cfcfcf;
border-bottom: 1px solid rgba(0,0,0,0.35);
}
#main-window:not([active="true"]) > #topStackBar > #viewGroup {
opacity: 0.7;
}
#topStackBar {
display: -moz-box;
background-color: #969696;
border-bottom: 1px solid #404040;
background-image: url("chrome://global/skin/toolbar/toolbar-background.gif");
background-repeat: repeat-x;
background-position: top right;
-moz-appearance: -moz-mac-unified-toolbar;
padding: 4px 0 8px;
-moz-box-pack: center;
}

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

@ -1,17 +1,5 @@
/* Unified toolbar */
#places {
-moz-binding: url("chrome://global/skin/globalBindings.xml#unifiedWindow");
}
/* Inactive Window */
#places:not([active="true"]) > #placesToolbox > #placesToolbar {
background-image: url("chrome://global/skin/toolbar/toolbar-background-inactive.png");
background-color: #cfcfcf;
border-bottom: 1px solid rgba(0,0,0,0.35);
}
#places:not([active="true"]) > #placesToolbox > #placesToolbar > toolbarbutton,
#places:not([active="true"]) > #placesToolbox > #placesToolbar > #searchFilter {
opacity: 0.7;
@ -79,11 +67,6 @@
}
#placesToolbar {
background-color: #999;
border-bottom: 1px solid #404040;
background-image: url("chrome://global/skin/toolbar/toolbar-background.gif");
background-repeat: repeat-x;
background-position: 3px 0px;
margin-top: -3px;
padding: 0 4px;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.8 KiB

После

Ширина:  |  Высота:  |  Размер: 3.5 KiB

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

@ -39,16 +39,6 @@
# ***** END LICENSE BLOCK *****
*/
#BrowserPreferences {
-moz-binding: url("chrome://global/skin/globalBindings.xml#unifiedPrefwindow");
}
#BrowserPreferences:not([active="true"]) > .paneSelector {
background-image: url("chrome://global/skin/toolbar/toolbar-background-tall-inactive.png");
background-color: #cfcfcf;
border-bottom: 1px solid rgba(0,0,0,0.35);
}
#BrowserPreferences:not([active="true"]) > .paneSelector > radio {
opacity: 0.7;
}
@ -69,11 +59,7 @@
.paneSelector {
list-style-image: url("chrome://browser/skin/preferences/Options.png");
padding: 0 5px 2px 5px;
background-color: #999;
border-bottom: 1px solid #404040;
background-image: url("chrome://global/skin/toolbar/toolbar-background-tall.png");
background-repeat: repeat-x;
background-position: top right;
-moz-appearance: -moz-mac-unified-toolbar;
margin: 0;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 342 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 274 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 285 B

После

Ширина:  |  Высота:  |  Размер: 318 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 185 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 141 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 141 B

После

Ширина:  |  Высота:  |  Размер: 161 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 343 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 290 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 296 B

После

Ширина:  |  Высота:  |  Размер: 333 B

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

@ -1809,12 +1809,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
color: HighlightText !important;
}
/* Bookmark drag and drop styles */
.bookmark-item[dragover-into="true"] > .menu-iconic-text {
background: Highlight !important;
color: HighlightText !important;
}
/* rules for menupopup drop indicators */
.menupopup-drop-indicator-bar {
position: relative;

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

@ -1,5 +1,5 @@
#!env perl
#!env perl
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@ -35,33 +35,33 @@
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
use File::Spec::Unix;
use strict;
print "Usage: $0 dest_path start_path\n" if ($#ARGV+1 != 2);
my $finish = my_canonpath(shift);
my $start = my_canonpath(shift);
my $res = File::Spec::Unix->abs2rel($finish, $start);
#print STDERR "abs2rel($finish,$start) = $res\n";
print "$res\n";
sub my_canonpath($) {
my ($file) = @_;
my (@inlist, @outlist, $dir);
# Do what File::Spec::Unix->no_upwards should do
my @inlist = split(/\//, File::Spec::Unix->canonpath($file));
foreach $dir (@inlist) {
if ($dir eq '..') {
pop @outlist;
} else {
push @outlist, $dir;
}
}
$file = join '/',@outlist;
return $file;
}
use File::Spec::Unix;
use strict;
print "Usage: $0 dest_path start_path\n" if ($#ARGV+1 != 2);
my $finish = my_canonpath(shift);
my $start = my_canonpath(shift);
my $res = File::Spec::Unix->abs2rel($finish, $start);
#print STDERR "abs2rel($finish,$start) = $res\n";
print "$res\n";
sub my_canonpath($) {
my ($file) = @_;
my (@inlist, @outlist, $dir);
# Do what File::Spec::Unix->no_upwards should do
my @inlist = split(/\//, File::Spec::Unix->canonpath($file));
foreach $dir (@inlist) {
if ($dir eq '..') {
pop @outlist;
} else {
push @outlist, $dir;
}
}
$file = join '/',@outlist;
return $file;
}

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

@ -1708,7 +1708,8 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
if (NS_FAILED(rv)) return rv;
if (appType == nsIDocShell::APP_TYPE_MAIL)
{
*result = mIsMailJavaScriptEnabled;
// we are temporarily disabling js in mail for TB 3.0 b1
*result = PR_FALSE; // mIsMailJavaScriptEnabled;
}
}
}

436
config/JarMaker.py Normal file
Просмотреть файл

@ -0,0 +1,436 @@
# ***** 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 build system.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# 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 *****
'''jarmaker.py provides a python class to package up chrome content by
processing jar.mn files.
See the documentation for jar.mn on MDC for further details on the format.
'''
import sys
import os
import os.path
import re
import logging
from time import localtime
from optparse import OptionParser
from MozZipFile import ZipFile
from cStringIO import StringIO
from datetime import datetime
from utils import pushback_iter
from Preprocessor import Preprocessor
__all__ = ['JarMaker']
class ZipEntry:
'''Helper class for jar output.
This class defines a simple file-like object for a zipfile.ZipEntry
so that we can consecutively write to it and then close it.
This methods hooks into ZipFile.writestr on close().
'''
def __init__(self, name, zipfile):
self._zipfile = zipfile
self._name = name
self._inner = StringIO()
def write(self, content):
'Append the given content to this zip entry'
self._inner.write(content)
return
def close(self):
'The close method writes the content back to the zip file.'
self._zipfile.writestr(self._name, self._inner.getvalue())
def getModTime(aPath):
if not os.path.isfile(aPath):
return 0
mtime = os.stat(aPath).st_mtime
return localtime(mtime)
class JarMaker(object):
'''JarMaker reads jar.mn files and process those into jar files or
flat directories, along with chrome.manifest files.
'''
ignore = re.compile('\s*(\#.*)?$')
jarline = re.compile('(?:(?P<jarfile>[\w\d.\-\_\\\/]+).jar\:)|(?:\s*(\#.*)?)\s*$')
regline = re.compile('\%\s+(.*)$')
entryre = '(?P<optPreprocess>\*)?(?P<optOverwrite>\+?)\s+'
entryline = re.compile(entryre + '(?P<output>[\w\d.\-\_\\\/\+]+)\s*(\((?P<locale>\%?)(?P<source>[\w\d.\-\_\\\/]+)\))?\s*$')
def __init__(self, outputFormat = 'flat', useJarfileManifest = True,
useChromeManifest = False):
self.outputFormat = outputFormat
self.useJarfileManifest = useJarfileManifest
self.useChromeManifest = useChromeManifest
self.pp = Preprocessor()
def getCommandLineParser(self):
'''Get a optparse.OptionParser for jarmaker.
This OptionParser has the options for jarmaker as well as
the options for the inner PreProcessor.
'''
# HACK, we need to unescape the string variables we get,
# the perl versions didn't grok strings right
p = self.pp.getCommandLineParser(unescapeDefines = True)
p.add_option('-f', type="choice", default="jar",
choices=('jar', 'flat', 'symlink'),
help="fileformat used for output", metavar="[jar, flat, symlink]")
p.add_option('-v', action="store_true", dest="verbose",
help="verbose output")
p.add_option('-q', action="store_false", dest="verbose",
help="verbose output")
p.add_option('-e', action="store_true",
help="create chrome.manifest instead of jarfile.manifest")
p.add_option('-s', type="string", action="append", default=[],
help="source directory")
p.add_option('-t', type="string",
help="top source directory")
p.add_option('-c', '--l10n-src', type="string", action="append",
help="localization directory")
p.add_option('--l10n-base', type="string", action="append", default=[],
help="base directory to be used for localization (multiple)")
p.add_option('-j', type="string",
help="jarfile directory")
# backwards compat, not needed
p.add_option('-a', action="store_false", default=True,
help="NOT SUPPORTED, turn auto-registration of chrome off (installed-chrome.txt)")
p.add_option('-d', type="string",
help="UNUSED, chrome directory")
p.add_option('-o', help="cross compile for auto-registration, ignored")
p.add_option('-l', action="store_true",
help="ignored (used to switch off locks)")
p.add_option('-x', action="store_true",
help="force Unix")
p.add_option('-z', help="backwards compat, ignored")
p.add_option('-p', help="backwards compat, ignored")
return p
def processIncludes(self, includes):
'''Process given includes with the inner PreProcessor.
Only use this for #defines, the includes shouldn't generate
content.
'''
self.pp.out = StringIO()
for inc in includes:
self.pp.do_include(inc)
includesvalue = self.pp.out.getvalue()
if includesvalue:
logging.info("WARNING: Includes produce non-empty output")
self.pp.out = None
pass
def finalizeJar(self, jarPath, chromebasepath, register,
doZip=True):
'''Helper method to write out the chrome registration entries to
jarfile.manifest or chrome.manifest, or both.
The actual file processing is done in updateManifest.
'''
# rewrite the manifest, if entries given
if not register:
return
if self.useJarfileManifest:
self.updateManifest(jarPath + '.manifest', chromebasepath % '',
register)
if self.useChromeManifest:
manifestPath = os.path.join(os.path.dirname(jarPath),
'..', 'chrome.manifest')
self.updateManifest(manifestPath, chromebasepath % 'chrome/',
register)
def updateManifest(self, manifestPath, chromebasepath, register):
'''updateManifest replaces the % in the chrome registration entries
with the given chrome base path, and updates the given manifest file.
'''
myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
register.iterkeys()))
manifestExists = os.path.isfile(manifestPath)
mode = (manifestExists and 'r+b') or 'wb'
mf = open(manifestPath, mode)
if manifestExists:
# import previous content into hash, ignoring empty ones and comments
imf = re.compile('(#.*)?$')
for l in re.split('[\r\n]+', mf.read()):
if imf.match(l):
continue
myregister[l] = None
mf.seek(0)
for k in myregister.iterkeys():
mf.write(k + os.linesep)
mf.close()
def makeJar(self, infile=None,
jardir='',
sourcedirs=[], topsourcedir='', localedirs=None):
'''makeJar is the main entry point to JarMaker.
It takes the input file, the output directory, the source dirs and the
top source dir as argument, and optionally the l10n dirs.
'''
if isinstance(infile, basestring):
logging.info("processing " + infile)
pp = self.pp.clone()
pp.out = StringIO()
pp.do_include(infile)
lines = pushback_iter(pp.out.getvalue().splitlines())
try:
while True:
l = lines.next()
m = self.jarline.match(l)
if not m:
raise RuntimeError(l)
if m.group('jarfile') is None:
# comment
continue
self.processJarSection(m.group('jarfile'), lines,
jardir, sourcedirs, topsourcedir,
localedirs)
except StopIteration:
# we read the file
pass
return
def processJarSection(self, jarfile, lines,
jardir, sourcedirs, topsourcedir, localedirs):
'''Internal method called by makeJar to actually process a section
of a jar.mn file.
jarfile is the basename of the jarfile or the directory name for
flat output, lines is a pushback_iterator of the lines of jar.mn,
the remaining options are carried over from makeJar.
'''
# chromebasepath is used for chrome registration manifests
# %s is getting replaced with chrome/ for chrome.manifest, and with
# an empty string for jarfile.manifest
chromebasepath = '%s' + jarfile
if self.outputFormat == 'jar':
chromebasepath = 'jar:' + chromebasepath + '.jar!'
chromebasepath += '/'
jarfile = os.path.join(jardir, jarfile)
jf = None
if self.outputFormat == 'jar':
#jar
jarfilepath = jarfile + '.jar'
if os.path.isfile(jarfilepath) and \
os.path.getsize(jarfilepath) > 0:
jf = ZipFile(jarfilepath, 'a', lock = True)
else:
if not os.path.isdir(os.path.dirname(jarfilepath)):
os.makedirs(os.path.dirname(jarfilepath))
jf = ZipFile(jarfilepath, 'w', lock = True)
outHelper = self.OutputHelper_jar(jf)
else:
outHelper = getattr(self, 'OutputHelper_' + self.outputFormat)(jarfile)
register = {}
# This loop exits on either
# - the end of the jar.mn file
# - an line in the jar.mn file that's not part of a jar section
while True:
try:
l = lines.next()
except StopIteration:
# we're done with this jar.mn, and this jar section
self.finalizeJar(jarfile, chromebasepath, register)
if jf is not None:
jf.close()
# reraise the StopIteration for makeJar
raise
if self.ignore.match(l):
continue
m = self.regline.match(l)
if m:
rline = m.group(1)
register[rline] = 1
continue
m = self.entryline.match(l)
if not m:
# neither an entry line nor chrome reg, this jar section is done
self.finalizeJar(jarfile, chromebasepath, register)
if jf is not None:
jf.close()
lines.pushback(l)
return
self._processEntryLine(m, sourcedirs, topsourcedir, localedirs,
outHelper, jf)
return
def _processEntryLine(self, m,
sourcedirs, topsourcedir, localedirs,
outHelper, jf):
out = m.group('output')
src = m.group('source') or os.path.basename(out)
# pick the right sourcedir -- l10n, topsrc or src
if m.group('locale'):
src_base = localedirs
elif src.startswith('/'):
# path/in/jar/file_name.xul (/path/in/sourcetree/file_name.xul)
# refers to a path relative to topsourcedir, use that as base
# and strip the leading '/'
src_base = [topsourcedir]
src = src[1:]
else:
# use srcdirs and the objdir (current working dir) for relative paths
src_base = sourcedirs + ['.']
# check if the source file exists
realsrc = None
for _srcdir in src_base:
if os.path.isfile(os.path.join(_srcdir, src)):
realsrc = os.path.join(_srcdir, src)
break
if realsrc is None:
if jf is not None:
jf.close()
raise RuntimeError("file not found: " + src)
if m.group('optPreprocess'):
outf = outHelper.getOutput(out)
inf = open(realsrc)
pp = self.pp.clone()
if src[-4:] == '.css':
pp.setMarker('%')
pp.out = outf
pp.do_include(inf)
outf.close()
inf.close()
return
# copy or symlink if newer or overwrite
if (m.group('optOverwrite')
or (getModTime(realsrc) >
outHelper.getDestModTime(m.group('output')))):
if self.outputFormat == 'symlink' and hasattr(os, 'symlink'):
outHelper.symlink(realsrc, out)
return
outf = outHelper.getOutput(out)
# open in binary mode, this can be images etc
inf = open(realsrc, 'rb')
outf.write(inf.read())
outf.close()
inf.close()
class OutputHelper_jar(object):
'''Provide getDestModTime and getOutput for a given jarfile.
'''
def __init__(self, jarfile):
self.jarfile = jarfile
def getDestModTime(self, aPath):
try :
info = self.jarfile.getinfo(aPath)
return info.date_time
except:
return 0
def getOutput(self, name):
return ZipEntry(name, self.jarfile)
class OutputHelper_flat(object):
'''Provide getDestModTime and getOutput for a given flat
output directory. The helper method ensureDirFor is used by
the symlink subclass.
'''
def __init__(self, basepath):
self.basepath = basepath
def getDestModTime(self, aPath):
return getModTime(os.path.join(self.basepath, aPath))
def getOutput(self, name):
out = self.ensureDirFor(name)
return open(out, 'wb')
def ensureDirFor(self, name):
out = os.path.join(self.basepath, name)
outdir = os.path.dirname(out)
if not os.path.isdir(outdir):
os.makedirs(outdir)
return out
class OutputHelper_symlink(OutputHelper_flat):
'''Subclass of OutputHelper_flat that provides a helper for
creating a symlink including creating the parent directories.
'''
def symlink(self, src, dest):
out = self.ensureDirFor(dest)
os.symlink(src, out)
def main():
jm = JarMaker()
p = jm.getCommandLineParser()
(options, args) = p.parse_args()
jm.processIncludes(options.I)
jm.outputFormat = options.f
if options.e:
jm.useChromeManifest = True
jm.useJarfileManifest = False
noise = logging.INFO
if options.verbose is not None:
noise = (options.verbose and logging.DEBUG) or logging.WARN
logging.basicConfig(level = noise, format = "%(message)s")
if not args:
jm.makeJar(infile=sys.stdin,
sourcedirs=options.s, topsourcedir=options.t,
localedirs=options.l10n_src,
jardir=options.j)
return
topsrc = options.t
topsrc = os.path.normpath(os.path.abspath(topsrc))
for infile in args:
# guess srcdir and l10n dirs from jar.mn path and topsrcdir
# srcdir is the dir of the jar.mn and
# the l10n dirs are the relative path of topsrcdir to srcdir
# resolved against all l10n base dirs.
srcdir = os.path.normpath(os.path.abspath(os.path.dirname(infile)))
l10ndir = srcdir
if os.path.basename(srcdir) == 'locales':
l10ndir = os.path.dirname(l10ndir)
assert srcdir.startswith(topsrc), "src dir %s not in topsrcdir %s" % (srcdir, topsrc)
rell10ndir = l10ndir[len(topsrc):].lstrip(os.sep)
l10ndirs = map(lambda d: os.path.join(d, rell10ndir), options.l10n_base)
if options.l10n_src is not None:
l10ndirs += options.l10n_src
srcdirs = options.s + [srcdir]
jm.makeJar(infile=infile,
sourcedirs=srcdirs, topsourcedir=options.t,
localedirs=l10ndirs,
jardir=options.j)
if __name__ == "__main__":
main()

160
config/MozZipFile.py Normal file
Просмотреть файл

@ -0,0 +1,160 @@
# ***** 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 build system.
#
# 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):
# Axel Hecht <axel@pike.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import zipfile
import time
import binascii, struct
import zlib
from utils import lockFile
class ZipFile(zipfile.ZipFile):
""" Class with methods to open, read, write, close, list zip files.
Subclassing zipfile.ZipFile to allow for overwriting of existing
entries, though only for writestr, not for write.
"""
def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED,
lock = False):
zipfile.ZipFile.__init__(self, file, mode, compression)
self._remove = []
self.end = self.fp.tell()
self.debug = 0
if lock:
assert isinstance(file, basestring)
self.lockfile = lockFile(file + '.lck')
else:
self.lockfile = None
def writestr(self, zinfo_or_arcname, bytes):
"""Write contents into the archive.
The contents is the argument 'bytes', 'zinfo_or_arcname' is either
a ZipInfo instance or the name of the file in the archive.
This method is overloaded to allow overwriting existing entries.
"""
if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
zinfo = zipfile.ZipInfo(filename=zinfo_or_arcname,
date_time=time.localtime(time.time()))
zinfo.compress_type = self.compression
# Add some standard UNIX file access permissions (-rw-r--r--).
zinfo.external_attr = (0x81a4 & 0xFFFF) << 16L
else:
zinfo = zinfo_or_arcname
# Now to the point why we overwrote this in the first place,
# remember the entry numbers if we already had this entry.
# Optimizations:
# If the entry to overwrite is the last one, just reuse that.
# If we store uncompressed and the new content has the same size
# as the old, reuse the existing entry.
doSeek = False # store if we need to seek to the eof after overwriting
if self.NameToInfo.has_key(zinfo.filename):
# Find the last ZipInfo with our name.
# Last, because that's catching multiple overwrites
i = len(self.filelist)
while i > 0:
i -= 1
if self.filelist[i].filename == zinfo.filename:
break
zi = self.filelist[i]
if ((zinfo.compress_type == zipfile.ZIP_STORED
and zi.compress_size == len(bytes))
or (i + 1) == len(self.filelist)):
# make sure we're allowed to write, otherwise done by writestr below
self._writecheck(zi)
# overwrite existing entry
self.fp.seek(zi.header_offset)
if (i + 1) == len(self.filelist):
# this is the last item in the file, just truncate
self.fp.truncate()
else:
# we need to move to the end of the file afterwards again
doSeek = True
# unhook the current zipinfo, the writestr of our superclass
# will add a new one
self.filelist.pop(i)
self.NameToInfo.pop(zinfo.filename)
else:
# Couldn't optimize, sadly, just remember the old entry for removal
self._remove.append(self.filelist.pop(i))
zipfile.ZipFile.writestr(self, zinfo, bytes)
self.filelist.sort(lambda l, r: cmp(l.header_offset, r.header_offset))
if doSeek:
self.fp.seek(self.end)
self.end = self.fp.tell()
def close(self):
"""Close the file, and for mode "w" and "a" write the ending
records.
Overwritten to compact overwritten entries.
"""
if not self._remove:
# we don't have anything special to do, let's just call base
r = zipfile.ZipFile.close(self)
self.lockfile = None
return r
if self.fp.mode != 'r+b':
# adjust file mode if we originally just wrote, now we rewrite
self.fp.close()
self.fp = open(self.filename, 'r+b')
all = map(lambda zi: (zi, True), self.filelist) + \
map(lambda zi: (zi, False), self._remove)
all.sort(lambda l, r: cmp(l[0].header_offset, r[0].header_offset))
lengths = [all[i+1][0].header_offset - all[i][0].header_offset
for i in xrange(len(all)-1)]
lengths.append(self.end - all[-1][0].header_offset)
to_pos = 0
for (zi, keep), length in zip(all, lengths):
if not keep:
continue
oldoff = zi.header_offset
# python <= 2.4 has file_offset
if hasattr(zi, 'file_offset'):
zi.file_offset = zi.file_offset + to_pos - oldoff
zi.header_offset = to_pos
self.fp.seek(oldoff)
content = self.fp.read(length)
self.fp.seek(to_pos)
self.fp.write(content)
to_pos += length
self.fp.truncate()
zipfile.ZipFile.close(self)
self.lockfile = None

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

@ -49,8 +49,9 @@ from optparse import OptionParser
# hack around win32 mangling our line endings
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
if sys.platform == "win32":
import os, msvcrt
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
os.linesep = '\n'
import Expression
@ -157,9 +158,18 @@ class Preprocessor:
Parse a commandline into this parser.
Uses OptionParser internally, no args mean sys.argv[1:].
"""
includes = []
def handleI(option, opt, value, parser):
includes.append(value)
p = self.getCommandLineParser()
(options, args) = p.parse_args(args=args)
includes = options.I
if defaultToStdin and len(args) == 0:
args = [sys.stdin]
includes.extend(args)
for f in includes:
self.do_include(f)
pass
def getCommandLineParser(self, unescapeDefines = False):
escapedValue = re.compile('".*"$')
def handleE(option, opt, value, parser):
for k,v in os.environ.iteritems():
self.context[k] = v
@ -168,6 +178,9 @@ class Preprocessor:
assert len(vals) < 3
if len(vals) == 1:
vals.append(1)
elif unescapeDefines and escapedValue.match(vals[1]):
# strip escaped string values
vals[1] = vals[1][1:-1]
self.context[vals[0]] = vals[1]
def handleU(option, opt, value, parser):
del self.context[value]
@ -178,7 +191,7 @@ class Preprocessor:
def handleMarker(option, opt, value, parser):
self.setMarker(value)
p = OptionParser()
p.add_option('-I', action='callback', callback=handleI, type="string",
p.add_option('-I', action='append', type="string", default = [],
metavar="FILENAME", help='Include file')
p.add_option('-E', action='callback', callback=handleE,
help='Import the environment into the defined variables')
@ -194,13 +207,7 @@ class Preprocessor:
p.add_option('--marker', action='callback', callback=handleMarker,
type="string",
help='Use the specified marker instead of #')
(options, args) = p.parse_args(args=args)
if defaultToStdin and len(args) == 0:
args = [sys.stdin]
includes.extend(args)
for f in includes:
self.do_include(f)
pass
return p
def handleLine(self, aLine):
"""

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

@ -616,9 +616,17 @@ WINCE = @WINCE@
MOZ_DISTRIBUTION_ID = @MOZ_DISTRIBUTION_ID@
NS_HILDON = @NS_HILDON@
NS_OSSO = @NS_OSSO@
MOZ_PLATFORM_HILDON = @MOZ_PLATFORM_HILDON@
LIBHILDONMIME_CFLAGS = @LIBHILDONMIME_CFLAGS@
LIBHILDONMIME_LIBS = @LIBHILDONMIME_LIBS@
LIBOSSO_CFLAGS = @LIBOSSO_CFLAGS@
LIBOSSO_LIBS = @LIBOSSO_LIBS@
NS_MAEMO_LOCATION = @NS_MAEMO_LOCATION@
MOZ_LOCATION_CFLAGS = @MOZ_LOCATION_CFLAGS@
MOZ_LOCATION_LIBS = @MOZ_LOCATION_LIBS@
MACOS_SDK_DIR = @MACOS_SDK_DIR@
NEXT_ROOT = @NEXT_ROOT@
@ -631,8 +639,8 @@ HAVE_DTRACE= @HAVE_DTRACE@
VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
MOZ_V1_STRING_ABI = @MOZ_V1_STRING_ABI@
MOZ_EMBEDDING_LEVEL_DEFAULT = @MOZ_EMBEDDING_LEVEL_DEFAULT@
MOZ_EMBEDDING_LEVEL_BASIC = @MOZ_EMBEDDING_LEVEL_BASIC@
MOZ_EMBEDDING_LEVEL_MINIMAL = @MOZ_EMBEDDING_LEVEL_MINIMAL@
HAVE_ARM_SIMD= @HAVE_ARM_SIMD@

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

@ -1,6 +0,0 @@
# This is a shell script, sourced by configure.
MOZILLA_LOCALE_VERSION=1.9a1
MOZILLA_REGION_VERSION=1.9a1
MOZILLA_SKIN_VERSION=1.8

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше