mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to Places
This commit is contained in:
commit
06f60f7a34
@ -82,7 +82,6 @@ nsIStringBundle *nsAccessNode::gStringBundle = 0;
|
||||
nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
|
||||
nsINode *nsAccessNode::gLastFocusedNode = nsnull;
|
||||
|
||||
PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
|
||||
PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
|
||||
|
||||
nsApplicationAccessible *nsAccessNode::gApplicationAccessible = nsnull;
|
||||
@ -217,7 +216,6 @@ void nsAccessNode::InitXPAccessibility()
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (prefBranch) {
|
||||
prefBranch->GetBoolPref("accessibility.disablecache", &gIsCacheDisabled);
|
||||
prefBranch->GetBoolPref("browser.formfill.enable", &gIsFormFillEnabled);
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ public:
|
||||
*/
|
||||
virtual nsINode* GetNode() const { return mContent; }
|
||||
nsIContent* GetContent() const { return mContent; }
|
||||
nsIDocument* GetDocumentNode() const
|
||||
virtual nsIDocument* GetDocumentNode() const
|
||||
{ return mContent ? mContent->GetOwnerDoc() : nsnull; }
|
||||
|
||||
/**
|
||||
@ -212,7 +212,6 @@ protected:
|
||||
static nsIStringBundle *gStringBundle;
|
||||
static nsIStringBundle *gKeyStringBundle;
|
||||
|
||||
static PRBool gIsCacheDisabled;
|
||||
static PRBool gIsFormFillEnabled;
|
||||
|
||||
private:
|
||||
|
@ -100,6 +100,7 @@ ACCESSIBILITY_ATOM(a, "a")
|
||||
ACCESSIBILITY_ATOM(abbr, "abbr")
|
||||
ACCESSIBILITY_ATOM(acronym, "acronym")
|
||||
ACCESSIBILITY_ATOM(area, "area")
|
||||
ACCESSIBILITY_ATOM(article, "article") // HTML landmark
|
||||
ACCESSIBILITY_ATOM(autocomplete, "autocomplete")
|
||||
ACCESSIBILITY_ATOM(blockquote, "blockquote")
|
||||
ACCESSIBILITY_ATOM(br, "br")
|
||||
@ -111,7 +112,9 @@ ACCESSIBILITY_ATOM(dd, "dd")
|
||||
ACCESSIBILITY_ATOM(div, "div")
|
||||
ACCESSIBILITY_ATOM(dl, "dl")
|
||||
ACCESSIBILITY_ATOM(dt, "dt")
|
||||
ACCESSIBILITY_ATOM(footer, "footer") // HTML landmark
|
||||
ACCESSIBILITY_ATOM(form, "form")
|
||||
ACCESSIBILITY_ATOM(header, "header") // HTML landmark
|
||||
ACCESSIBILITY_ATOM(h1, "h1")
|
||||
ACCESSIBILITY_ATOM(h2, "h2")
|
||||
ACCESSIBILITY_ATOM(h3, "h3")
|
||||
@ -135,6 +138,7 @@ ACCESSIBILITY_ATOM(map, "map")
|
||||
ACCESSIBILITY_ATOM(math, "math")
|
||||
ACCESSIBILITY_ATOM(menupopup, "menupopup") // XUL
|
||||
ACCESSIBILITY_ATOM(object, "object")
|
||||
ACCESSIBILITY_ATOM(nav, "nav") // HTML landmark
|
||||
ACCESSIBILITY_ATOM(ol, "ol")
|
||||
ACCESSIBILITY_ATOM(optgroup, "optgroup")
|
||||
ACCESSIBILITY_ATOM(option, "option")
|
||||
@ -196,6 +200,7 @@ ACCESSIBILITY_ATOM(multiline, "multiline") // XUL
|
||||
ACCESSIBILITY_ATOM(name, "name")
|
||||
ACCESSIBILITY_ATOM(onclick, "onclick")
|
||||
ACCESSIBILITY_ATOM(popup, "popup")
|
||||
ACCESSIBILITY_ATOM(placeholder, "placeholder")
|
||||
ACCESSIBILITY_ATOM(readonly, "readonly")
|
||||
ACCESSIBILITY_ATOM(scope, "scope") // HTML table
|
||||
ACCESSIBILITY_ATOM(seltype, "seltype") // XUL listbox
|
||||
@ -289,3 +294,4 @@ ACCESSIBILITY_ATOM(live, "live")
|
||||
ACCESSIBILITY_ATOM(lineNumber, "line-number")
|
||||
ACCESSIBILITY_ATOM(posinset, "posinset")
|
||||
ACCESSIBILITY_ATOM(setsize, "setsize")
|
||||
ACCESSIBILITY_ATOM(xmlroles, "xml-roles")
|
||||
|
@ -477,32 +477,33 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG_CONTENTMUTATION
|
||||
nsAutoString tag;
|
||||
aStartChild->Tag()->ToString(tag);
|
||||
nsIAtom* id = aStartChild->GetID();
|
||||
nsCAutoString strid;
|
||||
if (id)
|
||||
id->ToUTF8String(strid);
|
||||
|
||||
nsIAtom* atomid = aStartChild->GetID();
|
||||
nsCAutoString id;
|
||||
if (atomid)
|
||||
atomid->ToUTF8String(id);
|
||||
|
||||
nsAutoString ctag;
|
||||
aContainer->Tag()->ToString(ctag);
|
||||
nsIAtom* cid = aContainer->GetID();
|
||||
nsCAutoString strcid;
|
||||
if (cid)
|
||||
cid->ToUTF8String(strcid);
|
||||
nsCAutoString cid;
|
||||
nsIAtom* catomid = nsnull;
|
||||
if (aContainer) {
|
||||
aContainer->Tag()->ToString(ctag);
|
||||
catomid = aContainer->GetID();
|
||||
if (catomid)
|
||||
catomid->ToUTF8String(cid);
|
||||
}
|
||||
|
||||
printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
|
||||
NS_ConvertUTF16toUTF8(tag).get(), strid.get(),
|
||||
NS_ConvertUTF16toUTF8(ctag).get(), strcid.get(), aEndChild);
|
||||
NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
NS_ConvertUTF16toUTF8(ctag).get(), cid.get(), aEndChild);
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, also we need to
|
||||
// update a content node of the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
||||
}
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -510,21 +511,34 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
nsAutoString id;
|
||||
aChild->Tag()->ToString(id);
|
||||
printf("\ncontent removed: %s\n", NS_ConvertUTF16toUTF8(id).get());
|
||||
#ifdef DEBUG_CONTENTMUTATION
|
||||
nsAutoString tag;
|
||||
aChild->Tag()->ToString(tag);
|
||||
|
||||
nsIAtom* atomid = aChild->GetID();
|
||||
nsCAutoString id;
|
||||
if (atomid)
|
||||
atomid->ToUTF8String(id);
|
||||
|
||||
nsAutoString ctag;
|
||||
nsCAutoString cid;
|
||||
nsIAtom* catomid = nsnull;
|
||||
if (aContainer) {
|
||||
aContainer->Tag()->ToString(ctag);
|
||||
catomid = aContainer->GetID();
|
||||
if (catomid)
|
||||
catomid->ToUTF8String(cid);
|
||||
}
|
||||
|
||||
printf("\ncontent removed: %s@id='%s', container: %s@id='%s'\n\n",
|
||||
NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
NS_ConvertUTF16toUTF8(ctag).get(), cid.get());
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, perhaps destroy
|
||||
// the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
||||
PR_FALSE);
|
||||
}
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -467,9 +467,6 @@ nsAccessible::GetFirstChild(nsIAccessible **aFirstChild)
|
||||
NS_ENSURE_ARG_POINTER(aFirstChild);
|
||||
*aFirstChild = nsnull;
|
||||
|
||||
if (gIsCacheDisabled)
|
||||
InvalidateChildren();
|
||||
|
||||
PRInt32 childCount = GetChildCount();
|
||||
NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
|
||||
|
||||
@ -2733,6 +2730,9 @@ nsAccessible::InvalidateChildren()
|
||||
PRBool
|
||||
nsAccessible::AppendChild(nsAccessible* aChild)
|
||||
{
|
||||
if (!aChild)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!mChildren.AppendElement(aChild))
|
||||
return PR_FALSE;
|
||||
|
||||
@ -2746,11 +2746,16 @@ nsAccessible::AppendChild(nsAccessible* aChild)
|
||||
PRBool
|
||||
nsAccessible::InsertChildAt(PRUint32 aIndex, nsAccessible* aChild)
|
||||
{
|
||||
if (!aChild)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!mChildren.InsertElementAt(aIndex, aChild))
|
||||
return PR_FALSE;
|
||||
|
||||
for (PRUint32 idx = aIndex + 1; idx < mChildren.Length(); idx++)
|
||||
mChildren[idx]->mIndexInParent++;
|
||||
for (PRUint32 idx = aIndex + 1; idx < mChildren.Length(); idx++) {
|
||||
NS_ASSERTION(mChildren[idx]->mIndexInParent == idx - 1, "Accessible child index doesn't match");
|
||||
mChildren[idx]->mIndexInParent = idx;
|
||||
}
|
||||
|
||||
if (nsAccUtils::IsText(aChild))
|
||||
mChildrenFlags = eMixedChildren;
|
||||
@ -2764,23 +2769,28 @@ nsAccessible::InsertChildAt(PRUint32 aIndex, nsAccessible* aChild)
|
||||
PRBool
|
||||
nsAccessible::RemoveChild(nsAccessible* aChild)
|
||||
{
|
||||
if (aChild->mParent != this || aChild->mIndexInParent == -1)
|
||||
if (!aChild)
|
||||
return PR_FALSE;
|
||||
|
||||
if (aChild->mIndexInParent >= mChildren.Length() ||
|
||||
mChildren[aChild->mIndexInParent] != aChild) {
|
||||
PRInt32 index = aChild->mIndexInParent;
|
||||
if (aChild->mParent != this || index == -1)
|
||||
return PR_FALSE;
|
||||
|
||||
if (index >= mChildren.Length() || mChildren[index] != aChild) {
|
||||
NS_ERROR("Child is bound to parent but parent hasn't this child at its index!");
|
||||
aChild->UnbindFromParent();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (PRUint32 idx = aChild->mIndexInParent + 1; idx < mChildren.Length(); idx++)
|
||||
mChildren[idx]->mIndexInParent--;
|
||||
|
||||
mChildren.RemoveElementAt(aChild->mIndexInParent);
|
||||
mEmbeddedObjCollector = nsnull;
|
||||
for (PRUint32 idx = index + 1; idx < mChildren.Length(); idx++) {
|
||||
NS_ASSERTION(mChildren[idx]->mIndexInParent == idx, "Accessible child index doesn't match");
|
||||
mChildren[idx]->mIndexInParent = idx - 1;
|
||||
}
|
||||
|
||||
aChild->UnbindFromParent();
|
||||
mChildren.RemoveElementAt(index);
|
||||
mEmbeddedObjCollector = nsnull;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -285,8 +285,12 @@ nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
return NS_OK_DEFUNCT_OBJECT;
|
||||
}
|
||||
|
||||
if (aExtraState)
|
||||
*aExtraState = 0;
|
||||
if (aExtraState) {
|
||||
// The root content of the document might be removed so that mContent is
|
||||
// out of date.
|
||||
*aExtraState = (mContent->GetCurrentDoc() == mDocument) ?
|
||||
0 : nsIAccessibleStates::EXT_STATE_STALE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
|
||||
@ -675,8 +679,10 @@ nsDocAccessible::Shutdown()
|
||||
mParent->RemoveChild(this);
|
||||
}
|
||||
|
||||
PRUint32 childDocCount = mChildDocuments.Length();
|
||||
for (PRUint32 idx = 0; idx < childDocCount; idx++)
|
||||
// Walk the array backwards because child documents remove themselves from the
|
||||
// array as they are shutdown.
|
||||
PRInt32 childDocCount = mChildDocuments.Length();
|
||||
for (PRInt32 idx = childDocCount - 1; idx >= 0; idx--)
|
||||
mChildDocuments[idx]->Shutdown();
|
||||
|
||||
mChildDocuments.Clear();
|
||||
@ -1239,12 +1245,17 @@ void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent2,
|
||||
nsEventStates aStateMask)
|
||||
{
|
||||
if (!aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
|
||||
return;
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
|
||||
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent1);
|
||||
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent2);
|
||||
}
|
||||
|
||||
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent1);
|
||||
nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent2);
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent1, nsIAccessibleStates::STATE_INVALID,
|
||||
PR_FALSE, PR_TRUE);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void nsDocAccessible::DocumentStatesChanged(nsIDocument* aDocument,
|
||||
@ -1346,22 +1357,49 @@ nsDocAccessible::UpdateTree(nsIContent* aContainerNode,
|
||||
// Since this information may be not correct then we need to fire some events
|
||||
// regardless the document loading state.
|
||||
|
||||
// Update the whole tree of this document accessible when the container is
|
||||
// null (document element is inserted or removed).
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
nsIEventStateManager* esm = presShell->GetPresContext()->EventStateManager();
|
||||
PRBool fireAllEvents = PR_TRUE;//IsContentLoaded() || esm->IsHandlingUserInputExternal();
|
||||
|
||||
// We don't create new accessibles on content removal.
|
||||
nsAccessible* container = aIsInsert ?
|
||||
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
||||
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode);
|
||||
|
||||
// XXX: bug 608887 reconsider accessible tree update logic because
|
||||
// 1) elements appended outside the HTML body don't get accessibles;
|
||||
// 2) the document having elements that should be accessible may function
|
||||
// without body.
|
||||
nsAccessible* container = nsnull;
|
||||
if (aIsInsert) {
|
||||
container = aContainerNode ?
|
||||
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
||||
this;
|
||||
|
||||
// The document children were changed; the root content might be affected.
|
||||
if (container == this) {
|
||||
nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocument);
|
||||
|
||||
// No root content (for example HTML document element was inserted but no
|
||||
// body). Nothing to update.
|
||||
if (!rootContent)
|
||||
return;
|
||||
|
||||
// New root content has been inserted, update it and update the tree.
|
||||
if (rootContent != mContent)
|
||||
mContent = rootContent;
|
||||
}
|
||||
|
||||
// XXX: Invalidate parent-child relations for container accessible and its
|
||||
// children because there's no good way to find insertion point of new child
|
||||
// accessibles into accessible tree. We need to invalidate children even
|
||||
// there's no inserted accessibles in the end because accessible children
|
||||
// are created while parent recaches child accessibles.
|
||||
container->InvalidateChildren();
|
||||
|
||||
} else {
|
||||
// Don't create new accessibles on content removal.
|
||||
container = aContainerNode ?
|
||||
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode) :
|
||||
this;
|
||||
}
|
||||
|
||||
EIsFromUserInput fromUserInput = esm->IsHandlingUserInputExternal() ?
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
virtual nsIFrame* GetFrame();
|
||||
virtual PRBool IsDefunct();
|
||||
virtual nsINode* GetNode() const { return mDocument; }
|
||||
virtual nsIDocument* GetDocumentNode() const { return mDocument; }
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
|
@ -196,8 +196,13 @@ nsOuterDocAccessible::InvalidateChildren()
|
||||
PRBool
|
||||
nsOuterDocAccessible::AppendChild(nsAccessible *aAccessible)
|
||||
{
|
||||
NS_ASSERTION(!mChildren.Length(),
|
||||
"Previous child document of outerdoc accessible wasn't removed!");
|
||||
// We keep showing the old document for a bit after creating the new one,
|
||||
// and while building the new DOM and frame tree. That's done on purpose
|
||||
// to avoid weird flashes of default background color.
|
||||
// The old viewer will be destroyed after the new one is created.
|
||||
// For a11y, it should be safe to shut down the old document now.
|
||||
if (mChildren.Length())
|
||||
mChildren[0]->Shutdown();
|
||||
|
||||
if (!nsAccessible::AppendChild(aAccessible))
|
||||
return PR_FALSE;
|
||||
|
@ -412,16 +412,24 @@ nsHTMLTextFieldAccessible::GetNameInternal(nsAString& aName)
|
||||
if (!aName.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (!mContent->GetBindingParent())
|
||||
if (mContent->GetBindingParent())
|
||||
{
|
||||
// XXX: bug 459640
|
||||
// There's a binding parent.
|
||||
// This means we're part of another control, so use parent accessible for name.
|
||||
// This ensures that a textbox inside of a XUL widget gets
|
||||
// an accessible name.
|
||||
nsAccessible* parent = GetParent();
|
||||
parent->GetName(aName);
|
||||
}
|
||||
|
||||
if (!aName.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
// XXX: bug 459640
|
||||
// There's a binding parent.
|
||||
// This means we're part of another control, so use parent accessible for name.
|
||||
// This ensures that a textbox inside of a XUL widget gets
|
||||
// an accessible name.
|
||||
nsAccessible* parent = GetParent();
|
||||
return parent ? parent->GetName(aName) : NS_OK;
|
||||
// text inputs and textareas might have useful placeholder text
|
||||
mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::placeholder, aName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLTextFieldAccessible::GetValue(nsAString& _retval)
|
||||
|
@ -134,8 +134,10 @@ nsHyperTextAccessible::NativeRole()
|
||||
if (tag == nsAccessibilityAtoms::form)
|
||||
return nsIAccessibleRole::ROLE_FORM;
|
||||
|
||||
if (tag == nsAccessibilityAtoms::div ||
|
||||
tag == nsAccessibilityAtoms::blockquote)
|
||||
if (tag == nsAccessibilityAtoms::article ||
|
||||
tag == nsAccessibilityAtoms::blockquote ||
|
||||
tag == nsAccessibilityAtoms::div ||
|
||||
tag == nsAccessibilityAtoms::nav)
|
||||
return nsIAccessibleRole::ROLE_SECTION;
|
||||
|
||||
if (tag == nsAccessibilityAtoms::h1 ||
|
||||
@ -146,6 +148,14 @@ nsHyperTextAccessible::NativeRole()
|
||||
tag == nsAccessibilityAtoms::h6)
|
||||
return nsIAccessibleRole::ROLE_HEADING;
|
||||
|
||||
// Deal with html landmark elements
|
||||
if (tag == nsAccessibilityAtoms::header)
|
||||
return nsIAccessibleRole::ROLE_HEADER;
|
||||
|
||||
if (tag == nsAccessibilityAtoms::footer)
|
||||
return nsIAccessibleRole::ROLE_FOOTER;
|
||||
|
||||
// Treat block frames as paragraphs
|
||||
nsIFrame *frame = GetFrame();
|
||||
if (frame && frame->GetType() == nsAccessibilityAtoms::blockFrame &&
|
||||
frame->GetContent()->Tag() != nsAccessibilityAtoms::input) {
|
||||
@ -1197,6 +1207,21 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
|
||||
}
|
||||
}
|
||||
|
||||
// For the html landmark elements we expose them like we do aria landmarks to
|
||||
// make AT navigation schemes "just work".
|
||||
if (mContent->Tag() == nsAccessibilityAtoms::nav)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("navigation"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::header)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("banner"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::footer)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("contentinfo"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::article)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("main"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ _TEST_FILES =\
|
||||
test_descr.html \
|
||||
test_editabletext_1.html \
|
||||
test_editabletext_2.html \
|
||||
test_elm_landmarks.html \
|
||||
test_elm_listbox.xul \
|
||||
$(warning test_elm_media.html temporarily disabled) \
|
||||
test_elm_nsApplicationAcc.html \
|
||||
|
@ -26,10 +26,6 @@
|
||||
{
|
||||
this.DOMNode = aDocNode;
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_STATE_CHANGE, getAccessible(this.DOMNode))
|
||||
];
|
||||
|
||||
this.invoke = function editabledoc_invoke() {
|
||||
// Note: this should fire an EVENT_STATE_CHANGE
|
||||
this.DOMNode.designMode = 'on';
|
||||
@ -58,6 +54,24 @@
|
||||
};
|
||||
}
|
||||
|
||||
function invalidInput(aNodeOrID)
|
||||
{
|
||||
this.DOMNode = getNode(aNodeOrID);
|
||||
|
||||
this.invoke = function invalidInput_invoke() {
|
||||
// Note: this should fire an EVENT_STATE_CHANGE
|
||||
this.DOMNode.value = "I am too long";
|
||||
};
|
||||
|
||||
this.check = function invalidInput_check() {
|
||||
testStates(aNodeOrID, STATE_INVALID);
|
||||
};
|
||||
|
||||
this.getID = function invalidInput_getID() {
|
||||
return prettyName(aNodeOrID) + " became invalid";
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Do tests
|
||||
|
||||
@ -67,12 +81,15 @@
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
|
||||
|
||||
// Test delayed editable state change
|
||||
var doc = document.getElementById("iframe").contentDocument;
|
||||
gQueue.push(new makeEditableDoc(doc));
|
||||
|
||||
// invalid state change
|
||||
gQueue.push(new invalidInput("maxlength"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -87,6 +104,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
|
||||
title="Make state change events async">
|
||||
Mozilla Bug 564471
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
|
||||
title="Fire a11y event based on HTML5 constraint validation">
|
||||
Mozilla Bug 555728
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
@ -97,6 +119,9 @@
|
||||
<div id="testContainer">
|
||||
<iframe id="iframe"></iframe>
|
||||
</div>
|
||||
|
||||
<input id="maxlength" maxlength="1">
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -19,11 +19,13 @@ const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
|
||||
const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
|
||||
const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
|
||||
const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
|
||||
const ROLE_FOOTER = nsIAccessibleRole.ROLE_FOOTER;
|
||||
const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
|
||||
const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
|
||||
const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC;
|
||||
const ROLE_GRID_CELL = nsIAccessibleRole.ROLE_GRID_CELL;
|
||||
const ROLE_GROUPING = nsIAccessibleRole.ROLE_GROUPING;
|
||||
const ROLE_HEADER = nsIAccessibleRole.ROLE_HEADER;
|
||||
const ROLE_HEADING = nsIAccessibleRole.ROLE_HEADING;
|
||||
const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP;
|
||||
const ROLE_INTERNAL_FRAME = nsIAccessibleRole.ROLE_INTERNAL_FRAME;
|
||||
|
@ -38,6 +38,7 @@ const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||
const EXT_STATE_STALE = nsIAccessibleStates.EXT_STATE_STALE;
|
||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
{
|
||||
var docAcc = getAccessible(document, [nsIAccessibleDocument]);
|
||||
if (docAcc) {
|
||||
testStates(docAcc, STATE_READONLY);
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
testStates(docAcc, 0, EXT_STATE_EDITABLE);
|
||||
testStates("article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
||||
|
||||
document.designMode = "off";
|
||||
|
68
accessible/tests/mochitest/test_elm_landmarks.html
Normal file
68
accessible/tests/mochitest/test_elm_landmarks.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML landmark 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="common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="attributes.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
testRole("nav", ROLE_SECTION);
|
||||
testRole("header", ROLE_HEADER);
|
||||
testRole("footer", ROLE_FOOTER);
|
||||
testRole("article", ROLE_SECTION);
|
||||
|
||||
// Some AT may look for this
|
||||
testAttrs("nav", {"xml-roles" : "navigation"}, true);
|
||||
testAttrs("header", {"xml-roles" : "banner"}, true);
|
||||
testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
|
||||
testAttrs("article", {"xml-roles" : "main"}, true);
|
||||
testAttrs("document", {"xml-roles" : "document"}, true); // ARIA override
|
||||
|
||||
// And some AT may look for this
|
||||
testAttrs("nav", {"tag" : "NAV"}, true);
|
||||
testAttrs("header", {"tag" : "HEADER"}, true);
|
||||
testAttrs("footer", {"tag" : "FOOTER"}, true);
|
||||
testAttrs("article", {"tag" : "ARTICLE"}, true);
|
||||
testAttrs("document", {"tag" : "ARTICLE"}, true); // no override expected
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Provide mappings for html5 <nav> <header> <footer> <article>"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">Bug 593368</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<nav id="nav">a nav</nav>
|
||||
<header id="header">a header</header>
|
||||
<footer id="footer">a footer</footer>
|
||||
<article id="article">an article</article>
|
||||
|
||||
<article id="document" role="document">a document</article>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -176,6 +176,14 @@
|
||||
testName("textboxinend", "This day was sunny");
|
||||
testName("textbox2", "This day was");
|
||||
|
||||
// placeholder
|
||||
testName("ph_password", "a placeholder");
|
||||
testName("ph_text", "a placeholder");
|
||||
testName("ph_textarea", "a placeholder");
|
||||
testName("ph_text2", "a label");
|
||||
testName("ph_textarea2", "a label");
|
||||
testName("ph_text3", "a label");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -196,6 +204,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=530081"
|
||||
title="Clean up our tree walker ">
|
||||
Mozilla Bug 530081
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=604391"
|
||||
title="Use placeholder as name if name is otherwise empty">
|
||||
Mozilla Bug 604391
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -421,5 +434,18 @@
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<!-- placeholder -->
|
||||
<input id="ph_password" type="password" value="" placeholder="a placeholder" />
|
||||
<input id="ph_text" type="text" placeholder="a placeholder" />
|
||||
<textarea id="ph_textarea" cols="5" placeholder="a placeholder"></textarea>
|
||||
|
||||
<!-- placeholder does not win -->
|
||||
<input id="ph_text2" type="text" aria-label="a label" placeholder="meh" />
|
||||
<textarea id="ph_textarea2" cols="5" aria-labelledby="ph_text2"
|
||||
placeholder="meh"></textarea>
|
||||
|
||||
<label for="ph_text3">a label</label>
|
||||
<input id="ph_text3" placeholder="meh" />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_doc.html \
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_recreation.html \
|
||||
|
370
accessible/tests/mochitest/treeupdate/test_doc.html
Normal file
370
accessible/tests/mochitest/treeupdate/test_doc.html
Normal file
@ -0,0 +1,370 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test document root content mutations</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="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
function getDocNode(aID)
|
||||
{
|
||||
return getNode(aID).contentDocument;
|
||||
}
|
||||
function getDocChildNode(aID)
|
||||
{
|
||||
return getDocNode(aID).body.firstChild;
|
||||
}
|
||||
|
||||
function rootContentReplaced(aID, aTextName)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
|
||||
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||
];
|
||||
|
||||
this.finalCheck = function rootContentReplaced_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: aTextName
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getDocNode(aID), tree);
|
||||
}
|
||||
}
|
||||
|
||||
function rootContentRemoved(aID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, null),
|
||||
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||
];
|
||||
|
||||
this.preinvoke = function rootContentRemoved_preinvoke()
|
||||
{
|
||||
// Set up target for hide event before we invoke.
|
||||
var text = getAccessible(getAccessible(getDocNode(aID)).firstChild,
|
||||
[nsIAccessNode]).DOMNode;
|
||||
this.eventSeq[0].target = text;
|
||||
}
|
||||
|
||||
this.finalCheck = function rootContentRemoved_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
states: {
|
||||
// Out of date root content involves stale state presence.
|
||||
states: 0,
|
||||
extraStates: EXT_STATE_STALE
|
||||
},
|
||||
children: [ ]
|
||||
};
|
||||
testAccessibleTree(getDocNode(aID), tree);
|
||||
}
|
||||
}
|
||||
|
||||
function rootContentInserted(aID, aTextName)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
|
||||
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||
];
|
||||
|
||||
this.finalCheck = function rootContentInserted_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
states: {
|
||||
states: 0,
|
||||
extraStates: 0,
|
||||
absentStates: 0,
|
||||
absentExtraStates: EXT_STATE_STALE
|
||||
},
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: aTextName
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getDocNode(aID), tree);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function writeIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentReplaced(aID, "hello");
|
||||
|
||||
this.invoke = function writeIFrameDoc_invoke()
|
||||
{
|
||||
var docNode = getDocNode(aID);
|
||||
|
||||
// We can't use open/write/close outside of iframe document because of
|
||||
// security error.
|
||||
var script = docNode.createElement("script");
|
||||
script.textContent = "document.open(); document.write('hello'); document.close();";
|
||||
docNode.body.appendChild(script);
|
||||
}
|
||||
|
||||
this.getID = function writeIFrameDoc_getID()
|
||||
{
|
||||
return "write document";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace HTML element.
|
||||
*/
|
||||
function replaceIFrameHTMLElm(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentReplaced(aID, "New Wave");
|
||||
|
||||
this.invoke = function replaceIFrameHTMLElm_invoke()
|
||||
{
|
||||
var docNode = getDocNode(aID);
|
||||
var newHTMLNode = docNode.createElement("html");
|
||||
var newBodyNode = docNode.createElement("body");
|
||||
var newTextNode = docNode.createTextNode("New Wave");
|
||||
newBodyNode.appendChild(newTextNode);
|
||||
newHTMLNode.appendChild(newBodyNode);
|
||||
docNode.replaceChild(newHTMLNode, docNode.documentElement);
|
||||
}
|
||||
|
||||
this.getID = function replaceIFrameBody_getID()
|
||||
{
|
||||
return "replace HTML element";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace HTML body.
|
||||
*/
|
||||
function replaceIFrameBody(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentReplaced(aID, "New Hello");
|
||||
|
||||
this.invoke = function replaceIFrameBody_invoke()
|
||||
{
|
||||
var docNode = getDocNode(aID);
|
||||
var newBodyNode = docNode.createElement("body");
|
||||
var newTextNode = docNode.createTextNode("New Hello");
|
||||
newBodyNode.appendChild(newTextNode);
|
||||
docNode.documentElement.replaceChild(newBodyNode, docNode.body);
|
||||
}
|
||||
|
||||
this.finalCheck = function replaceIFrameBody_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: "New Hello"
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getDocNode(aID), tree);
|
||||
}
|
||||
|
||||
this.getID = function replaceIFrameBody_getID()
|
||||
{
|
||||
return "replace body";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open/close document pair.
|
||||
*/
|
||||
function openIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentRemoved(aID);
|
||||
|
||||
this.invoke = function openIFrameDoc_invoke()
|
||||
{
|
||||
this.preinvoke();
|
||||
|
||||
// Open document.
|
||||
var docNode = getDocNode(aID);
|
||||
var script = docNode.createElement("script");
|
||||
script.textContent = "function closeMe() { document.write('Works?'); document.close(); } window.closeMe = closeMe; document.open();";
|
||||
docNode.body.appendChild(script);
|
||||
}
|
||||
|
||||
this.getID = function openIFrameDoc_getID()
|
||||
{
|
||||
return "open document";
|
||||
}
|
||||
}
|
||||
|
||||
function closeIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentInserted(aID, "Works?");
|
||||
|
||||
this.invoke = function closeIFrameDoc_invoke()
|
||||
{
|
||||
// Write and close document.
|
||||
getDocNode(aID).write('Works?'); getDocNode(aID).close();
|
||||
}
|
||||
|
||||
this.getID = function closeIFrameDoc_getID()
|
||||
{
|
||||
return "close document";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove/insert HTML element pair.
|
||||
*/
|
||||
function removeHTMLFromIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentRemoved(aID);
|
||||
|
||||
this.invoke = function removeHTMLFromIFrameDoc_invoke()
|
||||
{
|
||||
this.preinvoke();
|
||||
|
||||
// Remove HTML element.
|
||||
var docNode = getDocNode(aID);
|
||||
docNode.removeChild(docNode.firstChild);
|
||||
}
|
||||
|
||||
this.getID = function removeHTMLFromIFrameDoc_getID()
|
||||
{
|
||||
return "remove HTML element";
|
||||
}
|
||||
}
|
||||
|
||||
function insertHTMLToIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentInserted(aID, "Haha");
|
||||
|
||||
this.invoke = function insertHTMLToIFrameDoc_invoke()
|
||||
{
|
||||
// Insert HTML element.
|
||||
var docNode = getDocNode(aID);
|
||||
var html = docNode.createElement("html");
|
||||
var body = docNode.createElement("body");
|
||||
var text = docNode.createTextNode("Haha");
|
||||
body.appendChild(text);
|
||||
html.appendChild(body);
|
||||
docNode.appendChild(html);
|
||||
}
|
||||
|
||||
this.getID = function insertHTMLToIFrameDoc_getID()
|
||||
{
|
||||
return "insert HTML element document";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove/insert HTML body pair.
|
||||
*/
|
||||
function removeBodyFromIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentRemoved(aID);
|
||||
|
||||
this.invoke = function removeBodyFromIFrameDoc_invoke()
|
||||
{
|
||||
this.preinvoke();
|
||||
|
||||
// Remove body element.
|
||||
var docNode = getDocNode(aID);
|
||||
docNode.documentElement.removeChild(docNode.body);
|
||||
}
|
||||
|
||||
this.getID = function removeBodyFromIFrameDoc_getID()
|
||||
{
|
||||
return "remove body element";
|
||||
}
|
||||
}
|
||||
|
||||
function insertBodyToIFrameDoc(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentInserted(aID, "Yo ho ho i butylka roma!");
|
||||
|
||||
this.invoke = function insertBodyToIFrameDoc_invoke()
|
||||
{
|
||||
// Insert body element.
|
||||
var docNode = getDocNode(aID);
|
||||
var body = docNode.createElement("body");
|
||||
var text = docNode.createTextNode("Yo ho ho i butylka roma!");
|
||||
body.appendChild(text);
|
||||
docNode.documentElement.appendChild(body);
|
||||
}
|
||||
|
||||
this.getID = function insertBodyToIFrameDoc_getID()
|
||||
{
|
||||
return "insert body element";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new writeIFrameDoc("iframe"));
|
||||
gQueue.push(new replaceIFrameHTMLElm("iframe"));
|
||||
gQueue.push(new replaceIFrameBody("iframe"));
|
||||
gQueue.push(new openIFrameDoc("iframe"));
|
||||
gQueue.push(new closeIFrameDoc("iframe"));
|
||||
gQueue.push(new removeHTMLFromIFrameDoc("iframe"));
|
||||
gQueue.push(new insertHTMLToIFrameDoc("iframe"));
|
||||
gQueue.push(new removeBodyFromIFrameDoc("iframe"));
|
||||
gQueue.push(new insertBodyToIFrameDoc("iframe"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Update accessible tree when root element is changed"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606082">Mozilla Bug 606082</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<iframe id="iframe"></iframe>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
@ -59,9 +59,9 @@ pref("extensions.logging.enabled", false);
|
||||
// Preferences for AMO integration
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
pref("extensions.getAddons.maxResults", 15);
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%?src=firefox");
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/search?q=%TERMS%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox");
|
||||
pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/%APP%/discovery/%VERSION%/%OS%");
|
||||
|
||||
// Blocklist preferences
|
||||
@ -239,6 +239,8 @@ pref("browser.shell.checkDefaultBrowser", true);
|
||||
pref("browser.startup.page", 1);
|
||||
pref("browser.startup.homepage", "chrome://branding/locale/browserconfig.properties");
|
||||
|
||||
pref("browser.aboutHomeSnippets.updateUrl", "http://snippets.mozilla.com/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
|
||||
|
||||
pref("browser.enable_automatic_image_resizing", true);
|
||||
pref("browser.chrome.site_icons", true);
|
||||
pref("browser.chrome.favicons", true);
|
||||
|
@ -82,6 +82,7 @@ endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
|
||||
DEFINES += -DCAN_DRAW_IN_TITLEBAR=1
|
||||
DEFINES += -DMENUBAR_CAN_AUTOHIDE=1
|
||||
endif
|
||||
|
||||
|
@ -139,6 +139,10 @@ function loadSnippets()
|
||||
let updateURL = localStorage["snippets-update-url"];
|
||||
if (updateURL && (!lastUpdate ||
|
||||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
|
||||
// Even if fetching should fail we don't want to spam the server, thus
|
||||
// set the last update time regardless its results. Will retry tomorrow.
|
||||
localStorage["snippets-last-update"] = Date.now();
|
||||
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', updateURL, true);
|
||||
@ -149,7 +153,6 @@ function loadSnippets()
|
||||
{
|
||||
if (xhr.status == 200) {
|
||||
localStorage["snippets"] = xhr.responseText;
|
||||
localStorage["snippets-last-update"] = Date.now();
|
||||
}
|
||||
showSnippets();
|
||||
};
|
||||
@ -162,32 +165,39 @@ function loadSnippets()
|
||||
function showSnippets()
|
||||
{
|
||||
let snippets = localStorage["snippets"];
|
||||
// If there are remotely fetched snippets, try to to show them.
|
||||
if (snippets) {
|
||||
let snippetsElt = document.getElementById("snippets");
|
||||
snippetsElt.innerHTML = snippets;
|
||||
// Scripts injected by innerHTML are inactive, so we have to relocate them
|
||||
// through DOM manipulation to activate their contents.
|
||||
Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) {
|
||||
let relocatedScript = document.createElement("script");
|
||||
relocatedScript.type = "text/javascript;version=1.8";
|
||||
relocatedScript.text = elt.text;
|
||||
elt.parentNode.replaceChild(relocatedScript, elt);
|
||||
});
|
||||
snippetsElt.hidden = false;
|
||||
} else {
|
||||
// If there are no saved snippets, show one of the default ones.
|
||||
let defaultSnippetsElt = document.getElementById("defaultSnippets");
|
||||
let entries = defaultSnippetsElt.querySelectorAll("span");
|
||||
// Choose a random snippet. Assume there is always at least one.
|
||||
let randIndex = Math.round(Math.random() * (entries.length - 1));
|
||||
let entry = entries[randIndex];
|
||||
// Inject url in the eventual link.
|
||||
if (DEFAULT_SNIPPETS_URLS[randIndex]) {
|
||||
let links = entry.getElementsByTagName("a");
|
||||
if (links.length != 1)
|
||||
return; // Something is messed up in this entry, we support just 1 link.
|
||||
links[0].href = DEFAULT_SNIPPETS_URLS[randIndex];
|
||||
// Injecting snippets can throw if they're invalid XML.
|
||||
try {
|
||||
snippetsElt.innerHTML = snippets;
|
||||
// Scripts injected by innerHTML are inactive, so we have to relocate them
|
||||
// through DOM manipulation to activate their contents.
|
||||
Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) {
|
||||
let relocatedScript = document.createElement("script");
|
||||
relocatedScript.type = "text/javascript;version=1.8";
|
||||
relocatedScript.text = elt.text;
|
||||
elt.parentNode.replaceChild(relocatedScript, elt);
|
||||
});
|
||||
snippetsElt.hidden = false;
|
||||
return;
|
||||
} catch (ex) {
|
||||
// Bad content, continue to show default snippets.
|
||||
}
|
||||
entry.hidden = false;
|
||||
}
|
||||
|
||||
// Show default snippets otherwise.
|
||||
let defaultSnippetsElt = document.getElementById("defaultSnippets");
|
||||
let entries = defaultSnippetsElt.querySelectorAll("span");
|
||||
// Choose a random snippet. Assume there is always at least one.
|
||||
let randIndex = Math.round(Math.random() * (entries.length - 1));
|
||||
let entry = entries[randIndex];
|
||||
// Inject url in the eventual link.
|
||||
if (DEFAULT_SNIPPETS_URLS[randIndex]) {
|
||||
let links = entry.getElementsByTagName("a");
|
||||
if (links.length != 1)
|
||||
return; // Something is messed up in this entry, we support just 1 link.
|
||||
links[0].href = DEFAULT_SNIPPETS_URLS[randIndex];
|
||||
}
|
||||
entry.hidden = false;
|
||||
}
|
||||
|
@ -113,15 +113,6 @@
|
||||
label="&helpSafeMode.label;"
|
||||
oncommand="safeModeRestart();"/>
|
||||
<menuseparator/>
|
||||
<menuseparator id="updateSeparator"/>
|
||||
#ifdef XP_MACOSX
|
||||
#ifdef MOZ_UPDATER
|
||||
<menuitem id="checkForUpdates"
|
||||
label="&updateCmd.label;"
|
||||
class="menuitem-iconic"
|
||||
oncommand="checkForUpdates();"/>
|
||||
#endif
|
||||
#endif
|
||||
<menuseparator id="aboutSeparator"/>
|
||||
<menuitem id="aboutName"
|
||||
accesskey="&aboutProduct.accesskey;"
|
||||
|
@ -439,11 +439,17 @@
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="subscribeToPageMenuitem"
|
||||
#ifndef XP_MACOSX
|
||||
class="menuitem-iconic"
|
||||
#endif
|
||||
label="&subscribeToPageMenuitem.label;"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
observes="singleFeedMenuitemState"/>
|
||||
<menu id="subscribeToPageMenupopup"
|
||||
#ifndef XP_MACOSX
|
||||
class="menu-iconic"
|
||||
#endif
|
||||
label="&subscribeToPageMenupopup.label;"
|
||||
observes="multipleFeedsMenuState">
|
||||
<menupopup id="subscribeToPageSubmenuMenupopup"
|
||||
|
@ -51,7 +51,7 @@ tabbrowser {
|
||||
-moz-transition: opacity .25s;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[pinned] {
|
||||
.tabbrowser-tabs:not([pinnedonly]) > .tabbrowser-tab[pinned] {
|
||||
position: fixed;
|
||||
display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
|
||||
}
|
||||
@ -80,7 +80,7 @@ toolbar[printpreview="true"] {
|
||||
-moz-box-ordinal-group: 10;
|
||||
}
|
||||
|
||||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
%ifdef CAN_DRAW_IN_TITLEBAR
|
||||
#main-window[inFullscreen] > #titlebar {
|
||||
display: none;
|
||||
}
|
||||
|
@ -1913,12 +1913,7 @@ function BrowserReloadSkipCache() {
|
||||
BrowserReloadWithFlags(reloadFlags);
|
||||
}
|
||||
|
||||
function BrowserHome()
|
||||
{
|
||||
var homePage = gHomeButton.getHomePage();
|
||||
loadOneOrMoreURIs(homePage);
|
||||
}
|
||||
|
||||
var BrowserHome = BrowserGoHome;
|
||||
function BrowserGoHome(aEvent) {
|
||||
if (aEvent && "button" in aEvent &&
|
||||
aEvent.button == 2) // right-click: do nothing
|
||||
@ -1928,6 +1923,11 @@ function BrowserGoHome(aEvent) {
|
||||
var where = whereToOpenLink(aEvent, false, true);
|
||||
var urls;
|
||||
|
||||
// Home page should open in a new tab when current tab is an app tab
|
||||
if (where == "current" &&
|
||||
gBrowser.selectedTab.pinned)
|
||||
where = "tab";
|
||||
|
||||
// openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages
|
||||
switch (where) {
|
||||
case "current":
|
||||
@ -3489,9 +3489,10 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
|
||||
PlacesToolbarHelper.customizeDone();
|
||||
BookmarksMenuButton.customizeDone();
|
||||
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
// The url bar splitter state is dependent on whether stop/reload
|
||||
// and the location bar are combined, so we need this ordering
|
||||
CombinedStopReload.init();
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
// Update the urlbar
|
||||
if (gURLBar) {
|
||||
@ -4723,14 +4724,18 @@ function updateAppButtonDisplay() {
|
||||
window.menubar.visible &&
|
||||
document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
|
||||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
document.getElementById("titlebar").hidden = !displayAppButton;
|
||||
|
||||
if (displayAppButton)
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
else
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
function onTitlebarMaxClick() {
|
||||
if (window.windowState == window.STATE_MAXIMIZED)
|
||||
window.restore();
|
||||
@ -4983,134 +4988,159 @@ function asyncOpenWebPanel(event)
|
||||
* - gatherTextUnder
|
||||
*/
|
||||
|
||||
// Called whenever the user clicks in the content area,
|
||||
// except when left-clicking on links (special case)
|
||||
// should always return true for click to go through
|
||||
function contentAreaClick(event, fieldNormalClicks)
|
||||
{
|
||||
if (!event.isTrusted || event.getPreventDefault()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Extracts linkNode and href for the current click target.
|
||||
*
|
||||
* @param event
|
||||
* The click event.
|
||||
* @return [href, linkNode].
|
||||
*
|
||||
* @note linkNode will be null if the click wasn't on an anchor
|
||||
* element (or XLink).
|
||||
*/
|
||||
function hrefAndLinkNodeForClickEvent(event)
|
||||
{
|
||||
function isHTMLLink(aNode)
|
||||
{
|
||||
return aNode instanceof HTMLAnchorElement ||
|
||||
aNode instanceof HTMLAreaElement ||
|
||||
aNode instanceof HTMLLinkElement;
|
||||
}
|
||||
|
||||
var target = event.target;
|
||||
var linkNode;
|
||||
let linkNode;
|
||||
if (isHTMLLink(event.target)) {
|
||||
// This is a hack to work around Gecko bug 266932.
|
||||
// Walk up the DOM looking for a parent link node, to match the existing
|
||||
// behaviour for left click.
|
||||
// TODO: this is no more needed and should be removed in bug 325652.
|
||||
let node = event.target;
|
||||
while (node) {
|
||||
if (isHTMLLink(node) && node.hasAttribute("href"))
|
||||
linkNode = node;
|
||||
node = node.parentNode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
let node = event.originalTarget;
|
||||
while (node && !(node instanceof HTMLAnchorElement)) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
// <a> cannot be nested. So if we find an anchor without an
|
||||
// href, there is no useful <a> around the target.
|
||||
if (node && node.hasAttribute("href"))
|
||||
linkNode = node;
|
||||
}
|
||||
|
||||
if (target instanceof HTMLAnchorElement ||
|
||||
target instanceof HTMLAreaElement ||
|
||||
target instanceof HTMLLinkElement) {
|
||||
if (target.hasAttribute("href"))
|
||||
linkNode = target;
|
||||
if (linkNode)
|
||||
return [linkNode.href, linkNode];
|
||||
|
||||
// xxxmpc: this is kind of a hack to work around a Gecko bug (see bug 266932)
|
||||
// we're going to walk up the DOM looking for a parent link node,
|
||||
// this shouldn't be necessary, but we're matching the existing behaviour for left click
|
||||
var parent = target.parentNode;
|
||||
while (parent) {
|
||||
if (parent instanceof HTMLAnchorElement ||
|
||||
parent instanceof HTMLAreaElement ||
|
||||
parent instanceof HTMLLinkElement) {
|
||||
if (parent.hasAttribute("href"))
|
||||
linkNode = parent;
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
linkNode = event.originalTarget;
|
||||
while (linkNode && !(linkNode instanceof HTMLAnchorElement))
|
||||
linkNode = linkNode.parentNode;
|
||||
// <a> cannot be nested. So if we find an anchor without an
|
||||
// href, there is no useful <a> around the target
|
||||
if (linkNode && !linkNode.hasAttribute("href"))
|
||||
linkNode = null;
|
||||
}
|
||||
var wrapper = null;
|
||||
if (linkNode) {
|
||||
wrapper = linkNode;
|
||||
if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
|
||||
!event.altKey && !event.metaKey) {
|
||||
// A Web panel's links should target the main content area. Do this
|
||||
// if no modifier keys are down and if there's no target or the target equals
|
||||
// _main (the IE convention) or _content (the Mozilla convention).
|
||||
// XXX Now that markLinkVisited is gone, we may not need to field _main and
|
||||
// _content here.
|
||||
target = wrapper.getAttribute("target");
|
||||
if (fieldNormalClicks &&
|
||||
(!target || target == "_content" || target == "_main"))
|
||||
// IE uses _main, SeaMonkey uses _content, we support both
|
||||
{
|
||||
if (!wrapper.href)
|
||||
return true;
|
||||
if (wrapper.getAttribute("onclick"))
|
||||
return true;
|
||||
// javascript links should be executed in the current browser
|
||||
if (wrapper.href.substr(0, 11) === "javascript:")
|
||||
return true;
|
||||
// data links should be executed in the current browser
|
||||
if (wrapper.href.substr(0, 5) === "data:")
|
||||
return true;
|
||||
// If there is no linkNode, try simple XLink.
|
||||
let href, baseURI;
|
||||
let node = event.target;
|
||||
while (node) {
|
||||
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (href)
|
||||
baseURI = node.baseURI;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
try {
|
||||
urlSecurityCheck(wrapper.href, wrapper.ownerDocument.nodePrincipal);
|
||||
}
|
||||
catch(ex) {
|
||||
return false;
|
||||
}
|
||||
// In case of XLink, we don't return the node we got href from since
|
||||
// callers expect <a>-like elements.
|
||||
return [href ? makeURLAbsolute(baseURI, href) : null, null];
|
||||
}
|
||||
|
||||
var postData = { };
|
||||
var url = getShortcutOrURI(wrapper.href, postData);
|
||||
if (!url)
|
||||
return true;
|
||||
loadURI(url, null, postData.value, false);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
else if (linkNode.getAttribute("rel") == "sidebar") {
|
||||
// This is the Opera convention for a special link that - when clicked - allows
|
||||
// you to add a sidebar panel. We support the Opera convention here. The link's
|
||||
// title attribute contains the title that should be used for the sidebar panel.
|
||||
PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
|
||||
wrapper.getAttribute("title"),
|
||||
null, null, true, true);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
handleLinkClick(event, wrapper.href, linkNode);
|
||||
}
|
||||
/**
|
||||
* Called whenever the user clicks in the content area.
|
||||
*
|
||||
* @param event
|
||||
* The click event.
|
||||
* @param isPanelClick
|
||||
* Whether the event comes from a web panel.
|
||||
* @note default event is prevented if the click is handled.
|
||||
*/
|
||||
function contentAreaClick(event, isPanelClick)
|
||||
{
|
||||
if (!event.isTrusted || event.getPreventDefault() || event.button == 2)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// Try simple XLink
|
||||
var href, realHref, baseURI;
|
||||
linkNode = target;
|
||||
while (linkNode) {
|
||||
if (linkNode.nodeType == Node.ELEMENT_NODE) {
|
||||
wrapper = linkNode;
|
||||
let [href, linkNode] = hrefAndLinkNodeForClickEvent(event);
|
||||
if (!href) {
|
||||
// Not a link, handle middle mouse navigation.
|
||||
if (event.button == 1 &&
|
||||
gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
|
||||
!gPrefService.getBoolPref("general.autoScroll")) {
|
||||
middleMousePaste(event);
|
||||
event.preventDefault();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
realHref = wrapper.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (realHref) {
|
||||
href = realHref;
|
||||
baseURI = wrapper.baseURI
|
||||
}
|
||||
}
|
||||
linkNode = linkNode.parentNode;
|
||||
}
|
||||
if (href) {
|
||||
href = makeURLAbsolute(baseURI, href);
|
||||
handleLinkClick(event, href, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event.button == 1 &&
|
||||
gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
|
||||
!gPrefService.getBoolPref("general.autoScroll")) {
|
||||
middleMousePaste(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// This code only applies if we have a linkNode (i.e. clicks on real anchor
|
||||
// elements, as opposed to XLink).
|
||||
if (linkNode && event.button == 0 &&
|
||||
!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
|
||||
// A Web panel's links should target the main content area. Do this
|
||||
// if no modifier keys are down and if there's no target or the target
|
||||
// equals _main (the IE convention) or _content (the Mozilla convention).
|
||||
let target = linkNode.target;
|
||||
let mainTarget = !target || target == "_content" || target == "_main";
|
||||
if (isPanelClick && mainTarget) {
|
||||
// javascript and data links should be executed in the current browser.
|
||||
if (linkNode.getAttribute("onclick") ||
|
||||
href.substr(0, 11) === "javascript:" ||
|
||||
href.substr(0, 5) === "data:")
|
||||
return true;
|
||||
|
||||
try {
|
||||
urlSecurityCheck(href, linkNode.ownerDocument.nodePrincipal);
|
||||
}
|
||||
catch(ex) {
|
||||
// Prevent loading unsecure destinations.
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
let postData = {};
|
||||
let url = getShortcutOrURI(href, postData);
|
||||
if (!url)
|
||||
return true;
|
||||
loadURI(url, null, postData.value, false);
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (linkNode.getAttribute("rel") == "sidebar") {
|
||||
// This is the Opera convention for a special link that, when clicked,
|
||||
// allows to add a sidebar panel. The link's title attribute contains
|
||||
// the title that should be used for the sidebar panel.
|
||||
PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(href),
|
||||
linkNode.getAttribute("title"),
|
||||
null, null, true, true);
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
handleLinkClick(event, href, linkNode);
|
||||
|
||||
// Mark the page as a user followed link. This is done so that history can
|
||||
// distinguish automatic embed visits from user activated ones. For example
|
||||
// pages loaded in frames are embed visits and lost with the session, while
|
||||
// visits across frames should be preserved.
|
||||
try {
|
||||
PlacesUIUtils.markPageAsFollowedLink(href);
|
||||
} catch (ex) { /* Skip invalid URIs. */ }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles clicks on links.
|
||||
*
|
||||
* @return true if the click event was handled, false otherwise.
|
||||
*/
|
||||
function handleLinkClick(event, href, linkNode) {
|
||||
if (event.button == 2) // right click
|
||||
return false;
|
||||
@ -5124,6 +5154,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||
if (where == "save") {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5131,7 +5162,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||
openLinkIn(href, where, { fromContent: true,
|
||||
referrerURI: doc.documentURIObject,
|
||||
charset: doc.characterSet });
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7835,17 +7866,11 @@ function switchToTabHavingURI(aURI, aOpenNew, aCallback) {
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let browser = browsers[i];
|
||||
if (browser.currentURI.equals(aURI)) {
|
||||
gURLBar.handleRevert();
|
||||
// We need the current tab so we can check if we should close it
|
||||
let prevTab = gBrowser.selectedTab;
|
||||
// Focus the matching window & tab
|
||||
aWindow.focus();
|
||||
aWindow.gBrowser.tabContainer.selectedIndex = i;
|
||||
if (aCallback)
|
||||
aCallback(browser);
|
||||
// Close the previously selected tab if it was empty
|
||||
if (isTabEmpty(prevTab))
|
||||
gBrowser.removeTab(prevTab);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -429,29 +429,25 @@
|
||||
<tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
|
||||
</popupset>
|
||||
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
<vbox id="titlebar">
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
<vbox id="titlebar">
|
||||
<hbox id="titlebar-content">
|
||||
<hbox id="appmenu-button-container" align="start">
|
||||
<button id="appmenu-button"
|
||||
type="menu"
|
||||
#ifdef XP_WIN
|
||||
label="&brandShortName;"
|
||||
#else
|
||||
label="&appMenuButton.label;"
|
||||
#endif
|
||||
style="-moz-user-focus: ignore;">
|
||||
<hbox id="appmenu-button-container" align="start">
|
||||
<button id="appmenu-button"
|
||||
type="menu"
|
||||
label="&brandShortName;"
|
||||
style="-moz-user-focus: ignore;">
|
||||
#include browser-appmenu.inc
|
||||
</button>
|
||||
</button>
|
||||
</hbox>
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox">
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox">
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
#endif
|
||||
|
||||
<deck flex="1" id="tab-view-deck">
|
||||
@ -580,13 +576,16 @@
|
||||
onclick="gURLBar.handleCommand(event);"/>
|
||||
</hbox>
|
||||
<toolbarbutton id="urlbar-go-button"
|
||||
class="chromeclass-toolbar-additional"
|
||||
onclick="gURLBar.handleCommand(event);"
|
||||
tooltiptext="&goEndCap.tooltip;"/>
|
||||
<toolbarbutton id="urlbar-reload-button"
|
||||
class="chromeclass-toolbar-additional"
|
||||
command="Browser:ReloadOrDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
tooltiptext="&reloadButton.tooltip;"/>
|
||||
<toolbarbutton id="urlbar-stop-button"
|
||||
class="chromeclass-toolbar-additional"
|
||||
command="Browser:Stop"
|
||||
tooltiptext="&stopButton.tooltip;"/>
|
||||
</textbox>
|
||||
@ -652,11 +651,17 @@
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="BMB_subscribeToPageMenuitem"
|
||||
#ifndef XP_MACOSX
|
||||
class="menuitem-iconic"
|
||||
#endif
|
||||
label="&subscribeToPageMenuitem.label;"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
observes="singleFeedMenuitemState"/>
|
||||
<menu id="BMB_subscribeToPageMenupopup"
|
||||
#ifndef XP_MACOSX
|
||||
class="menu-iconic"
|
||||
#endif
|
||||
label="&subscribeToPageMenupopup.label;"
|
||||
observes="multipleFeedsMenuState">
|
||||
<menupopup id="BMB_subscribeToPageSubmenuMenupopup"
|
||||
|
@ -524,8 +524,10 @@
|
||||
browserHistory.unregisterOpenPage(this.mBrowser.registeredOpenURI);
|
||||
delete this.mBrowser.registeredOpenURI;
|
||||
}
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
this.mBrowser.registeredOpenURI = aLocation;
|
||||
if (aLocation.spec != "about:blank") {
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
this.mBrowser.registeredOpenURI = aLocation;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.mBlank) {
|
||||
@ -830,31 +832,48 @@
|
||||
// Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
|
||||
if (!this._previewMode) {
|
||||
// We've selected the new tab, so go ahead and notify listeners.
|
||||
var event = document.createEvent("Events");
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("TabSelect", true, false);
|
||||
this.mCurrentTab.dispatchEvent(event);
|
||||
|
||||
this._tabAttrModified(oldTab);
|
||||
this._tabAttrModified(this.mCurrentTab);
|
||||
|
||||
// Change focus to the new browser unless the findbar is focused.
|
||||
if (!gFindBarInitialized ||
|
||||
gFindBar.hidden ||
|
||||
gFindBar.getElement("findbar-textbox").getAttribute("focused") != "true") {
|
||||
// Adjust focus
|
||||
do {
|
||||
// Focus the location bar if it was previously focused for that tab.
|
||||
// In full screen mode, only bother making the location bar visible
|
||||
// if the tab is a blank one.
|
||||
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
|
||||
if (newBrowser._urlbarFocused && gURLBar) {
|
||||
if (!window.fullScreen) {
|
||||
gURLBar.focus();
|
||||
break;
|
||||
} else if (isTabEmpty(this.mCurrentTab)) {
|
||||
focusAndSelectUrlBar();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var fm = Components.classes["@mozilla.org/focus-manager;1"].
|
||||
getService(Components.interfaces.nsIFocusManager);
|
||||
var newFocusedElement = fm.getFocusedElementForWindow(window.content, true, {});
|
||||
// If the find bar is focused, keep it focused.
|
||||
if (gFindBarInitialized &&
|
||||
!gFindBar.hidden &&
|
||||
gFindBar.getElement("findbar-textbox").getAttribute("focused") == "true")
|
||||
break;
|
||||
|
||||
// Otherwise, focus the content area.
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
let newFocusedElement = fm.getFocusedElementForWindow(window.content, true, {});
|
||||
|
||||
// for anchors, use FLAG_SHOWRING so that it is clear what link was
|
||||
// last clicked when switching back to that tab
|
||||
var focusFlags = fm.FLAG_NOSCROLL;
|
||||
let focusFlags = fm.FLAG_NOSCROLL;
|
||||
if (newFocusedElement &&
|
||||
(newFocusedElement instanceof HTMLAnchorElement ||
|
||||
newFocusedElement.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple"))
|
||||
focusFlags |= fm.FLAG_SHOWRING;
|
||||
fm.setFocus(newBrowser, focusFlags);
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
@ -1900,15 +1919,11 @@
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.visibleTabs.length == 1)
|
||||
if (this.tabs.length == 1)
|
||||
return null;
|
||||
|
||||
// tell a new window to take the "dropped" tab
|
||||
return Services.ww.openWindow(window,
|
||||
getBrowserURL(),
|
||||
null,
|
||||
"chrome,dialog=no,all",
|
||||
aTab);
|
||||
return window.openDialog(getBrowserURL(), "_blank", "dialog=no,all", aTab);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -2706,11 +2721,18 @@
|
||||
<method name="_positionPinnedTabs">
|
||||
<body><![CDATA[
|
||||
var width = 0;
|
||||
var scrollButtonWidth = this.getAttribute("overflow") != "true" ? 0 :
|
||||
var pinnedOnly = (this.tabbrowser._numPinnedTabs == this.tabbrowser.visibleTabs.length);
|
||||
|
||||
if (pinnedOnly)
|
||||
this.tabbrowser.tabContainer.setAttribute("pinnedonly", "true");
|
||||
else
|
||||
this.tabbrowser.tabContainer.removeAttribute("pinnedonly");
|
||||
|
||||
var scrollButtonWidth = (this.getAttribute("overflow") != "true" || pinnedOnly) ? 0 :
|
||||
this.mTabstrip._scrollButtonDown.scrollWidth;
|
||||
for (var i = this.tabbrowser._numPinnedTabs - 1; i >= 0; i--) {
|
||||
let tab = this.childNodes[i];
|
||||
width += tab.scrollWidth;
|
||||
width += pinnedOnly ? 0 : tab.scrollWidth;
|
||||
tab.style.MozMarginStart = - (width + scrollButtonWidth) + "px";
|
||||
}
|
||||
this.style.MozMarginStart = width + "px";
|
||||
|
@ -81,6 +81,8 @@ function GroupItem(listOfEls, options) {
|
||||
this.locked = (options.locked ? Utils.copy(options.locked) : {});
|
||||
this.topChild = null;
|
||||
this.hidden = false;
|
||||
this.fadeAwayUndoButtonDelay = 15000;
|
||||
this.fadeAwayUndoButtonDuration = 300;
|
||||
|
||||
this.keepProportional = false;
|
||||
|
||||
@ -277,6 +279,7 @@ function GroupItem(listOfEls, options) {
|
||||
|
||||
// ___ Undo Close
|
||||
this.$undoContainer = null;
|
||||
this._undoButtonTimeoutId = null;
|
||||
|
||||
// ___ Superclass initialization
|
||||
this._init($container[0]);
|
||||
@ -637,28 +640,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
});
|
||||
}, 50);
|
||||
|
||||
let remove = function() {
|
||||
// close all children
|
||||
let toClose = self._children.concat();
|
||||
toClose.forEach(function(child) {
|
||||
child.removeSubscriber(self, "close");
|
||||
child.close();
|
||||
});
|
||||
|
||||
// remove all children
|
||||
self.removeAll();
|
||||
GroupItems.unregister(self);
|
||||
self._sendToSubscribers("close");
|
||||
self.removeTrenches();
|
||||
|
||||
iQ(self.container).remove();
|
||||
self.$undoContainer.remove();
|
||||
self.$undoContainer = null;
|
||||
Items.unsquish();
|
||||
|
||||
self.deleteData();
|
||||
};
|
||||
|
||||
this.$undoContainer.click(function(e) {
|
||||
// Only do this for clicks on this actual element.
|
||||
if (e.target.nodeName != self.$undoContainer[0].nodeName)
|
||||
@ -667,6 +648,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
self.$undoContainer.fadeOut(function() {
|
||||
iQ(this).remove();
|
||||
self.hidden = false;
|
||||
self._cancelFadeAwayUndoButtonTimer();
|
||||
self.$undoContainer = null;
|
||||
|
||||
iQ(self.container).show().animate({
|
||||
@ -686,31 +668,92 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
});
|
||||
|
||||
undoClose.click(function() {
|
||||
self.$undoContainer.fadeOut(remove);
|
||||
self._cancelFadeAwayUndoButtonTimer();
|
||||
self.$undoContainer.fadeOut(function() { self._removeHiddenGroupItem(); });
|
||||
});
|
||||
|
||||
// After 15 seconds, fade away.
|
||||
const WAIT = 15000;
|
||||
const FADE = 300;
|
||||
this.setupFadeAwayUndoButtonTimer();
|
||||
// Cancel the fadeaway if you move the mouse over the undo
|
||||
// button, and restart the countdown once you move out of it.
|
||||
this.$undoContainer.mouseover(function() {
|
||||
self._cancelFadeAwayUndoButtonTimer();
|
||||
});
|
||||
this.$undoContainer.mouseout(function() {
|
||||
self.setupFadeAwayUndoButtonTimer();
|
||||
});
|
||||
},
|
||||
|
||||
let fadeaway = function() {
|
||||
if (self.$undoContainer)
|
||||
// ----------
|
||||
// Sets up fade away undo button timeout.
|
||||
setupFadeAwayUndoButtonTimer: function() {
|
||||
let self = this;
|
||||
|
||||
if (!this._undoButtonTimeoutId) {
|
||||
this._undoButtonTimeoutId = setTimeout(function() {
|
||||
self._fadeAwayUndoButton();
|
||||
}, this.fadeAwayUndoButtonDelay);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Cancels the fade away undo button timeout.
|
||||
_cancelFadeAwayUndoButtonTimer: function() {
|
||||
clearTimeout(this._undoButtonTimeoutId);
|
||||
this._undoButtonTimeoutId = null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Fades away the undo button
|
||||
_fadeAwayUndoButton: function() {
|
||||
let self = this;
|
||||
|
||||
if (this.$undoContainer) {
|
||||
// if there is one or more orphan tabs or there is more than one group
|
||||
// and other groupS are not empty, fade away the undo button.
|
||||
let shouldFadeAway = GroupItems.getOrphanedTabs().length > 0;
|
||||
|
||||
if (!shouldFadeAway && GroupItems.groupItems.length > 1) {
|
||||
shouldFadeAway =
|
||||
GroupItems.groupItems.some(function(groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length > 0);
|
||||
});
|
||||
}
|
||||
if (shouldFadeAway) {
|
||||
self.$undoContainer.animate({
|
||||
color: "transparent",
|
||||
opacity: 0
|
||||
}, {
|
||||
duration: FADE,
|
||||
complete: remove
|
||||
duration: this.fadeAwayUndoButtonDuration,
|
||||
complete: function() { self._removeHiddenGroupItem(); }
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
let timeoutId = setTimeout(fadeaway, WAIT);
|
||||
// Cancel the fadeaway if you move the mouse over the undo
|
||||
// button, and restart the countdown once you move out of it.
|
||||
this.$undoContainer.mouseover(function() clearTimeout(timeoutId));
|
||||
this.$undoContainer.mouseout(function() {
|
||||
timeoutId = setTimeout(fadeaway, WAIT);
|
||||
// ----------
|
||||
// Removes the group item, its children and its container.
|
||||
_removeHiddenGroupItem: function() {
|
||||
let self = this;
|
||||
|
||||
// close all children
|
||||
let toClose = this._children.concat();
|
||||
toClose.forEach(function(child) {
|
||||
child.removeSubscriber(self, "close");
|
||||
child.close();
|
||||
});
|
||||
|
||||
// remove all children
|
||||
this.removeAll();
|
||||
GroupItems.unregister(this);
|
||||
this._sendToSubscribers("close");
|
||||
this.removeTrenches();
|
||||
|
||||
iQ(this.container).remove();
|
||||
this.$undoContainer.remove();
|
||||
this.$undoContainer = null;
|
||||
Items.unsquish();
|
||||
|
||||
this.deleteData();
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -977,19 +1020,22 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
// ----------
|
||||
// Function: shouldStack
|
||||
// Returns true if the groupItem, given "count", should stack (instead of grid).
|
||||
// Returns true if the groupItem should stack (instead of grid).
|
||||
shouldStack: function GroupItem_shouldStack(count) {
|
||||
if (count <= 1)
|
||||
return false;
|
||||
|
||||
var bb = this.getContentBounds();
|
||||
var options = {
|
||||
pretend: true,
|
||||
count: count
|
||||
return: 'widthAndColumns',
|
||||
count: count || this._children.length
|
||||
};
|
||||
let {childWidth, columns} = Items.arrange(null, bb, options);
|
||||
|
||||
var rects = Items.arrange(null, bb, options);
|
||||
return (rects[0].width < 55);
|
||||
let shouldStack = childWidth < TabItems.minTabWidth * 1.35;
|
||||
this._columns = shouldStack ? null : columns;
|
||||
|
||||
return shouldStack;
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1006,35 +1052,30 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
Items.arrange(this._children, box, Utils.extend({}, options, {z: 99999}));
|
||||
} else {
|
||||
var bb = this.getContentBounds();
|
||||
var count = this._children.length;
|
||||
if (!this.shouldStack(count)) {
|
||||
if (!this.shouldStack()) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
var animate;
|
||||
if (typeof options.animate == 'undefined')
|
||||
animate = true;
|
||||
else
|
||||
animate = options.animate;
|
||||
|
||||
this._children.forEach(function(child) {
|
||||
child.removeClass("stacked")
|
||||
});
|
||||
|
||||
this.topChild = null;
|
||||
|
||||
var arrangeOptions = Utils.copy(options);
|
||||
Utils.extend(arrangeOptions, {
|
||||
pretend: true,
|
||||
count: count
|
||||
});
|
||||
|
||||
if (!count) {
|
||||
if (!this._children.length) {
|
||||
this.xDensity = 0;
|
||||
this.yDensity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var arrangeOptions = Utils.copy(options);
|
||||
Utils.extend(arrangeOptions, {
|
||||
columns: this._columns
|
||||
});
|
||||
|
||||
// Items.arrange will rearrange the children, but also return an array
|
||||
// of the Rect's used.
|
||||
|
||||
var rects = Items.arrange(this._children, bb, arrangeOptions);
|
||||
|
||||
// yDensity = (the distance of the bottom of the last tab to the top of the content area)
|
||||
@ -1055,15 +1096,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
this.xDensity = (rightMostRight - bb.left) / (bb.width);
|
||||
|
||||
this._children.forEach(function(child, index) {
|
||||
if (!child.locked.bounds) {
|
||||
child.setBounds(rects[index], !animate);
|
||||
child.setRotation(0);
|
||||
if (options.z)
|
||||
child.setZ(options.z);
|
||||
}
|
||||
});
|
||||
|
||||
this._isStacked = false;
|
||||
} else
|
||||
this._stackArrange(bb, options);
|
||||
|
@ -1,252 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is infoitems.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Aza Raskin <aza@mozilla.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Ehsan Akhgari <ehsan@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 ***** */
|
||||
|
||||
// **********
|
||||
// Title: infoitems.js
|
||||
|
||||
// ##########
|
||||
// Class: InfoItem
|
||||
// An <Item> in TabView used for displaying information, such as the welcome video.
|
||||
// Note that it implements the <Subscribable> interface.
|
||||
//
|
||||
// ----------
|
||||
// Constructor: InfoItem
|
||||
//
|
||||
// Parameters:
|
||||
// bounds - a <Rect> for where the item should be located
|
||||
// options - various options for this infoItem (see below)
|
||||
//
|
||||
// Possible options:
|
||||
// locked - see <Item.locked>; default is {}
|
||||
// dontPush - true if this infoItem shouldn't push away on creation; default is false
|
||||
// immediately - place the item immediately, without animation
|
||||
function InfoItem(bounds, options) {
|
||||
try {
|
||||
Utils.assertThrow(Utils.isRect(bounds), 'bounds');
|
||||
|
||||
if (typeof options == 'undefined')
|
||||
options = {};
|
||||
|
||||
this._inited = false;
|
||||
this.isAnInfoItem = true;
|
||||
this.defaultSize = bounds.size();
|
||||
this.locked = (options.locked ? Utils.copy(options.locked) : {});
|
||||
this.bounds = new Rect(bounds);
|
||||
this.isDragging = false;
|
||||
|
||||
var self = this;
|
||||
|
||||
var $container = iQ('<div>')
|
||||
.addClass('info-item')
|
||||
.css(this.bounds)
|
||||
.appendTo('body');
|
||||
|
||||
this.$contents = iQ('<div>')
|
||||
.appendTo($container);
|
||||
|
||||
var $close = iQ('<div>')
|
||||
.addClass('close')
|
||||
.click(function() {
|
||||
self.close();
|
||||
})
|
||||
.appendTo($container);
|
||||
|
||||
// ___ locking
|
||||
if (this.locked.bounds)
|
||||
$container.css({cursor: 'default'});
|
||||
|
||||
if (this.locked.close)
|
||||
$close.hide();
|
||||
|
||||
// ___ Superclass initialization
|
||||
this._init($container[0]);
|
||||
|
||||
if (this.$debug)
|
||||
this.$debug.css({zIndex: -1000});
|
||||
|
||||
// ___ Finish Up
|
||||
if (!this.locked.bounds)
|
||||
this.draggable();
|
||||
|
||||
// ___ Position
|
||||
if (!options.dontPush)
|
||||
this.snap(options.immediately);
|
||||
|
||||
this._inited = true;
|
||||
this.save();
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
// ----------
|
||||
InfoItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
// ----------
|
||||
// Function: getStorageData
|
||||
// Returns all of the info worth storing about this item.
|
||||
getStorageData: function InfoItem_getStorageData() {
|
||||
var data = null;
|
||||
|
||||
try {
|
||||
data = {
|
||||
bounds: this.getBounds(),
|
||||
locked: Utils.copy(this.locked)
|
||||
};
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: save
|
||||
// Saves this item to persistent storage.
|
||||
save: function InfoItem_save() {
|
||||
try {
|
||||
if (!this._inited) // too soon to save now
|
||||
return;
|
||||
|
||||
var data = this.getStorageData();
|
||||
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setBounds
|
||||
// Sets the bounds with the given <Rect>, animating unless "immediately" is false.
|
||||
setBounds: function InfoItem_setBounds(rect, immediately) {
|
||||
try {
|
||||
Utils.assertThrow(Utils.isRect(rect), 'InfoItem.setBounds: rect must be a real rectangle!');
|
||||
|
||||
// ___ Determine what has changed
|
||||
var css = {};
|
||||
|
||||
if (rect.left != this.bounds.left)
|
||||
css.left = rect.left;
|
||||
|
||||
if (rect.top != this.bounds.top)
|
||||
css.top = rect.top;
|
||||
|
||||
if (rect.width != this.bounds.width)
|
||||
css.width = rect.width;
|
||||
|
||||
if (rect.height != this.bounds.height)
|
||||
css.height = rect.height;
|
||||
|
||||
if (Utils.isEmptyObject(css))
|
||||
return;
|
||||
|
||||
this.bounds = new Rect(rect);
|
||||
Utils.assertThrow(Utils.isRect(this.bounds),
|
||||
'InfoItem.setBounds: this.bounds must be a real rectangle!');
|
||||
|
||||
// ___ Update our representation
|
||||
if (immediately) {
|
||||
iQ(this.container).css(css);
|
||||
} else {
|
||||
TabItems.pausePainting();
|
||||
iQ(this.container).animate(css, {
|
||||
duration: 350,
|
||||
easing: "tabviewBounce",
|
||||
complete: function() {
|
||||
TabItems.resumePainting();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._updateDebugBounds();
|
||||
this.setTrenches(rect);
|
||||
this.save();
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setZ
|
||||
// Set the Z order for the item's container.
|
||||
setZ: function InfoItem_setZ(value) {
|
||||
try {
|
||||
Utils.assertThrow(typeof value == 'number', 'value must be a number');
|
||||
|
||||
this.zIndex = value;
|
||||
|
||||
iQ(this.container).css({zIndex: value});
|
||||
|
||||
if (this.$debug)
|
||||
this.$debug.css({zIndex: value + 1});
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: close
|
||||
// Closes the item.
|
||||
close: function InfoItem_close() {
|
||||
try {
|
||||
this._sendToSubscribers("close");
|
||||
this.removeTrenches();
|
||||
iQ(this.container).fadeOut(function() {
|
||||
iQ(this).remove();
|
||||
Items.unsquish();
|
||||
});
|
||||
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: html
|
||||
// Sets the item's container's html to the specified value.
|
||||
html: function InfoItem_html(value) {
|
||||
try {
|
||||
Utils.assertThrow(typeof value == 'string', 'value must be a string');
|
||||
this.$contents.html(value);
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}
|
||||
});
|
@ -601,7 +601,7 @@ Item.prototype = {
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
// positioning
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
if (!startSent) {
|
||||
if(Math.abs(mouse.x - startMouse.x) > self.dragOptions.minDragDistance ||
|
||||
Math.abs(mouse.y - startMouse.y) > self.dragOptions.minDragDistance) {
|
||||
@ -892,39 +892,41 @@ let Items = {
|
||||
// maximizing item size but maintaining standard tab aspect ratio for each
|
||||
//
|
||||
// Parameters:
|
||||
// items - an array of <Item>s. Can be null if the pretend and count options are set.
|
||||
// items - an array of <Item>s. Can be null, in which case we won't
|
||||
// actually move anything.
|
||||
// bounds - a <Rect> defining the space to arrange within
|
||||
// options - an object with various properites (see below)
|
||||
//
|
||||
// Possible "options" properties:
|
||||
// animate - whether to animate; default: true.
|
||||
// z - the z index to set all the items; default: don't change z.
|
||||
// pretend - whether to collect and return the rectangle rather than moving the items; default: false
|
||||
// count - overrides the item count for layout purposes; default: the actual item count
|
||||
// return - if set to 'widthAndColumns', it'll return an object with the
|
||||
// width of children and the columns.
|
||||
// count - overrides the item count for layout purposes;
|
||||
// default: the actual item count
|
||||
// padding - pixels between each item
|
||||
// columns - (int) a preset number of columns to use
|
||||
//
|
||||
// Returns:
|
||||
// the list of rectangles if the pretend option is set; otherwise null
|
||||
// an object with the width value of the child items and the number of columns,
|
||||
// if the return option is set to 'widthAndColumns'; otherwise the list of <Rect>s
|
||||
arrange: function Items_arrange(items, bounds, options) {
|
||||
var animate;
|
||||
if (!options || typeof options.animate == 'undefined')
|
||||
animate = true;
|
||||
else
|
||||
animate = options.animate;
|
||||
|
||||
if (typeof options == 'undefined')
|
||||
options = {};
|
||||
|
||||
var rects = null;
|
||||
if (options.pretend)
|
||||
rects = [];
|
||||
var animate = true;
|
||||
if (typeof options.animate != 'undefined')
|
||||
animate = options.animate;
|
||||
var immediately = !animate;
|
||||
|
||||
var rects = [];
|
||||
|
||||
var tabAspect = TabItems.tabHeight / TabItems.tabWidth;
|
||||
var count = options.count || (items ? items.length : 0);
|
||||
if (!count)
|
||||
return rects;
|
||||
|
||||
var columns = 1;
|
||||
var columns = options.columns || 1;
|
||||
// We'll assume for the time being that all the items have the same styling
|
||||
// and that the margin is the same width around.
|
||||
var itemMargin = items && items.length ?
|
||||
@ -954,20 +956,17 @@ let Items = {
|
||||
tabWidth = Math.min(tabWidth, (bounds.height - 2 * itemMargin) / tabAspect);
|
||||
tabHeight = tabWidth * tabAspect;
|
||||
}
|
||||
|
||||
if (options.return == 'widthAndColumns')
|
||||
return {childWidth: tabWidth, columns: columns};
|
||||
|
||||
var box = new Rect(bounds.left, bounds.top, tabWidth, tabHeight);
|
||||
var row = 0;
|
||||
var column = 0;
|
||||
var immediately;
|
||||
|
||||
var a;
|
||||
for (a = 0; a < count; a++) {
|
||||
immediately = !animate;
|
||||
|
||||
if (rects)
|
||||
rects.push(new Rect(box));
|
||||
else if (items && a < items.length) {
|
||||
var item = items[a];
|
||||
for (let a = 0; a < count; a++) {
|
||||
rects.push(new Rect(box));
|
||||
if (items && a < items.length) {
|
||||
let item = items[a];
|
||||
if (!item.locked.bounds) {
|
||||
item.setBounds(box, immediately);
|
||||
item.setRotation(0);
|
||||
@ -982,7 +981,6 @@ let Items = {
|
||||
box.left = bounds.left;
|
||||
box.top += (box.height * yScale) + padding;
|
||||
column = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,5 @@ XPCOMUtils.defineLazyGetter(this, "gPrivateBrowsing", function() {
|
||||
#include tabitems.js
|
||||
#include drag.js
|
||||
#include trench.js
|
||||
#include infoitems.js
|
||||
#include ui.js
|
||||
#include search.js
|
||||
|
||||
|
||||
|
@ -249,16 +249,19 @@ let UI = {
|
||||
// Resets the Panorama view to have just one group with all tabs
|
||||
// and, if firstTime == true, add the welcome video/tab
|
||||
reset: function UI_reset(firstTime) {
|
||||
let padding = 10;
|
||||
let infoWidth = 350;
|
||||
let infoHeight = 232;
|
||||
let padding = Trenches.defaultRadius;
|
||||
let welcomeWidth = 300;
|
||||
let pageBounds = Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let $actions = iQ("#actions");
|
||||
if ($actions)
|
||||
pageBounds.width -= $actions.width();
|
||||
|
||||
// ___ make a fresh groupItem
|
||||
let box = new Rect(pageBounds);
|
||||
box.width =
|
||||
Math.min(box.width * 0.667, pageBounds.width - (infoWidth + padding));
|
||||
box.width = Math.min(box.width * 0.667,
|
||||
pageBounds.width - (welcomeWidth + padding));
|
||||
box.height = box.height * 0.667;
|
||||
|
||||
GroupItems.groupItems.forEach(function(group) {
|
||||
@ -280,17 +283,18 @@ let UI = {
|
||||
if (firstTime) {
|
||||
gPrefBranch.setBoolPref("experienced_first_run", true);
|
||||
|
||||
// ___ make info item
|
||||
let video =
|
||||
"http://videos-cdn.mozilla.net/firefox4beta/tabcandy_howto.webm";
|
||||
let html =
|
||||
"<div class='intro'>"
|
||||
+ "<video src='" + video + "' width='100%' preload controls>"
|
||||
+ "</div>";
|
||||
let infoBox = new Rect(box.right + padding, box.top,
|
||||
infoWidth, infoHeight);
|
||||
let infoItem = new InfoItem(infoBox);
|
||||
infoItem.html(html);
|
||||
let url = gPrefBranch.getCharPref("welcome_url");
|
||||
let newTab = gBrowser.loadOneTab(url, {inBackground: true});
|
||||
let newTabItem = newTab.tabItem;
|
||||
let parent = newTabItem.parent;
|
||||
Utils.assert(parent, "should have a parent");
|
||||
|
||||
newTabItem.parent.remove(newTabItem);
|
||||
let aspect = TabItems.tabHeight / TabItems.tabWidth;
|
||||
let welcomeBounds = new Rect(box.right + padding, box.top,
|
||||
welcomeWidth, welcomeWidth * aspect);
|
||||
newTabItem.setBounds(welcomeBounds, true);
|
||||
GroupItems.setActiveGroupItem(groupItem);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -145,6 +145,7 @@ _BROWSER_FILES = \
|
||||
browser_bug561636.js \
|
||||
browser_bug562649.js \
|
||||
browser_bug563588.js \
|
||||
browser_bug565575.js \
|
||||
browser_bug575561.js \
|
||||
browser_bug577121.js \
|
||||
browser_bug579872.js \
|
||||
@ -159,6 +160,7 @@ _BROWSER_FILES = \
|
||||
browser_bug595507.js \
|
||||
browser_bug596687.js \
|
||||
browser_bug597218.js \
|
||||
browser_bug609700.js \
|
||||
browser_contextSearchTabPosition.js \
|
||||
browser_ctrlTab.js \
|
||||
browser_discovery.js \
|
||||
@ -221,6 +223,7 @@ _BROWSER_FILES = \
|
||||
browser_aboutHome.js \
|
||||
app_bug575561.html \
|
||||
app_subframe_bug575561.html \
|
||||
browser_contentAreaClick.js \
|
||||
$(NULL)
|
||||
|
||||
# compartment-disabled
|
||||
|
@ -94,6 +94,32 @@ let gTests = [
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check default snippets are shown if snippets are invalid xml",
|
||||
setup: function ()
|
||||
{
|
||||
let storage = getStorage();
|
||||
// This must be some incorrect xhtml code.
|
||||
storage.setItem("snippets", "<p><b></p></b>");
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
|
||||
let snippetsElt = doc.getElementById("snippets");
|
||||
ok(snippetsElt, "Found snippets element");
|
||||
ok(snippetsElt.hidden, "Snippets element is hidden");
|
||||
|
||||
let defaultsElt = doc.getElementById("defaultSnippets");
|
||||
ok(defaultsElt, "Found default snippets element")
|
||||
ok(Array.some(defaultsElt.getElementsByTagName("span"), function(elt) {
|
||||
return !elt.hidden;
|
||||
}), "A default snippet is visible.");
|
||||
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
function test()
|
||||
|
13
browser/base/content/test/browser_bug565575.js
Normal file
13
browser/base/content/test/browser_bug565575.js
Normal file
@ -0,0 +1,13 @@
|
||||
function test() {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
BrowserOpenTab();
|
||||
ok(gURLBar.focused, "location bar is focused for a new tab");
|
||||
|
||||
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||
ok(!gURLBar.focused, "location bar isn't focused for the previously selected tab");
|
||||
|
||||
gBrowser.selectedTab = gBrowser.tabs[1];
|
||||
ok(gURLBar.focused, "location bar is re-focused when selecting the new tab");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
20
browser/base/content/test/browser_bug609700.js
Normal file
20
browser/base/content/test/browser_bug609700.js
Normal file
@ -0,0 +1,20 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.ww.registerNotification(function (aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(arguments.callee);
|
||||
|
||||
ok(true, "duplicateTabIn opened a new window");
|
||||
|
||||
aSubject.addEventListener("load", function () {
|
||||
executeSoon(function () {
|
||||
aSubject.close();
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
|
||||
duplicateTabIn(gBrowser.selectedTab, "window");
|
||||
}
|
296
browser/base/content/test/browser_contentAreaClick.js
Normal file
296
browser/base/content/test/browser_contentAreaClick.js
Normal file
@ -0,0 +1,296 @@
|
||||
/* ***** 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 Firefox Browser Test Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* 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
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* Test for bug 549340.
|
||||
* Test for browser.js::contentAreaClick() util.
|
||||
*
|
||||
* The test opens a new browser window, then replaces browser.js methods invoked
|
||||
* by contentAreaClick with a mock function that tracks which methods have been
|
||||
* called.
|
||||
* Each sub-test synthesizes a mouse click event on links injected in content,
|
||||
* the event is collected by a click handler that ensures that contentAreaClick
|
||||
* correctly prevent default events, and follows the correct code path.
|
||||
*/
|
||||
|
||||
let gTests = [
|
||||
|
||||
{
|
||||
desc: "Simple left click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: {},
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [],
|
||||
preventDefault: false,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Ctrl/Cmd left click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { ctrlKey: true,
|
||||
metaKey: true },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
// The next test was once handling feedService.forcePreview(). Now it should
|
||||
// just be like Alt click.
|
||||
{
|
||||
desc: "Shift+Alt left click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { shiftKey: true,
|
||||
altKey: true },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Shift click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { shiftKey: true },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Alt click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { altKey: true },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Panel click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: {},
|
||||
target: "panellink",
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Simple middle click opentab",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { button: 1 },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Simple middle click openwin",
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("browser.tabs.opentabfor.middleclick", false);
|
||||
},
|
||||
clean: function() {
|
||||
try {
|
||||
gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick");
|
||||
} catch(ex) {}
|
||||
},
|
||||
event: { button: 1 },
|
||||
target: "commonlink",
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Middle mouse paste",
|
||||
setup: function() {
|
||||
gPrefService.setBoolPref("middlemouse.contentLoadURL", true);
|
||||
gPrefService.setBoolPref("general.autoScroll", false);
|
||||
},
|
||||
clean: function() {
|
||||
try {
|
||||
gPrefService.clearUserPref("middlemouse.contentLoadURL");
|
||||
} catch(ex) {}
|
||||
try {
|
||||
gPrefService.clearUserPref("general.autoScroll");
|
||||
} catch(ex) {}
|
||||
},
|
||||
event: { button: 1 },
|
||||
target: "emptylink",
|
||||
expectedInvokedMethods: [ "middleMousePaste" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
// Array of method names that will be replaced in the new window.
|
||||
let gReplacedMethods = [
|
||||
"middleMousePaste",
|
||||
"urlSecurityCheck",
|
||||
"loadURI",
|
||||
"gatherTextUnder",
|
||||
"saveURL",
|
||||
"openLinkIn",
|
||||
"getShortcutOrURI",
|
||||
];
|
||||
|
||||
// Reference to the new window.
|
||||
let gTestWin = null;
|
||||
|
||||
// List of methods invoked by a specific call to contentAreaClick.
|
||||
let gInvokedMethods = [];
|
||||
|
||||
// The test currently running.
|
||||
let gCurrentTest = null;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
|
||||
gTestWin.addEventListener("load", function (event) {
|
||||
info("Window loaded.");
|
||||
gTestWin.removeEventListener("load", arguments.callee, false);
|
||||
waitForFocus(function() {
|
||||
info("Setting up browser...");
|
||||
setupTestBrowserWindow();
|
||||
info("Running tests...");
|
||||
executeSoon(runNextTest);
|
||||
}, gTestWin.content, true);
|
||||
}, false);
|
||||
}
|
||||
|
||||
// Click handler used to steal click events.
|
||||
let gClickHandler = {
|
||||
handleEvent: function (event) {
|
||||
let linkId = event.target.id;
|
||||
is(event.type, "click",
|
||||
gCurrentTest.desc + ":Handler received a click event on " + linkId);
|
||||
|
||||
let isPanelClick = linkId == "panellink";
|
||||
let returnValue = gTestWin.contentAreaClick(event, isPanelClick);
|
||||
let prevent = event.getPreventDefault();
|
||||
is(prevent, gCurrentTest.preventDefault,
|
||||
gCurrentTest.desc + ": event.getPreventDefault() is correct (" + prevent + ")")
|
||||
|
||||
// Check that all required methods have been called.
|
||||
gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) {
|
||||
isnot(gInvokedMethods.indexOf(aExpectedMethodName), -1,
|
||||
gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked");
|
||||
});
|
||||
|
||||
if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) {
|
||||
is(false, "More than the expected methods have been called");
|
||||
gInvokedMethods.forEach(function (method) info(method + " was invoked"));
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps around the methods' replacement mock function.
|
||||
function wrapperMethod(aInvokedMethods, aMethodName) {
|
||||
return function () {
|
||||
aInvokedMethods.push(aMethodName);
|
||||
// At least getShortcutOrURI requires to return url that is the first param.
|
||||
return arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
function setupTestBrowserWindow() {
|
||||
// Steal click events and don't propagate them.
|
||||
gTestWin.addEventListener("click", gClickHandler, true);
|
||||
|
||||
// Replace methods.
|
||||
gReplacedMethods.forEach(function (aMethodName) {
|
||||
gTestWin["old_" + aMethodName] = gTestWin[aMethodName];
|
||||
gTestWin[aMethodName] = wrapperMethod(gInvokedMethods, aMethodName);
|
||||
});
|
||||
|
||||
// Inject links in content.
|
||||
let doc = gTestWin.content.document;
|
||||
let mainDiv = doc.createElement("div");
|
||||
mainDiv.innerHTML =
|
||||
'<a id="commonlink" href="http://mochi.test/moz/">Common link</a>' +
|
||||
'<a id="panellink" href="http://mochi.test/moz/">Panel link</a>' +
|
||||
'<a id="emptylink">Empty link</a>';
|
||||
doc.body.appendChild(mainDiv);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (gCurrentTest) {
|
||||
info(gCurrentTest.desc + ": cleaning up...")
|
||||
gCurrentTest.clean();
|
||||
gInvokedMethods.length = 0;
|
||||
}
|
||||
|
||||
if (gTests.length > 0) {
|
||||
gCurrentTest = gTests.shift();
|
||||
|
||||
info(gCurrentTest.desc + ": starting...");
|
||||
// Prepare for test.
|
||||
gCurrentTest.setup();
|
||||
|
||||
// Fire click event.
|
||||
let target = gTestWin.content.document.getElementById(gCurrentTest.target);
|
||||
ok(target, gCurrentTest.desc + ": target is valid (" + target.id + ")");
|
||||
EventUtils.synthesizeMouse(target, 2, 2, gCurrentTest.event, gTestWin.content);
|
||||
}
|
||||
else {
|
||||
// No more tests to run.
|
||||
finishTest()
|
||||
}
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
info("Restoring browser...");
|
||||
gTestWin.removeEventListener("click", gClickHandler, true);
|
||||
|
||||
// Restore original methods.
|
||||
gReplacedMethods.forEach(function (aMethodName) {
|
||||
gTestWin[aMethodName] = gTestWin["old_" + aMethodName];
|
||||
delete gTestWin["old_" + aMethodName];
|
||||
});
|
||||
|
||||
gTestWin.close();
|
||||
finish();
|
||||
}
|
@ -121,7 +121,7 @@ var gTestSteps = [
|
||||
},
|
||||
function() {
|
||||
info("Running step 7 - remove tab immediately");
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
let tab = gBrowser.addTab("about:logo");
|
||||
gBrowser.removeTab(tab);
|
||||
ensure_opentabs_match_db();
|
||||
nextStep();
|
||||
@ -208,6 +208,8 @@ function ensure_opentabs_match_db() {
|
||||
for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) {
|
||||
let browser = browserWin.gBrowser.getBrowserAtIndex(i);
|
||||
let url = browser.currentURI.spec;
|
||||
if (url == "about:blank")
|
||||
continue;
|
||||
if (!(url in tabs))
|
||||
tabs[url] = 1;
|
||||
else
|
||||
@ -247,6 +249,10 @@ function ensure_opentabs_match_db() {
|
||||
ok(dbtabs.indexOf(url) > -1,
|
||||
"tab is open (" + tabs[url] + " times) and should recorded in db: " + url);
|
||||
}
|
||||
dbtabs.forEach(function (url) {
|
||||
ok(url in tabs,
|
||||
"db-recorded tab should actually exist: " + url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,11 +44,8 @@ function test() {
|
||||
browser2.contentWindow, null, true,
|
||||
"focusedElement after tab change, focus in new tab");
|
||||
|
||||
// switching tabs when the urlbar is focused and nothing in the new tab is focused
|
||||
// switching tabs when nothing in the new tab is focused
|
||||
// should focus the browser
|
||||
expectFocusShift(function () gURLBar.focus(),
|
||||
window, gURLBar.inputField, true,
|
||||
"url field focused");
|
||||
expectFocusShift(function () gBrowser.selectedTab = tab1,
|
||||
browser1.contentWindow, null, true,
|
||||
"focusedElement after tab change, focus in new tab");
|
||||
@ -89,6 +86,9 @@ function test() {
|
||||
window, gURLBar.inputField, true,
|
||||
"focusedWindow after url field focused");
|
||||
is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "url field focused, button in tab");
|
||||
expectFocusShift(function () gURLBar.blur(),
|
||||
window, null, true,
|
||||
"focusedWindow after browser focused");
|
||||
|
||||
// when a chrome element is focused, switching tabs to a tab with a button
|
||||
// with the current focus should focus the button
|
||||
|
@ -53,6 +53,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug594176.js \
|
||||
browser_tabview_bug595191.js \
|
||||
browser_tabview_bug595518.js \
|
||||
browser_tabview_bug595521.js \
|
||||
browser_tabview_bug595804.js \
|
||||
browser_tabview_bug595930.js \
|
||||
browser_tabview_bug595943.js \
|
||||
|
101
browser/base/content/test/tabview/browser_tabview_bug595521.js
Normal file
101
browser/base/content/test/tabview/browser_tabview_bug595521.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* ***** 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 a test for bug 595521.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.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 ***** */
|
||||
|
||||
let fadeAwayUndoButtonDelay;
|
||||
let fadeAwayUndoButtonDuration;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", testCloseLastGroup, false);
|
||||
TabView.toggle();
|
||||
}
|
||||
|
||||
function testCloseLastGroup() {
|
||||
window.removeEventListener("tabviewshown", testCloseLastGroup, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has one group only");
|
||||
|
||||
let groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
|
||||
let checkExistence = function() {
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"Still has one group after delay");
|
||||
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "click" }, groupItem.$undoContainer[0], contentWindow);
|
||||
};
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
// it should still stay after 3 ms.
|
||||
setTimeout(checkExistence, 3);
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupShown", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupShown");
|
||||
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
groupItem.fadeAwayUndoButtonDelay = fadeAwayUndoButtonDelay;
|
||||
groupItem.fadeAwayUndoButtonDuration = fadeAwayUndoButtonDuration;
|
||||
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
|
||||
TabView.toggle();
|
||||
});
|
||||
|
||||
let closeButton = groupItem.container.getElementsByClassName("close");
|
||||
ok(closeButton, "Group item close button exists");
|
||||
|
||||
// store the original values
|
||||
fadeAwayUndoButtonDelay = groupItem.fadeAwayUndoButtonDelay;
|
||||
fadeAwayUndoButtonDuration = groupItem.fadeAwayUndoButtonDuration;
|
||||
|
||||
// set both fade away delay and duration to 1ms
|
||||
groupItem.fadeAwayUndoButtonDelay = 1;
|
||||
groupItem.fadeAwayUndoButtonDuration = 1;
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
|
||||
}
|
@ -35,15 +35,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
let newWin;
|
||||
let prefService;
|
||||
|
||||
function test() {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
prefService =
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).
|
||||
getBranch("browser.panorama.");
|
||||
// make sure we don't trigger the 'first run' behavior
|
||||
prefService.setBoolPref("experienced_first_run", true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
@ -104,7 +97,6 @@ function test() {
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
|
||||
|
||||
// clean up and finish
|
||||
prefService.setBoolPref("experienced_first_run", false);
|
||||
newWin.close();
|
||||
|
||||
finish();
|
||||
|
@ -44,8 +44,10 @@ function test() {
|
||||
|
||||
ok(!TabView.isVisible(), "Main window TabView is hidden");
|
||||
|
||||
ok(experienced(), "should start as experienced");
|
||||
|
||||
prefsBranch.setBoolPref("experienced_first_run", false);
|
||||
ok(!experienced(), "not experienced");
|
||||
ok(!experienced(), "set to not experienced");
|
||||
|
||||
newWindowWithTabView(checkFirstRun, part2);
|
||||
}
|
||||
@ -58,11 +60,14 @@ function experienced() {
|
||||
function checkFirstRun(win) {
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
let infoItems = contentWindow.iQ(".info-item");
|
||||
is(infoItems.length, 1, "There should be an info item");
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There should be two tabs");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There should be one group");
|
||||
is(groupItems[0].getChildren().length, 1, "...with one child");
|
||||
|
||||
let orphanTabCount = contentWindow.GroupItems.getOrphanedTabs().length;
|
||||
is(orphanTabCount, 1, "There should also be an orphaned tab");
|
||||
|
||||
ok(experienced(), "we're now experienced");
|
||||
}
|
||||
@ -74,12 +79,19 @@ function part2() {
|
||||
function checkNotFirstRun(win) {
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
let infoItems = contentWindow.iQ(".info-item");
|
||||
is(infoItems.length, 0, "There should be no info items");
|
||||
is(win.gBrowser.tabs.length, 1, "There should be one tab");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There should be one group");
|
||||
is(groupItems[0].getChildren().length, 1, "...with one child");
|
||||
|
||||
let orphanTabCount = contentWindow.GroupItems.getOrphanedTabs().length;
|
||||
is(orphanTabCount, 0, "There should also be no orphaned tabs");
|
||||
}
|
||||
|
||||
function endGame() {
|
||||
ok(!TabView.isVisible(), "Main window TabView is still hidden");
|
||||
ok(experienced(), "should finish as experienced");
|
||||
finish();
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
||||
pasteAndGo.setAttribute("label", label);
|
||||
pasteAndGo.setAttribute("anonid", "paste-and-go");
|
||||
pasteAndGo.setAttribute("oncommand",
|
||||
"gURLBar.value = ''; goDoCommand('cmd_paste'); gURLBar.handleCommand();");
|
||||
"gURLBar.select(); goDoCommand('cmd_paste'); gURLBar.handleCommand();");
|
||||
cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling);
|
||||
}
|
||||
]]></constructor>
|
||||
@ -248,8 +248,13 @@
|
||||
if (action) {
|
||||
url = action.param;
|
||||
if (!(aTriggeringEvent && aTriggeringEvent.altKey)) {
|
||||
if (action.type == "switchtab")
|
||||
switchToTabHavingURI(url);
|
||||
if (action.type == "switchtab") {
|
||||
this.handleRevert();
|
||||
let prevTab = gBrowser.selectedTab;
|
||||
if (switchToTabHavingURI(url) &&
|
||||
isTabEmpty(prevTab))
|
||||
gBrowser.removeTab(prevTab);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -272,8 +277,13 @@
|
||||
if (aTriggeringEvent instanceof MouseEvent) {
|
||||
// We have a mouse event (from the go button), so use the standard
|
||||
// UI link behaviors
|
||||
openUILink(url, aTriggeringEvent, false, false,
|
||||
true /* allow third party fixup */, postData);
|
||||
let where = whereToOpenLink(aTriggeringEvent, false, false);
|
||||
if (where != "current") {
|
||||
this.handleRevert();
|
||||
content.focus();
|
||||
}
|
||||
openUILinkIn(url, where,
|
||||
{ allowThirdPartyFixup: true, postData: postData });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -412,9 +412,8 @@ function isBidiEnabled() {
|
||||
function openAboutDialog() {
|
||||
var enumerator = Services.wm.getEnumerator("Browser:About");
|
||||
while (enumerator.hasMoreElements()) {
|
||||
// Only open one about window (Bug 599573)
|
||||
let win = enumerator.getNext();
|
||||
if (win.opener != window)
|
||||
continue;
|
||||
win.focus();
|
||||
return;
|
||||
}
|
||||
@ -486,107 +485,12 @@ function openFeedbackPage()
|
||||
openUILinkIn("http://input.mozilla.com/feedback", "tab");
|
||||
}
|
||||
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
/**
|
||||
* Opens the update manager and checks for updates to the application.
|
||||
*/
|
||||
function checkForUpdates()
|
||||
{
|
||||
var um =
|
||||
Components.classes["@mozilla.org/updates/update-manager;1"].
|
||||
getService(Components.interfaces.nsIUpdateManager);
|
||||
var prompter =
|
||||
Components.classes["@mozilla.org/updates/update-prompt;1"].
|
||||
createInstance(Components.interfaces.nsIUpdatePrompt);
|
||||
|
||||
// If there's an update ready to be applied, show the "Update Downloaded"
|
||||
// UI instead and let the user know they have to restart the browser for
|
||||
// the changes to be applied.
|
||||
if (um.activeUpdate && um.activeUpdate.state == "pending")
|
||||
prompter.showUpdateDownloaded(um.activeUpdate);
|
||||
else
|
||||
prompter.checkForUpdates();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
/**
|
||||
* Updates an element to reflect the state of available update services.
|
||||
*/
|
||||
function setupCheckForUpdates(checkForUpdates, aStringBundle)
|
||||
{
|
||||
var updates =
|
||||
Components.classes["@mozilla.org/updates/update-service;1"].
|
||||
getService(Components.interfaces.nsIApplicationUpdateService);
|
||||
var um =
|
||||
Components.classes["@mozilla.org/updates/update-manager;1"].
|
||||
getService(Components.interfaces.nsIUpdateManager);
|
||||
|
||||
// Disable the UI if the update enabled pref has been locked by the
|
||||
// administrator or if we cannot update for some other reason
|
||||
var canCheckForUpdates = updates.canCheckForUpdates;
|
||||
checkForUpdates.setAttribute("disabled", !canCheckForUpdates);
|
||||
if (!canCheckForUpdates)
|
||||
return;
|
||||
|
||||
var activeUpdate = um.activeUpdate;
|
||||
|
||||
// If there's an active update, substitute its name into the label
|
||||
// we show for this item, otherwise display a generic label.
|
||||
function getStringWithUpdateName(key) {
|
||||
if (activeUpdate && activeUpdate.name)
|
||||
return aStringBundle.formatStringFromName(key, [activeUpdate.name], 1);
|
||||
return aStringBundle.GetStringFromName(key + "Fallback");
|
||||
}
|
||||
|
||||
// By default, show "Check for Updates..."
|
||||
var key = "default";
|
||||
if (activeUpdate) {
|
||||
switch (activeUpdate.state) {
|
||||
case "downloading":
|
||||
// If we're downloading an update at present, show the text:
|
||||
// "Downloading Firefox x.x..." otherwise we're paused, and show
|
||||
// "Resume Downloading Firefox x.x..."
|
||||
key = updates.isDownloading ? "downloading" : "resume";
|
||||
break;
|
||||
case "pending":
|
||||
// If we're waiting for the user to restart, show: "Apply Downloaded
|
||||
// Updates Now..."
|
||||
key = "pending";
|
||||
break;
|
||||
}
|
||||
}
|
||||
checkForUpdates.label = getStringWithUpdateName("updatesItem_" + key);
|
||||
checkForUpdates.accessKey = aStringBundle.
|
||||
GetStringFromName("updatesItem_" + key + ".accesskey");
|
||||
if (um.activeUpdate && updates.isDownloading)
|
||||
checkForUpdates.setAttribute("loading", "true");
|
||||
else
|
||||
checkForUpdates.removeAttribute("loading");
|
||||
}
|
||||
#endif
|
||||
|
||||
function buildHelpMenu()
|
||||
{
|
||||
// Enable/disable the "Report Web Forgery" menu item. safebrowsing object
|
||||
// may not exist in OSX
|
||||
if (typeof safebrowsing != "undefined")
|
||||
safebrowsing.setReportPhishingMenu();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#ifdef MOZ_UPDATER
|
||||
var checkForUpdates = document.getElementById("checkForUpdates");
|
||||
var browserBundle = document.getElementById("bundle_browser").stringBundle;
|
||||
setupCheckForUpdates(checkForUpdates, browserBundle);
|
||||
#else
|
||||
// Needed by safebrowsing for inserting its menuitem so just hide it
|
||||
document.getElementById("updateSeparator").hidden = true;
|
||||
#endif
|
||||
#else
|
||||
// Needed by safebrowsing for inserting its menuitem so just hide it
|
||||
document.getElementById("updateSeparator").hidden = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
function isElementVisible(aElement)
|
||||
|
@ -1,5 +1,6 @@
|
||||
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
|
||||
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
||||
pref("browser.panorama.welcome_url", "http://www.mozilla.com/firefox/panorama/");
|
||||
// The time interval between checks for a new version (in seconds)
|
||||
// nightly=8 hours, official=24 hours
|
||||
pref("app.update.interval", 28800);
|
||||
|
@ -1,5 +1,6 @@
|
||||
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
|
||||
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
||||
pref("browser.panorama.welcome_url", "http://www.mozilla.com/firefox/panorama/");
|
||||
// The time interval between checks for a new version (in seconds)
|
||||
// nightly=8 hours, official=24 hours
|
||||
pref("app.update.interval", 28800);
|
||||
|
@ -37,6 +37,8 @@
|
||||
const kIMig = Components.interfaces.nsIBrowserProfileMigrator;
|
||||
const kIPStartup = Components.interfaces.nsIProfileStartup;
|
||||
const kProfileMigratorContractIDPrefix = "@mozilla.org/profile/migrator;1?app=browser&type=";
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var MigrationWizard = {
|
||||
_source: "", // Source Profile Migrator ContractID suffix
|
||||
@ -54,6 +56,7 @@ var MigrationWizard = {
|
||||
os.addObserver(this, "Migration:Started", false);
|
||||
os.addObserver(this, "Migration:ItemBeforeMigrate", false);
|
||||
os.addObserver(this, "Migration:ItemAfterMigrate", false);
|
||||
os.addObserver(this, "Migration:ItemError", false);
|
||||
os.addObserver(this, "Migration:Ended", false);
|
||||
|
||||
this._wiz = document.documentElement;
|
||||
@ -81,6 +84,7 @@ var MigrationWizard = {
|
||||
os.removeObserver(this, "Migration:Started");
|
||||
os.removeObserver(this, "Migration:ItemBeforeMigrate");
|
||||
os.removeObserver(this, "Migration:ItemAfterMigrate");
|
||||
os.removeObserver(this, "Migration:ItemError");
|
||||
os.removeObserver(this, "Migration:Ended");
|
||||
},
|
||||
|
||||
@ -489,6 +493,35 @@ var MigrationWizard = {
|
||||
nextButton.click();
|
||||
}
|
||||
break;
|
||||
case "Migration:ItemError":
|
||||
var type = "undefined";
|
||||
switch (parseInt(aData)) {
|
||||
case Ci.nsIBrowserProfileMigrator.SETTINGS:
|
||||
type = "settings";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.COOKIES:
|
||||
type = "cookies";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.HISTORY:
|
||||
type = "history";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.FORMDATA:
|
||||
type = "form data";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.PASSWORDS:
|
||||
type = "passwords";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.BOOKMARKS:
|
||||
type = "bookmarks";
|
||||
break;
|
||||
case Ci.nsIBrowserProfileMigrator.OTHERDATA:
|
||||
type = "misc. data";
|
||||
break;
|
||||
}
|
||||
Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService)
|
||||
.logStringMessage("some " + type + " did not successfully migrate.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define browserprofilemigratorutils___h___
|
||||
|
||||
#define MIGRATION_ITEMBEFOREMIGRATE "Migration:ItemBeforeMigrate"
|
||||
#define MIGRATION_ITEMMIGRATEERROR "Migration:ItemError"
|
||||
#define MIGRATION_ITEMAFTERMIGRATE "Migration:ItemAfterMigrate"
|
||||
#define MIGRATION_STARTED "Migration:Started"
|
||||
#define MIGRATION_ENDED "Migration:Ended"
|
||||
@ -47,11 +48,12 @@
|
||||
mObserverService->NotifyObservers(nsnull, message, item)
|
||||
|
||||
#define COPY_DATA(func, replace, itemIndex) \
|
||||
if (NS_SUCCEEDED(rv) && (aItems & itemIndex || !aItems)) { \
|
||||
if ((aItems & itemIndex || !aItems)) { \
|
||||
nsAutoString index; \
|
||||
index.AppendInt(itemIndex); \
|
||||
NOTIFY_OBSERVERS(MIGRATION_ITEMBEFOREMIGRATE, index.get()); \
|
||||
rv = func(replace); \
|
||||
if (NS_FAILED(func(replace))) \
|
||||
NOTIFY_OBSERVERS(MIGRATION_ITEMMIGRATEERROR, index.get()); \
|
||||
NOTIFY_OBSERVERS(MIGRATION_ITEMAFTERMIGRATE, index.get()); \
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,8 @@
|
||||
#include "nsILocalFileWin.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "prnetdb.h"
|
||||
|
||||
#include <objbase.h>
|
||||
#include <shlguid.h>
|
||||
#include <urlhist.h>
|
||||
@ -1919,14 +1921,20 @@ nsIEProfileMigrator::CopyCookiesFromBuffer(char *aBuffer,
|
||||
nsDependentCString stringName(name),
|
||||
stringPath(path);
|
||||
|
||||
// delete any possible extant matching host cookie
|
||||
if (hostCopy[0] == '.')
|
||||
// delete any possible extant matching host cookie and
|
||||
// check if we're dealing with an IPv4/IPv6 hostname.
|
||||
PRBool isIPAddress = PR_FALSE;
|
||||
if (hostCopy[0] == '.') {
|
||||
aCookieManager->Remove(nsDependentCString(hostCopy+1),
|
||||
stringName, stringPath, PR_FALSE);
|
||||
PRNetAddr addr;
|
||||
if (PR_StringToNetAddr(hostCopy+1, &addr) == PR_SUCCESS)
|
||||
isIPAddress = PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult onerv;
|
||||
// Add() makes a new domain cookie
|
||||
onerv = aCookieManager->Add(nsDependentCString(hostCopy),
|
||||
onerv = aCookieManager->Add(nsDependentCString(hostCopy + (isIPAddress ? 1 : 0)),
|
||||
stringPath,
|
||||
stringName,
|
||||
nsDependentCString(value),
|
||||
|
@ -574,8 +574,6 @@ nsBrowserContentHandler.prototype = {
|
||||
get defaultArgs() {
|
||||
var prefb = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(nsIPrefBranch);
|
||||
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
|
||||
.getService(Components.interfaces.nsIURLFormatter);
|
||||
|
||||
var overridePage = "";
|
||||
var haveUpdateSession = false;
|
||||
@ -589,7 +587,7 @@ nsBrowserContentHandler.prototype = {
|
||||
switch (override) {
|
||||
case OVERRIDE_NEW_PROFILE:
|
||||
// New profile.
|
||||
overridePage = formatter.formatURLPref("startup.homepage_welcome_url");
|
||||
overridePage = Services.urlFormatter.formatURLPref("startup.homepage_welcome_url");
|
||||
break;
|
||||
case OVERRIDE_NEW_MSTONE:
|
||||
// Existing profile, new milestone build.
|
||||
@ -600,12 +598,19 @@ nsBrowserContentHandler.prototype = {
|
||||
var ss = Components.classes["@mozilla.org/browser/sessionstartup;1"]
|
||||
.getService(Components.interfaces.nsISessionStartup);
|
||||
haveUpdateSession = ss.doRestore();
|
||||
overridePage = formatter.formatURLPref("startup.homepage_override_url");
|
||||
overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
|
||||
if (prefb.prefHasUserValue("app.update.postupdate"))
|
||||
overridePage = getPostUpdateOverridePage(overridePage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No need to override homepage, but update snippets url if the pref has
|
||||
// been manually changed.
|
||||
if (Services.prefs.prefHasUserValue(AboutHomeUtils.SNIPPETS_URL_PREF)) {
|
||||
AboutHomeUtils.loadSnippetsURL();
|
||||
}
|
||||
}
|
||||
} catch (ex) {}
|
||||
|
||||
// formatURLPref might return "about:blank" if getting the pref fails
|
||||
@ -882,6 +887,7 @@ nsDefaultCommandLineHandler.prototype = {
|
||||
};
|
||||
|
||||
let AboutHomeUtils = {
|
||||
SNIPPETS_URL_PREF: "browser.aboutHomeSnippets.updateUrl",
|
||||
get _storage() {
|
||||
let aboutHomeURI = Services.io.newURI("moz-safe-about:home", null, null);
|
||||
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
|
||||
@ -908,10 +914,10 @@ let AboutHomeUtils = {
|
||||
loadSnippetsURL: function AHU_loadSnippetsURL()
|
||||
{
|
||||
const STARTPAGE_VERSION = 1;
|
||||
const SNIPPETS_URL = "http://snippets.mozilla.com/" + STARTPAGE_VERSION + "/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/";
|
||||
let updateURL = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"].
|
||||
getService(Components.interfaces.nsIURLFormatter).
|
||||
formatURL(SNIPPETS_URL);
|
||||
let updateURL = Services.prefs
|
||||
.getCharPref(this.SNIPPETS_URL_PREF)
|
||||
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);
|
||||
updateURL = Services.urlFormatter.formatURL(updateURL);
|
||||
this._storage.setItem("snippets-update-url", updateURL);
|
||||
},
|
||||
};
|
||||
|
@ -499,10 +499,10 @@ PlacesViewBase.prototype = {
|
||||
// Many users consider toolbars as shortcuts containers, so explicitly
|
||||
// allow empty labels on toolbarbuttons. For any other element try to be
|
||||
// smarter, guessing a title from the uri.
|
||||
elt.label = PlacesUIUtils.getBestTitle(aPlacesNode);
|
||||
elt.setAttribute("label", PlacesUIUtils.getBestTitle(aPlacesNode));
|
||||
}
|
||||
else {
|
||||
elt.label = aNewTitle;
|
||||
elt.setAttribute("label", aNewTitle);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -720,7 +720,7 @@ var PlacesUIUtils = {
|
||||
* This is actually used to distinguish user-initiated visits in frames
|
||||
* so automatic visits can be correctly ignored.
|
||||
*/
|
||||
markPageAsFollowedLink: function PUIU_markPageAsUserClicked(aURL) {
|
||||
markPageAsFollowedLink: function PUIU_markPageAsFollowedLink(aURL) {
|
||||
PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory)
|
||||
.markPageAsFollowedLink(this.createFixedURI(aURL));
|
||||
},
|
||||
|
@ -66,6 +66,10 @@ _BROWSER_TEST_FILES = \
|
||||
browser_sidebarpanels_click.js \
|
||||
sidebarpanels_click_test_page.html \
|
||||
browser_library_infoBox.js \
|
||||
browser_markPageAsFollowedLink.js \
|
||||
framedPage.html \
|
||||
frameLeft.html \
|
||||
frameRight.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
@ -0,0 +1,89 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests that visits across frames are correctly represented in the database.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const BASE_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser";
|
||||
const PAGE_URL = BASE_URL + "/framedPage.html";
|
||||
const LEFT_URL = BASE_URL + "/frameLeft.html";
|
||||
const RIGHT_URL = BASE_URL + "/frameRight.html";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let gTabLoaded = false;
|
||||
let gLeftFrameVisited = false;
|
||||
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
let url = aSubject.QueryInterface(Ci.nsIURI).spec;
|
||||
if (url == LEFT_URL ) {
|
||||
is(getTransitionForUrl(url), PlacesUtils.history.TRANSITION_EMBED,
|
||||
"Frames should get a EMBED transition.");
|
||||
gLeftFrameVisited = true;
|
||||
maybeClickLink();
|
||||
}
|
||||
else if (url == RIGHT_URL ) {
|
||||
is(getTransitionForUrl(url), PlacesUtils.history.TRANSITION_FRAMED_LINK,
|
||||
"User activated visits should get a FRAMED_LINK transition.");
|
||||
finish();
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(observer, "uri-visit-saved", false);
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab(PAGE_URL);
|
||||
let frameCount = 0;
|
||||
gBrowser.selectedTab.linkedBrowser.addEventListener("DOMContentLoaded",
|
||||
function (event)
|
||||
{
|
||||
// Wait for all the frames.
|
||||
if (frameCount++ < 2)
|
||||
return;
|
||||
gBrowser.selectedTab.linkedBrowser.removeEventListener("DOMContentLoaded", arguments.callee, false)
|
||||
gTabLoaded = true;
|
||||
maybeClickLink();
|
||||
}, false
|
||||
);
|
||||
}
|
||||
|
||||
function maybeClickLink() {
|
||||
if (gTabLoaded && gLeftFrameVisited) {
|
||||
// Click on the link in the left frame to cause a page load in the
|
||||
// right frame.
|
||||
EventUtils.sendMouseEvent({type: "click"}, "clickme", content.frames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function getTransitionForUrl(aUrl)
|
||||
{
|
||||
let dbConn = PlacesUtils.history
|
||||
.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT visit_type FROM moz_historyvisits_view WHERE place_id = " +
|
||||
"(SELECT id FROM moz_places_view WHERE url = :page_url)");
|
||||
stmt.params.page_url = aUrl;
|
||||
try {
|
||||
ok(stmt.executeStep(), "Found the visit in the database");
|
||||
return stmt.row.visit_type;
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function ()
|
||||
{
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.obs.removeObserver(observer, "uri-visit-saved");
|
||||
})
|
@ -291,8 +291,8 @@ var bookmarksObserver = {
|
||||
}
|
||||
else {
|
||||
if (!aNewValue && aElementOrTreeIndex.localName != "toolbarbutton")
|
||||
return aElementOrTreeIndex.label == PlacesUIUtils.getBestTitle(aElementOrTreeIndex._placesNode);
|
||||
return aElementOrTreeIndex.label == aNewValue;
|
||||
return aElementOrTreeIndex.getAttribute("label") == PlacesUIUtils.getBestTitle(aElementOrTreeIndex._placesNode);
|
||||
return aElementOrTreeIndex.getAttribute("label") == aNewValue;
|
||||
}
|
||||
};
|
||||
|
||||
|
8
browser/components/places/tests/browser/frameLeft.html
Normal file
8
browser/components/places/tests/browser/frameLeft.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Left frame</title>
|
||||
</head>
|
||||
<body>
|
||||
<a id="clickme" href="frameRight.html" target="right">Open page in the right frame.</a>
|
||||
</body>
|
||||
</html>
|
8
browser/components/places/tests/browser/frameRight.html
Normal file
8
browser/components/places/tests/browser/frameRight.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Right Frame</title>
|
||||
</head>
|
||||
<body>
|
||||
This is the right frame.
|
||||
</body>
|
||||
</html>
|
9
browser/components/places/tests/browser/framedPage.html
Normal file
9
browser/components/places/tests/browser/framedPage.html
Normal file
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Framed page</title>
|
||||
</head>
|
||||
<frameset cols="*,*">
|
||||
<frame name="left" src="frameLeft.html">
|
||||
<frame name="right" src="about:robots">
|
||||
</frameset>
|
||||
</html>
|
@ -45,12 +45,10 @@
|
||||
%globalDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
#ifdef XP_WIN
|
||||
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
|
||||
#elifdef XP_MACOSX
|
||||
#ifdef XP_MACOSX
|
||||
<!ENTITY basePBMenu.label "&toolsMenu.label;">
|
||||
#else
|
||||
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&appMenuButton.label;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
|
||||
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
|
||||
#endif
|
||||
<!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
|
||||
%privatebrowsingpageDTD;
|
||||
|
@ -469,8 +469,10 @@ PrivateBrowsingService.prototype = {
|
||||
if (aCmdLine.handleFlag("private", false))
|
||||
; // It has already been handled
|
||||
else if (aCmdLine.handleFlag("private-toggle", false)) {
|
||||
if (this._autoStarted) {
|
||||
throw Cr.NS_ERROR_ABORT;
|
||||
}
|
||||
this.privateBrowsingEnabled = !this.privateBrowsingEnabled;
|
||||
this._autoStarted = false;
|
||||
this._lastChangedByCommandLine = true;
|
||||
}
|
||||
},
|
||||
|
@ -52,14 +52,14 @@
|
||||
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
|
||||
label="&reportPhishSiteMenu.title2;"
|
||||
accesskey="&reportPhishSiteMenu.accesskey;"
|
||||
insertbefore="updateSeparator"
|
||||
insertbefore="aboutSeparator"
|
||||
observes="reportPhishingBroadcaster"
|
||||
oncommand="openUILink(safebrowsing.getReportURL('Phish'), event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
|
||||
label="&safeb.palm.notforgery.label2;"
|
||||
accesskey="&reportPhishSiteMenu.accesskey;"
|
||||
insertbefore="updateSeparator"
|
||||
insertbefore="aboutSeparator"
|
||||
observes="reportPhishingErrorBroadcaster"
|
||||
oncommand="openUILinkIn(safebrowsing.getReportURL('Error'), 'tab');"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
|
@ -605,7 +605,7 @@
|
||||
element.setAttribute("label", label);
|
||||
element.setAttribute("anonid", "paste-and-search");
|
||||
element.setAttribute("oncommand",
|
||||
"BrowserSearch.searchBar.value = ''; goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
|
||||
"BrowserSearch.searchBar.select(); goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
|
||||
cxmenu.insertBefore(element, insertLocation.nextSibling);
|
||||
pasteAndSearch = element;
|
||||
}
|
||||
|
@ -745,24 +745,59 @@ SessionStoreService.prototype = {
|
||||
!this._inPrivateBrowsing) {
|
||||
// default to the most-recently closed window
|
||||
// don't use popup windows
|
||||
let state = null;
|
||||
let newClosedWindows = this._closedWindows.filter(function(aWinState) {
|
||||
if (!state && !aWinState.isPopup) {
|
||||
state = aWinState;
|
||||
return false;
|
||||
let closedWindowState = null;
|
||||
let closedWindowIndex;
|
||||
for (let i = 0; i < this._closedWindows.length; i++) {
|
||||
// Take the first non-popup, point our object at it, and break out.
|
||||
if (!this._closedWindows[i].isPopup) {
|
||||
closedWindowState = this._closedWindows[i];
|
||||
closedWindowIndex = i;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (state) {
|
||||
delete state.hidden;
|
||||
}
|
||||
|
||||
if (closedWindowState) {
|
||||
let newWindowState;
|
||||
#ifndef XP_MACOSX
|
||||
if (!this._doResumeSession())
|
||||
if (!this._doResumeSession()) {
|
||||
#endif
|
||||
state.tabs = state.tabs.filter(function (tab) tab.pinned);
|
||||
if (state.tabs.length > 0) {
|
||||
this._closedWindows = newClosedWindows;
|
||||
// We want to split the window up into pinned tabs and unpinned tabs.
|
||||
// Pinned tabs should be restored. If there are any remaining tabs,
|
||||
// they should be added back to _closedWindows.
|
||||
// We'll cheat a little bit and reuse _prepDataForDeferredRestore
|
||||
// even though it wasn't built exactly for this.
|
||||
let [appTabsState, normalTabsState] =
|
||||
this._prepDataForDeferredRestore(JSON.stringify({ windows: [closedWindowState] }));
|
||||
|
||||
// These are our pinned tabs, which we should restore
|
||||
if (appTabsState.windows.length) {
|
||||
newWindowState = appTabsState.windows[0];
|
||||
delete newWindowState.__lastSessionWindowID;
|
||||
}
|
||||
|
||||
// In case there were no unpinned tabs, remove the window from _closedWindows
|
||||
if (!normalTabsState.windows.length) {
|
||||
this._closedWindows.splice(closedWindowIndex, 1);
|
||||
}
|
||||
// Or update _closedWindows with the modified state
|
||||
else {
|
||||
delete normalTabsState.windows[0].__lastSessionWindowID;
|
||||
this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
|
||||
}
|
||||
#ifndef XP_MACOSX
|
||||
}
|
||||
else {
|
||||
// If we're just restoring the window, make sure it gets removed from
|
||||
// _closedWindows.
|
||||
this._closedWindows.splice(closedWindowIndex, 1);
|
||||
newWindowState = closedWindowState;
|
||||
delete newWindowState.hidden;
|
||||
}
|
||||
#endif
|
||||
if (newWindowState) {
|
||||
// Ensure that the window state isn't hidden
|
||||
this._restoreCount = 1;
|
||||
state = { windows: [state] };
|
||||
let state = { windows: [newWindowState] };
|
||||
this.restoreWindow(aWindow, state, this._isCmdLineEmpty(aWindow, state));
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_581593.js \
|
||||
browser_586147.js \
|
||||
browser_586068-cascaded_restore.js \
|
||||
browser_589246.js \
|
||||
browser_590268.js \
|
||||
browser_600545.js \
|
||||
$(NULL)
|
||||
|
276
browser/components/sessionstore/test/browser/browser_589246.js
Normal file
276
browser/components/sessionstore/test/browser/browser_589246.js
Normal file
@ -0,0 +1,276 @@
|
||||
/* ***** 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 sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Paul O’Shannessy <paul@oshannessy.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 ***** */
|
||||
|
||||
// Mirrors WINDOW_ATTRIBUTES IN nsSessionStore.js
|
||||
const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
|
||||
let stateBackup = ss.getBrowserState();
|
||||
|
||||
let originalWarnOnClose = gPrefService.getBoolPref("browser.tabs.warnOnClose");
|
||||
let originalStartupPage = gPrefService.getIntPref("browser.startup.page");
|
||||
let originalWindowType = document.documentElement.getAttribute("windowtype");
|
||||
|
||||
let gotLastWindowClosedTopic = false;
|
||||
let shouldPinTab = false;
|
||||
let shouldOpenTabs = false;
|
||||
let shouldCloseTab = false;
|
||||
let testNum = 0;
|
||||
let afterTestCallback;
|
||||
|
||||
// Set state so we know the closed windows content
|
||||
let testState = {
|
||||
windows: [
|
||||
{ tabs: [{ entries: [{ url: "http://example.org" }] }] }
|
||||
],
|
||||
_closedWindows: []
|
||||
};
|
||||
|
||||
// We'll push a set of conditions and callbacks into this array
|
||||
// Ideally we would also test win/linux under a complete set of conditions, but
|
||||
// the tests for osx mirror the other set of conditions possible on win/linux.
|
||||
let tests = [];
|
||||
|
||||
// the third & fourth test share a condition check, keep it DRY
|
||||
function checkOSX34Generator(num) {
|
||||
return function(aPreviousState, aCurState) {
|
||||
// In here, we should have restored the pinned tab, so only the unpinned tab
|
||||
// should be in aCurState. So let's shape our expectations.
|
||||
let expectedState = JSON.parse(aPreviousState);
|
||||
expectedState[0].tabs.shift();
|
||||
// size attributes are stripped out in _prepDataForDeferredRestore in nsSessionStore.
|
||||
// This isn't the best approach, but neither is comparing JSON strings
|
||||
WINDOW_ATTRIBUTES.forEach(function (attr) delete expectedState[0][attr]);
|
||||
|
||||
is(aCurState, JSON.stringify(expectedState),
|
||||
"test #" + num + ": closedWindowState is as expected");
|
||||
};
|
||||
}
|
||||
function checkNoWindowsGenerator(num) {
|
||||
return function(aPreviousState, aCurState) {
|
||||
is(aCurState, "[]", "test #" + num + ": there should be no closedWindowsLeft");
|
||||
};
|
||||
}
|
||||
|
||||
// The first test has 0 pinned tabs and 1 unpinned tab
|
||||
tests.push({
|
||||
pinned: false,
|
||||
extra: false,
|
||||
close: false,
|
||||
checkWinLin: checkNoWindowsGenerator(1),
|
||||
checkOSX: function(aPreviousState, aCurState) {
|
||||
is(aCurState, aPreviousState, "test #1: closed window state is unchanged");
|
||||
}
|
||||
});
|
||||
|
||||
// The second test has 1 pinned tab and 0 unpinned tabs.
|
||||
tests.push({
|
||||
pinned: true,
|
||||
extra: false,
|
||||
close: false,
|
||||
checkWinLin: checkNoWindowsGenerator(2),
|
||||
checkOSX: checkNoWindowsGenerator(2)
|
||||
});
|
||||
|
||||
// The third test has 1 pinned tab and 2 unpinned tabs.
|
||||
tests.push({
|
||||
pinned: true,
|
||||
extra: true,
|
||||
close: false,
|
||||
checkWinLin: checkNoWindowsGenerator(3),
|
||||
checkOSX: checkOSX34Generator(3)
|
||||
});
|
||||
|
||||
// The fourth test has 1 pinned tab, 2 unpinned tabs, and closes one unpinned tab.
|
||||
tests.push({
|
||||
pinned: true,
|
||||
extra: true,
|
||||
close: "one",
|
||||
checkWinLin: checkNoWindowsGenerator(4),
|
||||
checkOSX: checkOSX34Generator(4)
|
||||
});
|
||||
|
||||
// The fifth test has 1 pinned tab, 2 unpinned tabs, and closes both unpinned tabs.
|
||||
tests.push({
|
||||
pinned: true,
|
||||
extra: true,
|
||||
close: "both",
|
||||
checkWinLin: checkNoWindowsGenerator(5),
|
||||
checkOSX: checkNoWindowsGenerator(5)
|
||||
});
|
||||
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 589246 - Closed window state getting corrupted when closing
|
||||
and reopening last browser window without exiting browser **/
|
||||
waitForExplicitFinish();
|
||||
// windows opening & closing, so extending the timeout
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// We don't want the quit dialog pref
|
||||
gPrefService.setBoolPref("browser.tabs.warnOnClose", false);
|
||||
// Ensure that we would restore the session (important for Windows)
|
||||
gPrefService.setIntPref("browser.startup.page", 3);
|
||||
|
||||
runNextTestOrFinish();
|
||||
}
|
||||
|
||||
function runNextTestOrFinish() {
|
||||
if (tests.length) {
|
||||
setupForTest(tests.shift())
|
||||
}
|
||||
else {
|
||||
// some state is cleaned up at the end of each test, but not all
|
||||
["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
|
||||
if (gPrefService.prefHasUserValue(p))
|
||||
gPrefService.clearUserPref(p);
|
||||
});
|
||||
|
||||
ss.setBrowserState(stateBackup);
|
||||
executeSoon(finish);
|
||||
}
|
||||
}
|
||||
|
||||
function setupForTest(aConditions) {
|
||||
// reset some checks
|
||||
gotLastWindowClosedTopic = false;
|
||||
shouldPinTab = aConditions.pinned;
|
||||
shouldOpenTabs = aConditions.extra;
|
||||
shouldCloseTab = aConditions.close;
|
||||
testNum++;
|
||||
|
||||
// set our test callback
|
||||
afterTestCallback = /Mac/.test(navigator.platform) ? aConditions.checkOSX
|
||||
: aConditions.checkWinLin;
|
||||
|
||||
// Add observers
|
||||
Services.obs.addObserver(onLastWindowClosed, "browser-lastwindow-close-granted", false);
|
||||
|
||||
// Set the state
|
||||
Services.obs.addObserver(onStateRestored, "sessionstore-browser-state-restored", false);
|
||||
ss.setBrowserState(JSON.stringify(testState));
|
||||
}
|
||||
|
||||
function onStateRestored(aSubject, aTopic, aData) {
|
||||
info("test #" + testNum + ": onStateRestored");
|
||||
Services.obs.removeObserver(onStateRestored, "sessionstore-browser-state-restored", false);
|
||||
|
||||
// change this window's windowtype so that closing a new window will trigger
|
||||
// browser-lastwindow-close-granted.
|
||||
document.documentElement.setAttribute("windowtype", "navigator:testrunner");
|
||||
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "http://example.com");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
newWin.gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
newWin.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
// pin this tab
|
||||
if (shouldPinTab)
|
||||
newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab);
|
||||
|
||||
newWin.addEventListener("unload", onWindowUnloaded, false);
|
||||
// Open a new tab as well. On Windows/Linux this will be restored when the
|
||||
// new window is opened below (in onWindowUnloaded). On OS X we'll just
|
||||
// restore the pinned tabs, leaving the unpinned tab in the closedWindowsData.
|
||||
if (shouldOpenTabs) {
|
||||
let newTab = newWin.gBrowser.addTab("about:config");
|
||||
let newTab2 = newWin.gBrowser.addTab("about:buildconfig");
|
||||
|
||||
newTab.linkedBrowser.addEventListener("load", function() {
|
||||
newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
if (shouldCloseTab == "one") {
|
||||
newWin.gBrowser.removeTab(newTab2);
|
||||
}
|
||||
else if (shouldCloseTab == "both") {
|
||||
newWin.gBrowser.removeTab(newTab);
|
||||
newWin.gBrowser.removeTab(newTab2);
|
||||
}
|
||||
newWin.BrowserTryToCloseWindow();
|
||||
}, true);
|
||||
}
|
||||
else {
|
||||
newWin.BrowserTryToCloseWindow();
|
||||
}
|
||||
}, true);
|
||||
}, false);
|
||||
}
|
||||
|
||||
// This will be called before the window is actually closed
|
||||
function onLastWindowClosed(aSubject, aTopic, aData) {
|
||||
info("test #" + testNum + ": onLastWindowClosed");
|
||||
Services.obs.removeObserver(onLastWindowClosed, "browser-lastwindow-close-granted", false);
|
||||
gotLastWindowClosedTopic = true;
|
||||
}
|
||||
|
||||
// This is the unload event listener on the new window (from onStateRestored).
|
||||
// Unload is fired after the window is closed, so sessionstore has already
|
||||
// updated _closedWindows (which is important). We'll open a new window here
|
||||
// which should actually trigger the bug.
|
||||
function onWindowUnloaded() {
|
||||
info("test #" + testNum + ": onWindowClosed");
|
||||
ok(gotLastWindowClosedTopic, "test #" + testNum + ": browser-lastwindow-close-granted was notified prior");
|
||||
|
||||
let previousClosedWindowData = ss.getClosedWindowData();
|
||||
|
||||
// Now we want to open a new window
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:robots");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
newWin.gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
// Good enough for checking the state
|
||||
afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
|
||||
afterTestCleanup(newWin);
|
||||
}, true);
|
||||
|
||||
}, false);
|
||||
}
|
||||
|
||||
function afterTestCleanup(aNewWin) {
|
||||
executeSoon(function() {
|
||||
aNewWin.close();
|
||||
document.documentElement.setAttribute("windowtype", originalWindowType);
|
||||
runNextTestOrFinish();
|
||||
});
|
||||
}
|
||||
|
@ -260,10 +260,7 @@ var WinTaskbarJumpList =
|
||||
|
||||
_pendingStatements: {},
|
||||
_hasPendingStatements: function WTBJL__hasPendingStatements() {
|
||||
for (let listType in this._pendingStatements) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Object.keys(this._pendingStatements).length > 0;
|
||||
},
|
||||
|
||||
_buildList: function WTBJL__buildList() {
|
||||
@ -344,6 +341,11 @@ var WinTaskbarJumpList =
|
||||
},
|
||||
|
||||
_buildFrequent: function WTBJL__buildFrequent() {
|
||||
// If history is empty, just bail out.
|
||||
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows supports default frequent and recent lists,
|
||||
// but those depend on internal windows visit tracking
|
||||
// which we don't populate. So we build our own custom
|
||||
@ -377,6 +379,11 @@ var WinTaskbarJumpList =
|
||||
},
|
||||
|
||||
_buildRecent: function WTBJL__buildRecent() {
|
||||
// If history is empty, just bail out.
|
||||
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
// Frequent items will be skipped, so we select a double amount of
|
||||
|
@ -213,6 +213,7 @@
|
||||
@BINPATH@/components/necko_strconv.xpt
|
||||
@BINPATH@/components/necko_viewsource.xpt
|
||||
@BINPATH@/components/necko_wifi.xpt
|
||||
@BINPATH@/components/necko_wyciwyg.xpt
|
||||
@BINPATH@/components/necko.xpt
|
||||
@BINPATH@/components/loginmgr.xpt
|
||||
@BINPATH@/components/parentalcontrols.xpt
|
||||
@ -383,8 +384,6 @@
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/components/SyncComponents.manifest
|
||||
@BINPATH@/components/Weave.js
|
||||
@BINPATH@/components/WeaveCrypto.manifest
|
||||
@BINPATH@/components/WeaveCrypto.js
|
||||
#endif
|
||||
|
||||
; Modules
|
||||
|
@ -67,6 +67,8 @@ components/nsUrlClassifierTable.js
|
||||
components/nsXmlRpcClient.js
|
||||
components/pluginGlue.js
|
||||
components/sidebar.xpt
|
||||
components/WeaveCrypto.js
|
||||
components/WeaveCrypto.manifest
|
||||
components/xmlextras.xpt
|
||||
components/xpcom.xpt
|
||||
components/xpti.dat
|
||||
@ -621,7 +623,6 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/storage-Legacy.js
|
||||
components/storage-mozStorage.js
|
||||
components/txEXSLTRegExFunctions.js
|
||||
components/WeaveCrypto.js
|
||||
components/Weave.js
|
||||
components/WebContentConverter.js
|
||||
defaults/autoconfig/platform.js
|
||||
|
@ -233,7 +233,7 @@ menuitem.bookmark-item {
|
||||
}
|
||||
|
||||
/* Stock icons for the menu bar items */
|
||||
menuitem:not([type]) {
|
||||
menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
||||
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
|
||||
}
|
||||
|
||||
@ -472,6 +472,13 @@ menuitem:not([type]) {
|
||||
-moz-image-region: rect(0px 48px 16px 32px);
|
||||
}
|
||||
|
||||
#subscribeToPageMenuitem:not([disabled]),
|
||||
#subscribeToPageMenupopup,
|
||||
#BMB_subscribeToPageMenuitem:not([disabled]),
|
||||
#BMB_subscribeToPageMenupopup {
|
||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
||||
}
|
||||
|
||||
#bookmarksToolbarFolderMenu,
|
||||
#BMB_bookmarksToolbar {
|
||||
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
|
||||
|
@ -36,7 +36,7 @@
|
||||
}
|
||||
|
||||
#sanitizeEverythingWarningIcon {
|
||||
list-style-image: url("chrome://global/skin/icons/warning-large.png");
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-warning?size=dialog");
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -14,11 +14,11 @@
|
||||
}
|
||||
|
||||
.statusIcon[status="error"] {
|
||||
list-style-image: url("chrome://global/skin/icons/error-16.png");
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-error?size=menu");
|
||||
}
|
||||
|
||||
.statusIcon[status="success"] {
|
||||
list-style-image: url("chrome://global/skin/icons/information-16.png");
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-info?size=menu");
|
||||
}
|
||||
|
||||
/* .data is only used by syncGenericChange.xul, but it seems unnecessary to have
|
||||
|
@ -355,8 +355,16 @@ toolbar:not([mode="icons"]) #restore-button {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-menu-dropmarker,
|
||||
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
list-style-image: url(chrome://browser/skin/toolbarbutton-dropmarker.png);
|
||||
}
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-menu-dropmarker {
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
width: 14px;
|
||||
padding-top: 2px;
|
||||
-moz-border-start: none !important;
|
||||
@ -1937,7 +1945,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
}
|
||||
|
||||
#notification-popup {
|
||||
color: #fff;
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
}
|
||||
|
@ -33,19 +33,12 @@
|
||||
0 0 2px 1px rgba(255,255,255,.25) inset;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] #appmenu-button:not(:-moz-window-inactive) {
|
||||
#main-window[privatebrowsingmode=temporary] #appmenu-button {
|
||||
-moz-border-left-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
|
||||
-moz-border-bottom-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
|
||||
-moz-border-right-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
|
||||
}
|
||||
|
||||
#appmenu-button:-moz-window-inactive {
|
||||
-moz-border-left-colors: rgba(255,255,255,.4) rgba(0,0,0,.5);
|
||||
-moz-border-bottom-colors: rgba(255,255,255,.4) rgba(0,0,0,.5);
|
||||
-moz-border-right-colors: rgba(255,255,255,.4) rgba(0,0,0,.5);
|
||||
box-shadow: 0 0 0 1px rgba(255,255,255,.25) inset;
|
||||
}
|
||||
|
||||
/* Bug 413060, comment 16: Vista Aero is a special case where we use a
|
||||
tooltip appearance for the address bar popup panels */
|
||||
#identity-popup,
|
||||
|
@ -126,16 +126,11 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] #appmenu-button:not(:-moz-window-inactive) {
|
||||
#main-window[privatebrowsingmode=temporary] #appmenu-button {
|
||||
background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%);
|
||||
border-color: rgba(43,8,65,.9);
|
||||
}
|
||||
|
||||
#appmenu-button:-moz-window-inactive {
|
||||
background-image: none;
|
||||
border-color: rgba(0,0,0,.4);
|
||||
}
|
||||
|
||||
#appmenu-button:hover:not(:active):not([open]) {
|
||||
background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(252,240,89,.5) 10%, rgba(252,240,89,0) 70%),
|
||||
-moz-radial-gradient(center bottom, farthest-side, rgb(236,133,0), rgba(255,229,172,0)),
|
||||
@ -302,14 +297,6 @@
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
|
||||
}
|
||||
|
||||
#BMB_subscribeToPage:not([disabled]),
|
||||
#BMB_subscribeToPageMenu,
|
||||
#appmenu_subscribeToPage:not([disabled]),
|
||||
#appmenu_subscribeToPageMenu {
|
||||
list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png");
|
||||
-moz-image-region: rect(0px 16px 16px 0px);
|
||||
}
|
||||
|
||||
#BMB_bookmarkThisPage,
|
||||
#appmenu_bookmarkThisPage {
|
||||
list-style-image: url("chrome://browser/skin/places/bookmark.png");
|
||||
@ -1872,7 +1859,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
}
|
||||
|
||||
.geolocation-text-link {
|
||||
padding-top: 5px;
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="xpinstall-disabled"],
|
||||
@ -1936,6 +1923,15 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
}
|
||||
|
||||
/* Bookmarks roots menu-items */
|
||||
#appmenu_subscribeToPage:not([disabled]),
|
||||
#appmenu_subscribeToPageMenu,
|
||||
#subscribeToPageMenuitem:not([disabled]),
|
||||
#subscribeToPageMenupopup,
|
||||
#BMB_subscribeToPageMenuitem:not([disabled]),
|
||||
#BMB_subscribeToPageMenupopup {
|
||||
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
|
||||
}
|
||||
|
||||
#bookmarksToolbarFolderMenu,
|
||||
#appmenu_bookmarksToolbar,
|
||||
#BMB_bookmarksToolbar {
|
||||
|
@ -360,6 +360,7 @@ user_pref("network.http.prompt-temp-redirect", false);
|
||||
user_pref("media.cache_size", 100);
|
||||
user_pref("security.warn_viewing_mixed", false);
|
||||
user_pref("app.update.enabled", false);
|
||||
user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
|
||||
|
||||
// Only load extensions from the application and user profile
|
||||
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
|
||||
|
@ -115,10 +115,18 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
||||
for d in dumps:
|
||||
log.info("PROCESS-CRASH | %s | application crashed (minidump found)", testName)
|
||||
if symbolsPath and stackwalkPath and os.path.exists(stackwalkPath):
|
||||
nullfd = open(os.devnull, 'w')
|
||||
# eat minidump_stackwalk errors
|
||||
subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd)
|
||||
nullfd.close()
|
||||
p = subprocess.Popen([stackwalkPath, d, symbolsPath],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(out, err) = p.communicate()
|
||||
if len(out) > 3:
|
||||
# minidump_stackwalk is chatty, so ignore stderr when it succeeds.
|
||||
print out
|
||||
else:
|
||||
print "stderr from minidump_stackwalk:"
|
||||
print err
|
||||
if p.returncode != 0:
|
||||
print "minidump_stackwalk exited with return code %d" % p.returncode
|
||||
elif stackwalkCGI and symbolsPath and isURL(symbolsPath):
|
||||
f = None
|
||||
try:
|
||||
@ -131,7 +139,11 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
||||
datagen, headers = multipart_encode({"minidump": f,
|
||||
"symbols": symbolsPath})
|
||||
request = urllib2.Request(stackwalkCGI, datagen, headers)
|
||||
print urllib2.urlopen(request).read()
|
||||
result = urllib2.urlopen(request).read()
|
||||
if len(result) > 3:
|
||||
print result
|
||||
else:
|
||||
print "stackwalkCGI returned nothing."
|
||||
finally:
|
||||
if f:
|
||||
f.close()
|
||||
|
@ -457,7 +457,7 @@ EnumerateOverride(nsIURI* aURIKey,
|
||||
|
||||
struct EnumerationArgs
|
||||
{
|
||||
nsTArray<ChromePackage>& packages;
|
||||
InfallibleTArray<ChromePackage>& packages;
|
||||
const nsCString& selectedLocale;
|
||||
const nsCString& selectedSkin;
|
||||
};
|
||||
@ -466,9 +466,9 @@ void
|
||||
nsChromeRegistryChrome::SendRegisteredChrome(
|
||||
mozilla::dom::PContentParent* aParent)
|
||||
{
|
||||
nsTArray<ChromePackage> packages;
|
||||
nsTArray<ResourceMapping> resources;
|
||||
nsTArray<OverrideMapping> overrides;
|
||||
InfallibleTArray<ChromePackage> packages;
|
||||
InfallibleTArray<ResourceMapping> resources;
|
||||
InfallibleTArray<OverrideMapping> overrides;
|
||||
|
||||
EnumerationArgs args = {
|
||||
packages, mSelectedLocale, mSelectedSkin
|
||||
|
@ -44,6 +44,7 @@ See the documentation for jar.mn on MDC for further details on the format.
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import errno
|
||||
import re
|
||||
import logging
|
||||
from time import localtime
|
||||
@ -445,7 +446,7 @@ class JarMaker(object):
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError, e:
|
||||
if e.errno != 2:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return open(out, 'wb')
|
||||
def ensureDirFor(self, name):
|
||||
@ -465,7 +466,7 @@ class JarMaker(object):
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError, e:
|
||||
if e.errno != 2:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
os.symlink(src, out)
|
||||
|
||||
|
@ -132,6 +132,7 @@ export::
|
||||
-DMOZ_NATIVE_PNG=$(MOZ_NATIVE_PNG) \
|
||||
-DMOZ_NATIVE_JPEG=$(MOZ_NATIVE_JPEG) \
|
||||
-DMOZ_NATIVE_LIBEVENT=$(MOZ_NATIVE_LIBEVENT) \
|
||||
-DMOZ_NATIVE_LIBVPX=$(MOZ_NATIVE_LIBVPX) \
|
||||
$(srcdir)/system-headers | $(PERL) $(topsrcdir)/nsprpub/config/make-system-wrappers.pl system_wrappers
|
||||
$(INSTALL) system_wrappers $(DIST)
|
||||
|
||||
|
@ -101,7 +101,6 @@ MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@
|
||||
MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@
|
||||
MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
|
||||
MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
|
||||
MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
|
||||
MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
|
||||
MOZ_IPC = @MOZ_IPC@
|
||||
MOZ_IPDL_TESTS = @MOZ_IPDL_TESTS@
|
||||
@ -166,7 +165,11 @@ MOZ_TREMOR = @MOZ_TREMOR@
|
||||
MOZ_WEBM = @MOZ_WEBM@
|
||||
VPX_AS = @VPX_AS@
|
||||
VPX_ASFLAGS = @VPX_ASFLAGS@
|
||||
VPX_DASH_C_FLAG = @VPX_DASH_C_FLAG@
|
||||
VPX_AS_CONVERSION = @VPX_AS_CONVERSION@
|
||||
VPX_ASM_SUFFIX = @VPX_ASM_SUFFIX@
|
||||
VPX_X86_ASM = @VPX_X86_ASM@
|
||||
VPX_ARM_ASM = @VPX_ARM_ASM@
|
||||
NS_PRINTING = @NS_PRINTING@
|
||||
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
||||
MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
|
||||
@ -232,6 +235,10 @@ MOZ_NATIVE_LIBEVENT = @MOZ_NATIVE_LIBEVENT@
|
||||
MOZ_LIBEVENT_LIBS = @MOZ_LIBEVENT_LIBS@
|
||||
MOZ_LIBEVENT_INCLUDES = @MOZ_LIBEVENT_INCLUDES@
|
||||
|
||||
MOZ_NATIVE_LIBVPX = @MOZ_NATIVE_LIBVPX@
|
||||
MOZ_LIBVPX_LIBS = @MOZ_LIBVPX_LIBS@
|
||||
MOZ_LIBVPX_INCLUDES = @MOZ_LIBVPX_INCLUDES@
|
||||
|
||||
MOZ_NATIVE_ZLIB = @SYSTEM_ZLIB@
|
||||
MOZ_NATIVE_BZ2 = @SYSTEM_BZ2@
|
||||
MOZ_NATIVE_JPEG = @SYSTEM_JPEG@
|
||||
@ -605,7 +612,6 @@ AIX_OBJMODEL = @AIX_OBJMODEL@
|
||||
|
||||
# For OS/2 build
|
||||
MOZ_OS2_TOOLS = @MOZ_OS2_TOOLS@
|
||||
MOZ_OS2_USE_DECLSPEC = @MOZ_OS2_USE_DECLSPEC@
|
||||
MOZ_OS2_HIGH_MEMORY = @MOZ_OS2_HIGH_MEMORY@
|
||||
|
||||
HAVE_XIE=@HAVE_XIE@
|
||||
|
@ -234,7 +234,7 @@ endif
|
||||
#
|
||||
ifdef NS_TRACE_MALLOC
|
||||
MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF -OPT:nowin98
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
|
||||
endif # NS_TRACE_MALLOC
|
||||
|
||||
endif # MOZ_DEBUG
|
||||
|
@ -59,15 +59,13 @@
|
||||
|
||||
|
||||
#define MODULE(_name) \
|
||||
NSMODULE_NAME(_name),
|
||||
&NSMODULE_NAME(_name),
|
||||
|
||||
/**
|
||||
* The nsStaticModuleInfo
|
||||
*/
|
||||
static const mozilla::Module *const kStaticModules[] = {
|
||||
const mozilla::Module *const *const kPStaticModules[] = {
|
||||
%MODULE_LIST%
|
||||
#line 70 "nsStaticComponents.cpp.in"
|
||||
NULL
|
||||
};
|
||||
|
||||
mozilla::Module const *const *const kPStaticModules = kStaticModules;
|
||||
|
@ -43,6 +43,6 @@
|
||||
// These symbols are provided by nsStaticComponents.cpp, and also by other
|
||||
// static component providers such as nsStaticXULComponents (libxul).
|
||||
|
||||
extern mozilla::Module const *const *const kPStaticModules;
|
||||
extern mozilla::Module const *const *const kPStaticModules[];
|
||||
|
||||
#endif
|
||||
|
@ -1249,26 +1249,10 @@ $(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
|
||||
echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@
|
||||
echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
|
||||
echo EXPORTS >> $@
|
||||
ifeq ($(IS_COMPONENT),1)
|
||||
ifeq ($(HAS_EXTRAEXPORTS),1)
|
||||
ifndef MOZ_OS2_USE_DECLSPEC
|
||||
$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
|
||||
endif
|
||||
else
|
||||
echo _NSModule >> $@
|
||||
endif
|
||||
else
|
||||
ifndef MOZ_OS2_USE_DECLSPEC
|
||||
$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
|
||||
endif
|
||||
endif
|
||||
|
||||
$(ADD_TO_DEF_FILE)
|
||||
|
||||
ifdef MOZ_OS2_USE_DECLSPEC
|
||||
$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
|
||||
else
|
||||
$(IMPORT_LIBRARY): $(DEF_FILE)
|
||||
endif
|
||||
rm -f $@
|
||||
$(IMPLIB) $@ $^
|
||||
$(RANLIB) $@
|
||||
|
@ -1051,3 +1051,7 @@ pixman.h
|
||||
#if MOZ_ENABLE_MEEGOTOUCHSHARE
|
||||
shareuiinterface.h
|
||||
#endif
|
||||
#if MOZ_NATIVE_LIBVPX==1
|
||||
vpx/vpx_decoder.h
|
||||
vpx/vp8dx.h
|
||||
#endif
|
||||
|
131
configure.in
131
configure.in
@ -992,7 +992,7 @@ else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
MOZ_PATH_PROGS(PYTHON, $PYTHON python2.6 python2.5 python2.4 python)
|
||||
MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python2.6 python2.5 python)
|
||||
if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([python was not found in \$PATH])
|
||||
fi
|
||||
@ -1846,8 +1846,6 @@ case "$host" in
|
||||
;;
|
||||
|
||||
*cygwin*|*mingw*|*mks*|*msvc*|*wince|*winmo)
|
||||
# we need Python 2.5 on Windows
|
||||
PYTHON_VERSION=2.5
|
||||
if test -n "$_WIN32_MSVC"; then
|
||||
HOST_AR=lib
|
||||
HOST_AR_FLAGS='-NOLOGO -OUT:"$@"'
|
||||
@ -1921,8 +1919,7 @@ case "$host" in
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl We require version 2.4 or newer of Python to build,
|
||||
dnl and 2.5 or newer on Windows.
|
||||
dnl We require version 2.5 or newer of Python to build.
|
||||
AC_MSG_CHECKING([for minimum required Python version >= $PYTHON_VERSION])
|
||||
changequote(,)
|
||||
$PYTHON -c "import sys; sys.exit(sys.version[:3] < sys.argv[1])" $PYTHON_VERSION
|
||||
@ -2645,7 +2642,7 @@ ia64*-hpux*)
|
||||
DSO_LDOPTS='-Zdll'
|
||||
BIN_FLAGS='-Zlinker /ST:0x100000'
|
||||
IMPLIB='emximp -o'
|
||||
FILTER='emxexp -o'
|
||||
FILTER='true'
|
||||
LDFLAGS='-Zmap'
|
||||
WARNINGS_AS_ERRORS='-Werror'
|
||||
MOZ_DEBUG_FLAGS="-g -fno-inline"
|
||||
@ -2681,9 +2678,8 @@ ia64*-hpux*)
|
||||
[return 0;],
|
||||
ac_os2_declspec="yes",
|
||||
ac_os2_declspec="no")])
|
||||
if test "$ac_os2_declspec" = "yes"; then
|
||||
FILTER='true'
|
||||
MOZ_OS2_USE_DECLSPEC='1'
|
||||
if test "$ac_os2_declspec" != "yes"; then
|
||||
AC_MSG_ERROR([Compiler does not support __declspec(dllexport), install GCC-4.3.2 or newer])
|
||||
fi
|
||||
;;
|
||||
|
||||
@ -3408,11 +3404,9 @@ case $target in
|
||||
*-os2*)
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_LIB(m, atan)
|
||||
AC_CHECK_LIB(dl, dlopen,
|
||||
AC_CHECK_HEADER(dlfcn.h,
|
||||
LIBS="-ldl $LIBS"
|
||||
AC_DEFINE(HAVE_LIBDL)))
|
||||
AC_SEARCH_LIBS(dlopen, dl,
|
||||
AC_CHECK_HEADER(dlfcn.h,
|
||||
AC_DEFINE(HAVE_DLOPEN)))
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -4728,10 +4722,10 @@ AC_CHECK_PROGS(YASM, yasm, "")
|
||||
if test -n "$YASM"; then
|
||||
dnl Pull out yasm's version string
|
||||
changequote(,)
|
||||
_YASM_VER_FILTER='s|.* ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*|\1|p'
|
||||
_YASM_VER_FILTER='s|.* \([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\).*|\1|p'
|
||||
changequote([,])
|
||||
|
||||
YASM_VERSION=`yasm --version | sed -nre "$_YASM_VER_FILTER"`
|
||||
YASM_VERSION=`yasm --version | sed -ne "$_YASM_VER_FILTER"`
|
||||
_YASM_MAJOR_VERSION=`echo ${YASM_VERSION} | $AWK -F\. '{ print $1 }'`
|
||||
_YASM_MINOR_VERSION=`echo ${YASM_VERSION} | $AWK -F\. '{ print $2 }'`
|
||||
_YASM_RELEASE=` echo ${YASM_VERSION} | $AWK -F\. '{ print $3 }'`
|
||||
@ -4942,7 +4936,6 @@ MOZ_ACTIVEX_SCRIPTING_SUPPORT=
|
||||
MOZ_BRANDING_DIRECTORY=
|
||||
MOZ_OFFICIAL_BRANDING=
|
||||
MOZ_FEEDS=1
|
||||
MOZ_IMG_ENCODERS_DEFAULT="png jpeg"
|
||||
MOZ_INSTALLER=1
|
||||
MOZ_IPC=1
|
||||
MOZ_JAVAXPCOM=
|
||||
@ -4964,7 +4957,11 @@ MOZ_MEDIA=
|
||||
MOZ_WEBM=1
|
||||
VPX_AS=
|
||||
VPX_ASFLAGS=
|
||||
VPX_AS_DASH_C_FLAG=
|
||||
VPX_AS_CONVERSION=
|
||||
VPX_ASM_SUFFIX=
|
||||
VPX_X86_ASM=
|
||||
VPX_ARM_ASM=
|
||||
MOZ_PANGO=1
|
||||
MOZ_PERMISSIONS=1
|
||||
MOZ_PLACES=1
|
||||
@ -5994,8 +5991,50 @@ MOZ_ARG_DISABLE_BOOL(webm,
|
||||
MOZ_WEBM=,
|
||||
MOZ_WEBM=1)
|
||||
|
||||
dnl system libvpx Support
|
||||
dnl ========================================================
|
||||
MOZ_ARG_WITH_STRING(system-libvpx,
|
||||
[ --with-system-libvpx=[PFX]
|
||||
Use system libvpx [installed at prefix PFX]],
|
||||
LIBVPX_DIR=$withval)
|
||||
|
||||
MOZ_NATIVE_LIBVPX=
|
||||
MOZ_LIBVPX_INCLUDES=
|
||||
MOZ_LIBVPX_LIBS=
|
||||
|
||||
if test -n "$MOZ_WEBM"; then
|
||||
AC_DEFINE(MOZ_WEBM)
|
||||
|
||||
if test -n "$LIBVPX_DIR" -a "$LIBVPX_DIR" != no; then
|
||||
_SAVE_CFLAGS=$CFLAGS
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
_SAVE_LIBS=$LIBS
|
||||
if test "${LIBVPX_DIR}" = "yes"; then
|
||||
LIBVPX_DIR=/usr
|
||||
fi
|
||||
CFLAGS="-I${LIBVPX_DIR}/include $CFLAGS"
|
||||
LDFLAGS="-L${LIBVPX_DIR}/lib $LDFLAGS"
|
||||
AC_CHECK_HEADER(vpx/vpx_decoder.h,
|
||||
[if test ! -f "${LIBVPX_DIR}/include/vpx/vpx_decoder.h"; then
|
||||
AC_MSG_ERROR([vpx/vpx_decoder.h found, but is not in ${LIBVPX_DIR}/include])
|
||||
fi],
|
||||
AC_MSG_ERROR([--with-system-libvpx requested but vpx/vpx_decoder.h not found]))
|
||||
AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver,
|
||||
[MOZ_NATIVE_LIBVPX=1
|
||||
MOZ_LIBVPX_INCLUDES="-I${LIBVPX_DIR}/include"
|
||||
MOZ_LIBVPX_LIBS="-L${LIBVPX_DIR}/lib -lvpx"],
|
||||
([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found]))
|
||||
CFLAGS=$_SAVE_CFLAGS
|
||||
LDFLAGS=$_SAVE_LDFLAGS
|
||||
LIBS=$_SAVE_LIBS
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_NATIVE_LIBVPX)
|
||||
AC_SUBST(MOZ_LIBVPX_INCLUDES)
|
||||
AC_SUBST(MOZ_LIBVPX_LIBS)
|
||||
|
||||
if test -n "$MOZ_WEBM" -a -z "$MOZ_NATIVE_LIBVPX"; then
|
||||
MOZ_SYDNEYAUDIO=1
|
||||
MOZ_MEDIA=1
|
||||
case "$target_cpu" in
|
||||
@ -6009,8 +6048,10 @@ if test -n "$MOZ_WEBM"; then
|
||||
|
||||
|
||||
dnl Detect if we can use an assembler to compile optimized assembly for libvpx.
|
||||
dnl We currently require yasm on all platforms and require yasm 1.1.0 on Win32.
|
||||
dnl We currently require yasm on all x86 platforms and require yasm 1.1.0 on Win32.
|
||||
dnl We currently require gcc on all arm platforms.
|
||||
VPX_AS=$YASM
|
||||
VPX_ASM_SUFFIX=asm
|
||||
|
||||
dnl See if we have assembly on this platform.
|
||||
case "$OS_ARCH:$CPU_ARCH" in
|
||||
@ -6057,6 +6098,17 @@ if test -n "$MOZ_WEBM"; then
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*:arm*)
|
||||
if test -n "$GNU_AS" ; then
|
||||
VPX_AS=$AS
|
||||
dnl These flags are a lie; they're just used to enable the requisite
|
||||
dnl opcodes; actual arch detection is done at runtime.
|
||||
VPX_ASFLAGS="-march=armv7-a -mfpu=neon"
|
||||
VPX_DASH_C_FLAG="-c"
|
||||
VPX_AS_CONVERSION="$PERL ${srcdir}/media/libvpx/build/make/ads2gas.pl"
|
||||
VPX_ASM_SUFFIX="$ASM_SUFFIX"
|
||||
VPX_ARM_ASM=1
|
||||
fi
|
||||
esac
|
||||
|
||||
if test -n "$COMPILE_ENVIRONMENT" -a -n "$VPX_X86_ASM" -a -z "$VPX_AS"; then
|
||||
@ -6065,6 +6117,8 @@ if test -n "$MOZ_WEBM"; then
|
||||
|
||||
if test -n "$VPX_X86_ASM"; then
|
||||
AC_DEFINE(VPX_X86_ASM)
|
||||
elif test -n "$VPX_ARM_ASM"; then
|
||||
AC_DEFINE(VPX_ARM_ASM)
|
||||
else
|
||||
AC_MSG_WARN([No assembler or assembly support for libvpx. Using unoptimized C routines.])
|
||||
fi
|
||||
@ -6367,15 +6421,11 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c tridentprofile` -ne 0; then
|
||||
MOZ_EXTENSIONS="$MOZ_EXTENSIONS tridentprofile"
|
||||
fi
|
||||
|
||||
dnl xforms requires xtf and schema-validation
|
||||
dnl xforms requires xtf
|
||||
if test -z "$MOZ_XTF" -a `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0; then
|
||||
AC_MSG_WARN([Cannot build XForms without XTF support. Removing XForms from MOZ_EXTENSIONS.])
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|xforms||g'`
|
||||
fi
|
||||
if test `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0 && test `echo "$MOZ_EXTENSIONS" | grep -c schema-validation` -eq 0; then
|
||||
AC_MSG_WARN([Cannot build XForms without schema validation. Removing XForms from MOZ_EXTENSIONS.])
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|xforms||g'`
|
||||
fi
|
||||
|
||||
if test `echo "$MOZ_EXTENSIONS" | grep -c auth` -ne 0; then
|
||||
AC_MSG_WARN([auth is no longer an extension, use --disable-negotiateauth to disable.])
|
||||
@ -6418,33 +6468,6 @@ for extension in $MOZ_EXTENSIONS; do
|
||||
fi
|
||||
done
|
||||
|
||||
dnl ========================================================
|
||||
dnl Image encoders
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_STRING(image-encoders,
|
||||
[ --enable-image-encoders[={mod1,mod2,default,all,none}]
|
||||
Enable specific image encoders],
|
||||
[ for option in `echo $enableval | sed 's/,/ /g'`; do
|
||||
if test "$option" = "yes" -o "$option" = "all"; then
|
||||
addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
|
||||
elif test "$option" = "no" -o "$option" = "none"; then
|
||||
MOZ_IMG_ENCODERS=""
|
||||
addencoder=""
|
||||
elif test "$option" = "default"; then
|
||||
addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
|
||||
elif test `echo "$option" | grep -c \^-` != 0; then
|
||||
option=`echo $option | sed 's/^-//'`
|
||||
addencoder=`echo "$MOZ_IMG_ENCODERS" | sed "s/ ${option}//"`
|
||||
else
|
||||
addencoder="$option"
|
||||
fi
|
||||
MOZ_IMG_ENCODERS="$MOZ_IMG_ENCODERS $addencoder"
|
||||
done],
|
||||
MOZ_IMG_ENCODERS="$MOZ_IMG_ENCODERS_DEFAULT")
|
||||
|
||||
dnl Remove dupes
|
||||
MOZ_IMG_ENCODERS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_IMG_ENCODERS}`
|
||||
|
||||
dnl ========================================================
|
||||
dnl MathML on by default
|
||||
dnl ========================================================
|
||||
@ -8573,7 +8596,7 @@ if test "$MOZ_TREE_CAIRO"; then
|
||||
if test "$MOZ_TREE_PIXMAN"; then
|
||||
MOZ_CAIRO_LIBS="$MOZ_CAIRO_LIBS"' $(call EXPAND_LIBNAME_PATH,mozlibpixman,$(DEPTH)/gfx/cairo/libpixman/src)'
|
||||
else
|
||||
PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.17.3)
|
||||
PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.19.2)
|
||||
MOZ_CAIRO_CFLAGS="$MOZ_CAIRO_CFLAGS $PIXMAN_CFLAGS"
|
||||
MOZ_CAIRO_LIBS="$MOZ_CAIRO_LIBS $PIXMAN_LIBS"
|
||||
fi
|
||||
@ -8848,7 +8871,6 @@ AC_SUBST(MOZ_DEBUG_FLAGS)
|
||||
AC_SUBST(MOZ_DEBUG_LDFLAGS)
|
||||
AC_SUBST(WARNINGS_AS_ERRORS)
|
||||
AC_SUBST(MOZ_EXTENSIONS)
|
||||
AC_SUBST(MOZ_IMG_ENCODERS)
|
||||
AC_SUBST(MOZ_JSDEBUGGER)
|
||||
AC_SUBST(MOZ_PLUGINS)
|
||||
AC_SUBST(MOZ_LOG_REFCNT)
|
||||
@ -8911,7 +8933,6 @@ AC_SUBST(USE_DEPENDENT_LIBS)
|
||||
|
||||
AC_SUBST(MOZ_BUILD_ROOT)
|
||||
AC_SUBST(MOZ_OS2_TOOLS)
|
||||
AC_SUBST(MOZ_OS2_USE_DECLSPEC)
|
||||
|
||||
AC_SUBST(MOZ_POST_DSO_LIB_COMMAND)
|
||||
AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
|
||||
@ -9078,7 +9099,11 @@ AC_SUBST(MOZ_OGG)
|
||||
AC_SUBST(MOZ_ALSA_LIBS)
|
||||
AC_SUBST(VPX_AS)
|
||||
AC_SUBST(VPX_ASFLAGS)
|
||||
AC_SUBST(VPX_DASH_C_FLAG)
|
||||
AC_SUBST(VPX_AS_CONVERSION)
|
||||
AC_SUBST(VPX_ASM_SUFFIX)
|
||||
AC_SUBST(VPX_X86_ASM)
|
||||
AC_SUBST(VPX_ARM_ASM)
|
||||
|
||||
if test "$USING_HCC"; then
|
||||
CC='${topsrcdir}/build/hcc'
|
||||
|
@ -1700,6 +1700,14 @@ public:
|
||||
*/
|
||||
static bool IsSubDocumentTabbable(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Flushes the layout tree (recursively)
|
||||
*
|
||||
* @param aWindow the window the flush should start at
|
||||
*
|
||||
*/
|
||||
static void FlushLayoutForTree(nsIDOMWindow* aWindow);
|
||||
|
||||
private:
|
||||
|
||||
static PRBool InitializeEventTable();
|
||||
|
@ -121,8 +121,8 @@ class Element;
|
||||
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x7fb1e97d, 0xbd2c, 0x47cf, \
|
||||
{ 0xa3, 0x05, 0x5b, 0x31, 0xd4, 0x1d, 0x3a, 0x52 } }
|
||||
{ 0xc38a7935, 0xc854, 0x4df7, \
|
||||
{ 0x8f, 0xd4, 0xa2, 0x6f, 0x0d, 0x27, 0x9f, 0x31 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -1280,6 +1280,11 @@ public:
|
||||
virtual nsSMILAnimationController* GetAnimationController() = 0;
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
// Makes the images on this document capable of having their animation
|
||||
// active or suspended. An Image will animate as long as at least one of its
|
||||
// owning Documents needs it to animate; otherwise it can suspend.
|
||||
virtual void SetImagesNeedAnimating(PRBool aAnimating) = 0;
|
||||
|
||||
/**
|
||||
* Prevents user initiated events from being dispatched to the document and
|
||||
* subdocuments.
|
||||
|
@ -738,7 +738,7 @@ public:
|
||||
nsSlots* s = GetSlots();
|
||||
if (s) {
|
||||
NS_ASSERTION(s->mMutationObservers.IndexOf(aMutationObserver) ==
|
||||
nsTArray_base::NoIndex,
|
||||
nsTArray<int>::NoIndex,
|
||||
"Observer already in the list");
|
||||
s->mMutationObservers.AppendElement(aMutationObserver);
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ var gPrefObserver = {
|
||||
|
||||
function CSPWarning(aMsg) {
|
||||
var textMessage = 'CSP WARN: ' + aMsg + "\n";
|
||||
dump(textMessage);
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptError);
|
||||
@ -99,7 +98,6 @@ function CSPWarning(aMsg) {
|
||||
|
||||
function CSPError(aMsg) {
|
||||
var textMessage = 'CSP ERROR: ' + aMsg + "\n";
|
||||
dump(textMessage);
|
||||
|
||||
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptError);
|
||||
@ -115,7 +113,6 @@ function CSPdebug(aMsg) {
|
||||
if (!gPrefObserver.debugEnabled) return;
|
||||
|
||||
aMsg = 'CSP debug: ' + aMsg + "\n";
|
||||
dump(aMsg);
|
||||
Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService)
|
||||
.logStringMessage(aMsg);
|
||||
|
@ -58,8 +58,9 @@ class nsIAtom;
|
||||
class nsICSSStyleRule;
|
||||
class nsISVGValue;
|
||||
class nsIDocument;
|
||||
template<class E> class nsTArray;
|
||||
template<class E> class nsTPtrArray;
|
||||
template<class E, class A> class nsTArray;
|
||||
template<class E, class A> class nsTPtrArray;
|
||||
struct nsTArrayDefaultAllocator;
|
||||
|
||||
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
|
||||
|
||||
@ -381,7 +382,7 @@ private:
|
||||
PRBool aCanBePercent = PR_FALSE,
|
||||
PRBool* aIsPercent = nsnull) const;
|
||||
|
||||
static nsTPtrArray<const EnumTable>* sEnumTableArray;
|
||||
static nsTPtrArray<const EnumTable, nsTArrayDefaultAllocator>* sEnumTableArray;
|
||||
|
||||
PtrBits mBits;
|
||||
};
|
||||
|
@ -4803,8 +4803,12 @@ static void ProcessViewportToken(nsIDocument *aDocument,
|
||||
return;
|
||||
|
||||
/* Extract the key and value. */
|
||||
const nsAString &key = Substring(tail, tip);
|
||||
const nsAString &value = Substring(++tip, end);
|
||||
const nsAString &key =
|
||||
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
|
||||
PR_TRUE);
|
||||
const nsAString &value =
|
||||
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
|
||||
PR_TRUE);
|
||||
|
||||
/* Check for known keys. If we find a match, insert the appropriate
|
||||
* information into the document header. */
|
||||
@ -4823,7 +4827,9 @@ static void ProcessViewportToken(nsIDocument *aDocument,
|
||||
aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
|
||||
}
|
||||
|
||||
#define IS_SEPARATOR(c) ((c == ' ') || (c == ',') || (c == ';'))
|
||||
#define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
|
||||
(c == '\t') || (c == '\n') || (c == '\r'))
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
||||
@ -4839,12 +4845,12 @@ nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
||||
viewportInfo.EndReading(end);
|
||||
|
||||
/* Read the tip to the first non-separator character. */
|
||||
while ((tip != end) && IS_SEPARATOR(*tip))
|
||||
while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
||||
++tip;
|
||||
|
||||
/* Read through and find tokens separated by separators. */
|
||||
while (tip != end) {
|
||||
|
||||
|
||||
/* Synchronize tip and tail. */
|
||||
tail = tip;
|
||||
|
||||
@ -4852,11 +4858,22 @@ nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
||||
while ((tip != end) && !IS_SEPARATOR(*tip))
|
||||
++tip;
|
||||
|
||||
/* Allow white spaces that surround the '=' character */
|
||||
if ((tip != end) && (*tip == '=')) {
|
||||
++tip;
|
||||
|
||||
while ((tip != end) && nsCRT::IsAsciiSpace(*tip))
|
||||
++tip;
|
||||
|
||||
while ((tip != end) && !(IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
||||
++tip;
|
||||
}
|
||||
|
||||
/* Our token consists of the characters between tail and tip. */
|
||||
ProcessViewportToken(aDocument, Substring(tail, tip));
|
||||
|
||||
/* Skip separators. */
|
||||
while ((tip != end) && IS_SEPARATOR(*tip))
|
||||
while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
||||
++tip;
|
||||
}
|
||||
|
||||
@ -6286,6 +6303,40 @@ nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
|
||||
return !zombieViewer;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
|
||||
if (!piWin)
|
||||
return;
|
||||
|
||||
// Note that because FlushPendingNotifications flushes parents, this
|
||||
// is O(N^2) in docshell tree depth. However, the docshell tree is
|
||||
// usually pretty shallow.
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
aWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
if (doc) {
|
||||
doc->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeNode> node =
|
||||
do_QueryInterface(piWin->GetDocShell());
|
||||
if (node) {
|
||||
PRInt32 i = 0, i_end;
|
||||
node->GetChildCount(&i_end);
|
||||
for (; i < i_end; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> item;
|
||||
node->GetChildAt(i, getter_AddRefs(item));
|
||||
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
|
||||
if (win) {
|
||||
FlushLayoutForTree(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsContentUtils::RemoveNewlines(nsString &aString)
|
||||
{
|
||||
// strip CR/LF and null
|
||||
|
@ -205,6 +205,8 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
typedef nsTArray<Link*> LinkArray;
|
||||
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gDocumentLeakPRLog;
|
||||
@ -3902,7 +3904,7 @@ nsDocument::InternalAllowXULXBL()
|
||||
void
|
||||
nsDocument::AddObserver(nsIDocumentObserver* aObserver)
|
||||
{
|
||||
NS_ASSERTION(mObservers.IndexOf(aObserver) == nsTArray_base::NoIndex,
|
||||
NS_ASSERTION(mObservers.IndexOf(aObserver) == nsTArray<int>::NoIndex,
|
||||
"Observer already in the list");
|
||||
mObservers.AppendElement(aObserver);
|
||||
AddMutationObserver(aObserver);
|
||||
@ -5543,6 +5545,13 @@ nsDocument::GetAnimationController()
|
||||
}
|
||||
}
|
||||
|
||||
// If we're hidden (or being hidden), notify the newly-created animation
|
||||
// controller. (Skip this check for SVG-as-an-image documents, though,
|
||||
// because they don't get OnPageShow / OnPageHide calls).
|
||||
if (!mIsShowing && !mIsBeingUsedAsImage) {
|
||||
mAnimationController->OnPageHide();
|
||||
}
|
||||
|
||||
return mAnimationController;
|
||||
}
|
||||
#endif // MOZ_SMIL
|
||||
@ -7541,7 +7550,7 @@ static
|
||||
PLDHashOperator
|
||||
EnumerateStyledLinks(nsPtrHashKey<Link>* aEntry, void* aArray)
|
||||
{
|
||||
nsTArray<Link*>* array = static_cast<nsTArray<Link*>*>(aArray);
|
||||
LinkArray* array = static_cast<LinkArray*>(aArray);
|
||||
(void)array->AppendElement(aEntry->GetKey());
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
@ -7552,12 +7561,12 @@ nsDocument::RefreshLinkHrefs()
|
||||
// Get a list of all links we know about. We will reset them, which will
|
||||
// remove them from the document, so we need a copy of what is in the
|
||||
// hashtable.
|
||||
nsTArray<Link*> linksToNotify(mStyledLinks.Count());
|
||||
LinkArray linksToNotify(mStyledLinks.Count());
|
||||
(void)mStyledLinks.EnumerateEntries(EnumerateStyledLinks, &linksToNotify);
|
||||
|
||||
// Reset all of our styled links.
|
||||
MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
for (nsTArray_base::size_type i = 0; i < linksToNotify.Length(); i++) {
|
||||
for (LinkArray::size_type i = 0; i < linksToNotify.Length(); i++) {
|
||||
linksToNotify[i]->ResetLinkState(true);
|
||||
}
|
||||
}
|
||||
|
@ -919,6 +919,8 @@ public:
|
||||
nsSMILAnimationController* GetAnimationController();
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
void SetImagesNeedAnimating(PRBool aAnimating);
|
||||
|
||||
virtual void SuppressEventHandling(PRUint32 aIncrease);
|
||||
|
||||
virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents);
|
||||
@ -1252,12 +1254,6 @@ private:
|
||||
protected:
|
||||
PRBool mWillReparent;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Makes the images on this document capable of having their animation
|
||||
// active or suspended. An Image will animate as long as at least one of its
|
||||
// owning Documents needs it to animate; otherwise it can suspend.
|
||||
void SetImagesNeedAnimating(PRBool aAnimating);
|
||||
};
|
||||
|
||||
#define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class) \
|
||||
|
@ -653,7 +653,18 @@ nsFrameLoader::Show(PRInt32 marginWidth, PRInt32 marginHeight,
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
|
||||
NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
|
||||
baseWindow->InitWindow(nsnull, view->GetWidget(), 0, 0, 10, 10);
|
||||
nsIntSize size;
|
||||
if (!(frame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
// We have a useful size already; use it, since we might get no
|
||||
// more size updates.
|
||||
size = GetSubDocumentSize(frame);
|
||||
} else {
|
||||
// Pick some default size for now. Using 10x10 because that's what the
|
||||
// code here used to do.
|
||||
size.SizeTo(10, 10);
|
||||
}
|
||||
baseWindow->InitWindow(nsnull, view->GetWidget(), 0, 0,
|
||||
size.width, size.height);
|
||||
// This is kinda whacky, this "Create()" call doesn't really
|
||||
// create anything, one starts to wonder why this was named
|
||||
// "Create"...
|
||||
@ -712,8 +723,7 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
|
||||
mRemoteBrowser->Show(size);
|
||||
mRemoteBrowserShown = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIChromeFrameMessageManager> dummy;
|
||||
GetMessageManager(getter_AddRefs(dummy)); // Initialize message manager.
|
||||
EnsureMessageManager();
|
||||
} else {
|
||||
mRemoteBrowser->Move(size);
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ nsFrameMessageManager::SendSyncMessage()
|
||||
nsString json;
|
||||
nsresult rv = GetParamsForMessage(messageName, json);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsTArray<nsString> retval;
|
||||
InfallibleTArray<nsString> retval;
|
||||
if (mSyncCallback(mCallbackData, messageName, json, &retval)) {
|
||||
nsAXPCNativeCallContext* ncc = nsnull;
|
||||
rv = nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&ncc);
|
||||
@ -326,7 +326,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
const nsAString& aMessage,
|
||||
PRBool aSync, const nsAString& aJSON,
|
||||
JSObject* aObjectsArray,
|
||||
nsTArray<nsString>* aJSONRetVal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext)
|
||||
{
|
||||
JSContext* ctx = mContext ? mContext : aContext;
|
||||
@ -742,7 +742,7 @@ bool SendAsyncMessageToChildProcess(void* aCallbackData,
|
||||
bool SendSyncMessageToParentProcess(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
|
@ -66,7 +66,7 @@ typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL)
|
||||
typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal);
|
||||
InfallibleTArray<nsString>* aJSONRetVal);
|
||||
typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON);
|
||||
@ -129,7 +129,7 @@ public:
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
|
||||
PRBool aSync, const nsAString& aJSON,
|
||||
JSObject* aObjectsArray,
|
||||
nsTArray<nsString>* aJSONRetVal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal,
|
||||
JSContext* aContext = nsnull);
|
||||
void AddChildManager(nsFrameMessageManager* aManager,
|
||||
PRBool aLoadScripts = PR_TRUE);
|
||||
|
@ -54,7 +54,7 @@
|
||||
bool SendSyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsInProcessTabChildGlobal* tabChild =
|
||||
static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user