Merge mozilla-central into electrolysis.
Merge mozilla-central into electrolysis.
--- a/Makefile.in
+++ b/Makefile.in
@@ -126,26 +126,16 @@ tier_necko::
$(foreach tier,$(TIERS),$(MAKE) tools_tier_$(tier); )
endif
distclean::
cat unallmakefiles | $(XARGS) rm -f
rm -f unallmakefiles $(DIST_GARBAGE)
ifeq ($(OS_ARCH),WINNT)
-rebase:
-ifdef MOZILLA_OFFICIAL
- echo rebasing $(DIST)
- /bin/find $(DIST) -name "*.dll" -a -not -name "msvc*" > rebase.lst
- rebase -b 60000000 -R . -G rebase.lst
- rm rebase.lst
-endif
-endif # WINNT
-
-ifeq ($(OS_ARCH),WINNT)
# we want to copy PDB files on Windows
MAKE_SYM_STORE_ARGS := -c
ifdef PDBSTR_PATH
MAKE_SYM_STORE_ARGS += -i
endif
ifeq (,$(CYGWIN_WRAPPER))
# this doesn't work with Cygwin Python
MAKE_SYM_STORE_ARGS += --vcs-info
@@ -201,29 +191,16 @@ ifdef MOZ_CRASHREPORTER
zip -r9D "../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip" .
endif # MOZ_CRASHREPORTER
uploadsymbols:
ifdef MOZ_CRASHREPORTER
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh "$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip"
endif
-ifeq ($(OS_ARCH),WINNT)
-signnss:
-ifdef MOZILLA_OFFICIAL
- echo signing NSS libs
- cd $(DIST)/bin; ./shlibsign.exe -v -i softokn3.dll
- cd $(DIST)/bin; ./shlibsign.exe -v -i freebl3.dll
- cd $(DIST)/bin; ./shlibsign.exe -v -i nssdbm3.dll
-endif # MOZILLA_OFFICIAL
-
-deliver: rebase signnss
-
-endif # WINNT
-
ifneq (,$(wildcard $(DIST)/bin/application.ini))
BUILDID = $(shell $(PYTHON) $(srcdir)/config/printconfigsetting.py $(DIST)/bin/application.ini App BuildID)
else
BUILDID = $(shell $(PYTHON) $(srcdir)/config/printconfigsetting.py $(DIST)/bin/platform.ini Build BuildID)
endif
#XXX: this is a hack, since we don't want to clobber for MSVC
# PGO support, but we can't do this test in client.mk
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -357,20 +357,24 @@ NS_IMETHODIMP nsAccessibilityService::On
return NS_OK;
}
nsresult
nsAccessibilityService::GetInfo(nsIFrame* aFrame, nsIWeakReference** aShell, nsIDOMNode** aNode)
{
NS_ASSERTION(aFrame,"Error -- 1st argument (aFrame) is null!!");
+ if (!aFrame) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsIContent> content = aFrame->GetContent();
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
if (!content || !node)
return NS_ERROR_FAILURE;
+
*aNode = node;
NS_IF_ADDREF(*aNode);
nsCOMPtr<nsIDocument> document = content->GetDocument();
if (!document)
return NS_ERROR_FAILURE;
NS_ASSERTION(document->GetPrimaryShell(),"Error no shells!");
@@ -1321,16 +1325,22 @@ NS_IMETHODIMP nsAccessibilityService::Ge
if (!aPresShell || !aWeakShell || gIsShutdown) {
return NS_ERROR_FAILURE;
}
NS_ASSERTION(aNode, "GetAccessible() called with no node.");
*aIsHidden = PR_FALSE;
+ // Frames can be deallocated when we flush layout, or when we call into code
+ // that can flush layout, either directly, or via DOM manipulation, or some
+ // CSS styles like :hover. We use the weak frame checks to avoid calling
+ // methods on a dead frame pointer.
+ nsWeakFrame weakFrame(*aFrameHint);
+
#ifdef DEBUG_A11Y
// Please leave this in for now, it's a convenient debugging method
nsAutoString name;
aNode->GetLocalName(name);
if (name.LowerCaseEqualsLiteral("h1"))
printf("## aaronl debugging tag name\n");
nsAutoString attrib;
@@ -1391,124 +1401,140 @@ NS_IMETHODIMP nsAccessibilityService::Ge
return NS_ERROR_FAILURE;
}
NS_ASSERTION(content->GetDocument() == aPresShell->GetDocument(), "Creating accessible for wrong pres shell");
if (content->GetDocument() != aPresShell->GetDocument()) {
return NS_ERROR_FAILURE;
}
// We have a content node
- nsIFrame *frame = *aFrameHint;
#ifdef DEBUG_A11Y
static int frameHintFailed, frameHintTried, frameHintNonexistant, frameHintFailedForText;
++frameHintTried;
#endif
- if (!frame || content != frame->GetContent()) {
+
+ if (!weakFrame.GetFrame() || content != weakFrame.GetFrame()->GetContent()) {
// Frame hint not correct, get true frame, we try to optimize away from this
- frame = aPresShell->GetRealPrimaryFrameFor(content);
- if (frame) {
+ weakFrame = aPresShell->GetRealPrimaryFrameFor(content);
+ if (weakFrame.GetFrame()) {
#ifdef DEBUG_A11Y_FRAME_OPTIMIZATION
// Frame hint debugging
++frameHintFailed;
if (content->IsNodeOfType(nsINode::eTEXT)) {
++frameHintFailedForText;
}
frameHintNonexistant += !*aFrameHint;
printf("Frame hint failures: %d / %d . Text fails = %d. No hint fails = %d \n", frameHintFailed, frameHintTried, frameHintFailedForText, frameHintNonexistant);
if (frameHintTried >= 354) {
printf("* "); // Aaron's break point
}
#endif
- if (frame->GetContent() != content) {
+ if (weakFrame.GetFrame()->GetContent() != content) {
// Not the main content for this frame!
// For example, this happens because <area> elements return the
// image frame as their primary frame. The main content for the
// image frame is the image content.
// Check if frame is an image frame, and content is <area>
- nsIImageFrame *imageFrame = do_QueryFrame(frame);
+ nsIImageFrame *imageFrame = do_QueryFrame(weakFrame.GetFrame());
nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(content);
if (imageFrame && areaElmt) {
nsCOMPtr<nsIAccessible> imageAcc;
- CreateHTMLImageAccessible(frame, getter_AddRefs(imageAcc));
+ CreateHTMLImageAccessible(weakFrame.GetFrame(), getter_AddRefs(imageAcc));
if (imageAcc) {
// cache children
PRInt32 childCount;
imageAcc->GetChildCount(&childCount);
// area accessible should be in cache now
return GetCachedAccessible(aNode, aWeakShell, aAccessible);
}
}
return NS_OK;
}
- *aFrameHint = frame;
+ *aFrameHint = weakFrame.GetFrame();
}
}
// Check frame to see if it is hidden
- if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
+ if (!weakFrame.GetFrame() ||
+ !weakFrame.GetFrame()->GetStyleVisibility()->IsVisible()) {
*aIsHidden = PR_TRUE;
}
- if (*aIsHidden)
+ if (*aIsHidden) {
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
+ }
/**
* Attempt to create an accessible based on what we know
*/
if (content->IsNodeOfType(nsINode::eTEXT)) {
// --- Create HTML for visible text frames ---
- if (frame->IsEmpty()) {
+ nsIFrame* f = weakFrame.GetFrame();
+ if (f && f->IsEmpty()) {
nsAutoString renderedWhitespace;
- frame->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
+ f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
if (renderedWhitespace.IsEmpty()) {
// Really empty -- nothing is rendered
*aIsHidden = PR_TRUE;
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
}
}
- frame->GetAccessible(getter_AddRefs(newAcc));
- return InitAccessible(newAcc, aAccessible, nsnull);
+ if (weakFrame.IsAlive()) {
+ weakFrame.GetFrame()->GetAccessible(getter_AddRefs(newAcc));
+ }
+
+ nsresult rv = InitAccessible(newAcc, aAccessible, nsnull);
+ *aFrameHint = weakFrame.GetFrame();
+ return rv;
}
PRBool isHTML = content->IsHTML();
if (isHTML && content->Tag() == nsAccessibilityAtoms::map) {
// Create hyper text accessible for HTML map if it is used to group links
// (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
// map doesn't have 'name' attribute (or has empty name attribute) then we
// suppose it is used for links grouping. Otherwise we think it is used in
// conjuction with HTML image element and in this case we don't create any
// accessible for it and don't walk into it. The accessibles for HTML area
// (nsHTMLAreaAccessible) the map contains are attached as children of the
// appropriate accessible for HTML image (nsHTMLImageAccessible).
nsAutoString name;
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name);
if (!name.IsEmpty()) {
*aIsHidden = PR_TRUE;
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
}
- nsresult rv = CreateHyperTextAccessible(frame, getter_AddRefs(newAcc));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ CreateHyperTextAccessible(weakFrame.GetFrame(), getter_AddRefs(newAcc));
+ if (NS_FAILED(rv)) {
+ *aFrameHint = weakFrame.GetFrame();
+ return rv;
+ }
}
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
!content->IsFocusable()) { // For presentation only
// Only create accessible for role of "presentation" if it is focusable --
// in that case we need an accessible in case it gets focused, we
// don't want focus ever to be 'lost'
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
}
- if (!newAcc && isHTML) { // HTML accessibles
+ if (weakFrame.IsAlive() && !newAcc && isHTML) { // HTML accessibles
PRBool tryTagNameOrFrame = PR_TRUE;
- nsIAtom *frameType = frame->GetType();
+ nsIAtom *frameType = weakFrame.GetFrame()->GetType();
PRBool partOfHTMLTable =
frameType == nsAccessibilityAtoms::tableCaptionFrame ||
frameType == nsAccessibilityAtoms::tableCellFrame ||
frameType == nsAccessibilityAtoms::tableRowGroupFrame ||
frameType == nsAccessibilityAtoms::tableRowFrame;
if (partOfHTMLTable) {
@@ -1549,16 +1575,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
"No accessible for parent table and it didn't have role of presentation");
#endif
if (!roleMapEntry && !content->IsFocusable()) {
// Table-related descendants of presentation table are also
// presentation if they aren't focusable and have not explicit ARIA
// role (don't create accessibles for them unless they need to fire
// focus events).
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
}
// otherwise create ARIA based accessible.
tryTagNameOrFrame = PR_FALSE;
break;
}
@@ -1593,44 +1620,56 @@ NS_IMETHODIMP nsAccessibilityService::Ge
}
if (!newAcc && tryTagNameOrFrame) {
// Prefer to use markup (mostly tag name, perhaps attributes) to
// decide if and what kind of accessible to create.
// The method creates accessibles for table related content too therefore
// we do not call it if accessibles for table related content are
// prevented above.
- nsresult rv = CreateHTMLAccessibleByMarkup(frame, aWeakShell, aNode,
- getter_AddRefs(newAcc));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ CreateHTMLAccessibleByMarkup(weakFrame.GetFrame(), aWeakShell, aNode,
+ getter_AddRefs(newAcc));
+ if (NS_FAILED(rv)) {
+ *aFrameHint = weakFrame.GetFrame();
+ return rv;
+ }
if (!newAcc) {
// Do not create accessible object subtrees for non-rendered table
// captions. This could not be done in
// nsTableCaptionFrame::GetAccessible() because the descendants of
// the table caption would still be created. By setting
// *aIsHidden = PR_TRUE we ensure that no descendant accessibles are
// created.
- if (frame->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
- frame->GetRect().IsEmpty()) {
+ nsIFrame* f = weakFrame.GetFrame();
+ if (!f) {
+ f = aPresShell->GetRealPrimaryFrameFor(content);
+ }
+ if (f->GetType() == nsAccessibilityAtoms::tableCaptionFrame &&
+ f->GetRect().IsEmpty()) {
// XXX This is not the ideal place for this code, but right now there
// is no better place:
*aIsHidden = PR_TRUE;
+ *aFrameHint = weakFrame.GetFrame();
return NS_OK;
}
- frame->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
+ f->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
}
}
}
if (!newAcc) {
// Elements may implement nsIAccessibleProvider via XBL. This allows them to
// say what kind of accessible to create.
nsresult rv = GetAccessibleByType(aNode, getter_AddRefs(newAcc));
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_FAILED(rv)) {
+ *aFrameHint = weakFrame.GetFrame();
+ return rv;
+ }
}
if (!newAcc) {
// Create generic accessibles for SVG and MathML nodes.
if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
content->Tag() == nsAccessibilityAtoms::svg) {
newAcc = new nsEnumRoleAccessible(aNode, aWeakShell,
nsIAccessibleRole::ROLE_DIAGRAM);
@@ -1646,34 +1685,36 @@ NS_IMETHODIMP nsAccessibilityService::Ge
GetAccessibleForDeckChildren(aNode, getter_AddRefs(newAcc));
}
// If no accessible, see if we need to create a generic accessible because
// of some property that makes this object interesting
// We don't do this for <body>, <html>, <window>, <dialog> etc. which
// correspond to the doc accessible and will be created in any case
if (!newAcc && content->Tag() != nsAccessibilityAtoms::body && content->GetParent() &&
- (frame->IsFocusable() ||
+ ((weakFrame.GetFrame() && weakFrame.GetFrame()->IsFocusable()) ||
(isHTML && nsCoreUtils::HasListener(content, NS_LITERAL_STRING("click"))) ||
HasUniversalAriaProperty(content, aWeakShell) || roleMapEntry ||
HasRelatedContent(content) || nsCoreUtils::IsXLink(content))) {
// This content is focusable or has an interesting dynamic content accessibility property.
// If it's interesting we need it in the accessibility hierarchy so that events or
// other accessibles can point to it, or so that it can hold a state, etc.
if (isHTML) {
// Interesting HTML container which may have selectable text and/or embedded objects
- CreateHyperTextAccessible(frame, getter_AddRefs(newAcc));
+ CreateHyperTextAccessible(weakFrame.GetFrame(), getter_AddRefs(newAcc));
}
else { // XUL, SVG, MathML etc.
// Interesting generic non-HTML container
newAcc = new nsAccessibleWrap(aNode, aWeakShell);
}
}
- return InitAccessible(newAcc, aAccessible, roleMapEntry);
+ nsresult rv = InitAccessible(newAcc, aAccessible, roleMapEntry);
+ *aFrameHint = weakFrame.GetFrame();
+ return rv;
}
PRBool
nsAccessibilityService::HasUniversalAriaProperty(nsIContent *aContent,
nsIWeakReference *aWeakShell)
{
// ARIA attributes that take token values (NMTOKEN, bool) are special cased.
return nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_atomic) ||
--- a/accessible/src/base/nsAccessibleTreeWalker.cpp
+++ b/accessible/src/base/nsAccessibleTreeWalker.cpp
@@ -41,30 +41,28 @@
#include "nsAccessibilityAtoms.h"
#include "nsAccessNode.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIServiceManager.h"
#include "nsIContent.h"
#include "nsIDOMXULElement.h"
#include "nsIPresShell.h"
-#include "nsIFrame.h"
#include "nsWeakReference.h"
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRBool aWalkAnonContent):
mWeakShell(aPresShell),
mAccService(do_GetService("@mozilla.org/accessibilityService;1")),
mWalkAnonContent(aWalkAnonContent)
{
mState.domNode = aNode;
mState.prevState = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
mState.siblingList = nsnull;
mState.isHidden = false;
- mState.frame = nsnull;
MOZ_COUNT_CTOR(nsAccessibleTreeWalker);
}
nsAccessibleTreeWalker::~nsAccessibleTreeWalker()
{
// Clear state stack from memory
while (NS_SUCCEEDED(PopState()))
@@ -116,22 +114,23 @@ void nsAccessibleTreeWalker::GetKids(nsI
}
}
mState.siblingList->Item(0 /* 0 == mState.siblingIndex */, getter_AddRefs(mState.domNode));
}
NS_IMETHODIMP nsAccessibleTreeWalker::PopState()
{
- nsIFrame *frameParent = mState.frame? mState.frame->GetParent(): nsnull;
+ nsIFrame *frameParent =
+ mState.frame.GetFrame() ? mState.frame.GetFrame()->GetParent() : nsnull;
if (mState.prevState) {
WalkState *toBeDeleted = mState.prevState;
mState = *mState.prevState; // deep copy
mState.isHidden = PR_FALSE; // If we were in a child, the parent wasn't hidden
- if (!mState.frame) {
+ if (!mState.frame.GetFrame()) {
mState.frame = frameParent;
}
delete toBeDeleted;
return NS_OK;
}
ClearState();
mState.frame = frameParent;
mState.isHidden = PR_FALSE;
@@ -161,18 +160,18 @@ NS_IMETHODIMP nsAccessibleTreeWalker::Pu
void nsAccessibleTreeWalker::GetNextDOMNode()
{
// Get next DOM node
if (mState.parentContent) {
mState.domNode = do_QueryInterface(mState.parentContent->GetChildAt(++mState.siblingIndex));
}
else if (mState.siblingIndex == eSiblingsWalkFrames) {
- if (mState.frame) {
- mState.domNode = do_QueryInterface(mState.frame->GetContent());
+ if (mState.frame.GetFrame()) {
+ mState.domNode = do_QueryInterface(mState.frame.GetFrame()->GetContent());
} else {
mState.domNode = nsnull;
}
}
else {
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(mState.domNode));
}
}
@@ -225,28 +224,30 @@ NS_IMETHODIMP nsAccessibleTreeWalker::Ge
}
PopState(); // Return to previous state
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::UpdateFrame(PRBool aTryFirstChild)
{
- if (!mState.frame) {
+ nsIFrame *curFrame = mState.frame.GetFrame();
+ if (!curFrame) {
return;
}
if (aTryFirstChild) {
// If the frame implements nsIAnonymousContentCreator interface then go down
// through the frames and obtain anonymous nodes for them.
- nsIAnonymousContentCreator* creator = do_QueryFrame(mState.frame);
- mState.frame = mState.frame->GetFirstChild(nsnull);
+ nsIAnonymousContentCreator* creator = do_QueryFrame(curFrame);
+ nsIFrame *child = curFrame->GetFirstChild(nsnull);
+ mState.frame = child;
- if (creator && mState.frame && mState.siblingIndex < 0) {
- mState.domNode = do_QueryInterface(mState.frame->GetContent());
+ if (creator && child && mState.siblingIndex < 0) {
+ mState.domNode = do_QueryInterface(child->GetContent());
mState.siblingIndex = eSiblingsWalkFrames;
}
// temporary workaround for Bug 359210. We never want to walk frames.
// Aaron Leventhal will refix :before and :after content later without walking frames.
#if 0
if (mState.frame && mState.siblingIndex < 0) {
// Container frames can contain generated content frames from
// :before and :after style rules, so we walk their frame trees
@@ -263,31 +264,33 @@ void nsAccessibleTreeWalker::UpdateFrame
// pseudoContext = presContext->StyleSet()->
// ProbePseudoStyleFor(content, nsAccessibilityAtoms::after, aStyleContext);
mState.domNode = do_QueryInterface(mState.frame->GetContent());
mState.siblingIndex = eSiblingsWalkFrames;
}
#endif
}
else {
- mState.frame = mState.frame->GetNextSibling();
+ mState.frame = curFrame->GetNextSibling();
}
}
/**
* If the DOM node's frame has an accessible or the DOMNode
* itself implements nsIAccessible return it.
*/
PRBool nsAccessibleTreeWalker::GetAccessible()
{
if (!mAccService) {
return PR_FALSE;
}
mState.accessible = nsnull;
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
+ nsIFrame *frame = mState.frame.GetFrame();
mAccService->GetAccessible(mState.domNode, presShell, mWeakShell,
- &mState.frame, &mState.isHidden,
+ &frame, &mState.isHidden,
getter_AddRefs(mState.accessible));
+ mState.frame = frame;
return mState.accessible ? PR_TRUE : PR_FALSE;
}
--- a/accessible/src/base/nsAccessibleTreeWalker.h
+++ b/accessible/src/base/nsAccessibleTreeWalker.h
@@ -34,36 +34,38 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsAccessibleTreeWalker_H_
#define _nsAccessibleTreeWalker_H_
-/* For documentation of the accessibility architecture, * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
+/* For documentation of the accessibility architecture, see
+ * http://www.mozilla.org/access/architecture
*/
#include "nsCOMPtr.h"
#include "nsIDocument.h"
#include "nsIAccessible.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIAccessibilityService.h"
#include "nsIWeakReference.h"
+#include "nsIFrame.h"
enum { eSiblingsUninitialized = -1, eSiblingsWalkFrames = -2 };
struct WalkState {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMNodeList> siblingList;
nsIContent *parentContent; // For walking normal DOM
WalkState *prevState;
- nsIFrame *frame; // Helps avoid GetPrimaryFrameFor() calls
+ nsWeakFrame frame; // Helps avoid GetPrimaryFrameFor() calls
PRInt32 siblingIndex; // Holds a state flag or an index into the siblingList
PRBool isHidden; // Don't enter subtree if hidden
};
/** This class is used to walk the DOM tree. It skips
* everything but nodes that either implement nsIAccessibleProvider
* or have primary frames that implement "GetAccessible"
*/
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -1152,18 +1152,17 @@ nsXULListCellAccessible::GetColumnHeader
NS_ENSURE_ARG_POINTER(aHeaderCells);
*aHeaderCells = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessibleTable> table;
GetTable(getter_AddRefs(table));
- if (!table)
- return NS_OK;
+ NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
// Get column header cell from XUL listhead.
nsCOMPtr<nsIAccessible> tableAcc(do_QueryInterface(table));
nsCOMPtr<nsIAccessible> list, nextChild;
tableAcc->GetFirstChild(getter_AddRefs(list));
while (list) {
if (nsAccUtils::Role(list) == nsIAccessibleRole::ROLE_LIST)
@@ -1204,18 +1203,17 @@ nsXULListCellAccessible::GetRowHeaderCel
NS_ENSURE_ARG_POINTER(aHeaderCells);
*aHeaderCells = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessibleTable> table;
GetTable(getter_AddRefs(table));
- if (!table)
- return NS_OK;
+ NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
// Calculate row header cells from ARIA markup.
return nsAccUtils::GetHeaderCellsFor(table, this,
nsAccUtils::eRowHeaderCells,
aHeaderCells);
}
NS_IMETHODIMP
@@ -1224,18 +1222,17 @@ nsXULListCellAccessible::IsSelected(PRBo
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = PR_FALSE;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessibleTable> table;
GetTable(getter_AddRefs(table));
- if (!table)
- return NS_OK;
+ NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
PRInt32 rowIdx = -1;
GetRowIndex(&rowIdx);
return table->IsRowSelected(rowIdx, aIsSelected);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1254,16 +1251,17 @@ nsXULListCellAccessible::GetAttributesIn
NS_ENSURE_ARG_POINTER(aAttributes);
if (IsDefunct())
return NS_ERROR_FAILURE;
// "table-cell-index" attribute
nsCOMPtr<nsIAccessibleTable> table;
GetTable(getter_AddRefs(table));
+ NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
PRInt32 rowIdx = -1;
GetRowIndex(&rowIdx);
PRInt32 colIdx = -1;
GetColumnIndex(&colIdx);
PRInt32 cellIdx = -1;
table->GetCellIndexAt(rowIdx, colIdx, &cellIdx);
--- a/accessible/tests/mochitest/test_name_nsRootAcc.xul
+++ b/accessible/tests/mochitest/test_name_nsRootAcc.xul
@@ -20,19 +20,23 @@
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js"></script>
<script type="application/javascript">
<![CDATA[
// var gA11yEventDumpID = "eventdump"; // debug stuff
SimpleTest.waitForExplicitFinish();
- window.openDialog("chrome://mochikit/content/a11y/accessible/name_nsRootAcc_wnd.xul",
- "nsRootAcc_name_test",
- "chrome,width=600,height=600");
+ var w = window.openDialog("chrome://mochikit/content/a11y/accessible/name_nsRootAcc_wnd.xul",
+ "nsRootAcc_name_test",
+ "chrome,width=600,height=600");
+ if (LINUX) {
+ w.focus();
+ }
+
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=507382"
title="focus is fired earlier than root accessible name is changed when switching between tabs">
--- a/browser/Makefile.in
+++ b/browser/Makefile.in
@@ -30,24 +30,34 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-DEPTH = ..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
include $(topsrcdir)/config/config.mk
-DIRS = base components locales themes fuel app
+PARALLEL_DIRS = \
+ base \
+ components \
+ fuel \
+ locales \
+ themes \
+ $(NULL)
+
+DIRS = \
+ app \
+ $(NULL)
ifeq ($(OS_ARCH),WINNT)
ifdef MOZ_INSTALLER
DIRS += installer/windows
endif
endif
include $(topsrcdir)/config/rules.mk
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -160,29 +160,29 @@ pref("app.update.incompatible.mode", 0);
// extensions.{GUID}.update.url
// .. etc ..
//
pref("extensions.update.enabled", true);
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%");
pref("extensions.update.interval", 86400); // Check for updates to Extensions and
// Themes every day
// Non-symmetric (not shared by extensions) extension-specific [update] preferences
-pref("extensions.getMoreExtensionsURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/%VERSION%/extensions/");
-pref("extensions.getMoreThemesURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/%VERSION%/themes/");
-pref("extensions.getMorePluginsURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/%VERSION%/plugins/");
+pref("extensions.getMoreThemesURL", "https://addons.mozilla.org/%LOCALE%/%APP%/getpersonas");
pref("extensions.dss.enabled", false); // Dynamic Skin Switching
pref("extensions.dss.switchPending", false); // Non-dynamic switch pending after next
// restart.
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
pref("xpinstall.whitelist.add", "addons.mozilla.org");
pref("xpinstall.whitelist.add.36", "getpersonas.com");
+pref("lightweightThemes.update.enabled", true);
+
pref("keyword.enabled", true);
pref("keyword.URL", "chrome://browser-region/locale/region.properties");
pref("general.useragent.locale", "@AB_CD@");
pref("general.skins.selectedSkin", "classic/1.0");
pref("general.useragent.extra.firefox", "@APP_UA_NAME@/@APP_VERSION@");
pref("general.smoothScroll", false);
--- a/browser/base/content/baseMenuOverlay.xul
+++ b/browser/base/content/baseMenuOverlay.xul
@@ -87,18 +87,18 @@
#endif
# Show IE Users menu item on Windows only
#ifdef XP_WIN
<menuitem label="&helpForIEUsers.label;"
accesskey="&helpForIEUsers.accesskey;"
oncommand="openHelpLink('ieusers');"/>
#endif
<menuitem id="troubleShooting"
- accesskey="&helpTroubleshooting.accesskey;"
- label="&helpTroubleshooting.label;"
+ accesskey="&helpTroubleshootingInfo.accesskey;"
+ label="&helpTroubleshootingInfo.label;"
oncommand="openTroubleshootingPage()"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="releaseNotes"
accesskey="&helpReleaseNotes.accesskey;"
label="&helpReleaseNotes.label;"
oncommand="openReleaseNotes()"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator id="updateSeparator"/>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -884,22 +884,22 @@ var BookmarksEventHandler = {
target._endMarker = target.childNodes.length;
target.appendChild(target._endOptSeparator);
}
if (siteURIString && !target._endOptOpenSiteURI) {
// Add "Open (Feed Name)" menuitem if it's a livemark with a siteURI
target._endOptOpenSiteURI = document.createElement("menuitem");
target._endOptOpenSiteURI.className = "openlivemarksite-menuitem";
- target._endOptOpenSiteURI.setAttribute("siteURI", siteURIString);
+ target._endOptOpenSiteURI.setAttribute("targetURI", siteURIString);
target._endOptOpenSiteURI.setAttribute("oncommand",
- "openUILink(this.getAttribute('siteURI'), event);");
+ "openUILink(this.getAttribute('targetURI'), event);");
// If a user middle-clicks this item we serve the oncommand event
// We are using checkForMiddleClick because of Bug 246720
- // Note: stopPropagation is needed to avoid serving middle-click
+ // Note: stopPropagation is needed to avoid serving middle-click
// with BT_onClick that would open all items in tabs
target._endOptOpenSiteURI.setAttribute("onclick",
"checkForMiddleClick(this, event); event.stopPropagation();");
target._endOptOpenSiteURI.setAttribute("label",
PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
[target.parentNode.getAttribute("label")]));
target.appendChild(target._endOptOpenSiteURI);
}
@@ -917,39 +917,50 @@ var BookmarksEventHandler = {
gNavigatorBundle.getString("menuOpenAllInTabs.label"));
target.appendChild(target._endOptOpenAllInTabs);
}
},
fillInBHTooltip: function(aDocument, aEvent) {
var node;
var cropped = false;
+ var targetURI;
if (aDocument.tooltipNode.localName == "treechildren") {
var tree = aDocument.tooltipNode.parentNode;
var row = {}, column = {};
var tbo = tree.treeBoxObject;
tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, column, {});
if (row.value == -1)
return false;
node = tree.view.nodeForTreeIndex(row.value);
cropped = tbo.isCellCropped(row.value, column.value);
}
- else
- node = aDocument.tooltipNode.node;
+ else {
+ // Check whether the tooltipNode is a Places node.
+ // In such a case use it, otherwise check for targetURI attribute.
+ var tooltipNode = aDocument.tooltipNode;
+ if (tooltipNode.node)
+ node = tooltipNode.node;
+ else {
+ // This is a static non-Places node.
+ targetURI = tooltipNode.getAttribute("targetURI");
+ }
+ }
- if (!node)
+ if (!node && !targetURI)
return false;
- var title = node.title;
- var url;
+ // Show node.label as tooltip's title for non-Places nodes.
+ var title = node ? node.title : tooltipNode.label;
- // Show URL only for URI-type nodes.
- if (PlacesUtils.nodeIsURI(node))
- url = node.uri;
+ // Show URL only for Places URI-nodes or nodes with a targetURI attribute.
+ var url;
+ if (targetURI || PlacesUtils.nodeIsURI(node))
+ url = targetURI || node.uri;
// Show tooltip for containers only if their title is cropped.
if (!cropped && !url)
return false;
var tooltipTitle = aDocument.getElementById("bhtTitleText");
tooltipTitle.hidden = (!title || (title == url));
if (!tooltipTitle.hidden)
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -43,16 +43,17 @@
# Johnathan Nightingale <johnath@mozilla.com>
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
# Dão Gottwald <dao@mozilla.com>
# Thomas K. Dyas <tdyas@zecador.org>
# Edward Lee <edward.lee@engineering.uiuc.edu>
# Paul O’Shannessy <paul@oshannessy.com>
# Nils Maier <maierman@web.de>
# Rob Arnold <robarnold@cmu.edu>
+# Dietrich Ayala <dietrich@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
@@ -147,16 +148,22 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
}
};
}
#endif
#endif
return null;
});
+#ifdef MOZ_CRASHREPORTER
+XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
+ "@mozilla.org/xre/app-info;1",
+ "nsICrashReporter");
+#endif
+
/**
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers.
*/
function pageShowEventHandlers(event) {
// Filter out events that are not about the document load we are interested in
if (event.originalTarget == content.document) {
charsetLoadListener(event);
@@ -4313,16 +4320,24 @@ var XULBrowserWindow = {
var TabsProgressListener = {
onProgressChange: function (aBrowser, aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
+#ifdef MOZ_CRASHREPORTER
+ if (!aRequest.URI)
+ aRequest.QueryInterface(Ci.nsIChannel);
+ if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
+ aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
+ gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
+ }
+#endif
},
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
// Filter out any sub-frame loads
if (aBrowser.contentWindow == aWebProgress.DOMWindow)
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
},
@@ -6835,35 +6850,58 @@ let gPrivateBrowsingUI = {
_privateBrowsingService: null,
_searchBarValue: null,
_findBarValue: null,
init: function PBUI_init() {
this._observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
this._observerService.addObserver(this, "private-browsing", false);
+ this._observerService.addObserver(this, "private-browsing-transition-complete", false);
this._privateBrowsingService = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
if (this.privateBrowsingEnabled)
this.onEnterPrivateBrowsing();
},
uninit: function PBUI_unint() {
this._observerService.removeObserver(this, "private-browsing");
+ this._observerService.removeObserver(this, "private-browsing-transition-complete");
+ },
+
+ get _disableUIOnToggle PBUI__disableUIOnTogle() {
+ if (this._privateBrowsingService.autoStarted)
+ return false;
+
+ try {
+ return !gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session");
+ }
+ catch (e) {
+ return true;
+ }
},
observe: function PBUI_observe(aSubject, aTopic, aData) {
if (aTopic == "private-browsing") {
if (aData == "enter")
this.onEnterPrivateBrowsing();
else if (aData == "exit")
this.onExitPrivateBrowsing();
}
+ else if (aTopic == "private-browsing-transition-complete") {
+ if (this._disableUIOnToggle) {
+ // use setTimeout here in order to make the code testable
+ setTimeout(function() {
+ document.getElementById("Tools:PrivateBrowsing")
+ .removeAttribute("disabled");
+ }, 0);
+ }
+ }
},
_shouldEnter: function PBUI__shouldEnter() {
try {
// Never prompt if the session is not going to be closed, or if user has
// already requested not to be prompted.
if (gPrefService.getBoolPref("browser.privatebrowsing.dont_prompt_on_enter") ||
gPrefService.getBoolPref("browser.privatebrowsing.keep_current_session"))
@@ -6949,16 +6987,20 @@ let gPrivateBrowsingUI = {
docElement.getAttribute("titlemodifier_privatebrowsing"));
docElement.setAttribute("browsingmode", "private");
gBrowser.updateTitlebar();
}
setTimeout(function () {
DownloadMonitorPanel.updateStatus();
}, 0);
+
+ if (this._disableUIOnToggle)
+ document.getElementById("Tools:PrivateBrowsing")
+ .setAttribute("disabled", "true");
},
onExitPrivateBrowsing: function PBUI_onExitPrivateBrowsing() {
if (BrowserSearch.searchBar) {
let searchBox = BrowserSearch.searchBar.textbox;
searchBox.reset();
if (this._searchBarValue) {
searchBox.value = this._searchBarValue;
@@ -6999,16 +7041,20 @@ let gPrivateBrowsingUI = {
document.getElementById("Tools:PrivateBrowsing")
.removeAttribute("disabled");
gLastOpenDirectory.reset();
setTimeout(function () {
DownloadMonitorPanel.updateStatus();
}, 0);
+
+ if (this._disableUIOnToggle)
+ document.getElementById("Tools:PrivateBrowsing")
+ .setAttribute("disabled", "true");
},
_setPBMenuTitle: function PBUI__setPBMenuTitle(aMode) {
let pbMenuItem = document.getElementById("privateBrowsingItem");
pbMenuItem.setAttribute("label", pbMenuItem.getAttribute(aMode + "label"));
pbMenuItem.setAttribute("accesskey", pbMenuItem.getAttribute(aMode + "accesskey"));
},
@@ -7119,19 +7165,21 @@ var LightWeightThemeWebInstaller = {
callback: function () {
LightWeightThemeWebInstaller._install(data);
}
}];
this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox();
- notificationBox.appendNotification(message, "lwtheme-install-request", "",
- notificationBox.PRIORITY_INFO_MEDIUM,
- buttons);
+ var notificationBar =
+ notificationBox.appendNotification(message, "lwtheme-install-request", "",
+ notificationBox.PRIORITY_INFO_MEDIUM,
+ buttons);
+ notificationBar.persistence = 1;
},
_install: function (newTheme) {
var previousTheme = this._manager.currentTheme;
this._manager.currentTheme = newTheme;
if (this._manager.currentTheme &&
this._manager.currentTheme.id == newTheme.id)
this._postInstallNotification(newTheme, previousTheme);
@@ -7155,20 +7203,23 @@ var LightWeightThemeWebInstaller = {
callback: function () {
BrowserOpenAddonsMgr("themes");
}
}];
this._removePreviousNotifications();
var notificationBox = gBrowser.getNotificationBox();
- notificationBox.appendNotification(text("message"),
- "lwtheme-install-notification", "",
- notificationBox.PRIORITY_INFO_MEDIUM,
- buttons);
+ var notificationBar =
+ notificationBox.appendNotification(text("message"),
+ "lwtheme-install-notification", "",
+ notificationBox.PRIORITY_INFO_MEDIUM,
+ buttons);
+ notificationBar.persistence = 1;
+ notificationBar.timeout = Date.now() + 20000; // 20 seconds
},
_removePreviousNotifications: function () {
var box = gBrowser.getNotificationBox();
["lwtheme-install-request",
"lwtheme-install-notification"].forEach(function (value) {
var notification = box.getNotificationWithValue(value);
@@ -7227,49 +7278,12 @@ var LightWeightThemeWebInstaller = {
}
});
var uri = node.ownerDocument.documentURIObject;
return pm.testPermission(uri, "install") == pm.ALLOW_ACTION;
},
_getThemeFromNode: function (node) {
- const MANDATORY = ["id", "name", "headerURL"];
- const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
- "previewURL", "author", "description", "homepageURL"];
-
- try {
- var data = JSON.parse(node.getAttribute("data-browsertheme"));
- } catch (e) {
- return null;
- }
-
- if (!data || typeof data != "object")
- return null;
-
- for (let prop in data) {
- if (!data[prop] ||
- typeof data[prop] != "string" ||
- MANDATORY.indexOf(prop) == -1 && OPTIONAL.indexOf(prop) == -1) {
- delete data[prop];
- continue;
- }
-
- if (/URL$/.test(prop)) {
- try {
- data[prop] = makeURLAbsolute(node.baseURI, data[prop]);
-
- if (/^https?:/.test(data[prop]))
- continue;
- } catch (e) {}
-
- delete data[prop];
- }
- }
-
- for (let i = 0; i < MANDATORY.length; i++) {
- if (!(MANDATORY[i] in data))
- return null;
- }
-
- return data;
+ return this._manager.parseTheme(node.getAttribute("data-browsertheme"),
+ node.baseURI);
}
}
--- a/browser/base/content/openLocationLastURL.jsm
+++ b/browser/base/content/openLocationLastURL.jsm
@@ -48,23 +48,31 @@ let observer = {
QueryInterface: function (aIID) {
if (aIID.equals(Components.interfaces.nsIObserver) ||
aIID.equals(Components.interfaces.nsISupports) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference))
return this;
throw Components.results.NS_NOINTERFACE;
},
observe: function (aSubject, aTopic, aData) {
- gOpenLocationLastURLData = "";
+ switch (aTopic) {
+ case "private-browsing":
+ gOpenLocationLastURLData = "";
+ break;
+ case "browser:purge-session-history":
+ gOpenLocationLastURL.reset();
+ break;
+ }
}
};
-Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService)
- .addObserver(observer, "private-browsing", true);
+let os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+os.addObserver(observer, "private-browsing", true);
+os.addObserver(observer, "browser:purge-session-history", true);
let gOpenLocationLastURLData = "";
let gOpenLocationLastURL = {
get value() {
if (pbSvc.privateBrowsingEnabled)
return gOpenLocationLastURLData;
else {
try {
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -80,17 +80,17 @@ pageInfoTreeView.prototype = {
{
this.data[row][column.index] = value;
},
addRow: function(row)
{
this.rows = this.data.push(row);
this.rowCountChanged(this.rows - 1, 1);
- if (this.selection.count == 0 && this.rowCount)
+ if (this.selection.count == 0 && this.rowCount && !gImageElement)
this.selection.select(0);
},
rowCountChanged: function(index, count)
{
this.tree.rowCountChanged(index, count);
},
--- a/browser/base/content/test/browser_bug441778.js
+++ b/browser/base/content/test/browser_bug441778.js
@@ -35,70 +35,43 @@
*
* ***** END LICENSE BLOCK ***** */
/*
* Test the fix for bug 441778 to ensure site-specific page zoom doesn't get
* modified by sub-document loads of content from a different domain.
*/
-let testPage = 'data:text/html,<body><iframe id="a" src=""></iframe></body>';
-
function test() {
waitForExplicitFinish();
- // The zoom level before the sub-document load. We set this in continueTest
- // and then compare it to the current zoom level in finishTest to make sure
- // it hasn't changed.
- let zoomLevel;
+ const TEST_PAGE_URL = 'data:text/html,<body><iframe src=""></iframe></body>';
+ const TEST_IFRAME_URL = "http://test2.example.org/";
// Prepare the test tab
gBrowser.selectedTab = gBrowser.addTab();
let testBrowser = gBrowser.selectedBrowser;
- let finishTest = function() {
- testBrowser.removeProgressListener(progressListener);
- is(ZoomManager.zoom, zoomLevel, "zoom is retained after sub-document load");
- gBrowser.removeCurrentTab();
- finish();
- };
+ testBrowser.addEventListener("load", function () {
+ testBrowser.removeEventListener("load", arguments.callee, true);
- let progressListener = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
- Ci.nsISupportsWeakReference]),
- onStateChange: function() {},
- onProgressChange: function() {},
- onLocationChange: function() {
- window.setTimeout(finishTest, 0);
- },
- onStatusChange: function() {},
- onSecurityChange: function() {}
- };
-
- let continueTest = function() {
// Change the zoom level and then save it so we can compare it to the level
// after loading the sub-document.
FullZoom.enlarge();
- zoomLevel = ZoomManager.zoom;
-
- // Finish the test in a timeout after the sub-document location change
- // to give the zoom controller time to respond to it.
- testBrowser.addProgressListener(progressListener);
+ var zoomLevel = ZoomManager.zoom;
// Start the sub-document load.
- content.document.getElementById("a").src = "http://test2.example.org/";
- };
+ executeSoon(function () {
+ testBrowser.addEventListener("load", function (e) {
+ testBrowser.removeEventListener("load", arguments.callee, true);
+
+ is(e.target.defaultView.location, TEST_IFRAME_URL, "got the load event for the iframe");
+ is(ZoomManager.zoom, zoomLevel, "zoom is retained after sub-document load");
- // Continue the test after the test page has loaded.
- // Note: in order for the sub-document load to trigger a location change
- // the way it does under real world usage scenarios, we have to continue
- // the test in a timeout for some unknown reason.
- let continueListener = function() {
- window.setTimeout(continueTest, 0);
-
- // Remove the load listener so it doesn't get called for the sub-document.
- testBrowser.removeEventListener("load", continueListener, true);
- };
- testBrowser.addEventListener("load", continueListener, true);
+ gBrowser.removeCurrentTab();
+ finish();
+ }, true);
+ content.document.querySelector("iframe").src = TEST_IFRAME_URL;
+ });
+ }, true);
- // Start the test by loading the test page.
- testBrowser.contentWindow.location = testPage;
+ content.location = TEST_PAGE_URL;
}
--- a/browser/base/content/test/browser_bug517902.js
+++ b/browser/base/content/test/browser_bug517902.js
@@ -26,13 +26,13 @@ function test() {
finish();
});
});
}, true);
}, true);
content.location =
"data:text/html," +
+ "<img src='about:logo?b' height=300 width=350 alt=2>" +
"<img src='about:logo?a' height=200 width=250>" +
"<img src='about:logo?b' height=200 width=250 alt=1>" +
- "<img src='about:logo?b' height=200 width=250 alt=2>" +
"<img src='about:logo?b' height=100 width=150 alt=2 id='test-image'>";
}
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -470,27 +470,27 @@ function buildHelpMenu()
// Enable/disable the "Report Web Forgery" menu item. safebrowsing object
// may not exist in OSX
if (typeof safebrowsing != "undefined")
safebrowsing.setReportPhishingMenu();
#ifdef MOZ_UPDATER
var updates =
Components.classes["@mozilla.org/updates/update-service;1"].
- getService(Components.interfaces.nsIApplicationUpdateService);
+ getService(Components.interfaces.nsIApplicationUpdateService2);
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 checkForUpdates = document.getElementById("checkForUpdates");
- var canUpdate = updates.canUpdate;
- checkForUpdates.setAttribute("disabled", !canUpdate);
- if (!canUpdate)
+ var canCheckForUpdates = updates.canCheckForUpdates;
+ checkForUpdates.setAttribute("disabled", !canCheckForUpdates);
+ if (!canCheckForUpdates)
return;
var strings = document.getElementById("bundle_browser");
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) {
--- a/browser/components/Makefile.in
+++ b/browser/components/Makefile.in
@@ -30,65 +30,65 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-DEPTH = ../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = browsercomps
XPIDL_MODULE = browsercompsbase
XPIDLSRCS = \
- nsIBrowserHandler.idl \
- nsIBrowserGlue.idl \
- $(NULL)
+ nsIBrowserGlue.idl \
+ nsIBrowserHandler.idl \
+ $(NULL)
EXTRA_PP_COMPONENTS = \
- nsBrowserContentHandler.js \
- nsBrowserGlue.js \
- $(NULL)
+ nsBrowserContentHandler.js \
+ nsBrowserGlue.js \
+ $(NULL)
EXTRA_JS_MODULES = distribution.js
-DIRS = \
- about \
- certerror \
- dirprovider \
- microsummaries \
- preferences \
- search \
- sessionstore \
- shell \
- sidebar \
- feeds \
- places \
- privatebrowsing \
- $(NULL)
+PARALLEL_DIRS = \
+ about \
+ certerror \
+ dirprovider \
+ feeds \
+ microsummaries \
+ places \
+ preferences \
+ privatebrowsing \
+ search \
+ sessionstore \
+ shell \
+ sidebar \
+ $(NULL)
ifndef WINCE
-DIRS += migration
+PARALLEL_DIRS += migration
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifndef WINCE
-DIRS += wintaskbar
+PARALLEL_DIRS += wintaskbar
endif
endif
ifdef MOZ_SAFE_BROWSING
-DIRS += safebrowsing
+PARALLEL_DIRS += safebrowsing
endif
DIRS += build
ifdef MOZILLA_OFFICIAL
DEFINES += -DOFFICIAL_BUILD=1
endif
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -505,18 +505,25 @@
return;
node = node.parentNode;
}
#endif
if (window.XULBrowserWindow) {
var nodeItem = event.target.node;
+
+ var linkURI;
if (nodeItem && PlacesUtils.nodeIsURI(nodeItem))
- window.XULBrowserWindow.setOverLink(nodeItem.uri, null);
+ linkURI = nodeItem.uri;
+ else if (node.hasAttribute("targetURI"))
+ linkURI = node.getAttribute("targetURI");
+
+ if (linkURI)
+ window.XULBrowserWindow.setOverLink(linkURI, null);
}
]]></handler>
<handler event="DOMMenuItemInactive"><![CDATA[
var node = event.target;
if (node.parentNode != this)
return;
if (window.XULBrowserWindow)
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -1193,17 +1193,17 @@ var PlacesUIUtils = {
return true;
}
catch(e) {
return false;
}
}
// Get all items marked as being the left pane folder.
- let items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
+ let items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
if (items.length > 1) {
// Something went wrong, we cannot have more than one left pane folder,
// remove all left pane folders and continue. We will create a new one.
items.forEach(safeRemoveItem);
}
else if (items.length == 1 && items[0] != -1) {
leftPaneRoot = items[0];
@@ -1218,17 +1218,17 @@ var PlacesUIUtils = {
if (leftPaneRoot != -1) {
// A valid left pane folder has been found.
// Build the leftPaneQueries Map. This is used to quickly access them,
// associating a mnemonic name to the real item ids.
delete this.leftPaneQueries;
this.leftPaneQueries = {};
- let items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO, {});
+ let items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO);
// While looping through queries we will also check for their validity.
let queriesCount = 0;
for(let i = 0; i < items.length; i++) {
let queryName = as.getItemAnnotation(items[i], ORGANIZER_QUERY_ANNO);
// Some extension did use our annotation to decorate their items
// with icons, so we should check only our elements, to avoid dataloss.
if (!(queryName in queries))
continue;
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -69,24 +69,30 @@ String.prototype.hasRootDomain = functio
////////////////////////////////////////////////////////////////////////////////
//// Constants
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
+const STATE_IDLE = 0;
+const STATE_TRANSITION_STARTED = 1;
+const STATE_WAITING_FOR_RESTORE = 2;
+const STATE_RESTORE_FINISHED = 3;
+
////////////////////////////////////////////////////////////////////////////////
//// PrivateBrowsingService
function PrivateBrowsingService() {
this._obs.addObserver(this, "profile-after-change", true);
this._obs.addObserver(this, "quit-application-granted", true);
this._obs.addObserver(this, "private-browsing", true);
this._obs.addObserver(this, "command-line-startup", true);
+ this._obs.addObserver(this, "sessionstore-browser-state-restored", true);
}
PrivateBrowsingService.prototype = {
// Observer Service
__obs: null,
get _obs() {
if (!this.__obs)
this.__obs = Cc["@mozilla.org/observer-service;1"].
@@ -110,18 +116,18 @@ PrivateBrowsingService.prototype = {
_savedBrowserState: null,
// Whether we're in the process of shutting down
_quitting: false,
// How to treat the non-private session
_saveSession: true,
- // Make sure we don't allow re-enterant changing of the private mode
- _alreadyChangingMode: false,
+ // The current status of the private browsing service
+ _currentStatus: STATE_IDLE,
// Whether the private browsing mode has been started automatically (ie. always-on)
_autoStarted: false,
// List of view source window URIs for restoring later
_viewSrcURLs: [],
// List of nsIXULWindows we are going to be closing during the transition
@@ -229,16 +235,17 @@ PrivateBrowsingService.prototype = {
// nothing to do here if we're enabling at startup or the current session is being
// used
if (!this._autoStarted && this._saveSession) {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
// if we have transitioned out of private browsing mode and the session is
// to be restored, do it now
if (!this._inPrivateBrowsing) {
+ this._currentStatus = STATE_WAITING_FOR_RESTORE;
ss.setBrowserState(this._savedBrowserState);
this._savedBrowserState = null;
this._closePageInfoWindows();
// re-open all view-source windows
let windowWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
@@ -270,21 +277,45 @@ PrivateBrowsingService.prototype = {
"entries": [{
"url": "about:privatebrowsing"
}]
}],
"_closedTabs": []
}]
};
// Transition into private browsing mode
+ this._currentStatus = STATE_WAITING_FOR_RESTORE;
ss.setBrowserState(JSON.stringify(privateBrowsingState));
}
}
},
+ _notifyIfTransitionComplete: function PBS__notifyIfTransitionComplete() {
+ switch (this._currentStatus) {
+ case STATE_TRANSITION_STARTED:
+ // no session store operation was needed, so just notify of transition completion
+ case STATE_RESTORE_FINISHED:
+ // restore has been completed
+ this._currentStatus = STATE_IDLE;
+ this._obs.notifyObservers(null, "private-browsing-transition-complete", "");
+ break;
+ case STATE_WAITING_FOR_RESTORE:
+ // too soon to notify...
+ break;
+ case STATE_IDLE:
+ // no need to notify
+ break;
+ default:
+ // unexpected state observed
+ Cu.reportError("Unexpected private browsing status reached: " +
+ this._currentStatus);
+ break;
+ }
+ },
+
_canEnterPrivateBrowsingMode: function PBS__canEnterPrivateBrowsingMode() {
let cancelEnter = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool);
cancelEnter.data = false;
this._obs.notifyObservers(cancelEnter, "private-browsing-cancel-vote", "enter");
return !cancelEnter.data;
},
@@ -377,16 +408,22 @@ PrivateBrowsingService.prototype = {
consoleService.reset();
}
break;
case "command-line-startup":
this._obs.removeObserver(this, "command-line-startup");
aSubject.QueryInterface(Ci.nsICommandLine);
this.handle(aSubject);
break;
+ case "sessionstore-browser-state-restored":
+ if (this._currentStatus == STATE_WAITING_FOR_RESTORE) {
+ this._currentStatus = STATE_RESTORE_FINISHED;
+ this._notifyIfTransitionComplete();
+ }
+ break;
}
},
// nsICommandLineHandler
handle: function PBS_handle(aCmdLine) {
if (aCmdLine.handleFlag("private", false)) {
this.privateBrowsingEnabled = true;
@@ -411,21 +448,21 @@ PrivateBrowsingService.prototype = {
* Enter or leave private browsing mode.
*/
set privateBrowsingEnabled PBS_set_privateBrowsingEnabled(val) {
// Allowing observers to set the private browsing status from their
// notification handlers is not desired, because it will change the
// status of the service while it's in the process of another transition.
// So, we detect a reentrant call here and throw an error.
// This is documented in nsIPrivateBrowsingService.idl.
- if (this._alreadyChangingMode)
+ if (this._currentStatus != STATE_IDLE)
throw Cr.NS_ERROR_FAILURE;
try {
- this._alreadyChangingMode = true;
+ this._currentStatus = STATE_TRANSITION_STARTED;
if (val != this._inPrivateBrowsing) {
if (val) {
if (!this._canEnterPrivateBrowsingMode())
return;
}
else {
if (!this._canLeavePrivateBrowsingMode())
@@ -460,17 +497,17 @@ PrivateBrowsingService.prototype = {
for (let i = 0; i < this._windowsToClose.length; i++)
this._windowsToClose[i].docShell.contentViewer.resetCloseWindow();
// We don't log an error when the transition is canceled from beforeunload
if (ex != Cr.NS_ERROR_ABORT)
Cu.reportError("Exception thrown while processing the " +
"private browsing mode change request: " + ex.toString());
} finally {
this._windowsToClose = [];
- this._alreadyChangingMode = false;
+ this._notifyIfTransitionComplete();
}
},
/**
* Whether private browsing has been started automatically.
*/
get autoStarted PBS_get_autoStarted() {
return this._inPrivateBrowsing && this._autoStarted;
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_console_clear.js \
browser_privatebrowsing_beforeunload.js \
browser_privatebrowsing_certexceptionsui.js \
browser_privatebrowsing_crh.js \
browser_privatebrowsing_downloadmonitor.js \
+ browser_privatebrowsing_fastswitch.js \
browser_privatebrowsing_findbar.js \
browser_privatebrowsing_forgetthissite.js \
browser_privatebrowsing_geoprompt.js \
browser_privatebrowsing_geoprompt_page.html \
browser_privatebrowsing_import.js \
browser_privatebrowsing_opendir.js \
browser_privatebrowsing_openlocation.js \
browser_privatebrowsing_pageinfo.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_fastswitch.js
@@ -0,0 +1,90 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 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 ***** */
+
+// This test makes sure that users are prevented from toggling the private
+// browsing mode too quickly, hence be proctected from symptoms in bug 526194.
+
+function test() {
+ // initialization
+ let pb = Cc["@mozilla.org/privatebrowsing;1"].
+ getService(Ci.nsIPrivateBrowsingService);
+ let os = Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService);
+ let ss = Cc["@mozilla.org/browser/sessionstore;1"].
+ getService(Ci.nsISessionStore);
+ let pbCmd = document.getElementById("Tools:PrivateBrowsing");
+ waitForExplicitFinish();
+
+ let observer = {
+ pass: 1,
+ observe: function(aSubject, aTopic, aData) {
+ switch (aTopic) {
+ case "private-browsing":
+ setTimeout(function() {
+ ok(document.getElementById("Tools:PrivateBrowsing").hasAttribute("disabled"),
+ "The private browsing command should be disabled immediately after the mode switch");
+ }, 0);
+ break;
+
+ case "private-browsing-transition-complete":
+ if (this.pass++ == 1) {
+ setTimeout(function() {
+ ok(!pbCmd.hasAttribute("disabled"),
+ "The private browsing command should be re-enabled after entering the private browsing mode");
+
+ pb.privateBrowsingEnabled = false;
+ }, 100);
+ }
+ else {
+ setTimeout(function() {
+ ok(!pbCmd.hasAttribute("disabled"),
+ "The private browsing command should be re-enabled after exiting the private browsing mode");
+
+ os.removeObserver(observer, "private-browsing");
+ os.removeObserver(observer, "private-browsing-transition-complete");
+ finish();
+ }, 100);
+ }
+ break;
+ }
+ }
+ };
+ os.addObserver(observer, "private-browsing", false);
+ os.addObserver(observer, "private-browsing-transition-complete", false);
+
+ pb.privateBrowsingEnabled = true;
+}
--- a/browser/components/privatebrowsing/test/unit/do_test_privatebrowsing_exit.js
+++ b/browser/components/privatebrowsing/test/unit/do_test_privatebrowsing_exit.js
@@ -39,19 +39,16 @@
// shutdown.
function do_test() {
// initialization
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
var expectedQuitting;
var called = 0;
var observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == kPrivateBrowsingNotification &&
aData == kExit) {
// increment the call counter
@@ -64,17 +61,16 @@ function do_test() {
do_throw("aSubject was not null, but wasn't an nsISupportsPRBool");
}
// check the "quitting" argument
do_check_eq(aSubject.data, expectedQuitting);
// finish up the test
if (expectedQuitting) {
os.removeObserver(this, kPrivateBrowsingNotification);
- prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
do_test_finished();
}
}
}
};
// set the observer
os.addObserver(observer, kPrivateBrowsingNotification, false);
--- a/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
+++ b/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js
@@ -37,16 +37,17 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const kPrivateBrowsingNotification = "private-browsing";
const kPrivateBrowsingCancelVoteNotification = "private-browsing-cancel-vote";
+const kPrivateBrowsingTransitionCompleteNotification = "private-browsing-transition-complete";
const kEnter = "enter";
const kExit = "exit";
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
const NS_APP_HISTORY_50_FILE = "UHist";
function LOG(aMsg) {
aMsg = ("*** PRIVATEBROWSING TESTS: " + aMsg);
@@ -89,16 +90,21 @@ if (!profileDir) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
}
+// Do not attempt to restore any session since we don't have any windows
+Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch).
+ setBoolPref("browser.privatebrowsing.keep_current_session", true);
+
/**
* Removes any files that could make our tests fail.
*/
function cleanUp()
{
let files = [
"downloads.sqlite",
"places.sqlite",
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/unit/tail_privatebrowsing.js
@@ -0,0 +1,41 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ehsan Akhgari <ehsan@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Be neat: clear the pref that we have set
+Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch).
+ clearUserPref("browser.privatebrowsing.keep_current_session");
--- a/browser/components/privatebrowsing/test/unit/test_0-privatebrowsing.js
+++ b/browser/components/privatebrowsing/test/unit/test_0-privatebrowsing.js
@@ -40,19 +40,16 @@
// This test should run before the rest of private browsing service unit tests,
// hence the naming used for this file.
function run_test_on_service() {
// initialization
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
// the contract ID should be available
do_check_true(PRIVATEBROWSING_CONTRACT_ID in Cc);
// the interface should be available
do_check_true("nsIPrivateBrowsingService" in Ci);
// it should be possible to initialize the component
@@ -215,15 +212,35 @@ function run_test_on_service() {
"enter phase 1",
kPrivateBrowsingNotification + " " + kEnter,
kPrivateBrowsingCancelVoteNotification + " " + kExit,
"enter phase 2",
kPrivateBrowsingNotification + " " + kExit,
];
do_check_eq(observer.notifications.join(","), reference_order.join(","));
- prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
+ // make sure that the private browsing transition complete notification is
+ // raised correctly.
+ observer = {
+ observe: function(aSubject, aTopic, aData) {
+ this.notifications.push(aTopic + " " + aData);
+ },
+ notifications: []
+ };
+ os.addObserver(observer, kPrivateBrowsingNotification, false);
+ os.addObserver(observer, kPrivateBrowsingTransitionCompleteNotification, false);
+ pb.privateBrowsingEnabled = true;
+ pb.privateBrowsingEnabled = false;
+ os.removeObserver(observer, kPrivateBrowsingNotification);
+ os.removeObserver(observer, kPrivateBrowsingTransitionCompleteNotification);
+ reference_order = [
+ kPrivateBrowsingNotification + " " + kEnter,
+ kPrivateBrowsingTransitionCompleteNotification + " ",
+ kPrivateBrowsingNotification + " " + kExit,
+ kPrivateBrowsingTransitionCompleteNotification + " ",
+ ];
+ do_check_eq(observer.notifications.join(","), reference_order.join(","));
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}
--- a/browser/components/privatebrowsing/test/unit/test_aboutprivatebrowsing.js
+++ b/browser/components/privatebrowsing/test/unit/test_aboutprivatebrowsing.js
@@ -58,36 +58,29 @@ function is_about_privatebrowsing_availa
return false;
}
function run_test_on_service() {
// initialization
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
- try {
- // about:privatebrowsing should be available before entering the private mode
- do_check_true(is_about_privatebrowsing_available());
+ // about:privatebrowsing should be available before entering the private mode
+ do_check_true(is_about_privatebrowsing_available());
- // enter the private browsing mode
- pb.privateBrowsingEnabled = true;
+ // enter the private browsing mode
+ pb.privateBrowsingEnabled = true;
- // about:privatebrowsing should be available inside the private mode
- do_check_true(is_about_privatebrowsing_available());
-
- // exit the private browsing mode
- pb.privateBrowsingEnabled = false;
+ // about:privatebrowsing should be available inside the private mode
+ do_check_true(is_about_privatebrowsing_available());
- // about:privatebrowsing should be available after leaving the private mode
- do_check_true(is_about_privatebrowsing_available());
- } finally {
- prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
- }
+ // exit the private browsing mode
+ pb.privateBrowsingEnabled = false;
+
+ // about:privatebrowsing should be available after leaving the private mode
+ do_check_true(is_about_privatebrowsing_available());
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}
--- a/browser/components/privatebrowsing/test/unit/test_httpauth.js
+++ b/browser/components/privatebrowsing/test/unit/test_httpauth.js
@@ -34,20 +34,16 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// This test makes sure the HTTP authenticated sessions are correctly cleared
// when entering and leaving the private browsing mode.
function run_test_on_service() {
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
var am = Cc["@mozilla.org/network/http-auth-manager;1"].
getService(Ci.nsIHttpAuthManager);
const kHost1 = "pbtest3.example.com";
const kHost2 = "pbtest4.example.com";
@@ -103,17 +99,15 @@ function run_test_on_service() {
do_throw("Auth entry should not be retrievable after exiting the private browsing mode");
} catch (e) {
do_check_eq(domain.value, kEmpty);
do_check_eq(user.value, kEmpty);
do_check_eq(pass.value, kEmpty);
}
} catch (e) {
do_throw("Unexpected exception while testing HTTP auth manager: " + e);
- } finally {
- prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
}
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}
--- a/browser/components/privatebrowsing/test/unit/test_openLocationLastURL.js
+++ b/browser/components/privatebrowsing/test/unit/test_openLocationLastURL.js
@@ -38,16 +38,23 @@
function run_test_on_service()
{
let Cc = Components.classes;
let Ci = Components.interfaces;
let Cu = Components.utils;
Cu.import("resource:///modules/openLocationLastURL.jsm");
+ function clearHistory() {
+ // simulate clearing the private data
+ Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService).
+ notifyObservers(null, "browser:purge-session-history", "");
+ }
+
let pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
let pref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
gOpenLocationLastURL.reset();
do_check_eq(typeof gOpenLocationLastURL, "object");
do_check_eq(gOpenLocationLastURL.value, "");
@@ -59,26 +66,39 @@ function run_test_on_service()
do_check_eq(gOpenLocationLastURL.value, url1);
gOpenLocationLastURL.value = "";
do_check_eq(gOpenLocationLastURL.value, "");
gOpenLocationLastURL.value = url2;
do_check_eq(gOpenLocationLastURL.value, url2);
+ clearHistory();
+ do_check_eq(gOpenLocationLastURL.value, "");
+ gOpenLocationLastURL.value = url2;
+
pb.privateBrowsingEnabled = true;
do_check_eq(gOpenLocationLastURL.value, "");
pb.privateBrowsingEnabled = false;
do_check_eq(gOpenLocationLastURL.value, url2);
pb.privateBrowsingEnabled = true;
gOpenLocationLastURL.value = url1;
do_check_eq(gOpenLocationLastURL.value, url1);
pb.privateBrowsingEnabled = false;
do_check_eq(gOpenLocationLastURL.value, url2);
+
+ pb.privateBrowsingEnabled = true;
+ gOpenLocationLastURL.value = url1;
+ do_check_neq(gOpenLocationLastURL.value, "");
+ clearHistory();
+ do_check_eq(gOpenLocationLastURL.value, "");
+
+ pb.privateBrowsingEnabled = false;
+ do_check_eq(gOpenLocationLastURL.value, "");
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}
--- a/browser/components/privatebrowsing/test/unit/test_transition_nooffline.js
+++ b/browser/components/privatebrowsing/test/unit/test_transition_nooffline.js
@@ -39,19 +39,16 @@
// the offline status (see bug 463256).
function run_test_on_service() {
// initialization
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
- prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
var observer = {
observe: function (aSubject, aTopic, aData) {
if (aTopic == "network:offline-status-changed")
this.events.push(aData);
},
events: []
};
@@ -61,15 +58,14 @@ function run_test_on_service() {
pb.privateBrowsingEnabled = true;
do_check_eq(observer.events.length, 0);
// leave the private browsing mode, and wait for the SSL page to load again
pb.privateBrowsingEnabled = false;
do_check_eq(observer.events.length, 0);
os.removeObserver(observer, "network:offline-status-changed", false);
- prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -105,16 +105,20 @@ eg: browser.docShell["allow" + aCapabili
XXX keep these in sync with all the attributes starting
with "allow" in /docshell/base/nsIDocShell.idl
*/
const CAPABILITIES = [
"Subframes", "Plugins", "Javascript", "MetaRedirects", "Images",
"DNSPrefetch", "Auth"
];
+#ifndef XP_WIN
+#define BROKEN_WM_Z_ORDER
+#endif
+
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function debug(aMsg) {
aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
.logStringMessage(aMsg);
}
@@ -177,16 +181,19 @@ SessionStoreService.prototype = {
_recentCrashes: 0,
// whether we are in private browsing mode
_inPrivateBrowsing: false,
// whether we clearing history on shutdown
_clearingOnShutdown: false,
+ // List of windows that are being closed during setBrowserState.
+ _closingWindows: [],
+
#ifndef XP_MACOSX
// whether the last window was closed and should be restored
_restoreLastWindow: false,
#endif
/* ........ Global Event Handlers .............. */
/**
@@ -331,16 +338,24 @@ SessionStoreService.prototype = {
switch (aTopic) {
case "domwindowopened": // catch new windows
aSubject.addEventListener("load", function(aEvent) {
aEvent.currentTarget.removeEventListener("load", arguments.callee, false);
_this.onLoad(aEvent.currentTarget);
}, false);
break;
case "domwindowclosed": // catch closed windows
+ if (this._closingWindows.length > 0) {
+ let index = this._closingWindows.indexOf(aSubject);
+ if (index != -1) {
+ this._closingWindows.splice(index, 1);
+ if (this._closingWindows.length == 0)
+ this._sendRestoreCompletedNotifications(true);
+ }
+ }
this.onClose(aSubject);
break;
case "quit-application-requested":
// get a current snapshot of all windows
this._forEachBrowserWindow(function(aWindow) {
this._collectWindowData(aWindow);
});
this._dirtyWindows = [];
@@ -895,29 +910,31 @@ SessionStoreService.prototype = {
var window = this._getMostRecentBrowserWindow();
if (!window) {
this._restoreCount = 1;
this._openWindowWithState(state);
return;
}
- // close all other browser windows
- this._forEachBrowserWindow(function(aWindow) {
- if (aWindow != window) {
- aWindow.close();
- }
- });
-
// make sure closed window data isn't kept
this._closedWindows = [];
// determine how many windows are meant to be restored
this._restoreCount = state.windows ? state.windows.length : 0;
+ var self = this;
+ // close all other browser windows
+ this._forEachBrowserWindow(function(aWindow) {
+ if (aWindow != window) {
+ self._closingWindows.push(aWindow);
+ aWindow.close();
+ }
+ });
+
// restore to the given state
this.restoreWindow(window, state, true);
},
getWindowState: function sss_getWindowState(aWindow) {
if (!aWindow.__SSi && !aWindow.__SS_dyingCache)
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
@@ -1186,25 +1203,26 @@ SessionStoreService.prototype = {
if (!aFullData)
browser.__SS_data = tabData;
}
else if (browser.currentURI.spec != "about:blank" ||
browser.contentDocument.body.hasChildNodes()) {
tabData.entries[0] = { url: browser.currentURI.spec };
tabData.index = 1;
}
- else if (browser.currentURI.spec == "about:blank" &&
- browser.userTypedValue) {
- // This can happen if the user opens a lot of tabs simultaneously and we
- // try to save state before all of them are properly loaded. If we crash
- // then we get a bunch of about:blank tabs which isn't what we want.
- tabData.entries[0] = { url: browser.userTypedValue };
- tabData.index = 1;
+
+ // If there is a userTypedValue set, then either the user has typed something
+ // in the URL bar, or a new tab was opened with a URI to load. userTypedClear
+ // is used to indicate whether the tab was in some sort of loading state with
+ // userTypedValue.
+ if (browser.userTypedValue) {
+ tabData.userTypedValue = browser.userTypedValue;
+ tabData.userTypedClear = browser.userTypedClear;
}
-
+
var disallow = [];
for (var i = 0; i < CAPABILITIES.length; i++)
if (!browser.docShell["allow" + CAPABILITIES[i]])
disallow.push(CAPABILITIES[i]);
if (disallow.length > 0)
tabData.disallow = disallow.join(",");
else if (tabData.disallow)
delete tabData.disallow;
@@ -2117,17 +2135,25 @@ SessionStoreService.prototype = {
// (mainly scroll state and text data)
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
browser.__SS_restore_text = tabData.text || "";
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
browser.__SS_restore_tab = tab;
browser.__SS_restore = this.restoreDocument_proxy;
browser.addEventListener("load", browser.__SS_restore, true);
}
-
+
+ // Handle userTypedValue. Setting userTypedValue seems to update gURLbar
+ // as needed. Calling loadURI will cancel form filling in restoreDocument_proxy
+ if (tabData.userTypedValue) {
+ browser.userTypedValue = tabData.userTypedValue;
+ if (tabData.userTypedClear)
+ browser.loadURI(tabData.userTypedValue, null, null, true);
+ }
+
aWindow.setTimeout(function(){ _this.restoreHistory(aWindow, aTabs, aTabData, aIdMap); }, 0);
},
/**
* expands serialized history data into a session-history-entry instance
* @param aEntry
* Object containing serialized history data for a URL
* @param aIdMap
@@ -2593,30 +2619,55 @@ SessionStoreService.prototype = {
*/
_forEachBrowserWindow: function sss_forEachBrowserWindow(aFunc) {
var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var windowsEnum = windowMediator.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
var window = windowsEnum.getNext();
- if (window.__SSi) {
+ if (window.__SSi && !window.closed) {
aFunc.call(this, window);
}
}
},
/**
* Returns most recent window
* @returns Window reference
*/
_getMostRecentBrowserWindow: function sss_getMostRecentBrowserWindow() {
- var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
- getService(Ci.nsIWindowMediator);
- return windowMediator.getMostRecentWindow("navigator:browser");
+ var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
+ getService(Ci.nsIWindowMediator);
+
+ var win = wm.getMostRecentWindow("navigator:browser");
+ if (!win)
+ return null;
+ if (!win.closed)
+ return win;
+
+#ifdef BROKEN_WM_Z_ORDER
+ win = null;
+ var windowsEnum = wm.getEnumerator("navigator:browser");
+ // this is oldest to newest, so this gets a bit ugly
+ while (windowsEnum.hasMoreElements()) {
+ let nextWin = windowsEnum.getNext();
+ if (!nextWin.closed)
+ win = nextWin;
+ }
+ return win;
+#else
+ var windowsEnum = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
+ while (windowsEnum.hasMoreElements()) {
+ win = windowsEnum.getNext();
+ if (!win.closed)
+ return win;
+ }
+ return null;
+#endif
},
/**
* open a new browser window for a given session state
* called when restoring a multi-window session
* @param aState
* Object containing session data
*/
@@ -2820,26 +2871,27 @@ SessionStoreService.prototype = {
// instead of evalInSandbox everywhere
jsonString = jsonString.replace(/[\u2028\u2029]/g,
function($0) "\\u" + $0.charCodeAt(0).toString(16));
}
return jsonString;
},
- _sendRestoreCompletedNotifications: function sss_sendRestoreCompletedNotifications() {
- if (this._restoreCount) {
+ _sendRestoreCompletedNotifications:
+ function sss_sendRestoreCompletedNotifications(aOnWindowClose) {
+ if (this._restoreCount && !aOnWindowClose)
this._restoreCount--;
- if (this._restoreCount == 0) {
- // This was the last window restored at startup, notify observers.
- this._observerService.notifyObservers(null,
- this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
- "");
- this._browserSetState = false;
- }
+
+ if (this._restoreCount == 0 && this._closingWindows.length == 0) {
+ // This was the last window restored at startup, notify observers.
+ this._observerService.notifyObservers(null,
+ this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
+ "");
+ this._browserSetState = false;
}
},
/**
* @param aWindow
* Window reference
* @returns whether this window's data is still cached in _statesToRestore
* because it's not fully loaded yet
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -40,19 +40,16 @@ DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/sessionstore/test/browser
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
-# browser_477657.js is disabled, because it's unreliable (bug 482975).
-# browser_480148.js is disabled, because it breaks browser_420786.js (see bug 483382).
-
_BROWSER_TEST_FILES = \
browser_248970_a.js \
browser_248970_b.js \
browser_248970_b_sample.html \
browser_339445.js \
browser_339445_sample.html \
browser_345898.js \
browser_346337.js \
@@ -92,24 +89,27 @@ include $(topsrcdir)/config/rules.mk
browser_464620_b.html \
browser_464620_xd.html \
browser_465215.js \
browser_465223.js \
browser_466937.js \
browser_466937_sample.html \
browser_476161.js \
browser_476161_sample.html \
+ browser_477657.js \
+ browser_480148.js \
browser_480893.js \
browser_483330.js \
browser_485482.js \
browser_485482_sample.html \
browser_485563.js \
browser_490040.js \
browser_491168.js \
browser_491577.js \
browser_493467.js \
browser_495495.js \
browser_514751.js \
+ browser_522545.js \
browser_526613.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/sessionstore/test/browser/browser_354894.js
+++ b/browser/components/sessionstore/test/browser/browser_354894.js
@@ -99,17 +99,32 @@
* @note Mac only tests the new notifications, as restoring the last window is
* not enabled on that platform (platform shim; the application is kept running
* although there are no windows left)
* @note There is a difference when closing a browser window with
* BrowserTryToCloseWindow() as opposed to close(). The former will make
* nsSessionStore restore a window next time it gets a chance and will post
* notifications. The latter won't.
*/
+
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
waitForExplicitFinish();
// Some urls that might be opened in tabs and/or popups
// Do not use about:blank:
// That one is reserved for special purposes in the tests
const TEST_URLS = ["about:mozilla", "about:buildconfig"];
// Number of -request notifications to except
@@ -212,19 +227,19 @@ function test() {
setPrefs();
// Prepare a window; open it and add more tabs
let newWin = openDialog(location, "_blank", CHROME_FEATURES, "about:config");
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.addEventListener("load", function(aEvent) {
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
- for each (let url in TEST_URLS) {
+ TEST_URLS.forEach(function (url) {
newWin.gBrowser.addTab(url);
- }
+ });
executeSoon(function() testFn(newWin));
}, true);
}, false);
}
/**
* Test 1: Normal in-session restore
@@ -493,29 +508,37 @@ function test() {
// Execution starts here
setupTestsuite();
if (navigator.platform.match(/Mac/)) {
// Mac tests
testMacNotifications(
function() testNotificationCount(
- function() cleanupTestsuite() + finish()
+ function() {
+ cleanupTestsuite();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
+ finish();
+ }
)
);
}
else {
// Non-Mac Tests
testOpenCloseNormal(
function() testOpenClosePrivateBrowsing(
function() testOpenCloseWindowAndPopup(
function() testOpenCloseOnlyPopup(
function() testOpenCloseRestoreFromPopup (
function() testNotificationCount(
- function() cleanupTestsuite() + finish()
+ function() {
+ cleanupTestsuite();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
+ finish();
+ }
)
)
)
)
)
);
}
}
--- a/browser/components/sessionstore/test/browser/browser_394759.js
+++ b/browser/components/sessionstore/test/browser/browser_394759.js
@@ -30,16 +30,28 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 394759 **/
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let pb = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService);
waitForExplicitFinish();
@@ -51,19 +63,18 @@ function test() {
let uniqueText = "pi != " + Math.random();
// make sure that the next closed window will increase getClosedWindowCount
let max_windows_undo = gPrefService.getIntPref("browser.sessionstore.max_windows_undo");
gPrefService.setIntPref("browser.sessionstore.max_windows_undo", max_windows_undo + 1);
let closedWindowCount = ss.getClosedWindowCount();
- let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL);
+ let newWin = openDialog(location, "", "chrome,all,dialog=no", testURL);
newWin.addEventListener("load", function(aEvent) {
- newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.addEventListener("load", function(aEvent) {
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
newWin.gBrowser.addTab().linkedBrowser.stop();
executeSoon(function() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
@@ -82,17 +93,16 @@ function test() {
let newWin2 = ss.undoCloseWindow(0);
ok(newWin2 instanceof ChromeWindow,
"undoCloseWindow actually returned a window");
is(ss.getClosedWindowCount(), closedWindowCount,
"The reopened window was removed from Recently Closed Windows");
newWin2.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, false);
newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) {
newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true);
is(newWin2.gBrowser.tabContainer.childNodes.length, 2,
"The window correctly restored 2 tabs");
is(newWin2.gBrowser.currentURI.spec, testURL,
"The window correctly restored the URL");
@@ -137,28 +147,27 @@ function test() {
executeSoon(recCallback);
return;
}
// hack to force window to be considered a popup (toolbar=no didn't work)
let winData = windowsToOpen.shift();
let settings = "chrome,dialog=no," +
(winData.isPopup ? "all=no" : "all");
let url = "http://window" + windowsToOpen.length + ".example.com";
- let window = openDialog(location, "_blank", settings, url);
- window.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
- window.gBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ let win = openDialog(location, "", settings, url);
+ win.addEventListener("load", function(aEvent) {
+ win.gBrowser.addEventListener("load", function(aEvent) {
+ win.gBrowser.removeEventListener("load", arguments.callee, true);
// the window _should_ have state with a tab of url, but it doesn't
// always happend before window.close(). addTab ensure we don't treat
// this window as a stateless window
- window.gBrowser.addTab();
+ win.gBrowser.addTab();
executeSoon(function() {
- window.close();
+ win.close();
executeSoon(function() {
openWindowRec(windowsToOpen, expectedResults, recCallback);
});
});
}, true);
}, true);
}
@@ -186,16 +195,22 @@ function test() {
function countClosedTabsByTitle(aClosedTabList, aTitle)
aClosedTabList.filter(function(aData) aData.title == aTitle).length;
function countOpenTabsByTitle(aOpenTabList, aTitle)
aOpenTabList.filter(function(aData) aData.entries.some(function(aEntry) aEntry.title == aTitle) ).length
// backup old state
let oldState = ss.getBrowserState();
+ let oldState_wins = JSON.parse(oldState).windows.length;
+ if (oldState_wins != 1) {
+ ok(false, "oldState in test_purge has " + oldState_wins + " windows instead of 1");
+ info(oldState);
+ }
+
// create a new state for testing
const REMEMBER = Date.now(), FORGET = Math.random();
let testState = {
windows: [ { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 } ],
_closedWindows : [
// _closedWindows[0]
{
tabs: [
@@ -252,47 +267,51 @@ function test() {
ss.setBrowserState(JSON.stringify(testState));
// purge domain & check that we purged correctly for closed windows
pb.removeDataFromDomain("mozilla.org");
let closedWindowData = JSON.parse(ss.getClosedWindowData());
// First set of tests for _closedWindows[0] - tests basics
- let window = closedWindowData[0];
- is(window.tabs.length, 1, "1 tab was removed");
- is(countOpenTabsByTitle(window.tabs, FORGET), 0,
+ let win = closedWindowData[0];
+ is(win.tabs.length, 1, "1 tab was removed");
+ is(countOpenTabsByTitle(win.tabs, FORGET), 0,
"The correct tab was removed");
- is(countOpenTabsByTitle(window.tabs, REMEMBER), 1,
+ is(countOpenTabsByTitle(win.tabs, REMEMBER), 1,
"The correct tab was remembered");
- is(window.selected, 1, "Selected tab has changed");
- is(window.title, REMEMBER, "The window title was correctly updated");
+ is(win.selected, 1, "Selected tab has changed");
+ is(win.title, REMEMBER, "The window title was correctly updated");
// Test more complicated case
- window = closedWindowData[1];
- is(window.tabs.length, 3, "2 tabs were removed");
- is(countOpenTabsByTitle(window.tabs, FORGET), 0,
+ win = closedWindowData[1];
+ is(win.tabs.length, 3, "2 tabs were removed");
+ is(countOpenTabsByTitle(win.tabs, FORGET), 0,
"The correct tabs were removed");
- is(countOpenTabsByTitle(window.tabs, REMEMBER), 3,
+ is(countOpenTabsByTitle(win.tabs, REMEMBER), 3,
"The correct tabs were remembered");
- is(window.selected, 3, "Selected tab has changed");
- is(window.title, REMEMBER, "The window title was correctly updated");
+ is(win.selected, 3, "Selected tab has changed");
+ is(win.title, REMEMBER, "The window title was correctly updated");
// Tests handling of _closedTabs
- window = closedWindowData[2];
- is(countClosedTabsByTitle(window._closedTabs, REMEMBER), 1,
+ win = closedWindowData[2];
+ is(countClosedTabsByTitle(win._closedTabs, REMEMBER), 1,
"The correct number of tabs were removed, and the correct ones");
- is(countClosedTabsByTitle(window._closedTabs, FORGET), 0,
+ is(countClosedTabsByTitle(win._closedTabs, FORGET), 0,
"All tabs to be forgotten were indeed removed");
// restore pre-test state
ss.setBrowserState(oldState);
executeSoon(callback);
}
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
test_basic(function() {
+ is(browserWindowsCount(), 1, "number of browser windows after test_basic");
test_behavior(function() {
+ is(browserWindowsCount(), 1, "number of browser windows after test_behavior");
test_purge(function() {
+ is(browserWindowsCount(), 1, "number of browser windows after test_purge");
finish();
});
});
});
}
--- a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js
+++ b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js
@@ -32,18 +32,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Private Browsing Test for Bug 394759 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
waitForExplicitFinish();
// Set interval to a large time so state won't be written while we setup env.
gPrefService.setIntPref("browser.sessionstore.interval", 100000);
// Set up the browser in a blank state. Popup windows in previous tests result
// in different states on different platforms.
@@ -80,18 +93,16 @@ function test() {
info("sessionstore.js was correctly removed: " + (!sessionStoreJS.exists()));
// Make sure that sessionstore.js can be forced to be created by setting
// the interval pref to 0.
gPrefService.setIntPref("browser.sessionstore.interval", 0);
}
function continue_test() {
- let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
- getService(Ci.nsIWindowWatcher);
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
// Ensure Private Browsing mode is disabled.
ok(!pb.privateBrowsingEnabled, "Private Browsing is disabled");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let closedWindowCount = ss.getClosedWindowCount();
@@ -103,31 +114,24 @@ function continue_test() {
{ url: "about:config",
key: "bug 394759 Non-PB",
value: "uniq" + (++now) },
{ url: "about:mozilla",
key: "bug 394759 PB",
value: "uniq" + (++now) },
];
- let loadWasCalled = false;
function openWindowAndTest(aTestIndex, aRunNextTestInPBMode) {
info("Opening new window");
- let windowObserver = {
- observe: function(aSubject, aTopic, aData) {
- if (aTopic === "domwindowopened") {
- info("New window has been opened");
- let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
- win.addEventListener("load", function onLoad(event) {
+ function onLoad(event) {
win.removeEventListener("load", onLoad, false);
info("New window has been loaded");
win.gBrowser.addEventListener("load", function(aEvent) {
win.gBrowser.removeEventListener("load", arguments.callee, true);
info("New window browser has been loaded");
- loadWasCalled = true;
executeSoon(function() {
// Add a tab.
win.gBrowser.addTab();
executeSoon(function() {
// Mark the window with some unique data to be restored later on.
ss.setWindowValue(win, TESTS[aTestIndex].key, TESTS[aTestIndex].value);
@@ -167,36 +171,26 @@ function continue_test() {
ok(data.toSource().indexOf(TESTS[aTestIndex - 1].value) > -1,
"The data associated with the recently closed window was " +
"restored when exiting PB mode");
}
if (aTestIndex == TESTS.length - 1) {
if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
gPrefService.clearUserPref("browser.sessionstore.interval");
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}
else {
// Run next test.
openWindowAndTest(aTestIndex + 1, !aRunNextTestInPBMode);
}
});
});
}, true);
- }, false);
- }
- else if (aTopic === "domwindowclosed") {
- info("Window closed");
- ww.unregisterNotification(this);
- if (!loadWasCalled) {
- ok(false, "Window was closed before load could fire!");
- finish();
- }
- }
- }
- };
- ww.registerNotification(windowObserver);
+ }
// Open a window.
- openDialog(location, "_blank", "chrome,all,dialog=no", TESTS[aTestIndex].url);
+ var win = openDialog(location, "", "chrome,all,dialog=no", TESTS[aTestIndex].url);
+ win.addEventListener("load", onLoad, false);
}
openWindowAndTest(0, true);
}
--- a/browser/components/sessionstore/test/browser/browser_408470.js
+++ b/browser/components/sessionstore/test/browser/browser_408470.js
@@ -40,26 +40,26 @@ function test() {
waitForExplicitFinish();
let pendingCount = 1;
let testUrl = "chrome://mochikit/content/browser/" +
"browser/components/sessionstore/test/browser/browser_408470_sample.html";
let tab = gBrowser.addTab(testUrl);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
// enable all stylesheets and verify that they're correctly persisted
Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) {
pendingCount++;
let ssTitle = aSS.title;
stylesheetSwitchAll(tab.linkedBrowser.contentWindow, ssTitle);
let newTab = gBrowser.duplicateTab(tab);
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets,
function(aSS) !aSS.disabled);
let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1;
if (/^fail_/.test(ssTitle))
ok(!correct, "didn't restore stylesheet " + ssTitle);
else
ok(correct, "restored stylesheet " + ssTitle);
@@ -69,17 +69,17 @@ function test() {
finish();
}, true);
});
// disable all styles and verify that this is correctly persisted
tab.linkedBrowser.markupDocumentViewer.authorStyleDisabled = true;
let newTab = gBrowser.duplicateTab(tab);
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
is(newTab.linkedBrowser.markupDocumentViewer.authorStyleDisabled, true,
"disabled all stylesheets");
gBrowser.removeTab(newTab);
if (--pendingCount == 0)
finish();
}, true);
--- a/browser/components/sessionstore/test/browser/browser_423132.js
+++ b/browser/components/sessionstore/test/browser/browser_423132.js
@@ -29,19 +29,32 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
// test that cookies are stored and restored correctly by sessionstore,
// bug 423132.
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
waitForExplicitFinish();
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
cs.removeAll();
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
@@ -96,13 +109,14 @@ function test() {
is(cookie.value, cookie2.value, "cookie value successfully restored");
is(cookie.path, cookie2.path, "cookie path successfully restored");
// clean up
if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
gPrefService.clearUserPref("browser.sessionstore.interval");
cs.removeAll();
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}, true);
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_447951.js
+++ b/browser/components/sessionstore/test/browser/browser_447951.js
@@ -40,26 +40,26 @@ function test() {
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
const baseURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_447951_sample.html#";
let tab = gBrowser.addTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let tabState = { entries: [] };
let max_entries = gPrefService.getIntPref("browser.sessionhistory.max_entries");
for (let i = 0; i < max_entries; i++)
tabState.entries.push({ url: baseURL + i });
ss.setTabState(tab, JSON.stringify(tabState));
tab.addEventListener("SSTabRestored", function(aEvent) {
- this.removeEventListener("SSTabRestored", arguments.callee, false);
+ tab.removeEventListener("SSTabRestored", arguments.callee, false);
tabState = eval("(" + ss.getTabState(tab) + ")");
is(tabState.entries.length, max_entries, "session history filled to the limit");
is(tabState.entries[0].url, baseURL + 0, "... but not more");
// visit yet another anchor (appending it to session history)
let doc = tab.linkedBrowser.contentDocument;
let event = doc.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, doc.defaultView, 1,
--- a/browser/components/sessionstore/test/browser/browser_448741.js
+++ b/browser/components/sessionstore/test/browser/browser_448741.js
@@ -55,25 +55,25 @@ function test() {
let cleaningObserver = {
observe: function(aSubject, aTopic, aData) {
ok(aTopic == "sessionstore-state-write", "observed correct topic?");
ok(aSubject instanceof Ci.nsISupportsString, "subject is a string?");
ok(aSubject.data.indexOf(uniqueValue) > -1, "data contains our value?");
// find the data for the newly added tab and delete it
let state = eval(aSubject.data);
- for each (let winData in state.windows) {
- for each (let tabData in winData.tabs) {
+ state.windows.forEach(function (winData) {
+ winData.tabs.forEach(function (tabData) {
if (tabData.extData && uniqueName in tabData.extData &&
tabData.extData[uniqueName] == uniqueValue) {
delete tabData.extData[uniqueName];
valueWasCleaned = true;
}
- }
- }
+ });
+ });
ok(valueWasCleaned, "found and removed the specific tab value");
aSubject.data = uneval(state);
os.removeObserver(this, aTopic, false);
}
};
// make sure that all later observers don't see that value any longer
--- a/browser/components/sessionstore/test/browser/browser_454908.js
+++ b/browser/components/sessionstore/test/browser/browser_454908.js
@@ -46,26 +46,26 @@ function test() {
// make sure we do save form data
gPrefService.setIntPref("browser.sessionstore.privacy_level", 0);
let testURL = "chrome://mochikit/content/browser/" +
"browser/components/sessionstore/test/browser/browser_454908_sample.html";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
for (let id in fieldValues)
doc.getElementById(id).value = fieldValues[id];
gBrowser.removeTab(tab);
tab = undoCloseTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
for (let id in fieldValues) {
let node = doc.getElementById(id);
if (node.type == "password")
is(node.value, "", "password wasn't saved/restored");
else
is(node.value, fieldValues[id], "username was saved/restored");
}
--- a/browser/components/sessionstore/test/browser/browser_459906.js
+++ b/browser/components/sessionstore/test/browser/browser_459906.js
@@ -31,63 +31,55 @@
* 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 ***** */
function test() {
/** Test for Bug 459906 **/
-
+
waitForExplicitFinish();
-
+
let testURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_459906_sample.html";
let uniqueValue = "<b>Unique:</b> " + Date.now();
-
+
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 2)
return;
- this.removeEventListener("load", arguments.callee, true);
-
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
+
let iframes = tab.linkedBrowser.contentWindow.frames;
iframes[1].document.body.innerHTML = uniqueValue;
-
+
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load (and reload!) completely
if (frameCount++ < 2)
return;
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
- let pass = 0;
- const MAX_PASS = 6;
executeSoon(function() {
- info("Checking innerHTML, pass: " + (pass + 1));
let iframes = tab2.linkedBrowser.contentWindow.frames;
- if (iframes[1].document.body.innerHTML != uniqueValue &&
- ++pass <= MAX_PASS) {
- setTimeout(arguments.callee, 500);
- return;
- }
is(iframes[1].document.body.innerHTML, uniqueValue,
"rich textarea's content correctly duplicated");
-
+
let innerDomain = null;
try {
innerDomain = iframes[0].document.domain;
}
catch (ex) { /* throws for chrome: documents */ }
is(innerDomain, "localhost", "XSS exploit prevented!");
-
+
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
-
+
finish();
});
}, true);
}, true);
}
--- a/browser/components/sessionstore/test/browser/browser_459906_sample.html
+++ b/browser/components/sessionstore/test/browser/browser_459906_sample.html
@@ -3,34 +3,40 @@
<!DOCTYPE html>
<title>Test for bug 459906</title>
<body>
<iframe src="data:text/html,not_on_localhost"></iframe>
<iframe></iframe>
<script type="application/javascript">
- frames[0].addEventListener("DOMContentLoaded", function() {
- frames[0].removeEventListener("DOMContentLoaded", arguments.callee, false);
+ var loadCount = 0;
+ frames[0].addEventListener("DOMContentLoaded", handleLoad, false);
+ frames[1].addEventListener("DOMContentLoaded", handleLoad, false);
+ function handleLoad() {
+ if (++loadCount < 2)
+ return;
+ frames[0].removeEventListener("DOMContentLoaded", handleLoad, false);
+ frames[1].removeEventListener("DOMContentLoaded", handleLoad, false);
frames[0].document.designMode = "on";
frames[0].document.__defineGetter__("designMode", function() {
// inject a cross domain file ...
var documentInjected = false;
document.getElementsByTagName("iframe")[0].onload =
function() { documentInjected = true; };
frames[0].location = "chrome://mochikit/content/browser/" +
"browser/components/sessionstore/test/browser/browser_459906_empty.html";
// ... and ensure that it has time to load
for (var c = 0; !documentInjected && c < 20; c++) {
var r = new XMLHttpRequest();
r.open("GET", location.href, false);
r.overrideMimeType("text/plain");
r.send(null);
}
-
+
return "on";
});
-
+
frames[1].document.designMode = "on";
- }, false);
+ };
</script>
</body>
--- a/browser/components/sessionstore/test/browser/browser_461634.js
+++ b/browser/components/sessionstore/test/browser/browser_461634.js
@@ -30,18 +30,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 461634 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = { windows: [{ "tabs": [{ "entries": [] }], _closedTabs: [
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
@@ -60,19 +73,18 @@ function test() {
return false;
}
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
}
}
// open a window and add the above closed tab list
- let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
+ let newWin = open(location, "", "chrome,all");
newWin.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, false);
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true);
let closedTabs = eval("(" + ss.getClosedTabData(newWin) + ")");
is(closedTabs.length, test_state.windows[0]._closedTabs.length,
"Closed tab list has the expected length");
is(countByTitle(closedTabs, FORGET),
@@ -98,12 +110,13 @@ function test() {
"The correct amout of tabs was removed");
is(countByTitle(closedTabs, FORGET), 0,
"All tabs specifically forgotten were indeed removed");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"... and tabs not specifically forgetten weren't.");
// clean up
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
finish();
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_461743.js
+++ b/browser/components/sessionstore/test/browser/browser_461743.js
@@ -31,42 +31,41 @@
* 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 ***** */
function test() {
/** Test for Bug 461743 **/
-
+
waitForExplicitFinish();
-
+
let testURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_461743_sample.html";
-
+
+ let frameCount = 0;
let tab = gBrowser.addTab(testURL);
- info("New tab added");
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- info("New tab loaded");
- this.removeEventListener("load", arguments.callee, true);
- executeSoon(function() {
- let tab2 = gBrowser.duplicateTab(tab);
- info("Duplicated tab");
- tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
- tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
- is(aEvent.data, "done", "XSS injection was attempted");
-
- executeSoon(function() {
- let iframes = tab2.linkedBrowser.contentWindow.frames;
- let innerHTML = iframes[1].document.body.innerHTML;
- isnot(innerHTML, Components.utils.reportError.toString(),
- "chrome access denied!");
-
- // clean up
- gBrowser.removeTab(tab2);
- gBrowser.removeTab(tab);
-
- finish();
- });
- }, true, true);
- });
+ // Wait for all frames to load completely.
+ if (frameCount++ < 2)
+ return;
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
+ let tab2 = gBrowser.duplicateTab(tab);
+ tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
+ tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
+ is(aEvent.data, "done", "XSS injection was attempted");
+
+ executeSoon(function() {
+ let iframes = tab2.linkedBrowser.contentWindow.frames;
+ let innerHTML = iframes[1].document.body.innerHTML;
+ isnot(innerHTML, Components.utils.reportError.toString(),
+ "chrome access denied!");
+
+ // Clean up.
+ gBrowser.removeTab(tab2);
+ gBrowser.removeTab(tab);
+
+ finish();
+ });
+ }, true, true);
}, true);
}
--- a/browser/components/sessionstore/test/browser/browser_461743_sample.html
+++ b/browser/components/sessionstore/test/browser/browser_461743_sample.html
@@ -5,43 +5,51 @@
<body>
<iframe src="data:text/html,empty"></iframe>
<iframe></iframe>
<script type="application/javascript">
var chromeUrl = "chrome://global/content/mozilla.xhtml";
var exploitUrl = "javascript:try { document.body.innerHTML = Components.utils.reportError; } catch (ex) { }";
-
- window.onload = function() {
+
+ var loadCount = 0;
+ frames[0].addEventListener("DOMContentLoaded", handleLoad, false);
+ frames[1].addEventListener("DOMContentLoaded", handleLoad, false);
+ function handleLoad() {
+ if (++loadCount < 2)
+ return;
+ frames[0].removeEventListener("DOMContentLoaded", handleLoad, false);
+ frames[1].removeEventListener("DOMContentLoaded", handleLoad, false);
+
var flip = 0;
MutationEvent.prototype.toString = function() {
return flip++ == 0 ? chromeUrl : exploitUrl;
};
-
+
var href = Components.lookupMethod(frames[1].location, "href");
var loadChrome = { handleEvent: href };
var loadExploit = { handleEvent: href };
-
+
function delay() {
var xhr = new XMLHttpRequest();
xhr.open("GET", location.href, false);
xhr.send(null);
}
function done() {
var event = document.createEvent("MessageEvent");
event.initMessageEvent("461743", true, false, "done", location.href, "", window);
document.dispatchEvent(event);
frames[0].document.removeEventListener("DOMNodeInserted", loadChrome, true);
frames[0].document.removeEventListener("DOMNodeInserted", delay, true);
frames[0].document.removeEventListener("DOMNodeInserted", loadExploit, true);
frames[0].document.removeEventListener("DOMNodeInserted", done, true);
}
-
+
frames[0].document.addEventListener("DOMNodeInserted", loadChrome, true);
frames[0].document.addEventListener("DOMNodeInserted", delay, true);
frames[0].document.addEventListener("DOMNodeInserted", loadExploit, true);
frames[0].document.addEventListener("DOMNodeInserted", done, true);
-
+
frames[0].document.designMode = "on";
};
</script>
</body>
--- a/browser/components/sessionstore/test/browser/browser_463205.js
+++ b/browser/components/sessionstore/test/browser/browser_463205.js
@@ -43,17 +43,17 @@ function test() {
"browser/components/sessionstore/test/browser/browser_463205_sample.html";
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 3)
return;
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
function typeText(aTextField, aValue) {
aTextField.value = aValue;
let event = aTextField.ownerDocument.createEvent("UIEvents");
event.initUIEvent("input", true, true, aTextField.ownerDocument.defaultView, 0);
aTextField.dispatchEvent(event);
}
@@ -64,17 +64,17 @@ function test() {
typeText(win.frames[1].document.getElementById("original"), uniqueValue);
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load (and reload!) completely
if (frameCount++ < 4)
return;
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
let win = tab2.linkedBrowser.contentWindow;
isnot(win.frames[0].document.getElementById("original").value, uniqueValue,
"subframes must match URL to get text restored");
is(win.frames[0].document.getElementById("original").value, "preserve me",
"subframes must match URL to get text restored");
is(win.frames[1].document.getElementById("original").value, uniqueValue,
"text still gets restored for all other subframes");
--- a/browser/components/sessionstore/test/browser/browser_463206.js
+++ b/browser/components/sessionstore/test/browser/browser_463206.js
@@ -43,17 +43,17 @@ function test() {
"browser/components/sessionstore/test/browser/browser_463206_sample.html";
var frameCount = 0;
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 5)
return;
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
function typeText(aTextField, aValue) {
aTextField.value = aValue;
let event = aTextField.ownerDocument.createEvent("UIEvents");
event.initUIEvent("input", true, true, aTextField.ownerDocument.defaultView, 0);
aTextField.dispatchEvent(event);
}
@@ -64,17 +64,17 @@ function test() {
typeText(doc.defaultView.frames[0].frames[1].document.getElementById("in1"), new Date());
frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
// wait for all frames to load completely
if (frameCount++ < 5)
return;
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab2.linkedBrowser.contentDocument;
let win = tab2.linkedBrowser.contentWindow;
isnot(doc.getElementById("out1").value,
win.frames[1].document.getElementById("out1").value,
"text isn't reused for frames");
isnot(doc.getElementsByName("1|#out2")[0].value, "",
"text containing | and # is correctly restored");
--- a/browser/components/sessionstore/test/browser/browser_464199.js
+++ b/browser/components/sessionstore/test/browser/browser_464199.js
@@ -29,18 +29,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 464199 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = { windows: [{ "tabs": [{ "entries": [] }], _closedTabs: [
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
@@ -68,19 +81,18 @@ function test() {
extData: { "setTabValue": "http://example.net:80" } }, title: REMEMBER }
] }] };
let remember_count = 5;
function countByTitle(aClosedTabList, aTitle)
aClosedTabList.filter(function(aData) aData.title == aTitle).length;
// open a window and add the above closed tab list
- let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
+ let newWin = open(location, "", "chrome,all");
newWin.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, false);
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true);
let closedTabs = eval("(" + ss.getClosedTabData(newWin) + ")");
is(closedTabs.length, test_state.windows[0]._closedTabs.length,
"Closed tab list has the expected length");
is(countByTitle(closedTabs, FORGET),
@@ -98,13 +110,14 @@ function test() {
"The correct amout of tabs was removed");
is(countByTitle(closedTabs, FORGET), 0,
"All tabs to be forgotten were indeed removed");
is(countByTitle(closedTabs, REMEMBER), remember_count,
"... and tabs to be remembered weren't.");
// clean up
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
if (gPrefService.prefHasUserValue("browser.sessionstore.max_tabs_undo"))
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
finish();
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_465223.js
+++ b/browser/components/sessionstore/test/browser/browser_465223.js
@@ -29,32 +29,44 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 465223 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let uniqueKey1 = "bug 465223.1";
let uniqueKey2 = "bug 465223.2";
let uniqueValue1 = "unik" + Date.now();
let uniqueValue2 = "pi != " + Math.random();
// open a window and set a value on it
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, false);
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
newState.windows[0].extData[uniqueKey2] = uniqueValue2;
ss.setWindowState(newWin, JSON.stringify(newState), false);
is(newWin.gBrowser.tabContainer.childNodes.length, 2,
"original tab wasn't overwritten");
@@ -70,11 +82,12 @@ function test() {
"original tabs were overwritten");
is(ss.getWindowValue(newWin, uniqueKey1), "",
"window value was cleared");
is(ss.getWindowValue(newWin, uniqueKey2), uniqueValue1,
"window value was correctly overwritten");
// clean up
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_466937.js
+++ b/browser/components/sessionstore/test/browser/browser_466937.js
@@ -40,24 +40,24 @@ function test() {
waitForExplicitFinish();
let testURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_466937_sample.html";
let testPath = "/home/user/regular.file";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("reverse_thief").value = "/home/user/secret2";
doc.getElementById("bystander").value = testPath;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
doc = tab2.linkedBrowser.contentDocument;
is(doc.getElementById("thief").value, "",
"file path wasn't set to text field value");
is(doc.getElementById("reverse_thief").value, "",
"text field value wasn't set to full file path");
is(doc.getElementById("bystander").value, testPath,
"normal case: file path was correctly preserved");
--- a/browser/components/sessionstore/test/browser/browser_476161.js
+++ b/browser/components/sessionstore/test/browser/browser_476161.js
@@ -38,25 +38,25 @@ function test() {
/** Test for Bug 476161 **/
waitForExplicitFinish();
let testURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_476161_sample.html";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("modify1").value += Math.random();
doc.getElementById("modify2").value += " " + Date.now();
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab2.linkedBrowser.contentDocument;
let changed = doc.getElementById("changed").textContent.trim().split();
is(changed.sort().join(" "), "modify1 modify2",
"input events were only dispatched for modified text fields");
// clean up
gBrowser.removeTab(tab2);
--- a/browser/components/sessionstore/test/browser/browser_477657.js
+++ b/browser/components/sessionstore/test/browser/browser_477657.js
@@ -29,25 +29,41 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 477657 **/
-
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
+ // Test fails randomly on OS X (bug 482975)
+ if ("nsILocalFileMac" in Ci)
+ return;
+
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, false);
let newState = { windows: [{
tabs: [{ entries: [] }],
_closedTabs: [{
state: { entries: [{ url: "about:" }]},
title: "About:"
}],
sizemode: "maximized"
}] };
@@ -83,14 +99,15 @@ function test() {
newState.windows[0].sizemode = "normal";
ss.setWindowState(newWin, JSON.stringify(newState), true);
setTimeout(function() {
isnot(newWin.windowState, newWin.STATE_MAXIMIZED,
"the window was explicitly unmaximized");
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}, 0);
}, 0);
}, 0);
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_480148.js
+++ b/browser/components/sessionstore/test/browser/browser_480148.js
@@ -29,18 +29,34 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 484108 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
+ let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+ waitForExplicitFinish();
// builds the tests state based on a few parameters
function buildTestState(num, selected) {
let state = { windows: [ { "tabs": [], "selected": selected } ] };
while (num--)
state.windows[0].tabs.push({entries: [{url: "http://example.com/"}]});
return state;
}
@@ -60,20 +76,16 @@ function test() {
for (let i = 0; i < num; i++) {
if (expected.indexOf(i) == -1) {
expected.push(i);
}
}
return expected;
}
- // test setup
- let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
- waitForExplicitFinish();
-
// the number of tests we're running
let numTests = 4;
let completedTests = 0;
// access the pref service just once
let tabMinWidth = gPrefService.getIntPref("browser.tabs.tabMinWidth");
function runTest(testNum, totalTabs, selectedTab, shownTabs, order) {
@@ -106,16 +118,17 @@ function test() {
"Test #" + testNum + ": 'visible' tabs restored first");
// cleanup
this.window.close();
// if we're all done, explicitly finish
if (++completedTests == numTests) {
this.window.removeEventListener("load", this, false);
this.window.removeEventListener("SSTabRestoring", this, false);
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}
},
handleLoad: function (aEvent) {
let _this = this;
executeSoon(function () {
_this.window.resizeTo(_this.windowWidth, _this.window.outerHeight);
@@ -148,9 +161,9 @@ function test() {
// actually create & run the tests
runTest(1, 13, 1, 6, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
runTest(2, 13, 13, 6, [12, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6]);
runTest(3, 13, 4, 6, [3, 4, 5, 6, 7, 8, 0, 1, 2, 9, 10, 11, 12]);
runTest(4, 13, 11, 6, [10, 7, 8, 9, 11, 12, 0, 1, 2, 3, 4, 5, 6]);
// finish() is run by the last test to finish, so no cleanup down here
-}
\ No newline at end of file
+}
--- a/browser/components/sessionstore/test/browser/browser_480893.js
+++ b/browser/components/sessionstore/test/browser/browser_480893.js
@@ -41,41 +41,41 @@ function test() {
// Test that starting a new session loads a blank page if Firefox is
// configured to display a blank page at startup (browser.startup.page = 0)
gPrefService.setIntPref("browser.startup.page", 0);
let tab = gBrowser.addTab("about:sessionrestore");
gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
browser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ browser.removeEventListener("load", arguments.callee, true);
let doc = browser.contentDocument;
// click on the "Start New Session" button after about:sessionrestore is loaded
doc.getElementById("errorCancel").click();
browser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ browser.removeEventListener("load", arguments.callee, true);
let doc = browser.contentDocument;
is(doc.URL, "about:blank", "loaded page is about:blank");
// Test that starting a new session loads the homepage (set to http://localhost:8888)
// if Firefox is configured to display a homepage at startup (browser.startup.page = 1)
let homepage = "http://localhost:8888/";
gPrefService.setCharPref("browser.startup.homepage", homepage);
gPrefService.setIntPref("browser.startup.page", 1);
gBrowser.loadURI("about:sessionrestore");
browser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ browser.removeEventListener("load", arguments.callee, true);
let doc = browser.contentDocument;
// click on the "Start New Session" button after about:sessionrestore is loaded
doc.getElementById("errorCancel").click();
browser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ browser.removeEventListener("load", arguments.callee, true);
let doc = browser.contentDocument;
is(doc.URL, homepage, "loaded page is the homepage");
// close tab, restore default values and finish the test
gBrowser.removeTab(tab);
// we need this if-statement because if there is no user set value,
// clearUserPref throws a uncatched exception and finish is not called
--- a/browser/components/sessionstore/test/browser/browser_485482.js
+++ b/browser/components/sessionstore/test/browser/browser_485482.js
@@ -40,24 +40,24 @@ function test() {
waitForExplicitFinish();
let uniqueValue = Math.random();
let testURL = "chrome://mochikit/content/browser/" +
"browser/components/sessionstore/test/browser/browser_485482_sample.html";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
doc.querySelector("input[type=text]").value = uniqueValue;
doc.querySelector("input[type=checkbox]").checked = true;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
doc = tab2.linkedBrowser.contentDocument;
is(doc.querySelector("input[type=text]").value, uniqueValue,
"generated XPath expression was valid");
ok(doc.querySelector("input[type=checkbox]").checked,
"generated XPath expression was valid");
// clean up
gBrowser.removeTab(tab2);
--- a/browser/components/sessionstore/test/browser/browser_485563.js
+++ b/browser/components/sessionstore/test/browser/browser_485563.js
@@ -39,17 +39,17 @@ function test() {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let uniqueValue = Math.random() + "\u2028Second line\u2029Second paragraph\u2027";
let tab = gBrowser.addTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) {
- this.removeEventListener("load", arguments.callee, true);
+ tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
ss.setTabValue(tab, "bug485563", uniqueValue);
let tabState = eval("(" + ss.getTabState(tab) + ")");
is(tabState.extData["bug485563"], uniqueValue,
"unicode line separator wasn't over-encoded");
ss.deleteTabValue(tab, "bug485563");
ss.setTabState(tab, tabState.toSource());
is(ss.getTabValue(tab, "bug485563"), uniqueValue,
"unicode line separator was correctly preserved");
--- a/browser/components/sessionstore/test/browser/browser_490040.js
+++ b/browser/components/sessionstore/test/browser/browser_490040.js
@@ -30,18 +30,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 490040 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
@@ -149,14 +162,15 @@ function test() {
function runNextTest() {
if (states.length) {
let state = states.shift();
testWithState(state);
}
else {
if (gPrefService.prefHasUserValue("browser.sessionstore.max_windows_undo"))
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}
}
runNextTest();
}
--- a/browser/components/sessionstore/test/browser/browser_491168.js
+++ b/browser/components/sessionstore/test/browser/browser_491168.js
@@ -29,18 +29,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 491168 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
waitForExplicitFinish();
const REFERRER1 = "http://www.example.net/?" + Date.now();
@@ -67,16 +80,17 @@ function test() {
gBrowser.removeTab(tab);
let newTab = ss.undoCloseTab(window, 0);
newTab.addEventListener("SSTabRestored", function() {
newTab.removeEventListener("SSTabRestored", arguments.callee, true);
is(window.content.document.referrer, REFERRER2, "document.referrer is still correct after closing and reopening the tab.");
gBrowser.removeTab(newTab);
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
}, true);
}, true);
},true);
let referrerURI = ioService.newURI(REFERRER1, null, null);
browser.loadURI("http://www.example.net", referrerURI, null);
}
--- a/browser/components/sessionstore/test/browser/browser_491577.js
+++ b/browser/components/sessionstore/test/browser/browser_491577.js
@@ -30,18 +30,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 491577 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
const REMEMBER = Date.now(), FORGET = Math.random();
let test_state = {
windows: [ { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 } ],
@@ -144,13 +157,14 @@ function test() {
"The correct amount of windows were removed");
is(countByTitle(closedWindows, FORGET), 0,
"All windows specifically forgotten were indeed removed");
is(countByTitle(closedWindows, REMEMBER), remember_count,
"... and windows not specifically forgetten weren't.");
// clean up
newWin.close();
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
if (gPrefService.prefHasUserValue("browser.sessionstore.max_windows_undo"))
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
finish();
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_493467.js
+++ b/browser/components/sessionstore/test/browser/browser_493467.js
@@ -29,18 +29,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 493467 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let tab = gBrowser.addTab();
tab.linkedBrowser.stop();
let tabState = JSON.parse(ss.getTabState(tab));
is(tabState.disallow || "", "", "Everything is allowed per default");
@@ -61,9 +74,10 @@ function test() {
let disallow = tabState.disallow.split(",");
permissions.forEach(function(aName) {
ok(disallow.indexOf(aName) > -1, "Saved state of allow" + aName);
});
// IF A TEST FAILS, please add the missing permission's name (without the
// leading "allow") to nsSessionStore.js's CAPABILITIES array. Thanks.
gBrowser.removeTab(tab);
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
}
--- a/browser/components/sessionstore/test/browser/browser_495495.js
+++ b/browser/components/sessionstore/test/browser/browser_495495.js
@@ -29,18 +29,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 495495 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no,toolbar=yes");
newWin.addEventListener("load", function() {
newWin.removeEventListener("load", arguments.callee, false);
@@ -74,16 +87,19 @@ function test() {
win.close();
executeSoon(callback);
}, false);
}
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
testState(state2, {readOnly: true, enablehistory: "false"}, function() {
- executeSoon(finish);
+ executeSoon(function () {
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
+ finish();
+ });
});
});
});
}, false);
});
}, false);
}
--- a/browser/components/sessionstore/test/browser/browser_514751.js
+++ b/browser/components/sessionstore/test/browser/browser_514751.js
@@ -29,18 +29,31 @@
* 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 ***** */
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
function test() {
/** Test for Bug 514751 (Wallpaper) **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
waitForExplicitFinish();
@@ -76,16 +89,17 @@ function test() {
theWin.close();
});
});
}, false);
break;
case "domwindowclosed":
ww.unregisterNotification(this);
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
finish();
break;
}
}
}
ww.registerNotification(windowObserver);
ww.openWindow(null,
location,
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_522545.js
@@ -0,0 +1,319 @@
+/* ***** 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 Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * 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 ***** */
+
+function browserWindowsCount() {
+ let count = 0;
+ let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("navigator:browser");
+ while (e.hasMoreElements()) {
+ if (!e.getNext().closed)
+ ++count;
+ }
+ return count;
+}
+
+function test() {
+ /** Test for Bug 522545 **/
+ is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
+ waitForExplicitFinish();
+
+ let ss = Cc["@mozilla.org/browser/sessionstore;1"].
+ getService(Ci.nsISessionStore);
+ let os = Cc["@mozilla.org/observer-service;1"].
+ getService(Ci.nsIObserverService);
+
+ function waitForBrowserState(aState, aSetStateCallback) {
+ let observer = {
+ observe: function(aSubject, aTopic, aData) {
+ os.removeObserver(this, "sessionstore-browser-state-restored");
+ executeSoon(aSetStateCallback);
+ }
+ };
+ os.addObserver(observer, "sessionstore-browser-state-restored", false);
+ ss.setBrowserState(JSON.stringify(aState));
+ }
+
+ // This tests the following use case:
+ // User opens a new tab which gets focus. The user types something into the
+ // address bar, then crashes or quits.
+ function test_newTabFocused() {
+ let state = {
+ windows: [{
+ tabs: [
+ { entries: [{ url: "about:mozilla" }] },
+ { entries: [], userTypedValue: "example.com", userTypedClear: 0 }
+ ],
+ selected: 2
+ }]
+ };
+
+ waitForBrowserState(state, function() {
+ let browser = gBrowser.selectedBrowser;
+ is(browser.currentURI.spec, "about:blank",
+ "No history entries still sets currentURI to about:blank");
+ is(browser.userTypedValue, "example.com",
+ "userTypedValue was correctly restored");
+ is(browser.userTypedClear, 0,
+ "userTypeClear restored as expected");
+ is(gURLBar.value, "example.com",
+ "Address bar's value correctly restored");
+ // Change tabs to make sure address bar value gets updated
+ gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(0);
+ is(gURLBar.value, "about:mozilla",
+ "Address bar's value correctly updated");
+ runNextTest();
+ });
+ }
+
+ // This tests the following use case:
+ // User opens a new tab which gets focus. The user types something into the
+ // address bar, switches back to the first tab, then crashes or quits.
+ function test_newTabNotFocused() {
+ let state = {
+ windows: [{
+ tabs: [
+ { entries: [{ url: "about:mozilla" }] },
+ { entries: [], userTypedValue: "example.org", userTypedClear: 0 }
+ ],
+ selected: 1
+ }]
+ };
+
+ waitForBrowserState(state, function() {
+ let browser = gBrowser.getBrowserAtIndex(1);
+ is(browser.currentURI.spec, "about:blank",
+ "No history entries still sets currentURI to about:blank");
+ is(browser.userTypedValue, "example.org",
+ "userTypedValue was correctly restored");
+ is(browser.userTypedClear, 0,
+ "userTypeClear restored as expected");
+ is(gURLBar.value, "about:mozilla",
+ "Address bar's value correctly restored");
+ // Change tabs to make sure address bar value gets updated
+ gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(1);
+ is(gURLBar.value, "example.org",
+ "Address bar's value correctly updated");
+ runNextTest();
+ });
+ }
+
+ // This tests the following use case:
+ // User is in a tab with session history, then types something in the
+ // address bar, then crashes or quits.
+ function test_existingSHEnd_noClear() {
+ let state = {
+ windows: [{
+ tabs: [{
+ entries: [{ url: "about:mozilla" }, { url: "about:config" }],
+ index: 2,
+ userTypedValue: "example.com",
+ userTypedClear: 0
+ }]
+ }]
+ };
+
+ waitForBrowserState(state, function() {
+ let browser = gBrowser.selectedBrowser;
+ is(browser.currentURI.spec, "about:config",
+ "browser.currentURI set to current entry in SH");
+ is(browser.userTypedValue, "example.com",
+ "userTypedValue was correctly restored");
+ is(browser.userTypedClear, 0,
+ "userTypeClear restored as expected");
+ is(gURLBar.value, "example.com",
+ "Address bar's value correctly restored to userTypedValue");
+ runNextTest();
+ });
+ }
+
+ // This tests the following use case:
+ // User is in a tab with session history, presses back at some point, then
+ // types something in the address bar, then crashes or quits.
+ function test_existingSHMiddle_noClear() {
+ let state = {
+ windows: [{
+ tabs: [{
+ entries: [{ url: "about:mozilla" }, { url: "about:config" }],
+ index: 1,
+ userTypedValue: "example.org",
+ userTypedClear: 0
+ }]
+ }]
+ };
+
+ waitForBrowserState(state, function() {
+ let browser = gBrowser.selectedBrowser;
+ is(browser.currentURI.spec, "about:mozilla",
+ "browser.currentURI set to current entry in SH");
+ is(browser.userTypedValue, "example.org",
+ "userTypedValue was correctly restored");
+ is(browser.userTypedClear, 0,
+ "userTypeClear restored as expected");
+ is(gURLBar.value, "example.org",
+ "Address bar's value correctly restored to userTypedValue");
+ runNextTest();
+ });
+ }
+
+ // This test simulates lots of tabs opening at once and then quitting/crashing.
+ function test_getBrowserState_lotsOfTabsOpening() {
+ let uris = [];
+ for (let i = 0; i < 25; i++)
+ uris.push("http://example.com/" + i);
+
+ // We're listening for the first non-"about:blank" load event, which should
+ // indicate one of the tabs has loaded and the others haven't. So one should
+ // be in a non-userTypedValue case, while others should still have
+ // userTypedValue and userTypedClear set.
+ gBrowser.addEventListener("load", function(aEvent) {
+ if (gBrowser.currentURI.spec == "about:blank")
+ return;
+ gBrowser.removeEventListener("load", arguments.callee, true);
+
+ let state = JSON.parse(ss.getBrowserState());
+
+ let hasSH = state.windows[0].tabs.some(function(aTab) {
+ return !("userTypedValue" in aTab) && aTab.entries[0].url;
+ });
+ let hasUTV = state.windows[0].tabs.some(function(aTab) {
+ return aTab.userTypedValue && aTab.userTypedClear && !aTab.entries.length;
+ });
+
+ ok(hasSH, "At least one tab has it's entry in SH");
+ ok(hasUTV, "At least one tab has a userTypedValue with userTypedClear with no loaded URL");
+
+ runNextTest();
+
+ }, true);
+ gBrowser.loadTabs(uris);
+ }
+
+ // This simulates setting a userTypedValue and ensures that just typing in the
+ // URL bar doesn't set userTypedClear as well.
+ function test_getBrowserState_userTypedValue() {
+ let state = {
+ windows: [{
+ tabs: [{ entries: [] }]
+ }]
+ };
+
+ waitForBrowserState(state, function() {
+ let browser = gBrowser.selectedBrowser;
+ // Make sure this tab isn't loading and state is clear before we test.
+ is(browser.userTypedValue, null, "userTypedValue is empty to start");
+ is(browser.userTypedClear, 0, "userTypedClear is 0 to start");
+
+ gURLBar.value = "mozilla.org";
+ let event = document.createEvent("Events");
+ event.initEvent("input", true, false);
+ gURLBar.dispatchEvent(event);
+
+ is(browser.userTypedValue, "mozilla.org",
+ "userTypedValue was set when changing gURLBar.value");
+ is(browser.userTypedClear, 0,
+ "userTypedClear was not changed when changing gURLBar.value");
+
+ // Now make sure ss gets these values too
+ let newState = JSON.parse(ss.getBrowserState());
+ is(newState.windows[0].tabs[0].userTypedValue, "mozilla.org",
+ "sessionstore got correct userTypedValue");
+ is(newState.windows[0].tabs[0].userTypedClear, 0,
+ "sessionstore got correct userTypedClear");
+ runNextTest();
+ });
+ }
+
+ // test_getBrowserState_lotsOfTabsOpening tested userTypedClear in a few cases,
+ // but not necessarily any that had legitimate URIs in the state of loading
+ // (eg, "http://example.com"), so this test will cover that case.
+ function test_userTypedClearLoadURI() {
+ let state = {
+ windows: [{
+ tabs: [
+ { entries: [], userTypedValue: "http://example.com", userTypedClear: 2 }
+ ]
+ }]
+ };
+
+ // Set state here and listen for load event because waitForBrowserState
+ // doesn't guarantee all the tabs have loaded, so the test could continue
+ // before we're in a testable state. This is important here because of the
+ // distinction between "http://example.com" and "http://example.com/".
+ ss.setBrowserState(JSON.stringify(state));
+ gBrowser.addEventListener("load", function(aEvent) {
+ if (gBrowser.currentURI.spec == "about:blank")
+ return;
+ gBrowser.removeEventListener("load", arguments.callee, true);
+
+ let browser = gBrowser.selectedBrowser;
+ is(browser.currentURI.spec, "http://example.com/",
+ "userTypedClear=2 caused userTypedValue to be loaded");
+ is(browser.userTypedValue, null,
+ "userTypedValue was null after loading a URI");
+ is(browser.userTypedClear, 0,
+ "userTypeClear reset to 0");
+ is(gURLBar.value, "http://example.com/",
+ "Address bar's value set after loading URI");
+ runNextTest();
+ }, true);
+ }
+
+
+ let tests = [test_newTabFocused, test_newTabNotFocused,
+ test_existingSHEnd_noClear, test_existingSHMiddle_noClear,
+ test_getBrowserState_lotsOfTabsOpening,
+ test_getBrowserState_userTypedValue, test_userTypedClearLoadURI];
+ let originalState = ss.getBrowserState();
+ info(JSON.parse(originalState).windows.length);
+ info(originalState);
+ function runNextTest() {
+ if (tests.length) {
+ tests.shift().call();
+ } else {
+ ss.setBrowserState(originalState);
+ executeSoon(function () {
+ is(browserWindowsCount(), 1, "Only one browser window should be open eventually");
+ finish();
+ });
+ }
+ }
+
+ // Run the tests!
+ runNextTest();
+}
--- a/browser/components/sessionstore/test/browser/browser_526613.js
+++ b/browser/components/sessionstore/test/browser/browser_526613.js
@@ -44,20 +44,30 @@ function test() {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
waitForExplicitFinish();
function browserWindowsCount() {
let count = 0;
- let e = wm.getXULWindowEnumerator("navigator:browser");
+ let e = wm.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
- ++count;
- e.getNext();
+ let win = e.getNext();
+ if (!win.closed) {
+ ++count;
+ if (win != window) {
+ try {
+ var tabs = win.gBrowser.mTabs.length;
+ } catch (e) {
+ info(e);
+ }
+ info("secondary window: " + [win.document.readyState, win.content.location, tabs]);
+ }
+ }
}
return count;
}
is(browserWindowsCount(), 1, "Only one browser window should be open initially");
// backup old state
@@ -77,24 +87,31 @@ function test() {
pass: 1,
observe: function(aSubject, aTopic, aData) {
is(aTopic, "sessionstore-browser-state-restored",
"The sessionstore-browser-state-restored notification was observed");
if (this.pass++ == 1) {
is(browserWindowsCount(), 2, "Two windows should exist at this point");
- // executeSoon is needed here in order to let the first window be focused
- // (see above)
- executeSoon(function() {
- ss.setBrowserState(oldState);
- });
+ // let the first window be focused (see above)
+ function pollMostRecentWindow() {
+ if (wm.getMostRecentWindow("navigator:browser") == window) {
+ ss.setBrowserState(oldState);
+ } else {
+ info("waiting for the current window to become active");
+ setTimeout(pollMostRecentWindow, 0);
+ }
+ }
+ window.focus(); //XXX Why is this needed?
+ pollMostRecentWindow();
}
else {
is(browserWindowsCount(), 1, "Only one window should exist after cleanup");
+ ok(!window.closed, "Restoring the old state should have left this window open");
os.removeObserver(this, "sessionstore-browser-state-restored");
finish();
}
}
};
os.addObserver(observer, "sessionstore-browser-state-restored", false);
// set browser to test state
--- a/browser/components/shell/test/browser_420786.js
+++ b/browser/components/shell/test/browser_420786.js
@@ -1,27 +1,14 @@
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-
const DG_BACKGROUND = "/desktop/gnome/background"
const DG_IMAGE_KEY = DG_BACKGROUND + "/picture_filename";
const DG_OPTION_KEY = DG_BACKGROUND + "/picture_options";
const DG_DRAW_BG_KEY = DG_BACKGROUND + "/draw_background";
-var testPage;
-
-function url(spec) {
- var ios = Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService);
- return ios.newURI(spec, null, null);
-}
-
function onPageLoad() {
- testPage.events.removeListener("load", onPageLoad);
-
var bs = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService);
var brandName = bs.createBundle("chrome://branding/locale/brand.properties").
GetStringFromName("brandShortName");
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIDirectoryServiceProvider);
var homeDir = dirSvc.getFile("Home", {});
@@ -44,17 +31,17 @@ function onPageLoad() {
getService(Ci.nsIShellService);
var gconf = Cc["@mozilla.org/gnome-gconf-service;1"].
getService(Ci.nsIGConfService);
var prevImageKey = gconf.getString(DG_IMAGE_KEY);
var prevOptionKey = gconf.getString(DG_OPTION_KEY);
var prevDrawBgKey = gconf.getBool(DG_DRAW_BG_KEY);
- var image = testPage.document.getElementsByTagName("img")[0];
+ var image = content.document.images[0];
function checkWallpaper(position, expectedGConfPosition) {
shell.setDesktopBackground(image, position);
ok(wpFile.exists(), "Wallpaper was written to disk");
is(gconf.getString(DG_IMAGE_KEY), wpFile.path,
"Wallpaper file GConf key is correct");
is(gconf.getString(DG_OPTION_KEY), expectedGConfPosition,
"Wallpaper position GConf key is correct");
@@ -67,32 +54,29 @@ function onPageLoad() {
// Restore GConf and wallpaper
gconf.setString(DG_IMAGE_KEY, prevImageKey);
gconf.setString(DG_OPTION_KEY, prevOptionKey);
gconf.setBool(DG_DRAW_BG_KEY, prevDrawBgKey);
wpFile.remove(false);
- if (wpFileBackup.exists()) {
- wpFileBackup.moveTo(null, wpFile.leafName);
- }
- testPage.close();
+ if (wpFileBackup.exists())
+ wpFileBackup.moveTo(null, wpFile.leafName);
+
+ gBrowser.removeCurrentTab();
finish();
}
function test() {
var osString = Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULRuntime).OS;
// This test is Linux specific for now
- if (osString != "Linux") {
- finish();
+ if (osString != "Linux")
return;
- }
- testPage = Application.activeWindow.open(url("about:blank"));
- testPage.events.addListener("load", onPageLoad);
- testPage.load(url("about:logo"));
- testPage.focus();
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener("load", onPageLoad, true);
+ content.location = "about:logo";
waitForExplicitFinish();
}
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -500,8 +500,13 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
; [FastStart]
#ifdef WINCE
#ifdef MOZ_FASTSTART
@BINPATH@/firefoxfaststart.exe
@BINPATH@/components/FastStartup.js
#endif
#endif
+
+; [OS/2]
+#ifdef XP_OS2
+@BINPATH@/MozSounds.cmd
+#endif
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -580,16 +580,18 @@ res/hiddenWindow.html
res/ua.css
res/html.css
res/quirk.css
res/forms.css
res/viewsource.css
res/mathml.css
res/loading-image.png
res/broken-image.png
+res/loading-image.gif
+res/broken-image.gif
res/html/gopher-audio.gif
res/html/gopher-binary.gif
res/html/gopher-find.gif
res/html/gopher-image.gif
res/html/gopher-menu.gif
res/html/gopher-movie.gif
res/html/gopher-sound.gif
res/html/gopher-telnet.gif
@@ -633,31 +635,30 @@ components/websrvcs.xpt
components/widget_mac.xpt
components/xml-rpc.xpt
components/xpcom_obsolete.xpt
updater.app/Contents/MacOS/updater.ini
init.d/README
redo-prebinding.sh
res/viewer.properties
res/bloatcycle.html
-res/broken-image.gif
-res/loading-image.gif
components/browsersearch.xpt
components/nsResetPref.js
plugins/Default Plugin.plugin/Contents/Info.plist
plugins/Default Plugin.plugin/Contents/MacOS/Default Plugin
plugins/Default Plugin.plugin/Contents/PkgInfo
plugins/Default Plugin.plugin/Contents/Resources/Default Plugin.rsrc
plugins/Default Plugin.plugin/Contents/Resources/English.lproj/InfoPlist.strings
../Plug-Ins/PrintPDE.plugin/Contents/Info.plist
../Plug-Ins/PrintPDE.plugin/Contents/MacOS/PrintPDE
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/Localizable.strings
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/classes.nib
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/info.nib
../Plug-Ins/PrintPDE.plugin/Contents/Resources/English.lproj/PrintPDE.nib/objects.xib
+../Resources/firefox-bin.rsrc
res/cursors/CVS/Entries
res/cursors/CVS/Repository
res/cursors/CVS/Root
res/cursors/CVS/Tag
components/alerts.xpt
components/appshell.xpt
components/appstartup.xpt
components/autocomplete.xpt
@@ -743,16 +744,17 @@ components/necko_dns.xpt
components/necko_file.xpt
components/necko_ftp.xpt
components/necko_http.xpt
components/necko_res.xpt
components/necko_socket.xpt
components/necko_strconv.xpt
components/necko_viewsource.xpt
components/necko_wifi.xpt
+components/oji.xpt
components/parentalcontrols.xpt
components/pipboot.xpt
components/pipnss.xpt
components/pippki.xpt
components/places.xpt
components/plugin.xpt
components/pref.xpt
components/prefetch.xpt
@@ -799,24 +801,27 @@ components/zipwriter.xpt
components/firefox.xpt
greprefs/all.js
greprefs/security-prefs.js
greprefs/xpinstall.js
run-mozilla.sh
firefox
dependentlibs.list
components/nsProgressDialog.js
+libwidget.rsrc
#endif
#ifdef XP_UNIX
#ifndef XP_MACOSX
readme.txt
chrome/icons/default/default.xpm
dictionaries/PL.dic
dictionaries/PL.aff
libjemalloc.so
+icons/mozicon16.xpm
+icons/mozicon50.xpm
#endif
#endif
#ifdef XP_WIN
#ifdef MOZ_MEMORY
Microsoft.VC80.CRT.manifest
msvcm80.dll
msvcp80.dll
msvcr80.dll
@@ -833,8 +838,9 @@ js3250.dll
#endif
#ifdef XP_WIN
components/brwsrcmp.dll
#endif
#ifndef MOZ_UPDATER
components/nsUpdateService.js
components/nsUpdateServiceStub.js
#endif
+old-homepage-default.properties
--- a/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
+++ b/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
@@ -17,18 +17,18 @@
<!ENTITY helpForIEUsers.label "For Internet Explorer Users">
<!ENTITY helpForIEUsers.accesskey "I">
<!ENTITY openHelp.commandkey "VK_F1">
<!ENTITY helpMac.commandkey "?">
<!ENTITY helpReleaseNotes.label "Release Notes">
<!ENTITY helpReleaseNotes.accesskey "N">
-<!ENTITY helpTroubleshooting.label "Troubleshooting Information">
-<!ENTITY helpTroubleshooting.accesskey "T">
+<!ENTITY helpTroubleshootingInfo.label "Troubleshooting Information">
+<!ENTITY helpTroubleshootingInfo.accesskey "T">
<!ENTITY updateCmd.label "Check for Updates…">
<!ENTITY preferencesCmdMac.label "Preferences…">
<!ENTITY preferencesCmdMac.commandkey ",">
<!ENTITY servicesMenuMac.label "Services">
--- a/browser/locales/en-US/searchplugins/yahoo.xml
+++ b/browser/locales/en-US/searchplugins/yahoo.xml
@@ -1,13 +1,13 @@
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Yahoo</ShortName>
<Description>Yahoo Search</Description>
<InputEncoding>UTF-8</InputEncoding>
-<Image width="16" height="16">data:image/x-icon;base64,R0lGODlhEAAQAJECAP8AAAAAAP///wAAACH5BAEAAAIALAAAAAAQABAAAAIplI+py+0NogQuyBDEnEd2kHkfFWUamEzmpZSfmaIHPHrRguUm/fT+UwAAOw==</Image>
+<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbgJqAIoCdgCaAnoAnhKCAKYijgCuLpIAskKeALpSpgC+Yq4AzHy8ANqezgDmvt4A7tLqAPz5+wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlRFIoABWAKERERE6ADcKMzzu2hOgAAhERK8REWCWBERE36ERMHMEREvo6iEgY6hEn6Pu0mAzqkz/xjMzoDNwpERERDoAMzAKlERIoAAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//AADAOQAAgBkAAAAPAAAACQAAAAkAAAAIAAAACAAAAAgAAIAYAADAOAAA//8AAP//AAD//wAA</Image>
<Url type="application/x-suggestions+json" method="GET"
template="http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}" />
<Url type="text/html" method="GET" template="http://search.yahoo.com/search">
<Param name="p" value="{searchTerms}"/>
<Param name="ei" value="UTF-8"/>
<MozParam name="fr" condition="pref" pref="yahoo-fr" />
</Url>
<SearchForm>http://search.yahoo.com/</SearchForm>
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1263,17 +1263,19 @@ tabpanels {
/* Tabstrip close button */
.tabs-closebutton {
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
border: none;
margin-bottom: 1px;
}
.tabs-closebutton > .toolbarbutton-icon {
- margin: 0;
+ /* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
+ use evil CSS to give the impression of smaller content */
+ margin: -2px;
}
/* Tabbrowser arrowscrollbox arrows */
.tabbrowser-arrowscrollbox > .scrollbutton-up {
-moz-appearance: tab-scroll-arrow-back;
margin: 0;
}
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -41,48 +41,29 @@
*
* ***** END LICENSE BLOCK ***** */
@import url("chrome://global/skin/");
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
-#urlbar:-moz-lwtheme:not([focused="true"]),
-.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
- opacity: .85;
-}
-
-.tabbrowser-tab:-moz-lwtheme[selected="true"] {
- text-shadow: none;
-}
-
-.tabbrowser-tabs:-moz-lwtheme {
- -moz-appearance: none;
- background: none;
- border-style: none;
-}
-
-.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) {
- color: inherit;
-}
-
#menubar-items {
-moz-box-orient: vertical; /* for flex hack */
}
#main-menubar {
-moz-box-flex: 1; /* make menu items expand to fill toolbar height */
}
#personal-bookmarks {
min-height: 24px;
}
-#navigator-toolbox:-moz-system-metric(windows-default-theme) {
+#navigator-toolbox:-moz-system-metric(windows-default-theme):not(:-moz-lwtheme) {
padding-bottom: 1px; /* uxtheme border drawing fix/hack */
}
#navigator-toolbox[inFullscreen="true"],
#navigator-toolbox[inFullscreen="true"] > #nav-bar {
border-top: none;
}
@@ -224,25 +205,16 @@ toolbar[mode="full"] .toolbarbutton-menu
.toolbarbutton-menubutton-button {
padding: 5px;
}
.toolbarbutton-1[checked="true"] {
padding: 5px !important;
}
-toolbar[iconsize="large"][mode="icons"] .toolbarbutton-1:-moz-system-metric(windows-default-theme),
-.toolbarbutton-menubutton-button:-moz-system-metric(windows-default-theme) {
- padding: 6px; /* uxtheme border drawing fix/hack */
-}
-
-toolbar[iconsize="large"][mode="icons"] .toolbarbutton-1[checked="true"]:-moz-system-metric(windows-default-theme) {
- padding: 6px !important; /* uxtheme border drawing fix/hack */
-}
-
#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
#back-forward-dropmarker:-moz-locale-dir(rtl) > .toolbarbutton-icon {
-moz-transform: scaleX(-1);
}
/* ::::: unified back and forward buttons ::::: */
@@ -879,16 +851,21 @@ toolbar[iconsize="small"] #fullscreen-bu
/* ::::: nav-bar-inner ::::: */
#urlbar {
width: 7em;
min-width: 7em;
}
+#urlbar:-moz-lwtheme:not([focused="true"]),
+.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
+ opacity: .85;
+}
+
#urlbar:-moz-system-metric(windows-default-theme) {
-moz-appearance: none;
border-width: 1px;
-moz-border-top-colors: ThreeDShadow;
-moz-border-bottom-colors: ThreeDShadow;
-moz-border-right-colors: ThreeDShadow;
-moz-border-left-colors: ThreeDShadow;
}
@@ -1154,38 +1131,67 @@ statusbarpanel#statusbar-display {
}
/* Tabstrip */
.tabbrowser-tabs {
-moz-appearance: -moz-win-browsertabbar-toolbox;
background: -moz-dialog url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
}
+.tabbrowser-tabs:-moz-lwtheme {
+ -moz-appearance: none;
+ background: none;
+ border-style: none;
+}
+
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
min-height: .81cm;
}
.tabs-container:not([overflow="true"]) {
-moz-padding-start: 3px;
}
/* Tabs */
-.tabbrowser-tab {
+.tabbrowser-tab,
+.tabbrowser-arrowscrollbox > .scrollbutton-up,
+.tabbrowser-arrowscrollbox > .scrollbutton-down,
+.tabs-newtab-button,
+.tabs-alltabs-button {
-moz-appearance: none;
background: url("chrome://browser/skin/tabbrowser/tab-bkgnd.png") repeat-x;
margin: 3px 0px 4px;
- padding: 0px 1px 1px 0px;
border: 2px solid;
border-right-width: 1px;
border-bottom: none;
+ -moz-border-top-colors: ThreeDShadow rgba(255,255,255,.3);
+ -moz-border-left-colors: ThreeDShadow rgba(255,255,255,.3);
+}
+
+.tabbrowser-tab:-moz-lwtheme-brighttext,
+.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-brighttext,
+.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-brighttext,
+.tabs-newtab-button:-moz-lwtheme-brighttext,
+.tabs-alltabs-button:-moz-lwtheme-brighttext {
+ background-color: rgba(0,0,0,.5);
+}
+
+.tabbrowser-tab:-moz-lwtheme-darktext,
+.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-darktext,
+.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-darktext,
+.tabs-newtab-button:-moz-lwtheme-darktext,
+.tabs-alltabs-button:-moz-lwtheme-darktext {
+ background-color: rgba(255,255,255,.5);
+}
+
+.tabbrowser-tab {
+ padding: 0 1px 1px 0;
-moz-border-radius-topleft: 2px;
-moz-border-radius-topright: 2px;
- -moz-border-top-colors: ThreeDShadow rgba(255,255,255,.3);
-moz-border-right-colors: rgba(0,0,0,.1);
- -moz-border-left-colors: ThreeDShadow rgba(255,255,255,.3);
}
.tabbrowser-tab:hover,
.tabbrowser-tab[selected="true"] {
border-width: 1px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
-moz-border-top-colors: ThreeDShadow;
@@ -1202,16 +1208,24 @@ statusbarpanel#statusbar-display {
.tabbrowser-tab[selected="true"] {
margin: 2px 0px 3px;
padding: 1px;
background-image: url("chrome://browser/skin/tabbrowser/tab-active-bkgnd.png");
background-color: -moz-dialog;
font-weight: bold;
}
+.tabbrowser-tab:-moz-lwtheme[selected="true"] {
+ text-shadow: none;
+}
+
+.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) {
+ color: inherit;
+}
+
.tabbrowser-tab[busy] > .tab-icon-image {
list-style-image: url("chrome://browser/skin/tabbrowser/progress.png") !important;
-moz-image-region: rect(0, 16px, 16px, 0);
}
.tabbrowser-tab[busy][stalled] > .tab-icon-image {
list-style-image: url("chrome://browser/skin/tabbrowser/progress-pulsing.png") !important;
}
.tabbrowser-tab[busy][progress="1"] > .tab-icon-image {
@@ -1327,27 +1341,19 @@ tabpanels {
outline: none !important;
}
/* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */
.tabbrowser-arrowscrollbox > .scrollbutton-up,
.tabbrowser-arrowscrollbox > .scrollbutton-down,
.tabs-newtab-button,
.tabs-alltabs-button {
- -moz-appearance: none;
width: 18px;
- margin: 3px 0px 4px;
- padding: 0px;
- border: 2px solid;
- border-right-width: 1px;
- border-bottom: none;
- -moz-border-top-colors: ThreeDShadow rgba(255,255,255,.3);
+ padding: 0;
-moz-border-right-colors: ThreeDShadow;
- -moz-border-left-colors: ThreeDShadow rgba(255,255,255,.3);
- background: url("chrome://browser/skin/tabbrowser/tab-bkgnd.png") repeat-x;
-moz-image-region: rect(0, 11px, 14px, 0);
}
.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-system-metric(touch-enabled),
.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-system-metric(touch-enabled),
.tabs-alltabs-button:-moz-system-metric(touch-enabled) {
min-width: .81cm;
}
@@ -1860,25 +1866,16 @@ toolbarbutton.bookmark-item[dragover="tr
#nav-bar[mode="full"][currentset$=",urlbar-container"],
#nav-bar[mode="full"][currentset$=",search-container"],
#nav-bar[iconsize="large"][mode="icons"]:not([currentset]),
#nav-bar[iconsize="large"][mode="icons"][currentset$=",urlbar-container"],
#nav-bar[iconsize="large"][mode="icons"][currentset$=",search-container"] {
-moz-padding-end: 2px;
}
-#nav-bar[mode="full"]:not([currentset]):-moz-system-metric(windows-default-theme),
-#nav-bar[mode="full"][currentset$=",urlbar-container"]:-moz-system-metric(windows-default-theme),
-#nav-bar[mode="full"][currentset$=",search-container"]:-moz-system-metric(windows-default-theme),
-#nav-bar[iconsize="large"][mode="icons"]:not([currentset]):-moz-system-metric(windows-default-theme),
-#nav-bar[iconsize="large"][mode="icons"][currentset$=",urlbar-container"]:-moz-system-metric(windows-default-theme),
-#nav-bar[iconsize="large"][mode="icons"][currentset$=",search-container"]:-moz-system-metric(windows-default-theme) {
- -moz-padding-end: 3px;
-}
-
/* ::::: Keyboard UI Panel ::::: */
.KUI-panel {
-moz-appearance: none;
background: rgba(27%,27%,27%,.9) url(KUI-background.png) repeat-x;
color: white;
border-style: none;
-moz-border-radius: 20px;
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -61,16 +61,17 @@ SCRIPT_DIR = os.path.abspath(os.path.rea
__all__ = [
"UNIXISH",
"IS_WIN32",
"IS_MAC",
"log",
"runApp",
"Process",
+ "addExtraCommonOptions",
"initializeProfile",
"DIST_BIN",
"DEFAULT_APP",
"CERTS_SRC_DIR",
"environment",
"IS_TEST_BUILD",
"IS_DEBUG_BUILD",
"DEFAULT_TIMEOUT",
@@ -346,16 +347,25 @@ user_pref("camino.use_system_proxy_setti
part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
prefs.append(part)
# write the preferences
prefsFile = open(profileDir + "/" + "user.js", "a")
prefsFile.write("".join(prefs))
prefsFile.close()
+def addExtraCommonOptions(parser):
+ "Adds command-line options which are common to mochitest and reftest."
+
+ parser.add_option("--setpref",
+ action = "append", type = "string",
+ default = [],
+ dest = "extraPrefs", metavar = "PREF=VALUE",
+ help = "defines an extra user preference")
+
def fillCertificateDB(profileDir, certPath, utilityPath, xrePath):
pwfilePath = os.path.join(profileDir, ".crtdbpw")
pwfile = open(pwfilePath, "w")
pwfile.write("\n")
pwfile.close()
# Create head of the ssltunnel configuration file
@@ -432,47 +442,51 @@ def environment(env = None, xrePath = DI
ldLibraryPath = ldLibraryPath + ":" + env[envVar]
env[envVar] = ldLibraryPath
elif IS_WIN32:
env["PATH"] = env["PATH"] + ";" + ldLibraryPath
if crashreporter:
env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
env['MOZ_CRASHREPORTER'] = '1'
+ else:
+ env['MOZ_CRASHREPORTER_DISABLE'] = '1'
+
env['GNOME_DISABLE_CRASH_DIALOG'] = "1"
return env
if IS_WIN32:
- #XXX: disabled on windows for now, see bug 525370
- def readWithTimeout(f, timeout):
- return (f.readline(), False)
-elif False:
- #XXX: figure out what's going wrong with this code!
import ctypes, time, msvcrt
PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
GetLastError = ctypes.windll.kernel32.GetLastError
def readWithTimeout(f, timeout):
"""Try to read a line of output from the file object |f|.
|f| must be a pipe, like the |stdout| member of a subprocess.Popen
object created with stdout=PIPE. If no output
is received within |timeout| seconds, return a blank line.
Returns a tuple (line, did_timeout), where |did_timeout| is True
if the read timed out, and False otherwise."""
+ if timeout is None:
+ # shortcut to allow callers to pass in "None" for no timeout.
+ return (f.readline(), False)
x = msvcrt.get_osfhandle(f.fileno())
l = ctypes.c_long()
- buf = ctypes.create_string_buffer('', 1024)
done = time.time() + timeout
while time.time() < done:
- if PeekNamedPipe(x, buf, len(buf), None, ctypes.byref(l), None) == 0:
- err = GetLastError()
- if err == 38 or err == 109: # ERROR_HANDLE_EOF || ERROR_BROKEN_PIPE
- return ('', False)
- if (l > 0 and '\n' in buf.value):
- return (f.readline(), False)
- time.sleep(0.1)
+ if PeekNamedPipe(x, None, 0, None, ctypes.byref(l), None) == 0:
+ err = GetLastError()
+ if err == 38 or err == 109: # ERROR_HANDLE_EOF || ERROR_BROKEN_PIPE
+ return ('', False)
+ else:
+ log.error("readWithTimeout got error: %d", err)
+ if l > 0:
+ # we're assuming that the output is line-buffered,
+ # which is not unreasonable
+ return (f.readline(), False)
+ time.sleep(0.01)
return ('', True)
else:
def readWithTimeout(f, timeout):
"""Try to read a line of output from the file object |f|. If no output
is received within |timeout| seconds, return a blank line.
Returns a tuple (line, did_timeout), where |did_timeout| is True
if the read timed out, and False otherwise."""
(r, w, e) = select.select([f], [], [], timeout)
@@ -488,17 +502,17 @@ def triggerBreakpad(proc, utilityPath):
# SEGV will get picked up by Breakpad's signal handler
os.kill(proc.pid, signal.SIGSEGV)
return
elif IS_WIN32:
# We should have a "crashinject" program in our utility path
crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe"))
if os.path.exists(crashinject) and subprocess.Popen([crashinject, str(proc.pid)]).wait() == 0:
return
- #TODO: kill the process such that it triggers Breakpad on OS X
+ #TODO: kill the process such that it triggers Breakpad on OS X (bug 525296)
log.info("Can't trigger Breakpad, just killing process")
proc.kill()
###############
# RUN THE APP #
###############
def runApp(testURL, env, app, profileDir, extraArgs,
--- a/build/pgo/profileserver.py.in
+++ b/build/pgo/profileserver.py.in
@@ -65,14 +65,11 @@ if __name__ == '__main__':
automation.initializeProfile(PROFILE_DIRECTORY)
browserEnv = automation.environment()
browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
url = "http://localhost:%d/index.html" % PORT
appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
# the profiling HTML doesn't output anything,
- # so let's just set this really high for now.
- #FIXME: the POSIX codepath accepts None
- # as "no timeout", the Windows codepath
- # should too.
- timeout = 1800.0)
+ # so let's just run this without a timeout
+ timeout = None)
sys.exit(status)
--- a/build/win32/crashinject.cpp
+++ b/build/win32/crashinject.cpp
@@ -1,128 +1,128 @@
-/* ***** 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 Crash Injection Utility
- *
- * The Initial Developer of the Original Code is
- * The Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ted Mielczarek <ted.mielczarek@gmail.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 ***** */
-
-/*
- * Given a PID, this program attempts to inject a DLL into the process
- * with that PID. The DLL it attempts to inject, "crashinjectdll.dll",
- * must exist alongside this exe. The DLL will then crash the process.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <Windows.h>
-
-int main(int argc, char** argv)
-{
- if (argc != 2) {
- fprintf(stderr, "Usage: crashinject <PID>\n");
- return 1;
- }
-
- int pid = atoi(argv[1]);
- if (pid <= 0) {
- fprintf(stderr, "Usage: crashinject <PID>\n");
- return 1;
- }
-
- // find our DLL to inject
- wchar_t filename[_MAX_PATH];
- if (GetModuleFileNameW(NULL, filename, sizeof(filename) / sizeof(wchar_t)) == 0)
- return 1;
-
- wchar_t* slash = wcsrchr(filename, L'\\');
- if (slash == NULL)
- return 1;
-
- slash++;
- wcscpy(slash, L"crashinjectdll.dll");
-
- // now find our target process
- HANDLE targetProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD,
- FALSE,
- pid);
- if (targetProc == NULL) {
- fprintf(stderr, "Error %d opening target process\n", GetLastError());
- return 1;
- }
-
- /*
- * This is sort of insane, but we're implementing a technique described here:
- * http://www.codeproject.com/KB/threads/winspy.aspx#section_2
- *
- * The gist is to use CreateRemoteThread to create a thread in the other
- * process, but cheat and make the thread function kernel32!LoadLibrary,
- * so that the only remote data we have to pass to the other process
- * is the path to the library we want to load. The library we're loading
- * will then do its dirty work inside the other process.
- */
- HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
- // allocate some memory to hold the path in the remote process
- void* pLibRemote = VirtualAllocEx(targetProc, NULL, sizeof(filename),
- MEM_COMMIT, PAGE_READWRITE);
- if (pLibRemote == NULL) {
- fprintf(stderr, "Error %d in VirtualAllocEx\n", GetLastError());
- CloseHandle(targetProc);
- return 1;
- }
-
- if (!WriteProcessMemory(targetProc, pLibRemote, (void*)filename,
- sizeof(filename), NULL)) {
- fprintf(stderr, "Error %d in WriteProcessMemory\n", GetLastError());
- VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
- CloseHandle(targetProc);
- return 1;
- }
- // Now create a thread in the target process that will load our DLL
- HANDLE hThread = CreateRemoteThread(
- targetProc, NULL, 0,
- (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32,
- "LoadLibraryW"),
- pLibRemote, 0, NULL);
- if (hThread == NULL) {
- fprintf(stderr, "Error %d in CreateRemoteThread\n", GetLastError());
- VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
- CloseHandle(targetProc);
- return 1;
- }
- WaitForSingleObject(hThread, INFINITE);
- // Cleanup, not that it's going to matter at this point
- CloseHandle(hThread);
- VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
- CloseHandle(targetProc);
-
- return 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 Crash Injection Utility
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ted Mielczarek <ted.mielczarek@gmail.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 ***** */
+
+/*
+ * Given a PID, this program attempts to inject a DLL into the process
+ * with that PID. The DLL it attempts to inject, "crashinjectdll.dll",
+ * must exist alongside this exe. The DLL will then crash the process.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+
+int main(int argc, char** argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: crashinject <PID>\n");
+ return 1;
+ }
+
+ int pid = atoi(argv[1]);
+ if (pid <= 0) {
+ fprintf(stderr, "Usage: crashinject <PID>\n");
+ return 1;
+ }
+
+ // find our DLL to inject
+ wchar_t filename[_MAX_PATH];
+ if (GetModuleFileNameW(NULL, filename, sizeof(filename) / sizeof(wchar_t)) == 0)
+ return 1;
+
+ wchar_t* slash = wcsrchr(filename, L'\\');
+ if (slash == NULL)
+ return 1;
+
+ slash++;
+ wcscpy(slash, L"crashinjectdll.dll");
+
+ // now find our target process
+ HANDLE targetProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD,
+ FALSE,
+ pid);
+ if (targetProc == NULL) {
+ fprintf(stderr, "Error %d opening target process\n", GetLastError());
+ return 1;
+ }
+
+ /*
+ * This is sort of insane, but we're implementing a technique described here:
+ * http://www.codeproject.com/KB/threads/winspy.aspx#section_2
+ *
+ * The gist is to use CreateRemoteThread to create a thread in the other
+ * process, but cheat and make the thread function kernel32!LoadLibrary,
+ * so that the only remote data we have to pass to the other process
+ * is the path to the library we want to load. The library we're loading
+ * will then do its dirty work inside the other process.
+ */
+ HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
+ // allocate some memory to hold the path in the remote process
+ void* pLibRemote = VirtualAllocEx(targetProc, NULL, sizeof(filename),
+ MEM_COMMIT, PAGE_READWRITE);
+ if (pLibRemote == NULL) {
+ fprintf(stderr, "Error %d in VirtualAllocEx\n", GetLastError());
+ CloseHandle(targetProc);
+ return 1;
+ }
+
+ if (!WriteProcessMemory(targetProc, pLibRemote, (void*)filename,
+ sizeof(filename), NULL)) {
+ fprintf(stderr, "Error %d in WriteProcessMemory\n", GetLastError());
+ VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+ CloseHandle(targetProc);
+ return 1;
+ }
+ // Now create a thread in the target process that will load our DLL
+ HANDLE hThread = CreateRemoteThread(
+ targetProc, NULL, 0,
+ (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32,
+ "LoadLibraryW"),
+ pLibRemote, 0, NULL);
+ if (hThread == NULL) {
+ fprintf(stderr, "Error %d in CreateRemoteThread\n", GetLastError());
+ VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+ CloseHandle(targetProc);
+ return 1;
+ }
+ WaitForSingleObject(hThread, INFINITE);
+ // Cleanup, not that it's going to matter at this point
+ CloseHandle(hThread);
+ VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE);
+ CloseHandle(targetProc);
+
+ return 0;
+}
--- a/build/win32/crashinjectdll/Makefile.in
+++ b/build/win32/crashinjectdll/Makefile.in
@@ -1,53 +1,53 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Mozilla core build scripts.
-#
-# The Initial Developer of the Original Code is
-# The Mozilla Foundation
-#
-# Portions created by the Initial Developer are Copyright (C) 2009
-# the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
-#
-# Contributor(s):
-# Ted Mielczarek <ted.mielczarek@gmail.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 *****
-
-DEPTH = ../../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-LIBRARY_NAME = crashinjectdll
-DEFFILE = $(srcdir)/crashinjectdll.def
-FORCE_SHARED_LIB = 1
-USE_STATIC_LIBS = 1
-
-CPPSRCS = crashinjectdll.cpp
-
-include $(topsrcdir)/config/rules.mk
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla core build scripts.
+#
+# The Initial Developer of the Original Code is
+# The Mozilla Foundation
+#
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+#
+# Contributor(s):
+# Ted Mielczarek <ted.mielczarek@gmail.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+LIBRARY_NAME = crashinjectdll
+DEFFILE = $(srcdir)/crashinjectdll.def
+FORCE_SHARED_LIB = 1
+USE_STATIC_LIBS = 1
+
+CPPSRCS = crashinjectdll.cpp
+
+include $(topsrcdir)/config/rules.mk
--- a/build/win32/crashinjectdll/crashinjectdll.cpp
+++ b/build/win32/crashinjectdll/crashinjectdll.cpp
@@ -1,34 +1,34 @@
-#include <stdio.h>
-#include <Windows.h>
-
-// make sure we only ever spawn one thread
-DWORD tid = -1;
-
-DWORD WINAPI CrashingThread(
- LPVOID lpParameter
-)
-{
- // not a very friendly DLL
- volatile int* x = (int *)0x0;
- *x = 1;
- return 0;
-}
-
-BOOL WINAPI DllMain(
- HANDLE hinstDLL,
- DWORD dwReason,
- LPVOID lpvReserved
-)
-{
- if (tid == -1)
- // we have to crash on another thread because LoadLibrary() will
- // catch memory access errors and return failure to the calling process
- CreateThread(
- NULL, // default security attributes
- 0, // use default stack size
- CrashingThread , // thread function name
- NULL, // argument to thread function
- 0, // use default creation flags
- &tid); // returns the thread identifier
- return TRUE;
-}
+#include <stdio.h>
+#include <windows.h>
+
+// make sure we only ever spawn one thread
+DWORD tid = -1;
+
+DWORD WINAPI CrashingThread(
+ LPVOID lpParameter
+)
+{
+ // not a very friendly DLL
+ volatile int* x = (int *)0x0;
+ *x = 1;
+ return 0;
+}
+
+BOOL WINAPI DllMain(
+ HANDLE hinstDLL,
+ DWORD dwReason,
+ LPVOID lpvReserved
+)
+{
+ if (tid == -1)
+ // we have to crash on another thread because LoadLibrary() will
+ // catch memory access errors and return failure to the calling process
+ CreateThread(
+ NULL, // default security attributes
+ 0, // use default stack size
+ CrashingThread , // thread function name
+ NULL, // argument to thread function
+ 0, // use default creation flags
+ &tid); // returns the thread identifier
+ return TRUE;
+}
--- a/build/win32/crashinjectdll/crashinjectdll.def
+++ b/build/win32/crashinjectdll/crashinjectdll.def
@@ -1,3 +1,3 @@
-LIBRARY crashinjectdll
-EXPORTS
- DllMain
+LIBRARY crashinjectdll
+EXPORTS
+ DllMain
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -627,16 +627,20 @@ MOZ_PLATFORM_HILDON = @MOZ_PLATFORM_HILD
LIBHILDONMIME_CFLAGS = @LIBHILDONMIME_CFLAGS@
LIBHILDONMIME_LIBS = @LIBHILDONMIME_LIBS@
LIBOSSO_CFLAGS = @LIBOSSO_CFLAGS@
LIBOSSO_LIBS = @LIBOSSO_LIBS@
LIBHILDONFM_CFLAGS = @LIBHILDONFM_CFLAGS@
LIBHILDONFM_LIBS = @LIBHILDONFM_LIBS@
+MOZ_ENABLE_LIBCONIC = @MOZ_ENABLE_LIBCONIC@
+LIBCONIC_CFLAGS = @LIBCONIC_CFLAGS@
+LIBCONIC_LIBS = @LIBCONIC_LIBS@
+
MACOS_SDK_DIR = @MACOS_SDK_DIR@
NEXT_ROOT = @NEXT_ROOT@
GCC_VERSION = @GCC_VERSION@
XCODEBUILD_VERSION= @XCODEBUILD_VERSION@
HAS_XCODE_2_1 = @HAS_XCODE_2_1@
UNIVERSAL_BINARY= @UNIVERSAL_BINARY@
HAVE_DTRACE= @HAVE_DTRACE@
--- a/config/system-headers
+++ b/config/system-headers
@@ -550,17 +550,16 @@ pango-modules.h
pango/pangocairo.h
pango/pangofc-decoder.h
pango/pangofc-font.h
pango/pangofc-fontmap.h
pango/pango-break.h
pango/pango-fontmap.h
pango/pango.h
pango/pangoxft.h
-pango/pangox.h
pango/pango-utils.h
pango-types.h
pascal.h
Patches.h
Path.h
pcfs/pc_dir.h
Pgenerr.h
PGenErr.h
--- a/config/utils.py
+++ b/config/utils.py
@@ -71,17 +71,17 @@ def lockFile(lockfile, max_wait = 600):
# should not occur
raise
try:
# the lock file exists, try to stat it to get its age
# and read its contents to report the owner PID
f = open(lockfile, "r")
s = os.stat(lockfile)
- except OSError, e:
+ except EnvironmentError, e:
if e.errno != errno.ENOENT:
sys.exit("%s exists but stat() failed: %s" %
(lockfile, e.strerror))
# we didn't create the lockfile, so it did exist, but it's
# gone now. Just try again
continue
# we didn't create the lockfile and it's still there, check
--- a/configure.in
+++ b/configure.in
@@ -1501,16 +1501,35 @@ if test "$GNU_CXX"; then
ac_has_wno_invalid_offsetof="yes",
ac_has_wno_invalid_offsetof="no")
CXXFLAGS="$_SAVE_CXXFLAGS"
AC_LANG_RESTORE
])
if test "$ac_has_wno_invalid_offsetof" = "yes"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
fi
+
+ AC_CACHE_CHECK(whether the compiler supports -Wno-variadic-macros,
+ ac_has_wno_variadic_macros,
+ [
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ _SAVE_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-variadic-macros"
+ AC_TRY_COMPILE([],
+ [return(0);],
+ ac_has_wno_variadic_macros="yes",
+ ac_has_wno_variadic_macros="no")
+ CXXFLAGS="$_SAVE_CXXFLAGS"
+ AC_LANG_RESTORE
+ ])
+ if test "$ac_has_wno_variadic_macros" = "yes"; then
+ _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-variadic-macros"
+ fi
+
else
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
fi
dnl gcc can come with its own linker so it is better to use the pass-thru calls
dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
dnl files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker to
dnl normal behavior.
@@ -4151,22 +4170,26 @@ AC_CACHE_CHECK(for trouble comparing to
template <class T> int operator!=(const T2*, const T&) { return 0; }],
[Foo<int> f; return (0 != f);],
ac_cv_trouble_comparing_to_zero=no,
ac_cv_trouble_comparing_to_zero=yes)])
if test "$ac_cv_trouble_comparing_to_zero" = yes ; then
AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
fi
+# try harder, when checking for __thread support, see bug 521750 comment #33 and below
+_SAVE_LDFLAGS=$LDFLAGS
+LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS $DSO_LDOPTS"
AC_CACHE_CHECK(for __thread keyword for TLS variables,
ac_cv_thread_keyword,
[AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
[return tlsIsMainThread;],
ac_cv_thread_keyword=yes,
ac_cv_thread_keyword=no)])
+LDFLAGS=$_SAVE_LDFLAGS
if test "$ac_cv_thread_keyword" = yes; then
AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
fi
dnl End of C++ language/feature checks
AC_LANG_C
dnl ========================================================
@@ -6216,16 +6239,38 @@ dnl = Disable zipwriter
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(zipwriter,
[ --disable-zipwriter Disable zipwriter component],
MOZ_ZIPWRITER=,
MOZ_ZIPWRITER=1 )
AC_SUBST(MOZ_ZIPWRITER)
dnl ========================================================
+dnl = Disable libconic
+dnl ========================================================
+MOZ_ENABLE_LIBCONIC=1
+MOZ_ARG_DISABLE_BOOL(libconic,
+[ --disable-libconic Disable libconic],
+ MOZ_ENABLE_LIBCONIC=,
+ MOZ_ENABLE_LIBCONIC=1 )
+
+if test -n "$MOZ_ENABLE_LIBCONIC"; then
+ PKG_CHECK_MODULES(LIBCONIC, conic,
+ MOZ_ENABLE_LIBCONIC=1,
+ MOZ_ENABLE_LIBCONIC=)
+fi
+if test "$MOZ_ENABLE_LIBCONIC"; then
+ AC_DEFINE(MOZ_ENABLE_LIBCONIC)
+fi
+
+AC_SUBST(MOZ_ENABLE_LIBCONIC)
+AC_SUBST(LIBCONIC_CFLAGS)
+AC_SUBST(LIBCONIC_LIBS)
+
+dnl ========================================================
dnl = Hildon and OSSO checks
dnl ========================================================
PKG_CHECK_MODULES(LIBHILDONMIME,libhildonmime,
MOZ_PLATFORM_HILDON=1,
MOZ_PLATFORM_HILDON=)
if test $MOZ_PLATFORM_HILDON; then
AC_DEFINE(MOZ_PLATFORM_HILDON)
X11_COMPOSITED_PLUGINS="yes"
--- a/content/base/public/nsIDOMFile.idl
+++ b/content/base/public/nsIDOMFile.idl
@@ -43,14 +43,14 @@ interface nsIDOMFileError;
interface nsIDOMFile : nsISupports
{
//fileName and fileSize are now deprecated attributes
readonly attribute DOMString fileName;
readonly attribute unsigned long long fileSize;
readonly attribute DOMString name;
readonly attribute unsigned long long size;
- readonly attribute DOMString mediaType;
+ readonly attribute DOMString type;
DOMString getAsText(in DOMString encoding); // raises(FileException) on retrieval
DOMString getAsDataURL(); // raises(FileException) on retrieval
DOMString getAsBinary(); // raises(FileException) on retrieval
};
--- a/content/base/public/nsIDOMFileReader.idl
+++ b/content/base/public/nsIDOMFileReader.idl
@@ -45,17 +45,17 @@ interface nsIDOMFileError;
interface nsIDOMFileReader : nsISupports
{
void readAsBinaryString(in nsIDOMFile filedata);
void readAsText(in nsIDOMFile filedata, [optional] in DOMString encoding);
void readAsDataURL(in nsIDOMFile file);
void abort();
- const unsigned short INITIAL = 0;
+ const unsigned short EMPTY = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute DOMString result;
readonly attribute nsIDOMFileError error;
// event handler attributes
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1173,24 +1173,26 @@ public:
* so once can know whether a document is expected to be rendered left-to-right
* or right-to-left.
*/
virtual PRBool IsDocumentRightToLeft() { return PR_FALSE; }
enum DocumentTheme {
Doc_Theme_Uninitialized, // not determined yet
Doc_Theme_None,
+ Doc_Theme_Neutral,
Doc_Theme_Dark,
Doc_Theme_Bright
};
/**
- * Returns Doc_Theme_None if there is no lightweight theme specified, Doc_Theme_Dark
- * for a dark theme and Doc_Theme_Bright for a light theme. This is used to
- * determine the state of the pseudoclasses :-moz-lwtheme and :-moz-lwtheme-text.
+ * Returns Doc_Theme_None if there is no lightweight theme specified,
+ * Doc_Theme_Dark for a dark theme, Doc_Theme_Bright for a light theme, and
+ * Doc_Theme_Neutral for any other theme. This is used to determine the state
+ * of the pseudoclasses :-moz-lwtheme and :-moz-lwtheme-text.
*/
virtual int GetDocumentLWTheme() { return Doc_Theme_None; }
/**
* Gets the document's cached pointer to the first <base> element in this
* document which has an href attribute. If the document doesn't contain any
* <base> elements with an href, returns null.
*/
--- a/content/base/public/nsIScriptElement.h
+++ b/content/base/public/nsIScriptElement.h
@@ -38,34 +38,36 @@
#ifndef nsIScriptElement_h___
#define nsIScriptElement_h___
#include "nsISupports.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#include "nsIScriptLoaderObserver.h"
+#include "nsWeakPtr.h"
+#include "nsIParser.h"
-// e68ddc48-4055-4ba9-978d-c49d9cf3189a
#define NS_ISCRIPTELEMENT_IID \
-{ 0xe68ddc48, 0x4055, 0x4ba9, \
- { 0x97, 0x8d, 0xc4, 0x9d, 0x9c, 0xf3, 0x18, 0x9a } }
+{ 0xa28c198e, 0x14f0, 0x42b1, \
+{ 0x8f, 0x6b, 0x0e, 0x7f, 0xca, 0xb4, 0xf4, 0xe8 } }
/**
* Internal interface implemented by script elements
*/
class nsIScriptElement : public nsIScriptLoaderObserver {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
nsIScriptElement()
: mLineNumber(0),
mIsEvaluated(PR_FALSE),
mMalformed(PR_FALSE),
- mDoneAddingChildren(PR_TRUE)
+ mDoneAddingChildren(PR_TRUE),
+ mCreatorParser(nsnull)
{
}
/**
* Content type identifying the scripting language. Can be empty, in
* which case javascript will be assumed.
*/
virtual void GetScriptType(nsAString& type) = 0;
@@ -117,18 +119,59 @@ public:
}
void WillCallDoneAddingChildren()
{
NS_ASSERTION(mDoneAddingChildren, "unexpected, but not fatal");
mDoneAddingChildren = PR_FALSE;
}
+ void SetCreatorParser(nsIParser* aParser)
+ {
+ mCreatorParser = getter_AddRefs(NS_GetWeakReference(aParser));
+ }
+
+ /**
+ * Informs the creator parser that the evaluation of this script is starting
+ */
+ void BeginEvaluating()
+ {
+ // Once the async attribute is supported, don't do this if this is an
+ // async script.
+ nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
+ if (parser) {
+ parser->BeginEvaluatingParserInsertedScript();
+ }
+ }
+
+ /**
+ * Informs the creator parser that the evaluation of this script is ending
+ */
+ void EndEvaluating()
+ {
+ // Once the async attribute is supported, don't do this if this is an
+ // async script.
+ nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
+ if (parser) {
+ parser->EndEvaluatingParserInsertedScript();
+ }
+ }
+
+ /**
+ * Retrieves a pointer to the creator parser if this has one or null if not
+ */
+ already_AddRefed<nsIParser> GetCreatorParser()
+ {
+ nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
+ return parser.forget();
+ }
+
protected:
PRUint32 mLineNumber;
PRPackedBool mIsEvaluated;
PRPackedBool mMalformed;
PRPackedBool mDoneAddingChildren;
+ nsWeakPtr mCreatorParser;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID)
#endif // nsIScriptElement_h___
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -120,35 +120,35 @@ nsDOMFile::GetSize(PRUint64 *aFileSize)
}
*aFileSize = fileSize;
return NS_OK;
}
NS_IMETHODIMP
-nsDOMFile::GetMediaType(nsAString &aMediaType)
+nsDOMFile::GetType(nsAString &aType)
{
if (!mContentType.Length()) {
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
- nsCAutoString mediaType;
- rv = mimeService->GetTypeFromFile(mFile, mediaType);
+ nsCAutoString mimeType;
+ rv = mimeService->GetTypeFromFile(mFile, mimeType);
if (NS_FAILED(rv)) {
- SetDOMStringToNull(aMediaType);
+ aType.Truncate();
return NS_OK;
}
- AppendUTF8toUTF16(mediaType, mContentType);
+ AppendUTF8toUTF16(mimeType, mContentType);
}
- aMediaType = mContentType;
+ aType = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFile::GetAsText(const nsAString &aCharset, nsAString &aResult)
{
aResult.Truncate();
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -149,17 +149,17 @@ nsDOMFileReader::Notify(const char *aCha
return NS_OK;
}
//nsDOMFileReader constructors/initializers
nsDOMFileReader::nsDOMFileReader()
: mFileData(nsnull), mReadCount(0),
mDataLen(0), mDataFormat(0),
- mReadyState(nsIDOMFileReader::INITIAL),
+ mReadyState(nsIDOMFileReader::EMPTY),
mProgressEventWasDelayed(PR_FALSE),
mTimerIsActive(PR_FALSE),
mReadTotal(0), mReadTransferred(0),
mReadComplete(PR_TRUE)
{
nsLayoutStatics::AddRef();
}
@@ -314,17 +314,17 @@ nsDOMFileReader::Abort()
//Clean up memory buffer
PR_Free(mFileData);
mFileData = nsnull;
//Dispatch the abort event
DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
- mReadyState = nsIDOMFileReader::INITIAL;
+ mReadyState = nsIDOMFileReader::EMPTY;
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP
nsDOMFileReader::Notify(nsITimer* aTimer)
{
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -504,16 +504,25 @@ nsScriptLoader::ProcessScriptElement(nsI
if (i != nsTArray<PreloadInfo>::NoIndex) {
request = mPreloads[i].mRequest;
request->mElement = aElement;
request->mJSVersion = version;
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
!aElement->GetScriptAsync();
mPreloads.RemoveElementAt(i);
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ nsCString spec;
+ request->mURI->GetSpec(spec);
+ printf("Grabbing existing speculative load for %s (%p). async:%d defer:%d\n",
+ spec.get(), request.get(), aElement->GetScriptAsync(),
+ request->mDefer);
+ }
+
+
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
if (NS_FAILED(rv)) {
// Note, we're dropping our last ref to request here.
return rv;
}
// Can we run the script now?
// This is true if we're done loading, the script isn't deferred and
@@ -553,28 +562,40 @@ nsScriptLoader::ProcessScriptElement(nsI
// First check to see if this is an external script
if (scriptURI) {
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
!aElement->GetScriptAsync();
request->mURI = scriptURI;
request->mIsInline = PR_FALSE;
request->mLoading = PR_TRUE;
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ nsCString spec;
+ request->mURI->GetSpec(spec);
+ printf("Starting normal load for %s (%p). async:%d defer:%d\n",
+ spec.get(), request.get(), aElement->GetScriptAsync(),
+ request->mDefer);
+ }
+
rv = StartLoad(request, type);
if (NS_FAILED(rv)) {
return rv;
}
} else {
request->mDefer = PR_FALSE;
request->mLoading = PR_FALSE;
request->mIsInline = PR_TRUE;
request->mURI = mDocument->GetDocumentURI();
request->mLineNo = aElement->GetScriptLineNumber();
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ printf("Creating inline request (%p).\n", request.get());
+ }
+
// If we've got existing pending requests, add ourselves
// to this list.
if (!hadPendingRequests && ReadyToExecuteScripts() &&
nsContentUtils::IsSafeToRunScript()) {
return ProcessRequest(request);
}
}
@@ -604,30 +625,36 @@ nsScriptLoader::ProcessRequest(nsScriptL
{
NS_ASSERTION(ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript(),
"Caller forgot to check ReadyToExecuteScripts()");
NS_ENSURE_ARG(aRequest);
nsAFlatString* script;
nsAutoString textData;
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ printf("Running request (%p).\n", aRequest);
+ }
+
// If there's no script text, we try to get it from the element
if (aRequest->mIsInline) {
// XXX This is inefficient - GetText makes multiple
// copies.
aRequest->mElement->GetScriptText(textData);
script = &textData;
}
else {
script = &aRequest->mScriptText;
}
FireScriptAvailable(NS_OK, aRequest);
+ aRequest->mElement->BeginEvaluating();
nsresult rv = EvaluateScript(aRequest, *script);
+ aRequest->mElement->EndEvaluating();
FireScriptEvaluated(rv, aRequest);
return rv;
}
void
nsScriptLoader::FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest)
@@ -952,16 +979,23 @@ nsScriptLoader::OnStreamComplete(nsIStre
nsresult aStatus,
PRUint32 aStringLen,
const PRUint8* aString)
{
nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
NS_ASSERTION(request, "null request in stream complete handler");
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ nsCString spec;
+ request->mURI->GetSpec(spec);
+ printf("Finished loading %s (%p). status:%d\n", spec.get(), request,
+ aStatus);
+ }
+
nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
aString);
if (NS_FAILED(rv)) {
if (mRequests.RemoveObject(request) ||
mAsyncRequests.RemoveObject(request)) {
FireScriptAvailable(rv, request);
} else {
mPreloads.RemoveElement(request, PreloadRequestComparator());
@@ -1105,16 +1139,24 @@ nsScriptLoader::PreloadURI(nsIURI *aURI,
return;
}
request->mURI = aURI;
request->mIsInline = PR_FALSE;
request->mLoading = PR_TRUE;
request->mDefer = PR_FALSE; // This is computed later when we go to execute the
// script.
+
+ if (nsContentUtils::GetBoolPref("content.scriptloader.logloads")) {
+ nsCString spec;
+ request->mURI->GetSpec(spec);
+ printf("Starting speculative load for %s (%p).\n", spec.get(),
+ request.get());
+ }
+
nsresult rv = StartLoad(request, aType);
if (NS_FAILED(rv)) {
return;
}
PreloadInfo *pi = mPreloads.AppendElement();
pi->mRequest = request;
pi->mCharset = aCharset;
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -91,16 +91,17 @@
#include "nsIHTMLDocument.h"
#include "nsIDOM3Document.h"
#include "nsIMultiPartChannel.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIStorageStream.h"
#include "nsIPromptFactory.h"
#include "nsIWindowWatcher.h"
#include "nsCommaSeparatedTokenizer.h"
+#include "nsIConsoleService.h"
#define LOAD_STR "load"
#define ERROR_STR "error"
#define ABORT_STR "abort"
#define LOADSTART_STR "loadstart"
#define PROGRESS_STR "progress"
#define UPLOADPROGRESS_STR "uploadprogress"
#define READYSTATE_STR "readystatechange"
@@ -1752,18 +1753,16 @@ nsXMLHttpRequest::OpenRequest(const nsAC
}
/* void open (in AUTF8String method, in AUTF8String url); */
NS_IMETHODIMP
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
PRBool async, const nsAString& user,
const nsAString& password, PRUint8 optional_argc)
{
- nsresult rv = NS_OK;
-
if (nsContentUtils::GetCurrentJSContext()) {
// We're (likely) called from JS
// Find out if UniversalBrowserRead privileges are enabled
if (nsContentUtils::IsCallerTrustedForRead()) {
mState |= XML_HTTP_REQUEST_XSITEENABLED;
} else {
mState &= ~XML_HTTP_REQUEST_XSITEENABLED;
@@ -2233,16 +2232,35 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
httpChannel->GetRequestMethod(method); // If GET, method name will be uppercase
if (!IsSystemPrincipal(mPrincipal)) {
nsCOMPtr<nsIURI> codebase;
mPrincipal->GetURI(getter_AddRefs(codebase));
httpChannel->SetReferrer(codebase);
}
+
+ // Some extensions override the http protocol handler and provide their own
+ // implementation. The channels returned from that implementation doesn't
+ // seem to always implement the nsIUploadChannel2 interface, presumably
+ // because it's a new interface.
+ // Eventually we should remove this and simply require that http channels
+ // implement the new interface.
+ // See bug 529041
+ nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
+ do_QueryInterface(httpChannel);
+ if (!uploadChannel2) {
+ nsCOMPtr<nsIConsoleService> consoleService =
+ do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService) {
+ consoleService->LogStringMessage(NS_LITERAL_STRING(
+ "Http channel implementation doesn't support nsIUploadChannel2. An extension has supplied a non-functional http protocol handler. This will break behavior and in future releases not work at all."
+ ).get());
+ }
+ }
}
mUploadTransferred = 0;
mUploadTotal = 0;
// By default we don't have any upload, so mark upload complete.
mUploadComplete = PR_TRUE;
mErrorLoad = PR_FALSE;
mLoadLengthComputable = PR_FALSE;
@@ -2374,19 +2392,16 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
NS_ENSURE_SUCCESS(rv, rv);
rv = converter->ConvertToInputStream(serial,
getter_AddRefs(postDataStream));
NS_ENSURE_SUCCESS(rv, rv);
}
if (postDataStream) {
- nsCOMPtr<nsIUploadChannel2> uploadChannel(do_QueryInterface(httpChannel));
- NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel");
-
// If no content type header was set by the client, we set it to
// application/xml.
nsCAutoString contentType;
if (NS_FAILED(httpChannel->
GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
contentType)) ||
contentType.IsEmpty()) {
contentType = defaultContentType;
@@ -2432,17 +2447,35 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
mUploadComplete = PR_FALSE;
PRUint32 uploadTotal = 0;
postDataStream->Available(&uploadTotal);
mUploadTotal = uploadTotal;
// We want to use a newer version of the upload channel that won't
// ignore the necessary headers for an empty Content-Type.
- rv = uploadChannel->ExplicitSetUploadStream(postDataStream, contentType, -1, method, PR_FALSE);
+ nsCOMPtr<nsIUploadChannel2> uploadChannel2(do_QueryInterface(httpChannel));
+ // This assertion will fire if buggy extensions are installed
+ NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel");
+ if (uploadChannel2) {
+ uploadChannel2->ExplicitSetUploadStream(postDataStream, contentType,
+ -1, method, PR_FALSE);
+ }
+ else {
+ // http channel doesn't support the new nsIUploadChannel2. Emulate
+ // as best we can using nsIUploadChannel
+ if (contentType.IsEmpty()) {
+ contentType.AssignLiteral("application/octet-stream");
+ }
+ nsCOMPtr<nsIUploadChannel> uploadChannel =
+ do_QueryInterface(httpChannel);
+ uploadChannel->SetUploadStream(postDataStream, contentType, -1);
+ // Reset the method to its original value
+ httpChannel->SetRequestMethod(method);
+ }
}
}
// Reset responseBody
mResponseBody.Truncate();
// Reset responseXML
mResponseXML = nsnull;
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -257,16 +257,17 @@ include $(topsrcdir)/config/rules.mk
file_XHRDocURI.xml \
file_XHRDocURI.xml^headers^ \
file_XHRDocURI.text \
file_XHRDocURI.text^headers^ \
test_bug459424.html \
bug461735-redirect1.sjs \
bug461735-redirect2.sjs \
bug461735-post-redirect.js \
+ test_bug513194.html \
test_bug461735.html \
test_bug380418.html \
test_bug465767.html \
test_bug380418.html^headers^ \
test_bug422403-1.html \
file_xhtmlserializer_1.xhtml \
file_xhtmlserializer_1_bodyonly.xhtml \
file_xhtmlserializer_1_format.xhtml \
@@ -332,10 +333,14 @@ include $(topsrcdir)/config/rules.mk
# Disabled; see bug 492181
# test_plugin_freezing.html
# Disabled for now. Mochitest isn't reliable enough for these.
# test_bug444546.html \
# bug444546.sjs \
+# Disabled due to making the harness time out
+# test_bug503473.html \
+# file_bug503473-frame.sjs \
+
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug503473-frame.sjs
@@ -0,0 +1,23 @@
+function handleRequest(request, response) {
+ response.processAsync();
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html; charset=utf-8", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+
+ response.write(
+ '<!DOCTYPE html>' +
+ '<div></div>' +
+ '<script>' +
+ 'function doWrite() {' +
+ ' document.write("<p></p>");' +
+ ' parent.done();' +
+ ' document.close();' +
+ '}' +
+ 'setTimeout(doWrite, 1);' +
+ '</script>'
+ );
+
+ response.bodyOutputStream.flush();
+ // leave the stream open
+}
+
--- a/content/base/test/file_bug503481b_inner.html
+++ b/content/base/test/file_bug503481b_inner.html
@@ -1,14 +1,21 @@
<!DOCTYPE HTML>
<html>
<head>
<!-- Async script that isn't preloaded -->
<script async src="file_bug503481.sjs?blockOn=R&body=runFirst();"></script>
<script>
+function enableLogs(b) {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ prefs.setBoolPref("content.scriptloader.logloads", b);
+}
+enableLogs(true);
firstRan = false;
secondRan = false;
thirdRan = false;
forthRan = false;
fifthRan = false;
sixthRan = false;
function runFirst() {
firstRan = true;
@@ -32,16 +39,17 @@ function runSixth() {
function done() {
parent.is(firstRan, true, "first should have run by onload");
parent.is(secondRan, true, "second should have run by onload");
parent.is(thirdRan, true, "third should have run by onload");
parent.is(forthRan, true, "forth should have run by onload");
parent.is(fifthRan, true, "fifth should have run by onload");
parent.is(sixthRan, true, "sixth should have run by onload");
+ enableLogs(false);
parent.SimpleTest.finish();
}
var reqs = [];
function unblock(s) {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_bug503481.sjs?unblock=" + s);
xhr.send();
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug503473.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=503473
+-->
+<head>
+ <title>Test for Bug 503473</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=503473">Mozilla Bug 503473</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 503473 **/
+
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+var gOriginalHtml5Pref = prefs.getBoolPref("html5.enable");
+prefs.setBoolPref("html5.enable", true);
+
+SimpleTest.waitForExplicitFinish();
+
+function done() {
+ var iframe = document.getElementById("iframe");
+ var divs = iframe.contentWindow.document.getElementsByTagName("div").length;
+ is(divs, 0, "Div wasn't blown away.")
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ prefs.setBoolPref("html5.enable", gOriginalHtml5Pref);
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+<div id="content" style="display: none">
+ <iframe id='iframe' src="file_bug503473-frame.sjs">
+ </iframe>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug513194.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=513194
+-->
+<head>
+ <title>Test for Bug 513194</title>
+ <script type="text/javascript" src="/MochiKit/packed.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ const Cr = Components.results;
+
+ var consoleService =
+ Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+
+ var consoleListener = {
+ seenError: false,
+
+ observe: function(message) {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+ if (this.seenError) {
+ ok(false, "Seen too many errors!");
+ }
+
+ this.seenError = true;
+
+ ok(message.message.indexOf("Unknown property") > -1,
+ "Wrong message");
+ },
+
+ finish: function() {
+ ok(this.seenError , "Didn't get message.");
+ SimpleTest.finish();
+ },
+
+ QueryInterface: function(iid) {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+ if (iid.equals(Ci.nsIConsoleListener) ||
+ iid.equals(Ci.nsISupports)) {
+ return this;
+ }
+ throw Cr.NS_NOINTERFACE;
+ }
+ };
+
+ consoleService.reset();
+ consoleService.registerListener(consoleListener);
+ SimpleTest.waitForExplicitFinish();
+
+ document.write("<style>qux { foo: bar; }<\/style>");
+
+ function done() {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+ consoleListener.finish();
+ consoleService.unregisterListener(consoleListener);
+ }
+ setTimeout(done, 1);
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/base/test/test_fileapi.html
+++ b/content/base/test/test_fileapi.html
@@ -22,16 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cg
<script class="testbody" type="text/javascript">
var testCounter = 0;
SimpleTest.waitForExplicitFinish();
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Write a test file > 8192 characters
+is(FileReader.EMPTY, 0, "correct EMPTY value");
+is(FileReader.LOADING, 1, "correct LOADING value");
+is(FileReader.DONE, 2, "correct DONE value");
+
var testData = "asdfblahqwer";
for (var i = 0; i < 10; i++) {
testData = testData + testData;
}
var testData2 = testData + "a";
var testData3 = testData + "as";
//Ensure we have different sizes of data for thoroughly testing data URI retrieval
@@ -57,18 +61,20 @@ var utf32File = createFileWithData(utf32
var file = createFileWithData(testData, "00");
var domFileData = file.getAsDataURL();
var domFileBinary = file.getAsBinary();
var domFileBinary2 = utf16File.getAsBinary();
var domFileBinary3 = utf32File.getAsBinary();
var request1 = new FileReader();
+is(request1.readyState, FileReader.EMPTY, "correct initial readyState");
request1.onload = handleTextISO1;
request1.readAsText(file, "iso-8859-1");
+is(request1.readyState, FileReader.LOADING, "correct loading readyState");
var request2 = new FileReader();
request2.onload = handleTextUTF8;
request2.readAsText(file);
var request3 = new FileReader();
request3.onload = handleTextUTF8;
request3.readAsText(file, "");
@@ -84,18 +90,20 @@ request5.onload = handleTextUTF16;
request5.readAsText(utf16File, "UTF-16");
var request6 = new FileReader();
request6.onload = handleTextUTF32;
request6.readAsText(utf32File, "UTF-32");
//Test binary data accessor
var request7 = new FileReader();
+is(request7.readyState, FileReader.EMPTY, "correct initial readyState");
request7.onload = handleDataBinary;
request7.readAsBinaryString(file);
+is(request7.readyState, FileReader.LOADING, "correct loading readyState");
var request71 = new FileReader();
request71.onload = handleDataBinary16;
request71.readAsBinaryString(utf16File);
var request72 = new FileReader();
request72.onload = handleDataBinary32;
request72.readAsBinaryString(utf32File);
@@ -167,16 +175,17 @@ function handleCancel(event) {
var fileAsText = event.target.result;
var error = event.target.error;
is(error.code, FileError.ABORT_ERR, "error code set to CANCELED for canceled reads");
is(fileAsText, null, "file data should be null on canceled reads");
testHasRun();
}
function handleTextISO1(event) {
+ is(event.target.readyState, FileReader.DONE, "correct final readyState");
var fileAsText = event.target.result;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsText.length, "iso-1 async length should match testdata");
is(testData, fileAsText, "iso-1 async string result should match testdata");
testHasRun();
}
@@ -227,16 +236,17 @@ function handleDataURI1(event) {
function handleDataURI2(event) {
var fileAsDataURI = event.target.result;
is(domFileData2.length, fileAsDataURI.length, "data URI async length should match dom file data2");
is(domFileData2, fileAsDataURI, "data URI async string result should match dom file data2");
testHasRun();
}
function handleDataBinary(event) {
+ is(event.target.readyState, FileReader.DONE, "correct final readyState");
var fileAsBinary = event.target.result;
is(domFileBinary.length, fileAsBinary.length, "binary data async length should match dom file binary");
is(domFileBinary, fileAsBinary, "binary data async string result should match dom file binary");
testHasRun();
}
function handleDataBinary16(event) {
var fileAsBinary = event.target.result;
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -293,64 +293,16 @@ WebGLContext::CreateUnsignedIntArray(nsI
/* readonly attribute nsIDOMHTMLCanvasElement canvas; */
NS_IMETHODIMP
WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **aCanvas)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
-/* readonly attribute nsIWebGLBuffer currentArrayBufferBinding; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentArrayBufferBinding(nsIWebGLBuffer **aCurrentArrayBufferBinding)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLBuffer currentElementArrayBufferBinding; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentElementArrayBufferBinding(nsIWebGLBuffer **aCurrentElementArrayBufferBinding)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLFramebuffer currentFramebufferBinding; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentFramebufferBinding(nsIWebGLFramebuffer **aCurrentFramebufferBinding)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLRenderbuffer currentRenderbufferBinding; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentRenderbufferBinding(nsIWebGLRenderbuffer **aCurrentRenderbufferBinding)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLTexture currentTextureBinding2D; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentTextureBinding2D(nsIWebGLTexture **aCurrentTextureBinding2D)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLTexture currentTextureBindingCubeMap; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentTextureBindingCubeMap(nsIWebGLTexture **aCurrentTextureBindingCubeMap)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIWebGLProgram currentProgram; */
-NS_IMETHODIMP
-WebGLContext::GetCurrentProgram(nsIWebGLProgram **aCurrentProgram)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
/* void present (); */
NS_IMETHODIMP
WebGLContext::Present()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
@@ -1505,16 +1457,44 @@ WebGLContext::GetBufferParameteri(GLenum
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
NS_IMETHODIMP
+WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
+{
+ NativeJSContext js;
+ if (NS_FAILED(js.error))
+ return js.error;
+
+ MakeContextCurrent();
+
+ switch (pname) {
+ case LOCAL_GL_BUFFER_SIZE:
+ case LOCAL_GL_BUFFER_USAGE:
+ case LOCAL_GL_BUFFER_ACCESS:
+ case LOCAL_GL_BUFFER_MAPPED:
+ {
+ PRInt32 iv = 0;
+ gl->fGetBufferParameteriv(target, pname, (GLint*) &iv);
+ js.SetRetVal(iv);
+ }
+ break;
+
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
WebGLContext::GetFramebufferAttachmentParameteri(GLenum target, GLenum attachment, GLenum pname, GLint *retval)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
@@ -1542,16 +1522,53 @@ WebGLContext::GetFramebufferAttachmentPa
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
NS_IMETHODIMP
+WebGLContext::GetFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname)
+{
+ NativeJSContext js;
+ if (NS_FAILED(js.error))
+ return js.error;
+
+ MakeContextCurrent();
+
+ switch (attachment) {
+ case LOCAL_GL_COLOR_ATTACHMENT0:
+ case LOCAL_GL_DEPTH_ATTACHMENT:
+ case LOCAL_GL_STENCIL_ATTACHMENT:
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ switch (pname) {
+ case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ {
+ PRInt32 iv = 0;
+ gl->fGetFramebufferAttachmentParameteriv(target, attachment, pname, (GLint*) &iv);
+ js.SetRetVal(iv);
+ }
+ break;
+
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
WebGLContext::GetRenderbufferParameteri(GLenum target, GLenum pname, GLint *retval)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
@@ -1575,16 +1592,49 @@ WebGLContext::GetRenderbufferParameteri(
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
NS_IMETHODIMP
+WebGLContext::GetRenderbufferParameter(GLenum target, GLenum pname)
+{
+ NativeJSContext js;
+ if (NS_FAILED(js.error))
+ return js.error;
+
+ MakeContextCurrent();
+
+ switch (pname) {
+ case LOCAL_GL_RENDERBUFFER_WIDTH:
+ case LOCAL_GL_RENDERBUFFER_HEIGHT:
+ case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
+ case LOCAL_GL_RENDERBUFFER_RED_SIZE:
+ case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
+ case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
+ case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
+ case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
+ case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
+ {
+ PRInt32 iv = 0;
+ gl->fGetRenderbufferParameteriv(target, pname, (GLint*) &iv);
+ js.SetRetVal(iv);
+ }
+ break;
+
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
WebGLContext::CreateBuffer(nsIWebGLBuffer **retval)
{
MakeContextCurrent();
GLuint name;
gl->fGenBuffers(1, &name);
WebGLBuffer *globj = new WebGLBuffer(name);
@@ -1660,16 +1710,55 @@ WebGLContext::GetProgrami(nsIWebGLProgra
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
NS_IMETHODIMP
+WebGLContext::GetProgramParameter(nsIWebGLProgram *prog, PRUint32 pname)
+{
+ if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
+ return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
+
+ GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
+
+ NativeJSContext js;
+ if (NS_FAILED(js.error))
+ return js.error;
+
+ MakeContextCurrent();
+
+ switch (pname) {
+ case LOCAL_GL_CURRENT_PROGRAM:
+ case LOCAL_GL_DELETE_STATUS:
+ case LOCAL_GL_LINK_STATUS:
+ case LOCAL_GL_VALIDATE_STATUS:
+ case LOCAL_GL_ATTACHED_SHADERS:
+ case LOCAL_GL_INFO_LOG_LENGTH:
+ case LOCAL_GL_ACTIVE_UNIFORMS:
+ case LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ case LOCAL_GL_ACTIVE_ATTRIBUTES:
+ case LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ {
+ PRInt32 iv = 0;
+ gl->fGetProgramiv(program, pname, (GLint*) &iv);
+ js.SetRetVal(iv);
+ }
+ break;
+
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
WebGLContext::GetProgramInfoLog(nsIWebGLProgram *prog, nsAString& retval)
{
if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
return ErrorMessage("%s: program is null or deleted!");
GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
MakeContextCurrent();
@@ -1858,45 +1947,16 @@ WebGLContext::GetTexParameterf(GLenum ta
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
-/* nsICanvasArray getTexParameterfv (in GLenum target, in GLenum pname); */
-NS_IMETHODIMP
-WebGLContext::GetTexParameterfv(GLenum target, GLenum pname, nsICanvasArray **retval)
-{
- NativeJSContext js;
- if (NS_FAILED(js.error))
- return js.error;
-
- MakeContextCurrent();
-
- switch (pname) {
- case LOCAL_GL_TEXTURE_MIN_FILTER:
- case LOCAL_GL_TEXTURE_MAG_FILTER:
- case LOCAL_GL_TEXTURE_WRAP_S:
- case LOCAL_GL_TEXTURE_WRAP_T:
- {
- float fv = 0;
- gl->fGetTexParameterfv(target, pname, (GLfloat*) &fv);
- js.SetRetVal(&fv, 1);
- }
- break;
-
- default:
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- return NS_OK;
-}
-
NS_IMETHODIMP
WebGLContext::GetTexParameteri(GLenum target, GLenum pname, GLint *retval)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
@@ -1915,48 +1975,48 @@ WebGLContext::GetTexParameteri(GLenum ta
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
-/* nsICanvasArray getTexParameteriv (in GLenum target, in GLenum pname); */
NS_IMETHODIMP
-WebGLContext::GetTexParameteriv(GLenum target, GLenum pname, nsICanvasArray **retval)
+WebGLContext::GetTexParameter(GLenum target, GLenum pname)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
case LOCAL_GL_TEXTURE_MAG_FILTER:
case LOCAL_GL_TEXTURE_WRAP_S:
case LOCAL_GL_TEXTURE_WRAP_T:
{
- PRInt32 iv = 0;
- gl->fGetTexParameteriv(target, pname, (GLint*) &iv);
- js.SetRetVal(&iv, 1);
+ float fv = 0;
+ gl->fGetTexParameterfv(target, pname, (GLfloat*) &fv);
+ js.SetRetVal(fv);
}
break;
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
/* XXX fix */
+/* any getUniform(in WebGLProgram program, in WebGLUniformLocation location) raises(DOMException); */
NS_IMETHODIMP
-WebGLContext::GetUniformf(nsIWebGLProgram *prog, GLint location, GLfloat *retval)
+WebGLContext::GetUniform(nsIWebGLProgram *prog, GLint location)
{
if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
NativeJSContext js;
if (NS_FAILED(js.error))
@@ -1993,99 +2053,32 @@ WebGLContext::GetUniformf(nsIWebGLProgra
gl->fGetUniformiv(program, location, iv);
js.SetRetVal((PRInt32*)iv, unitSize);
} else {
js.SetRetValAsJSVal(JSVAL_NULL);
}
return NS_OK;
}
-/* nsICanvasArray getUniformfv (in nsIWebGLProgram program, in GLint location); */
-NS_IMETHODIMP
-WebGLContext::GetUniformfv(nsIWebGLProgram *program, GLint location, nsICanvasArray **retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-/* GLint getUniformi (in nsIWebGLProgram program, in GLint location); */
-NS_IMETHODIMP
-WebGLContext::GetUniformi(nsIWebGLProgram *program, GLint location, GLint *retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* nsICanvasArray getUniformiv (in nsIWebGLProgram program, in GLint location); */
-NS_IMETHODIMP
-WebGLContext::GetUniformiv(nsIWebGLProgram *program, GLint location, nsICanvasArray **retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
NS_IMETHODIMP
WebGLContext::GetUniformLocation(nsIWebGLProgram *prog, const nsAString& name, GLint *retval)
{
if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
MakeContextCurrent();
*retval = gl->fGetUniformLocation(program, NS_LossyConvertUTF16toASCII(name).get());
return NS_OK;
}
NS_IMETHODIMP
-WebGLContext::GetVertexAttribf(GLuint index, GLenum pname, GLfloat *retval)
-{
- NativeJSContext js;
- if (NS_FAILED(js.error))
- return js.error;
-
- MakeContextCurrent();
-
- switch (pname) {
- // int
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- {
- PRInt32 iv = 0;
- gl->fGetVertexAttribiv(index, pname, (GLint*) &iv);
- *retval = (GLfloat) iv;
- }
- break;
-
- case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
- {
- GLfloat fv[4] = { 0 };
- gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &fv[0]);
- js.SetRetVal(fv, 4);
- }
- break;
-
- // not supported; doesn't make sense to return a pointer unless we have some kind of buffer object abstraction
- case LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER:
- default:
- return NS_ERROR_NOT_IMPLEMENTED;
-
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WebGLContext::GetVertexAttribfv(GLuint index, GLenum pname, nsICanvasArray **retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-WebGLContext::GetVertexAttribi(GLuint index, GLenum pname, GLint *retval)
+WebGLContext::GetVertexAttrib(GLuint index, GLenum pname)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
switch (pname) {
@@ -2116,22 +2109,16 @@ WebGLContext::GetVertexAttribi(GLuint in
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
-NS_IMETHODIMP
-WebGLContext::GetVertexAttribiv(GLuint index, GLenum pname, nsICanvasArray **retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
/* GLuint getVertexAttribOffset (in GLuint index, in GLenum pname); */
NS_IMETHODIMP
WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname, GLuint *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@@ -2739,21 +2726,48 @@ WebGLContext::GetShaderi(nsIWebGLShader
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
-/* nsICanvasIntArray getShaderiv (in nsIWebGLShader shader, in GLenum pname); */
NS_IMETHODIMP
-WebGLContext::GetShaderiv(nsIWebGLShader *shader, GLenum pname, nsICanvasIntArray **retval)
+WebGLContext::GetShaderParameter(nsIWebGLShader *shobj, GLenum pname)
{
- return NS_ERROR_NOT_IMPLEMENTED;
+ if (!shobj || static_cast<WebGLShader*>(shobj)->Deleted())
+ return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
+
+ GLuint shader = static_cast<WebGLShader*>(shobj)->GLName();
+
+ NativeJSContext js;
+ if (NS_FAILED(js.error))
+ return js.error;
+
+ MakeContextCurrent();
+
+ switch (pname) {
+ case LOCAL_GL_SHADER_TYPE:
+ case LOCAL_GL_DELETE_STATUS:
+ case LOCAL_GL_COMPILE_STATUS:
+ case LOCAL_GL_INFO_LOG_LENGTH:
+ case LOCAL_GL_SHADER_SOURCE_LENGTH:
+ {
+ PRInt32 iv = 0;
+ gl->fGetShaderiv(shader, pname, (GLint*) &iv);
+ js.SetRetVal(iv);
+ }
+ break;
+
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
}
NS_IMETHODIMP
WebGLContext::GetShaderInfoLog(nsIWebGLShader *shobj, nsAString& retval)
{
if (!shobj || static_cast<WebGLShader*>(shobj)->Deleted())
return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
@@ -2955,19 +2969,17 @@ WebGLContext::TexSubImage2D()
} else {
jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType;
JSObject *argPixelsObj;
jsuint argPixelsLen;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
&argTarget, &argLevel, &argX, &argY,
&argWidth, &argHeight, &argFormat, &argType,
&argPixelsObj) ||
- !argPixelsObj ||
- !::JS_IsArrayObject(js.ctx, argPixelsObj) ||
- !::JS_GetArrayLength(js.ctx, argPixelsObj, &argPixelsLen))
+ !argPixelsObj)
{
return ErrorMessage("texSubImage2D: argument error");
return NS_ERROR_DOM_SYNTAX_ERR;
}
switch (argTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -3038,22 +3050,27 @@ WebGLContext::TexSubImage2D()
return NS_ERROR_DOM_SYNTAX_ERR;
}
if ((PRUint32) tmp > argPixelsLen) {
return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
return NS_ERROR_DOM_SYNTAX_ERR;
}
- SimpleBuffer sbuffer(bufferType, bufferSize, js.ctx, argPixelsObj, argPixelsLen);
- if (!sbuffer.Valid())
- return NS_ERROR_FAILURE;
+ nsCOMPtr<nsICanvasArray> arrayObj;
+ nsresult rv;
+ rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
+ arrayObj = do_QueryInterface(arrayObj, &rv);
+
+ if (NS_FAILED(rv) || !arrayObj) {
+ return ErrorMessage("texSubImage2D: pixels arg is not a WebGL array");
+ }
MakeContextCurrent();
- gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, (void *) sbuffer.data);
+ gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, arrayObj->NativePointer());
}
return NS_OK;
}
NS_IMETHODIMP
WebGLContext::TexImage2D()
{
// void texImage2D(in GLenum target, in GLint level, in GLenum internalformat,
@@ -3110,19 +3127,17 @@ WebGLContext::TexImage2D()
} else if (js.argc == 9) {
JSObject *argPixelsObj;
jsuint argPixelsLen;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
&argTarget, &argLevel, &argInternalFormat, &argWidth,
&argHeight, &argBorder, &argFormat, &argType,
&argPixelsObj) ||
- !argPixelsObj ||
- !::JS_IsArrayObject(js.ctx, argPixelsObj) ||
- !::JS_GetArrayLength(js.ctx, argPixelsObj, &argPixelsLen))
+ !argPixelsObj)
{
return ErrorMessage("texImage2D: argument error");
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (argWidth == 0 || argHeight == 0) {
return ErrorMessage("texImage2D: width or height is zero");
return NS_ERROR_DOM_SYNTAX_ERR;
}
@@ -3220,22 +3235,27 @@ WebGLContext::TexImage2D()
MakeContextCurrent();
gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, NULL);
} else {
if ((PRUint32) tmp > argPixelsLen) {
return ErrorMessage("texImage2D: array dimensions too small for width, height and pixel format");
return NS_ERROR_DOM_SYNTAX_ERR;
}
- SimpleBuffer sbuffer(bufferType, bufferSize, js.ctx, argPixelsObj, argPixelsLen);
- if (!sbuffer.Valid())
- return NS_ERROR_FAILURE;
+ nsCOMPtr<nsICanvasArray> arrayObj;
+ nsresult rv;
+ rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
+ arrayObj = do_QueryInterface(arrayObj, &rv);
+
+ if (NS_FAILED(rv) || !arrayObj) {
+ return ErrorMessage("texImage2D: pixels arg is not a WebGL array");
+ }
MakeContextCurrent();
- gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, (void *) sbuffer.data);
+ gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, arrayObj->NativePointer());
}
}
return NS_OK;
}
#if 0
// ImageData getImageData (in float x, in float y, in float width, in float height);
NS_IMETHODIMP
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -950,16 +950,20 @@ nsCanvasRenderingContext2D::InitializeWi
mThebes->SetLineWidth(1.0);
mThebes->SetOperator(gfxContext::OPERATOR_OVER);
mThebes->SetMiterLimit(10.0);
mThebes->SetLineCap(gfxContext::LINE_CAP_BUTT);
mThebes->SetLineJoin(gfxContext::LINE_JOIN_MITER);
mThebes->NewPath();
+ // always force a redraw, because if the surface dimensions were reset
+ // then the surface became cleared, and we need to redraw everything.
+ Redraw();
+
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetIsOpaque(PRBool isOpaque)
{
if (isOpaque == mOpaque)
return NS_OK;
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -369,18 +369,17 @@ nsDOMUIEvent::GetIsChar(PRBool* aIsChar)
default:
*aIsChar = PR_FALSE;
return NS_OK;
}
}
NS_METHOD nsDOMUIEvent::GetCompositionReply(nsTextEventReply** aReply)
{
- if((mEvent->message == NS_COMPOSITION_START) ||
- (mEvent->message == NS_COMPOSITION_QUERY))
+ if((mEvent->message == NS_COMPOSITION_START))
{
*aReply = &(static_cast<nsCompositionEvent*>(mEvent)->theReply);
return NS_OK;
}
*aReply = nsnull;
return NS_ERROR_FAILURE;
}
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -206,19 +206,17 @@ static const EventDispatchData sMouseMot
static const EventDispatchData sContextMenuEvents[] = {
{ NS_CONTEXTMENU, HANDLER(&nsIDOMContextMenuListener::ContextMenu) }
};
static const EventDispatchData sCompositionEvents[] = {
{ NS_COMPOSITION_START,
HANDLER(&nsIDOMCompositionListener::HandleStartComposition) },
{ NS_COMPOSITION_END,
- HANDLER(&nsIDOMCompositionListener::HandleEndComposition) },
- { NS_COMPOSITION_QUERY,
- HANDLER(&nsIDOMCompositionListener::HandleQueryComposition) }
+ HANDLER(&nsIDOMCompositionListener::HandleEndComposition) }
};
static const EventDispatchData sTextEvents[] = {
{ NS_TEXT_TEXT, HANDLER(&nsIDOMTextListener::HandleText) }
};
static const EventDispatchData sKeyEvents[] = {
{ NS_KEY_UP, HANDLER(&nsIDOMKeyListener::KeyUp) },
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -494,16 +494,19 @@ nsIMEStateManager::OnTextStateFocus(nsPr
NS_ENSURE_TRUE(shell, NS_ERROR_NOT_AVAILABLE);
nsIViewManager* vm = shell->GetViewManager();
NS_ENSURE_TRUE(vm, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIWidget> widget;
nsresult rv = vm->GetRootWidget(getter_AddRefs(widget));
NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_AVAILABLE);
+ if (!widget) {
+ return NS_OK; // Sometimes, there are no widgets.
+ }
rv = widget->OnIMEFocusChange(PR_TRUE);
if (rv == NS_ERROR_NOT_IMPLEMENTED)
return NS_OK;
NS_ENSURE_SUCCESS(rv, rv);
// OnIMEFocusChange may cause focus and sTextStateObserver to change
// In that case return and keep the current sTextStateObserver
--- a/content/html/content/src/nsHTMLOptGroupElement.cpp
+++ b/content/html/content/src/nsHTMLOptGroupElement.cpp
@@ -181,17 +181,16 @@ nsHTMLOptGroupElement::InsertChildAt(nsI
safeMutation.MutationFailed();
}
return rv;
}
nsresult
nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent)
{
- NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutation events on optgroup child removal.");
nsSafeOptionListMutation safeMutation(GetSelect(), this, nsnull, aIndex);
nsresult rv = nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify, aMutationEvent);
if (NS_FAILED(rv)) {
safeMutation.MutationFailed();
}
return rv;
}
--- a/content/html/content/src/nsHTMLTableCellElement.cpp
+++ b/content/html/content/src/nsHTMLTableCellElement.cpp
@@ -366,17 +366,25 @@ void MapAttributesIntoRule(const nsMappe
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum)
aData->mTextData->mTextAlign.SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
}
if (aData->mTextData->mWhiteSpace.GetUnit() == eCSSUnit_Null) {
// nowrap: enum
if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
- aData->mTextData->mWhiteSpace.SetIntValue(NS_STYLE_WHITESPACE_NOWRAP, eCSSUnit_Enumerated);
+ // See if our width is not a nonzero integer width.
+ const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
+ nsCompatibility mode = aData->mPresContext->CompatibilityMode();
+ if (!value || value->Type() != nsAttrValue::eInteger ||
+ value->GetIntegerValue() == 0 ||
+ eCompatibility_NavQuirks != mode) {
+ aData->mTextData->mWhiteSpace.SetIntValue(NS_STYLE_WHITESPACE_NOWRAP, eCSSUnit_Enumerated);
+ }
+
}
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TextReset)) {
if (aData->mTextData->mVerticalAlign.GetUnit() == eCSSUnit_Null) {
// valign: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
if (value && value->Type() == nsAttrValue::eEnum)
--- a/content/html/content/test/test_bug523771.html
+++ b/content/html/content/test/test_bug523771.html
@@ -18,19 +18,19 @@ method="POST" enctype="multipart/form-da
<input id=singleFile name=singleFile type=file>
<input id=multiFile name=multiFile type=file multiple>
</form>
<pre id="test">
<script class="testbody" type="text/javascript">
var filesToKill = [];
singleFileInput = document.getElementById('singleFile');
multiFileInput = document.getElementById('multiFile');
-var input1File = { name: "523771_file1", type: null, body: "file1 contents"};
+var input1File = { name: "523771_file1", type: "", body: "file1 contents"};
var input2Files =
- [{ name: "523771_file2", type: null, body: "second file contents" },
+ [{ name: "523771_file2", type: "", body: "second file contents" },
{ name: "523771_file3.txt", type: "text/plain", body: "123456" },
{ name: "523771_file4.html", type: "text/html", body: "<html>content</html>" }
];
SimpleTest.waitForExplicitFinish();
function setFileInputs () {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
@@ -81,21 +81,21 @@ is(multiFileInput.files.length, 0, "mult
setFileInputs();
is(singleFileInput.multiple, false, "single-file input .multiple");
is(multiFileInput.multiple, true, "multi-file input .multiple");
is(singleFileInput.value, input1File.name, "single-file input .value");
is(multiFileInput.value, input2Files[0].name, "multi-file input .value");
is(singleFileInput.files[0].name, input1File.name, "single-file input .files[n].name");
is(singleFileInput.files[0].size, input1File.body.length, "single-file input .files[n].size");
-is(singleFileInput.files[0].mediaType, input1File.type, "single-file input .files[n].mediaType");
+is(singleFileInput.files[0].type, input1File.type, "single-file input .files[n].type");
for(i = 0; i < input2Files.length; ++i) {
is(multiFileInput.files[i].name, input2Files[i].name, "multi-file input .files[n].name");
is(multiFileInput.files[i].size, input2Files[i].body.length, "multi-file input .files[n].size");
- is(multiFileInput.files[i].mediaType, input2Files[i].type, "multi-file input .files[n].mediaType");
+ is(multiFileInput.files[i].type, input2Files[i].type, "multi-file input .files[n].type");
}
document.getElementById('form').submit();
iframe = document.getElementById('target_iframe');
iframe.onload = function() {
response = JSON.parse(iframe.contentDocument.documentElement.textContent);
is(response[0].headers["Content-Disposition"],
"form-data; name=\"singleFile\"; filename=\"" + input1File.name +
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -730,16 +730,17 @@ nsHTMLDocument::StartDocumentLoad(const
cachingChan->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken)
cacheDescriptor = do_QueryInterface(cacheToken);
}
if (needsParser) {
if (loadAsHtml5) {
mParser = nsHtml5Module::NewHtml5Parser();
+ mParser->MarkAsNotScriptCreated();
} else {
mParser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
}
PRInt32 textType = GET_BIDI_OPTION_TEXTTYPE(GetBidiOptions());
@@ -2137,17 +2138,18 @@ nsHTMLDocument::WriteCommon(const nsAStr
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
nsresult rv = NS_OK;
void *key = GenerateParserKey();
if (mWriteState == eDocumentClosed ||
(mWriteState == ePendingClose &&
- !mPendingScripts.Contains(key))) {
+ !mPendingScripts.Contains(key)) ||
+ (mParser && !mParser->IsInsertionPointDefined())) {
mWriteState = eDocumentClosed;
mParser->Terminate();
NS_ASSERTION(!mParser, "mParser should have been null'd out");
}
if (!mParser) {
rv = Open();
@@ -2930,17 +2932,31 @@ nsHTMLDocument::GenerateParserKey(void)
if (!mScriptLoader) {
// If we don't have a script loader, then the parser probably isn't parsing
// anything anyway, so just return null.
return nsnull;
}
// The script loader provides us with the currently executing script element,
// which is guaranteed to be unique per script.
- return mScriptLoader->GetCurrentScript();
+ if (nsHtml5Module::sEnabled) {
+ nsIScriptElement* script = mScriptLoader->GetCurrentScript();
+ if (script && mParser && mParser->IsScriptCreated()) {
+ nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
+ if (creatorParser != mParser) {
+ // Make scripts that aren't inserted by the active parser of this document
+ // participate in the context of the script that document.open()ed
+ // this document.
+ return mParser->GetRootContextKey();
+ }
+ }
+ return script;
+ } else {
+ return mScriptLoader->GetCurrentScript();
+ }
}
/* attribute DOMString designMode; */
NS_IMETHODIMP
nsHTMLDocument::GetDesignMode(nsAString & aDesignMode)
{
if (HasFlag(NODE_IS_EDITABLE)) {
aDesignMode.AssignLiteral("on");
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -29,63 +29,60 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-DEPTH = ../..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-MODULE = content
-LIBRARY_NAME = gkconmedia_s
-LIBXUL_LIBRARY = 1
-
+MODULE = content
+LIBRARY_NAME = gkconmedia_s
+LIBXUL_LIBRARY = 1
-EXPORTS = \
- nsMediaDecoder.h \
- nsMediaStream.h \
- nsMediaCache.h \
- $(NULL)
+EXPORTS = \
+ nsMediaDecoder.h \
+ nsMediaStream.h \
+ nsMediaCache.h \
+ $(NULL)
-CPPSRCS = \
- nsMediaDecoder.cpp \
- nsMediaCache.cpp \
- nsMediaStream.cpp \
- $(NULL)
+CPPSRCS = \
+ nsMediaDecoder.cpp \
+ nsMediaCache.cpp \
+ nsMediaStream.cpp \
+ $(NULL)
ifdef MOZ_SYDNEYAUDIO
-EXPORTS += \
- nsAudioStream.h \
- $(NULL)
-CPPSRCS += \
- nsAudioStream.cpp \
- $(NULL)
+EXPORTS += \
+ nsAudioStream.h \
+ $(NULL)
+CPPSRCS += \
+ nsAudioStream.cpp \
+ $(NULL)
endif
-DIRS =
-
ifdef MOZ_OGG
-DIRS += ogg
+PARALLEL_DIRS += ogg
endif
ifdef MOZ_WAVE
-DIRS += wave
+PARALLEL_DIRS += wave
endif
ifdef ENABLE_TESTS
-DIRS += test
+PARALLEL_DIRS += test
endif
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
-INCLUDES += \
- -I$(srcdir)/../base/src \
- -I$(srcdir)/../html/content/src \
- $(NULL)
+INCLUDES += \
+ -I$(srcdir)/../base/src \
+ -I$(srcdir)/../html/content/src \
+ $(NULL)
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -185,26 +185,30 @@ public:
// Verify invariants, especially block list invariants
void Verify();
#else
void Verify() {}
#endif
PRMonitor* Monitor() { return mMonitor; }
+ /**
+ * An iterator that makes it easy to iterate through all streams that
+ * have a given resource ID and are not closed.
+ */
class ResourceStreamIterator {
public:
ResourceStreamIterator(PRInt64 aResourceID) :
mResourceID(aResourceID), mNext(0) {}
nsMediaCacheStream* Next()
{
while (mNext < gMediaCache->mStreams.Length()) {
nsMediaCacheStream* stream = gMediaCache->mStreams[mNext];
++mNext;
- if (stream->GetResourceID() == mResourceID)
+ if (stream->GetResourceID() == mResourceID && !stream->IsClosed())
return stream;
}
return nsnull;
}
private:
PRInt64 mResourceID;
PRUint32 mNext;
};
@@ -1191,17 +1195,17 @@ nsMediaCache::Update()
enableReading = predictedNewDataUse < latestNextUse;
}
if (enableReading) {
for (PRUint32 j = 0; j < i; ++j) {
nsMediaCacheStream* other = mStreams[j];
if (other->mResourceID == stream->mResourceID &&
!other->mCacheSuspended &&
- other->mChannelOffset/BLOCK_SIZE == stream->mChannelOffset/BLOCK_SIZE) {
+ other->mChannelOffset/BLOCK_SIZE == desiredOffset/BLOCK_SIZE) {
// This block is already going to be read by the other stream.
// So don't try to read it from this stream as well.
enableReading = PR_FALSE;
break;
}
}
}
new file mode 100644
--- /dev/null
+++ b/content/smil/crashtests/526875-1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg">
+ <animate attributeName="fill-opacity" by="-1"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/content/smil/crashtests/526875-2.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg">
+ <animate attributeName="fill-opacity" by="1"/>
+</svg>
--- a/content/smil/crashtests/crashtests.list
+++ b/content/smil/crashtests/crashtests.list
@@ -1,2 +1,4 @@
load 523188-1.svg
load 525099-1.svg
+load 526875-1.svg
+load 526875-2.svg
--- a/content/smil/nsSMILCSSProperty.cpp
+++ b/content/smil/nsSMILCSSProperty.cpp
@@ -249,20 +249,20 @@ nsSMILCSSProperty::IsPropertyAnimatable(
case eCSSProperty_fill_opacity:
case eCSSProperty_fill_rule:
// case eCSSProperty_filter:
case eCSSProperty_flood_color:
case eCSSProperty_flood_opacity:
// case eCSSProperty_font_family:
case eCSSProperty_font_size:
case eCSSProperty_font_size_adjust:
- // case eCSSProperty_font_stretch:
+ case eCSSProperty_font_stretch:
case eCSSProperty_font_style:
case eCSSProperty_font_variant:
- // case eCSSProperty_font_weight:
+ case eCSSProperty_font_weight:
case eCSSProperty_image_rendering:
case eCSSProperty_letter_spacing:
case eCSSProperty_lighting_color:
// case eCSSProperty_marker_end:
// case eCSSProperty_marker_mid:
// case eCSSProperty_marker_start:
// case eCSSProperty_mask:
case eCSSProperty_opacity:
--- a/content/smil/nsSMILCSSValueType.cpp
+++ b/content/smil/nsSMILCSSValueType.cpp
@@ -177,40 +177,48 @@ nsSMILCSSValueType::Add(nsSMILValue& aDe
NS_ABORT_IF_FALSE(aValueToAdd.mType == this, "Unexpected source type");
ValueWrapper* destWrapper = ExtractValueWrapper(aDest);
const ValueWrapper* valueToAddWrapper = ExtractValueWrapper(aValueToAdd);
NS_ABORT_IF_FALSE(destWrapper && valueToAddWrapper,
"these pointers shouldn't be null");
+ const nsStyleAnimation::Value* realValueToAdd = &valueToAddWrapper->mCSSValue;
if (destWrapper->mPropID == eCSSProperty_UNKNOWN) {
- NS_ABORT_IF_FALSE(destWrapper->mCSSValue.IsNull(),
- "If property ID is unset, then the unit should be, too");
+ NS_ABORT_IF_FALSE(destWrapper->mCSSValue.IsNull() &&
+ !destWrapper->mPresContext,
+ "Partially-initialized ValueWrapper");
// We need to update destWrapper, since it's part of an outparam.
const nsStyleAnimation::Value* zeroVal =
GetZeroValueForUnit(valueToAddWrapper->mCSSValue.GetUnit());
if (!zeroVal) {
// No zero value for this unit --> doesn't support addition.
return NS_ERROR_FAILURE;
}
destWrapper->mCSSValue = *zeroVal;
destWrapper->mPropID = valueToAddWrapper->mPropID;
destWrapper->mPresContext = valueToAddWrapper->mPresContext;
+ } else if (valueToAddWrapper->mPropID == eCSSProperty_UNKNOWN) {
+ NS_ABORT_IF_FALSE(valueToAddWrapper->mCSSValue.IsNull() &&
+ !valueToAddWrapper->mPresContext,
+ "Partially-initialized ValueWrapper");
+ realValueToAdd = GetZeroValueForUnit(destWrapper->mCSSValue.GetUnit());
+ if (!realValueToAdd) {
+ // No zero value for this unit --> doesn't support addition.
+ return NS_ERROR_FAILURE;
+ }
}
- NS_ABORT_IF_FALSE(valueToAddWrapper->mPropID != eCSSProperty_UNKNOWN &&
- !valueToAddWrapper->mCSSValue.IsNull(),
- "Added amount should be a parsed value");
// Special case: font-size-adjust is explicitly non-additive
if (destWrapper->mPropID == eCSSProperty_font_size_adjust) {
return NS_ERROR_FAILURE;
}
- return nsStyleAnimation::Add(destWrapper->mCSSValue,
- valueToAddWrapper->mCSSValue, aCount) ?
+ return nsStyleAnimation::Add(destWrapper->mPropID, destWrapper->mCSSValue,
+ *realValueToAdd, aCount) ?
NS_OK : NS_ERROR_FAILURE;
}
nsresult
nsSMILCSSValueType::ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const
{
@@ -220,31 +228,33 @@ nsSMILCSSValueType::ComputeDistance(cons
const ValueWrapper* fromWrapper = ExtractValueWrapper(aFrom);
const ValueWrapper* toWrapper = ExtractValueWrapper(aTo);
NS_ABORT_IF_FALSE(fromWrapper && toWrapper,
"These pointers shouldn't be null");
const nsStyleAnimation::Value* fromCSSValue;
if (fromWrapper->mPropID == eCSSProperty_UNKNOWN) {
- NS_ABORT_IF_FALSE(fromWrapper->mCSSValue.IsNull(),
- "If property ID is unset, then the unit should be, too");
+ NS_ABORT_IF_FALSE(fromWrapper->mCSSValue.IsNull() &&
+ !fromWrapper->mPresContext,
+ "Partially-initialized ValueWrapper");
fromCSSValue = GetZeroValueForUnit(toWrapper->mCSSValue.GetUnit());
if (!fromCSSValue) {
// No zero value for this unit --> doesn't support distance-computation.
return NS_ERROR_FAILURE;
}
} else {
fromCSSValue = &fromWrapper->mCSSValue;
}
NS_ABORT_IF_FALSE(toWrapper->mPropID != eCSSProperty_UNKNOWN &&
- !toWrapper->mCSSValue.IsNull(),
+ !toWrapper->mCSSValue.IsNull() && toWrapper->mPresContext,
"ComputeDistance endpoint should be a parsed value");
- return nsStyleAnimation::ComputeDistance(*fromCSSValue, toWrapper->mCSSValue,
+ return nsStyleAnimation::ComputeDistance(toWrapper->mPropID,
+ *fromCSSValue, toWrapper->mCSSValue,
aDistance) ?
NS_OK : NS_ERROR_FAILURE;
}
nsresult
nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
@@ -262,31 +272,33 @@ nsSMILCSSValueType::Interpolate(const ns
const ValueWrapper* endWrapper = ExtractValueWrapper(aEndVal);
ValueWrapper* resultWrapper = ExtractValueWrapper(aResult);
NS_ABORT_IF_FALSE(startWrapper && endWrapper && resultWrapper,
"These pointers shouldn't be null");
const nsStyleAnimation::Value* startCSSValue;
if (startWrapper->mPropID == eCSSProperty_UNKNOWN) {
- NS_ABORT_IF_FALSE(startWrapper->mCSSValue.IsNull(),
- "If property ID is unset, then the unit should be, too");
+ NS_ABORT_IF_FALSE(startWrapper->mCSSValue.IsNull() &&
+ !startWrapper->mPresContext,
+ "Partially-initialized ValueWrapper");
startCSSValue = GetZeroValueForUnit(endWrapper->mCSSValue.GetUnit());
if (!startCSSValue) {
// No zero value for this unit --> doesn't support interpolation.
return NS_ERROR_FAILURE;
}
} else {
startCSSValue = &startWrapper->mCSSValue;
}
NS_ABORT_IF_FALSE(endWrapper->mPropID != eCSSProperty_UNKNOWN &&
- !endWrapper->mCSSValue.IsNull(),
+ !endWrapper->mCSSValue.IsNull() && endWrapper->mPresContext,
"Interpolate endpoint should be a parsed value");
- if (nsStyleAnimation::Interpolate(*startCSSValue,
+ if (nsStyleAnimation::Interpolate(endWrapper->mPropID,
+ *startCSSValue,
endWrapper->mCSSValue,
aUnitDistance,
resultWrapper->mCSSValue)) {
resultWrapper->mPropID = endWrapper->mPropID;
resultWrapper->mPresContext = endWrapper->mPresContext;
return NS_OK;
}
return NS_ERROR_FAILURE;
--- a/content/smil/test/Makefile.in
+++ b/content/smil/test/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
db_smilCSSFromBy.js \
db_smilCSSFromTo.js \
db_smilCSSPaced.js \
db_smilCSSPropertyList.js \
smilTestUtils.js \
+ test_smilCSSFontStretchRelative.xhtml \
test_smilCSSFromBy.xhtml \
test_smilCSSFromTo.xhtml \
test_smilCSSInherit.xhtml \
test_smilCSSPaced.xhtml \
test_smilRestart.xhtml \
test_smilGetStartTime.xhtml \
test_smilGetSimpleDuration.xhtml \
test_smilKeySplines.xhtml \
--- a/content/smil/test/db_smilCSSFromTo.js
+++ b/content/smil/test/db_smilCSSFromTo.js
@@ -265,44 +265,52 @@ var gFromToBundles = [
toComp: "40px"}),
])),
new TestcaseBundle(gPropList.font_size_adjust, [
new AnimTestcaseFromTo("0.9", "0.1", { midComp: "0.5" }),
new AnimTestcaseFromTo("0.5", "0.6", { midComp: "0.55" }),
new AnimTestcaseFromTo("none", "0.4"),
]),
new TestcaseBundle(gPropList.font_stretch, [
- new AnimTestcaseFromTo("normal", "wider"),
- new AnimTestcaseFromTo("narrower", "ultra-condensed"),
- new AnimTestcaseFromTo("extra-condensed", "condensed"),
- new AnimTestcaseFromTo("semi-condensed", "semi-expanded"),
- new AnimTestcaseFromTo("expanded", "extra-expanded"),
- new AnimTestcaseFromTo("ultra-expanded", "inherit", { toComp: "normal" }),
- ], "need support for all properties that get stored in nsFont"),
+ new AnimTestcaseFromTo("normal", "wider", {},
+ "need support for animating between " +
+ "relative 'font-stretch' values"),
+ new AnimTestcaseFromTo("narrower", "ultra-condensed", {},
+ "need support for animating between " +
+ "relative 'font-stretch' values"),
+ new AnimTestcaseFromTo("ultra-condensed", "condensed",
+ { midComp: "extra-condensed" }),
+ new AnimTestcaseFromTo("semi-condensed", "semi-expanded",
+ { midComp: "normal" }),
+ new AnimTestcaseFromTo("expanded", "ultra-expanded",
+ { midComp: "extra-expanded" }),
+ new AnimTestcaseFromTo("ultra-expanded", "inherit",
+ { midComp: "expanded", toComp: "normal" }),
+ ]),
new TestcaseBundle(gPropList.font_style, [
new AnimTestcaseFromTo("italic", "inherit", { toComp: "normal" }),
new AnimTestcaseFromTo("normal", "italic"),
new AnimTestcaseFromTo("italic", "oblique"),
new AnimTestcaseFromTo("oblique", "normal"),
]),
new TestcaseBundle(gPropList.font_variant, [
new AnimTestcaseFromTo("inherit", "small-caps", { fromComp: "normal" }),
new AnimTestcaseFromTo("small-caps", "normal"),
]),
new TestcaseBundle(gPropList.font_weight, [
- new AnimTestcaseFromTo("100", "900"),
- new AnimTestcaseFromTo("700", "100",
- // Note that '700' ends up as "bold" in computed
- // style (not the other way around)
- { fromComp: "bold" }),
+ new AnimTestcaseFromTo("100", "900", { midComp: "500" }),
+ new AnimTestcaseFromTo("700", "100", { midComp: "400" }),
new AnimTestcaseFromTo("inherit", "200",
- { fromComp: "400" }),
+ { fromComp: "400", midComp: "300" }),
new AnimTestcaseFromTo("normal", "bold",
- { fromComp: "400" }),
- ], "need support for all properties that get stored in nsFont"),
+ { fromComp: "400", midComp: "500", toComp: "700" }),
+ new AnimTestcaseFromTo("lighter", "bolder", {},
+ "need support for animating between " +
+ "relative 'font-weight' values"),
+ ]),
// NOTE: Mozilla doesn't currently support "glyph-orientation-horizontal" or
// "glyph-orientation-vertical", but I'm testing them here in case we ever
// add support for them, because they're explicitly not animatable in the SVG
// spec.
new TestcaseBundle(gPropList.glyph_orientation_horizontal,
[ new AnimTestcaseFromTo("45deg", "60deg") ]),
new TestcaseBundle(gPropList.glyph_orientation_vertical,
[ new AnimTestcaseFromTo("45deg", "60deg") ]),
new file mode 100644
--- /dev/null
+++ b/content/smil/test/test_smilCSSFontStretchRelative.xhtml
@@ -0,0 +1,109 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Test for Animation Behavior on CSS Properties</title>
+ <script type="text/javascript" src="/MochiKit/packed.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="smilTestUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+<svg id="svg" xmlns="http://www.w3.org/2000/svg">
+</svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+/* This testcase verifies that animated values of "wider" and "narrower" for
+ "font-stretch" have the expected effect, across all possible inherited
+ values of the property.
+ XXXdholbert Currently, we don't support animating relative values of
+ font-stretch, so most of the tests here use todo_is() rather than is().
+*/
+
+SimpleTest.waitForExplicitFinish();
+
+const gPropertyName="font-stretch";
+
+// List of non-relative font-stretch values, from smallest to largest
+const gFontStretchValues = [
+ "ultra-condensed",
+ "extra-condensed",
+ "condensed",
+ "semi-condensed",
+ "normal",
+ "semi-expanded",
+ "expanded",
+ "extra-expanded",
+ "ultra-expanded"
+];
+
+function testFontStretchValue(baseValue, narrowerStep, widerStep)
+{
+ var svg = SMILUtil.getSVGRoot();
+ var gElem = document.createElementNS(SVG_NS, "g");
+ gElem.setAttribute("style", "font-stretch: " + baseValue);
+ svg.appendChild(gElem);
+
+ var textElem = document.createElementNS(SVG_NS, "text");
+ gElem.appendChild(textElem);
+
+ var animElem = document.createElementNS(SVG_NS, "set");
+ animElem.setAttribute("attributeName", gPropertyName);
+ animElem.setAttribute("attributeType", "CSS");
+ animElem.setAttribute("begin", "0s");
+ animElem.setAttribute("dur", "indefinite");
+ textElem.appendChild(animElem);
+
+ // CHECK EFFECT OF 'narrower'
+ // NOTE: Using is() instead of todo_is() for ultra-condensed, since
+ // 'narrower' has no effect on that value.
+ var myIs = (baseValue == "ultra-condensed" ? is : todo_is);
+ animElem.setAttribute("to", "narrower");
+ SMILUtil.getSVGRoot().setCurrentTime(1.0); // Force a resample
+ myIs(SMILUtil.getComputedStyleSimple(textElem, gPropertyName), narrowerStep,
+ "checking effect of 'narrower' on inherited value '" + baseValue + "'");
+
+ // CHECK EFFECT OF 'wider'
+ // NOTE: using is() instead of todo_is() for ultra-expanded, since
+ // 'wider' has no effect on that value.
+ myIs = (baseValue == "ultra-expanded" ? is : todo_is);
+ animElem.setAttribute("to", "wider");
+ SMILUtil.getSVGRoot().setCurrentTime(1.0); // Force a resample
+ myIs(SMILUtil.getComputedStyleSimple(textElem, gPropertyName), widerStep,
+ "checking effect of 'wider' on inherited value '" + baseValue + "'");
+
+ // Removing animation should clear animated effects
+ textElem.removeChild(animElem);
+ svg.removeChild(gElem);
+}
+
+function main()
+{
+ if (!SMILUtil.isSMILEnabled()) {
+ ok(false, "SMIL dosn't seem to be enabled");
+ SimpleTest.finish();
+ return;
+ }
+
+ var valuesList = gFontStretchValues;
+ for (var baseIdx in valuesList) {
+ // 'narrower' and 'wider' are expected to shift us by one slot, but not
+ // past the ends of the list of possible values.
+ var narrowerIdx = Math.max(baseIdx - 1, 0);
+ var widerIdx = Math.min(baseIdx + 1, valuesList.length - 1);
+
+ testFontStretchValue(valuesList[baseIdx],
+ valuesList[narrowerIdx], valuesList[widerIdx]);
+ }
+
+ SimpleTest.finish();
+}
+
+window.addEventListener("load", main, false);
+]]>
+</script>
+</pre>
+</body>
+</html>
--- a/content/svg/content/test/bbox-helper.svg
+++ b/content/svg/content/test/bbox-helper.svg
@@ -1,6 +1,9 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g transform="scale(0.5)">
<foreignObject id="f" width="100" height="100"/>
</g>
+ <text id="b" x="20" y="20">b</text>
+ <text id="a" x="20" y="30">a</text>
+ <text id="y" x="20" y="40">y</text>
</svg>
--- a/content/svg/content/test/test_bbox.xhtml
+++ b/content/svg/content/test/test_bbox.xhtml
@@ -18,28 +18,37 @@ https://bugzilla.mozilla.org/show_bug.cg
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function run()
{
var doc = $("svg").contentDocument;
-
+
+ function getBBox(id) {
+ return doc.getElementById(id).getBBox();
+ }
function checkBBox(id, x, y, width, height) {
- var e = doc.getElementById(id);
- var bbox = e.getBBox();
+ var bbox = getBBox(id);
is(bbox.x, x, id + ".getBBox().x");
is(bbox.y, y, id + ".getBBox().y");
is(bbox.width, width, id + ".getBBox().width");
is(bbox.height, height, id + ".getBBox().height");
}
+ function checkBBoxHeight(id1, id2) {
+ var bbox1 = getBBox(id1);
+ var bbox2 = getBBox(id2);
+ is(bbox1.height, bbox2.height, id1 + ".getBBox().height");
+ }
checkBBox("f", 0, 0, 100, 100);
-
+ checkBBoxHeight("a", "b");
+ checkBBoxHeight("a", "y");
+
SimpleTest.finish();
}
window.addEventListener("load", run, false);
</script>
</pre>
</body>
</html>
--- a/content/test/unit/head_content.js
+++ b/content/test/unit/head_content.js
@@ -70,18 +70,18 @@ function ParseFile(file) {
}
var fileObj = __testsDirectory.clone();
fileObj.append(file);
file = fileObj;
}
do_check_eq(file instanceof nsILocalFile, true);
- fileStr = C["@mozilla.org/network/file-input-stream;1"]
- .createInstance(nsIFileInputStream);
+ var fileStr = C["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(nsIFileInputStream);
// Init for readonly reading
fileStr.init(file, 0x01, 0400, nsIFileInputStream.CLOSE_ON_EOF);
return ParseXML(fileStr);
}
function ParseXML(data) {
if (typeof(data) == "string") {
return DOMParser().parseFromString(data, "application/xml");
--- a/content/test/unit/test_range.js
+++ b/content/test/unit/test_range.js
@@ -257,17 +257,17 @@ function getParsedDocument(aPath) {
* Run the extraction tests.
*/
function run_extract_test() {
var filePath = "test_delete_range.xml";
var doc = getParsedDocument(filePath);
var tests = doc.getElementsByTagName("test");
// Run our deletion, extraction tests.
- for (i = 0; i < tests.length; i++) {
+ for (var i = 0; i < tests.length; i++) {
dump("Configuring for test " + i + "\n");
var currentTest = tests.item(i);
// Validate the test is properly formatted for what this harness expects.
var baseSource = currentTest.firstChild;
do_check_eq(baseSource.nodeName, "source");
var baseResult = baseSource.nextSibling;
do_check_eq(baseResult.nodeName, "result");
@@ -310,20 +310,20 @@ function run_extract_test() {
if (cutFragment) {
do_check_true(extractFrag.isEqualNode(cutFragment));
} else {
do_check_eq(extractFrag.firstChild, null);
}
do_check_true(baseFrag.isEqualNode(resultFrag));
dump("Ensure the original nodes weren't extracted - test " + i + "\n\n");
- walker = doc.createTreeWalker(baseFrag,
- C_i.nsIDOMNodeFilter.SHOW_ALL,
- null,
- false);
+ var walker = doc.createTreeWalker(baseFrag,
+ C_i.nsIDOMNodeFilter.SHOW_ALL,
+ null,
+ false);
var foundStart = false;
var foundEnd = false;
do {
do_check_true(walker.currentNode instanceof C_i.nsIDOM3Node);
if (walker.currentNode.isSameNode(startContainer)) {
foundStart = true;
}
@@ -410,23 +410,23 @@ function run_extract_test() {
*/
function run_miscellaneous_tests() {
var filePath = "test_delete_range.xml";
var doc = getParsedDocument(filePath);
var tests = doc.getElementsByTagName("test");
// Let's try some invalid inputs to our DOM range and see what happens.
var currentTest = tests.item(0);
- baseSource = currentTest.firstChild;
- baseResult = baseSource.nextSibling;
- baseExtract = baseResult.nextSibling;
+ var baseSource = currentTest.firstChild;
+ var baseResult = baseSource.nextSibling;
+ var baseExtract = baseResult.nextSibling;
- baseFrag = getFragment(baseSource);
+ var baseFrag = getFragment(baseSource);
- baseRange = getRange(baseSource, baseFrag);
+ var baseRange = getRange(baseSource, baseFrag);
var startContainer = baseRange.startContainer;
var endContainer = baseRange.endContainer;
var startOffset = baseRange.startOffset;
var endOffset = baseRange.endOffset;
// Text range manipulation.
if ((endOffset > startOffset) &&
(startContainer == endContainer) &&
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -603,16 +603,19 @@ ChangeDocumentForDefaultContent(nsISuppo
}
return PL_DHASH_NEXT;
}
void
nsXBLBinding::GenerateAnonymousContent()
{
+ NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
+ "Someone forgot a script blocker");
+
// Fetch the content element for this binding.
nsIContent* content =
mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
if (!content) {
// We have no anonymous content.
if (mNextBinding)
mNextBinding->GenerateAnonymousContent();
@@ -673,24 +676,19 @@ nsXBLBinding::GenerateAnonymousContent()
localName != nsGkAtoms::_template)) {
hasContent = PR_FALSE;
break;
}
}
}
if (hasContent || hasInsertionPoints) {
- nsIDocument *document = mBoundElement->GetOwnerDoc();
- if (!document) {
- return;
- }
-
nsCOMPtr<nsIDOMNode> clonedNode;
nsCOMArray<nsINode> nodesWithProperties;
- nsNodeUtils::Clone(content, PR_TRUE, document->NodeInfoManager(),
+ nsNodeUtils::Clone(content, PR_TRUE, doc->NodeInfoManager(),
nodesWithProperties, getter_AddRefs(clonedNode));
mContent = do_QueryInterface(clonedNode);
InstallAnonymousContent(mContent, mBoundElement);
if (hasInsertionPoints) {
// Now check and see if we have a single insertion point
// or multiple insertion points.
@@ -1158,42 +1156,46 @@ nsXBLBinding::ChangeDocument(nsIDocument
}
}
}
// Remove our event handlers
UnhookEventHandlers();
}
- // Then do our ancestors. This reverses the construction order, so that at
- // all times things are consistent as far as everyone is concerned.
- if (mNextBinding) {
- mNextBinding->ChangeDocument(aOldDocument, aNewDocument);
- }
+ {
+ nsAutoScriptBlocker scriptBlocker;
+
+ // Then do our ancestors. This reverses the construction order, so that at
+ // all times things are consistent as far as everyone is concerned.
+ if (mNextBinding) {
+ mNextBinding->ChangeDocument(aOldDocument, aNewDocument);
+ }
- // Update the anonymous content.
- // XXXbz why not only for style bindings?
- nsIContent *anonymous = mContent;
- if (anonymous) {
- // Also kill the default content within all our insertion points.
- if (mInsertionPointTable)
- mInsertionPointTable->Enumerate(ChangeDocumentForDefaultContent,
- nsnull);
+ // Update the anonymous content.
+ // XXXbz why not only for style bindings?
+ nsIContent *anonymous = mContent;
+ if (anonymous) {
+ // Also kill the default content within all our insertion points.
+ if (mInsertionPointTable)
+ mInsertionPointTable->Enumerate(ChangeDocumentForDefaultContent,
+ nsnull);
- nsXBLBinding::UninstallAnonymousContent(aOldDocument, anonymous);
- }
+ nsXBLBinding::UninstallAnonymousContent(aOldDocument, anonymous);
+ }
- // Make sure that henceforth we don't claim that mBoundElement's children
- // have insertion parents in the old document.
- nsBindingManager* bindingManager = aOldDocument->BindingManager();
- for (PRUint32 i = mBoundElement->GetChildCount(); i > 0; --i) {
- NS_ASSERTION(mBoundElement->GetChildAt(i-1),
- "Must have child at i for 0 <= i < GetChildCount()!");
- bindingManager->SetInsertionParent(mBoundElement->GetChildAt(i-1),
- nsnull);
+ // Make sure that henceforth we don't claim that mBoundElement's children
+ // have insertion parents in the old document.
+ nsBindingManager* bindingManager = aOldDocument->BindingManager();
+ for (PRUint32 i = mBoundElement->GetChildCount(); i > 0; --i) {
+ NS_ASSERTION(mBoundElement->GetChildAt(i-1),
+ "Must have child at i for 0 <= i < GetChildCount()!");
+ bindingManager->SetInsertionParent(mBoundElement->GetChildAt(i-1),
+ nsnull);
+ }
}
}
}
PRBool
nsXBLBinding::InheritsStyle() const
{
// XXX Will have to change if we ever allow multiple bindings to contribute anonymous content.
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -337,17 +337,17 @@ nsXBLPrototypeBinding::Init(const nsACSt
mXBLDocInfoWeak = aInfo;
SetBindingElement(aElement);
return NS_OK;
}
PRBool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const
{
- PRBool equal;
+ PRBool equal = PR_FALSE;
mBindingURI->Equals(aURI, &equal);
if (!equal && mAlternateBindingURI) {
mAlternateBindingURI->Equals(aURI, &equal);
}
return equal;
}
static PRIntn
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -615,33 +615,37 @@ nsXBLService::LoadBindings(nsIContent* a
binding->RootBinding()->SetBaseBinding(newBinding);
}
else {
// Install the binding on the content node.
bindingManager->SetBinding(aContent, newBinding);
}
}
- // Set the binding's bound element.
- newBinding->SetBoundElement(aContent);
+ {
+ nsAutoScriptBlocker scriptBlocker;
- // Tell the binding to build the anonymous content.
- newBinding->GenerateAnonymousContent();
+ // Set the binding's bound element.
+ newBinding->SetBoundElement(aContent);
- // Tell the binding to install event handlers
- newBinding->InstallEventHandlers();
+ // Tell the binding to build the anonymous content.
+ newBinding->GenerateAnonymousContent();
- // Set up our properties
- rv = newBinding->InstallImplementation();
- NS_ENSURE_SUCCESS(rv, rv);
+ // Tell the binding to install event handlers
+ newBinding->InstallEventHandlers();
- // Figure out if we have any scoped sheets. If so, we do a second resolve.
- *aResolveStyle = newBinding->HasStyleSheets();
+ // Set up our properties
+ rv = newBinding->InstallImplementation();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Figure out if we have any scoped sheets. If so, we do a second resolve.
+ *aResolveStyle = newBinding->HasStyleSheets();
- newBinding.swap(*aBinding);
+ newBinding.swap(*aBinding);
+ }
return NS_OK;
}
nsresult
nsXBLService::FlushStyleBindings(nsIContent* aContent)
{
nsCOMPtr<nsIDocument> document = aContent->GetOwnerDoc();
--- a/content/xtf/test/unit/xtfComponent.js
+++ b/content/xtf/test/unit/xtfComponent.js
@@ -204,17 +204,17 @@ const fooClassID = Components.ID("{f3
const fooClassDesc = "XTF unit test: Foo element factory";
const fooContractID = xtfClass + "xtf-tests;foo";
/* </foo:element> */
const Module = {
// nsIModule
registerSelf: function registerSelf(compMgr, fileSpec, location, type) {
- compReg = compMgr.QueryInterface(nsIComponentRegistrar);
+ var compReg = compMgr.QueryInterface(nsIComponentRegistrar);
compReg.registerFactoryLocation(fooClassID,
fooClassDesc,
fooContractID,
fileSpec,
location,
type);
},
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -4754,16 +4754,17 @@ nsXULDocument::GetDocumentLWTheme()
mDocLWTheme = Doc_Theme_None; // No lightweight theme by default
nsIContent* content = GetRootContent();
nsAutoString hasLWTheme;
if (content &&
content->GetAttr(kNameSpaceID_None, nsGkAtoms::lwtheme, hasLWTheme) &&
!(hasLWTheme.IsEmpty()) &&
hasLWTheme.EqualsLiteral("true")) {
+ mDocLWTheme = Doc_Theme_Neutral;
nsAutoString lwTheme;
content->GetAttr(kNameSpaceID_None, nsGkAtoms::lwthemetextcolor, lwTheme);
if (!(lwTheme.IsEmpty())) {
if (lwTheme.EqualsLiteral("dark"))
mDocLWTheme = Doc_Theme_Dark;
else if (lwTheme.EqualsLiteral("bright"))
mDocLWTheme = Doc_Theme_Bright;
}
--- a/db/Makefile.in
+++ b/db/Makefile.in
@@ -30,27 +30,26 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-DEPTH = ..
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifndef NSS_DISABLE_DBM
ifdef MOZ_MORK
-DIRS = mdb mork
+PARALLEL_DIRS = mdb mork
endif
endif
ifdef MOZ_MORKREADER
-DIRS += morkreader
+PARALLEL_DIRS += morkreader
endif
include $(topsrcdir)/config/rules.mk
-
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3789,45 +3789,24 @@ nsDocShell::LoadErrorPage(nsIURI *aURI,
else
chanName.AssignLiteral("<no channel>");
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n", this,
spec.get(), NS_ConvertUTF16toUTF8(aURL).get(), chanName.get()));
}
#endif
- // Create an shistory entry for the old load, if we have a channel
- if (aFailedChannel) {
- mURIResultedInDocument = PR_TRUE;
- OnLoadingSite(aFailedChannel, PR_TRUE, PR_FALSE);
- } else if (aURI) {
- mURIResultedInDocument = PR_TRUE;
- OnNewURI(aURI, nsnull, nsnull, mLoadType, PR_TRUE, PR_FALSE);
- }
- // Be sure to have a correct mLSHE, it may have been cleared by
- // EndPageLoad. See bug 302115.
- if (mSessionHistory && !mLSHE) {
- PRInt32 idx;
- mSessionHistory->GetRequestedIndex(&idx);
- if (idx == -1)
- mSessionHistory->GetIndex(&idx);
-
- nsCOMPtr<nsIHistoryEntry> entry;
- mSessionHistory->GetEntryAtIndex(idx, PR_FALSE,
- getter_AddRefs(entry));
- mLSHE = do_QueryInterface(entry);
- }
+ mFailedChannel = aFailedChannel;
+ mFailedURI = aURI;
+ mFailedLoadType = mLoadType;
nsCAutoString url;
nsCAutoString charset;
if (aURI)
{
- // Set our current URI
- SetCurrentURI(aURI);
-
nsresult rv = aURI->GetSpec(url);
rv |= aURI->GetOriginCharset(charset);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (aURL)
{
CopyUTF16toUTF8(aURL, url);
}
@@ -3946,20 +3925,25 @@ nsDocShell::Reload(PRUint32 aReloadFlags
}
NS_IMETHODIMP
nsDocShell::Stop(PRUint32 aStopFlags)
{
// Revoke any pending event related to content viewer restoration
mRestorePresentationEvent.Revoke();
- if (mLoadType == LOAD_ERROR_PAGE && mLSHE) {
- // Since error page loads never unset mLSHE, do so now
- SetHistoryEntry(&mOSHE, mLSHE);
- SetHistoryEntry(&mLSHE, nsnull);
+ if (mLoadType == LOAD_ERROR_PAGE) {
+ if (mLSHE) {
+ // Since error page loads never unset mLSHE, do so now
+ SetHistoryEntry(&mOSHE, mLSHE);
+ SetHistoryEntry(&mLSHE, nsnull);
+ }
+
+ mFailedChannel = nsnull;
+ mFailedURI = nsnull;
}
if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
// Stop the document loading
if (mContentViewer)
mContentViewer->Stop();
}
@@ -7026,16 +7010,59 @@ nsDocShell::CreateContentViewer(const ch
// *new* document will fire.
mFiredUnloadEvent = PR_FALSE;
// we've created a new document so go ahead and call
// OnLoadingSite(), but don't fire OnLocationChange()
// notifications before we've called Embed(). See bug 284993.
mURIResultedInDocument = PR_TRUE;
+ if (mLoadType == LOAD_ERROR_PAGE) {
+ // We need to set the SH entry and our current URI here and not
+ // at the moment we load the page. We want the same behavior
+ // of Stop() as for a normal page load. See bug 514232 for details.
+
+ // Revert mLoadType to load type to state the page load failed,
+ // following function calls need it.
+ mLoadType = mFailedLoadType;
+
+ nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
+ nsCOMPtr<nsIURI> failedURI = mFailedURI;
+ mFailedChannel = nsnull;
+ mFailedURI = nsnull;
+
+ // Create an shistory entry for the old load, if we have a channel
+ if (failedChannel) {
+ mURIResultedInDocument = PR_TRUE;
+ OnLoadingSite(failedChannel, PR_TRUE, PR_FALSE);
+ } else if (failedURI) {
+ mURIResultedInDocument = PR_TRUE;
+ OnNewURI(failedURI, nsnull, nsnull, mLoadType, PR_TRUE, PR_FALSE);
+ }
+
+ // Be sure to have a correct mLSHE, it may have been cleared by
+ // EndPageLoad. See bug 302115.
+ if (mSessionHistory && !mLSHE) {
+ PRInt32 idx;
+ mSessionHistory->GetRequestedIndex(&idx);
+ if (idx == -1)
+ mSessionHistory->GetIndex(&idx);
+
+ nsCOMPtr<nsIHistoryEntry> entry;
+ mSessionHistory->GetEntryAtIndex(idx, PR_FALSE,
+ getter_AddRefs(entry));
+ mLSHE = do_QueryInterface(entry);
+ }
+
+ // Set our current URI
+ SetCurrentURI(failedURI);
+
+ mLoadType = LOAD_ERROR_PAGE;
+ }
+
PRBool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, PR_FALSE);
// let's try resetting the load group if we need to...
nsCOMPtr<nsILoadGroup> currentLoadGroup;
NS_ENSURE_SUCCESS(aOpenedChannel->
GetLoadGroup(getter_AddRefs(currentLoadGroup)),
NS_ERROR_FAILURE);
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -692,16 +692,23 @@ protected:
// The URI we're currently loading. This is only relevant during the
// firing of a pagehide/unload. The caller of FirePageHideNotification()
// is responsible for setting it and unsetting it. It may be null if the
// pagehide/unload is happening for some reason other than just loading a
// new URI.
nsCOMPtr<nsIURI> mLoadingURI;
+ // Set in LoadErrorPage from the method argument and used later
+ // in CreateContentViewer. We have to delay an shistory entry creation
+ // for which these objects are needed.
+ nsCOMPtr<nsIURI> mFailedURI;
+ nsCOMPtr<nsIChannel> mFailedChannel;
+ PRUint32 mFailedLoadType;
+
// WEAK REFERENCES BELOW HERE.
// Note these are intentionally not addrefd. Doing so will create a cycle.
// For that reasons don't use nsCOMPtr.
nsIDocShellTreeOwner * mTreeOwner; // Weak Reference
nsPIDOMEventTarget * mChromeEventHandler; //Weak Reference
eCharsetReloadState mCharsetReloadState;
--- a/docshell/test/Makefile.in
+++ b/docshell/test/Makefile.in
@@ -73,16 +73,19 @@ include $(topsrcdir)/config/rules.mk
test_bug475636.html \
file_bug475636.sjs \
test_bug385434.html \
file_bug385434_1.html \
file_bug385434_2.html \
file_bug385434_3.html \
test_bug509055.html \
file_bug509055.html \
+ test_bug529119-1.html \
+ test_bug529119-2.html \
+ bug529119-window.html \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
_TEST_FILES += \
test_bug511449.html \
file_bug511449.html \
$(NULL)
endif
new file mode 100644
--- /dev/null
+++ b/docshell/test/bug529119-window.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119, sub-window</title>
+<body onload="window.opener.windowLoaded();">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/test_bug529119-1.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var workingURL = "http://localhost:8888/tests/docshell/test/bug529119-window.html";
+var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/";
+
+var w = null;
+var phase = 0;
+var gotWrongPageOnTryAgainClick = false;
+
+function pollForPage(expected_title, f, w)
+{
+ // Start with polling after a delay, we might mistakenly take the current page
+ // as an expected one.
+ window.setTimeout(function() {
+ var iterationsLeft = 20;
+ var int = window.setInterval(function() {
+ iterationsLeft--;
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ try {
+ var title = w.document.title;
+ }
+ catch (ex) {
+ alert(ex);
+ return;
+ }
+
+ if (iterationsLeft == 0 || title.match(expected_title)) {
+ window.clearInterval(int);
+ f(iterationsLeft > 0);
+ }
+ }, 100);
+ }, 1000);
+}
+
+function windowLoaded()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ switch (phase)
+ {
+ case 0:
+ /* 2. We have succeededfully loaded a page, now go to a faulty URL */
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ phase = 1;
+
+ pollForPage("Problem loading page", function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ /* 3. now, while we are on the error page, try to reload it, actually
+ click the "Try Again" button */
+ w.location.reload();
+
+ pollForPage("Problem loading page", function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ /* 4-finish, check we are still on the error page */
+ is(w.location.href, faultyURL, "Is on an error page");
+ isnot(w.location.href, workingURL, "Is not on the previous page");
+ is(gotWrongPageOnTryAgainClick, false,
+ "Must not get www.example.com page on reload of an error page");
+ w.close();
+ SimpleTest.finish();
+ }, w);
+ }, w);
+ break;
+
+ case 1:
+ /* 4-check, we must not get here! */
+ gotWrongPageOnTryAgainClick = true;
+ break;
+ }
+}
+
+function startTest()
+{
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/test_bug529119-2.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script type="text/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var workingURL = "http://localhost:8888/tests/docshell/test/bug529119-window.html";
+var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/";
+
+var w = null;
+var phase = 0;
+
+function pollForPage(expected_title, f, w)
+{
+ // Start with polling after a delay, we might mistakenly take the current page
+ // as an expected one.
+ window.setTimeout(function() {
+ var iterationsLeft = 20;
+ var int = window.setInterval(function() {
+ iterationsLeft--;
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ try {
+ var title = w.document.title;
+ }
+ catch (ex) {
+ alert(ex);
+ return;
+ }
+
+ if (iterationsLeft == 0 || title.match(expected_title)) {
+ window.clearInterval(int);
+ f(iterationsLeft > 0);
+ }
+ }, 100);
+ }, 1000);
+}
+
+function windowLoaded()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+ /* 2. We have successfully loaded a page, now go to a faulty URL */
+ // XXX The test fails when we change the location synchronously
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ pollForPage("Problem loading page", function(succeeded) {
+ ok(succeeded, "Waiting for error page succeeded");
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ /* 3. now, while we are on the error page, navigate back */
+ try {
+ w.back();
+ }
+ catch(ex) {
+ ok(false, "w.back() threw " + ex);
+ }
+
+ pollForPage("Test bug 529119, sub-window", function(succeeded) {
+ ok(succeeded, "Waiting for original page succeeded");
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ /* 4-finish, check we are back at the original page */
+ isnot(w.location.href, faultyURL, "Is on an error page");
+ is(w.location.href, workingURL, "Is not on the previous page");
+ w.close();
+ SimpleTest.finish();
+ }, w);
+ }, w);
+}
+
+function startTest()
+{
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8094,36 +8094,42 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
return;
}
PRBool isInterval = PR_FALSE;
// If we have a regular interval timer, we re-schedule the
// timeout, accounting for clock drift.
if (timeout->mInterval) {
- // Compute time to next timeout for interval timer. If we're
- // running pending timeouts because they've been temporarily
- // disabled (!aTimeout), set the next interval to be relative to
- // "now", and not to when the timeout that was pending should
- // have fired.
- // Also check if the next interval timeout is overdue. If so,
- // then restart the interval from now.
+ // Compute time to next timeout for interval timer.
PRTime nextInterval = (PRTime)timeout->mInterval * PR_USEC_PER_MSEC;
+
+ // Make sure nextInterval is at least DOM_MIN_TIMEOUT_VALUE.
+ // Note: We must cast the rhs expression to PRTime to work
+ // around what looks like a compiler bug on x86_64.
+ if (nextInterval < (PRTime)(DOM_MIN_TIMEOUT_VALUE * PR_USEC_PER_MSEC)) {
+ nextInterval = DOM_MIN_TIMEOUT_VALUE * PR_USEC_PER_MSEC;
+ }
+
+ // If we're running pending timeouts because they've been temporarily
+ // disabled (!aTimeout), set the next interval to be relative to "now",
+ // and not to when the timeout that was pending should have fired. Also
+ // check if the next interval timeout is overdue. If so, then restart
+ // the interval from now.
if (!aTimeout || nextInterval + timeout->mWhen <= now)
nextInterval += now;
else
nextInterval += timeout->mWhen;
PRTime delay = nextInterval - PR_Now();
- // Make sure the delay is at least DOM_MIN_TIMEOUT_VALUE.
- // Note: We must cast the rhs expression to PRTime to work
- // around what looks like a compiler bug on x86_64.
- if (delay < (PRTime)(DOM_MIN_TIMEOUT_VALUE * PR_USEC_PER_MSEC)) {
- delay = DOM_MIN_TIMEOUT_VALUE * PR_USEC_PER_MSEC;
+ // And make sure delay is nonnegative; that might happen if the timer
+ // thread is firing our timers somewhat early.
+ if (delay < 0) {
+ delay = 0;
}
if (timeout->mTimer) {
timeout->mWhen = nextInterval;
// Reschedule the OS timer. Don't bother returning any error
// codes if this fails since the callers of this method
// doesn't care about them nobody who cares about them
@@ -9377,16 +9383,18 @@ nsNavigator::GetPlatform(nsAString& aPla
#if defined(_WIN64)
aPlatform.AssignLiteral("Win64");
#elif defined(WIN32)
aPlatform.AssignLiteral("Win32");
#elif defined(XP_MACOSX) && defined(__ppc__)
aPlatform.AssignLiteral("MacPPC");
#elif defined(XP_MACOSX) && defined(__i386__)
aPlatform.AssignLiteral("MacIntel");
+#elif defined(XP_MACOSX) && defined(__x86_64__)
+ aPlatform.AssignLiteral("MacIntel");
#elif defined(XP_OS2)
aPlatform.AssignLiteral("OS/2");
#else
// XXX Communicator uses compiled-in build-time string defines
// to indicate the platform it was compiled *for*, not what it is
// currently running *on* which is what this does.
nsCAutoString plat;
rv = service->GetOscpu(plat);
@@ -9908,17 +9916,32 @@ nsNavigator::MozIsLocallyAvailable(const
//*****************************************************************************
// nsNavigator::nsIDOMNavigatorGeolocation
//*****************************************************************************
NS_IMETHODIMP nsNavigator::GetGeolocation(nsIDOMGeoGeolocation **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
-
- if (!mGeolocation && mDocShell) {
- nsCOMPtr<nsIDOMWindow> contentDOMWindow(do_GetInterface(mDocShell));
- mGeolocation = new nsGeolocation(contentDOMWindow);
- }
-
- NS_IF_ADDREF(*_retval = mGeolocation);
- return NS_OK;
-}
+ *_retval = nsnull;
+
+ if (mGeolocation) {
+ NS_ADDREF(*_retval = mGeolocation);
+ return NS_OK;
+ }
+
+ if (!mDocShell)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDOMWindow> contentDOMWindow(do_GetInterface(mDocShell));
+ if (!contentDOMWindow)
+ return NS_ERROR_FAILURE;
+
+ mGeolocation = new nsGeolocation();
+ if (!mGeolocation)
+ return NS_ERROR_FAILURE;
+
+ if (NS_FAILED(mGeolocation->Init(contentDOMWindow)))
+ return NS_ERROR_FAILURE;
+
+ NS_ADDREF(*_retval = mGeolocation);
+ return NS_OK;
+}
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -936,36 +936,58 @@ nsJSContext::DOMOperationCallback(JSCont
// lets see if CC() did anything, if not, cancel the script.
mem->IsLowMemory(&lowMemory);
if (lowMemory) {
if (nsContentUtils::GetBoolPref("dom.prevent_oom_dialog", PR_FALSE)) {
JS_ClearPendingException(cx);
return JS_FALSE;
}
-
- nsCOMPtr<nsIPrompt> prompt = GetPromptFromContext(ctx);
-
- nsXPIDLString title, msg;
- rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
- "LowMemoryTitle",
- title);
-
- rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
- "LowMemoryMessage",
- msg);
-
- //GetStringFromName can return NS_OK and still give NULL string
- if (NS_FAILED(rv) || !title || !msg) {
- NS_ERROR("Failed to get localized strings.");
- JS_ClearPendingException(cx);
- return JS_FALSE;
+
+ nsCOMPtr<nsIScriptError> errorObject =
+ do_CreateInstance("@mozilla.org/scripterror;1");
+
+ if (errorObject) {
+ nsXPIDLString msg;
+ nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
+ "LowMemoryMessage",
+ msg);
+
+ JSStackFrame *fp, *iterator = nsnull;
+ fp = ::JS_FrameIterator(cx, &iterator);
+ PRUint32 lineno = 0;
+ nsAutoString sourcefile;
+ if (fp) {
+ JSScript* script = ::JS_GetFrameScript(cx, fp);
+ if (script) {
+ const char* filename = ::JS_GetScriptFilename(cx, script);
+ if (filename) {
+ CopyUTF8toUTF16(nsDependentCString(filename), sourcefile);
+ }
+ jsbytecode* pc = ::JS_GetFramePC(cx, fp);
+ if (pc) {
+ lineno = ::JS_PCToLineNumber(cx, script, pc);
+ }
+ }
+ }
+
+ rv = errorObject->Init(msg.get(),
+ sourcefile.get(),
+ EmptyString().get(),
+ lineno, 0, nsIScriptError::errorFlag,
+ "content javascript");
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIConsoleService> consoleService =
+ do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ consoleService->LogMessage(errorObject);
+ }
+ }
}
-
- prompt->Alert(title, msg);
+
JS_ClearPendingException(cx);
return JS_FALSE;
}
}
}
PRTime now = PR_Now();
--- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
+++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
@@ -665,23 +665,16 @@ interface nsICanvasRenderingContextWebGL
const unsigned long MAX_RENDERBUFFER_SIZE = 0x84E8;
const unsigned long INVALID_FRAMEBUFFER_OPERATION = 0x0506;
//
// ATTRIBUTES
//
readonly attribute nsIDOMHTMLCanvasElement canvas;
- readonly attribute nsIWebGLBuffer currentArrayBufferBinding;
- readonly attribute nsIWebGLBuffer currentElementArrayBufferBinding;
- readonly attribute nsIWebGLFramebuffer currentFramebufferBinding;
- readonly attribute nsIWebGLRenderbuffer currentRenderbufferBinding;
- readonly attribute nsIWebGLTexture currentTextureBinding2D;
- readonly attribute nsIWebGLTexture currentTextureBindingCubeMap;
- readonly attribute nsIWebGLProgram currentProgram;
//
// METHODS
//
void present();
long sizeInBytes(in GLenum type);
void activeTexture (in GLenum texture);
@@ -775,74 +768,66 @@ interface nsICanvasRenderingContextWebGL
// Modified
//GLboolean getBoolean(in GLenum pname);
// NOTYET nsIWebGLBooleanArray getBooleanv(in GLenum pname);
//GLfloat getFloat(in GLenum pname);
//nsIWebGLArray getFloatv(in GLenum pname);
//GLint getInteger(in GLenum pname);
//nsIWebGLIntArray getIntegerv(in GLenum pname);
// js only
- void getParameter(in GLenum pname);
+ void getParameter (in GLenum pname);
// Modified: void glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
- GLint getBufferParameteri (in GLenum target, in GLenum pname);
- //nsIWebGLIntArray glGetBufferParameteriv (in GLenum target, in GLenum pname);
+ GLint getBufferParameteri (in GLenum target, in GLenum pname); // XXX remove
+ void getBufferParameter (in GLenum target, in GLenum pname);
GLenum getError ();
// Modified: void glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
- GLint getFramebufferAttachmentParameteri (in GLenum target, in GLenum attachment, in GLenum pname);
- //nsIWebGLIntArray glGetFramebufferAttachmentParameteriv (in GLenum target, in GLenum attachment, in GLenum pname);
+ GLint getFramebufferAttachmentParameteri (in GLenum target, in GLenum attachment, in GLenum pname); // XXX remove
+ void getFramebufferAttachmentParameter (in GLenum target, in GLenum attachment, in GLenum pname);
// Modified: void glGetProgramiv (nsIWebGLProgram program, GLenum pname, GLint* params);
- GLint getProgrami (in nsIWebGLProgram program, in GLenum pname);
- //nsIWebGLIntArray getProgramiv (in nsIWebGLProgram program, in GLenum pname);
- //void getProgramParameter (in nsIWebGLProgram program, in GLenum pname);
+ GLint getProgrami (in nsIWebGLProgram program, in GLenum pname); // XXX remove
+ void getProgramParameter (in nsIWebGLProgram program, in GLenum pname);
// Modified: void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
DOMString getProgramInfoLog (in nsIWebGLProgram program);
// Modified: void glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
//nsIWebGLIntArray getRenderbufferParameteriv (in GLenum target, in GLenum pname);
- GLint getRenderbufferParameteri (in GLenum target, in GLenum pname);
+ GLint getRenderbufferParameteri (in GLenum target, in GLenum pname); // XXX remove
+ void getRenderbufferParameter (in GLenum target, in GLenum pname);
- GLint getShaderi (in nsIWebGLShader shader, in GLenum pname);
- nsICanvasIntArray getShaderiv (in nsIWebGLShader shader, in GLenum pname);
- // GONE void getShaderParameter (in nsIWebGLShader shader, in GLenum pname);
+ GLint getShaderi (in nsIWebGLShader shader, in GLenum pname); // XXX remove
+ void getShaderParameter (in nsIWebGLShader shader, in GLenum pname);
// Modified: void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
DOMString getShaderInfoLog (in nsIWebGLShader shader);
// TBD
//void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
DOMString getShaderSource (in nsIWebGLShader shader);
DOMString getString (in GLenum name);
- GLfloat getTexParameterf (in GLenum target, in GLenum pname);
- nsICanvasArray getTexParameterfv (in GLenum target, in GLenum pname);
- GLint getTexParameteri (in GLenum target, in GLenum pname);
- nsICanvasArray getTexParameteriv (in GLenum target, in GLenum pname);
+ GLfloat getTexParameterf (in GLenum target, in GLenum pname); // XXX remove
+ GLint getTexParameteri (in GLenum target, in GLenum pname); // XXX remove
+ void getTexParameter (in GLenum target, in GLenum pname);
// FIXME: This is problematic. We don't implicitly know how big the returned data buffer
// needs to be like in the other glGet* calls. The only way to find out is to iterate
// through all the active uniforms with glGetActiveUniform() looking for the corresponding
// 'location'. This will give us the type and size of the data. Since this is a get call
// maybe that's ok?
- GLfloat getUniformf (in nsIWebGLProgram program, in GLint location);
- nsICanvasArray getUniformfv (in nsIWebGLProgram program, in GLint location);
- GLint getUniformi (in nsIWebGLProgram program, in GLint location);
- nsICanvasArray getUniformiv (in nsIWebGLProgram program, in GLint location);
+ void getUniform (in nsIWebGLProgram program, in GLint location);
GLint getUniformLocation (in nsIWebGLProgram program, in DOMString name);
- GLfloat getVertexAttribf (in GLuint index, in GLenum pname);
- nsICanvasArray getVertexAttribfv (in GLuint index, in GLenum pname);
- GLint getVertexAttribi (in GLuint index, in GLenum pname);
- nsICanvasArray getVertexAttribiv (in GLuint index, in GLenum pname);
+ void getVertexAttrib (in GLuint index, in GLenum pname);
// TBD
// void glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
GLuint getVertexAttribOffset(in GLuint index, in GLenum pname);
void hint (in GLenum target, in GLenum mode);
GLboolean isBuffer (in nsIWebGLBuffer buffer);
--- a/dom/interfaces/geolocation/nsIDOMGeoPositionError.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoPositionError.idl
@@ -32,19 +32,17 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
-[scriptable, uuid(1B493214-4E58-4A40-AA4C-1AB70C6DDBEC)]
+[scriptable, uuid(AD9FA4C8-EC71-4B2D-8294-9ADF06DDEC32)]
interface nsIDOMGeoPositionError : nsISupports
{
- const unsigned short UNKNOWN_ERROR = 0;
const unsigned short PERMISSION_DENIED = 1;
const unsigned short POSITION_UNAVAILABLE = 2;
const unsigned short TIMEOUT = 3;
readonly attribute short code;
- readonly attribute DOMString message;
};
--- a/dom/public/coreEvents/nsIDOMCompositionListener.h
+++ b/dom/public/coreEvents/nsIDOMCompositionListener.h
@@ -39,29 +39,28 @@
#define nsIDOMCompositionListener_h__
#include "nsIDOMEvent.h"
#include "nsIDOMEventListener.h"
/*
* Key pressed / released / typed listener interface.
*/
-// {93A5A335-AA51-4d32-977D-3680B7722AD5}
+// {47F158C0-C534-43a1-8415-8B17706E2FBC}
#define NS_IDOMCOMPOSITIONLISTENER_IID \
-{ 0x93a5a335, 0xaa51, 0x4d32, \
-{ 0x97, 0x7d, 0x36, 0x80, 0xb7, 0x72, 0x2a, 0xd5 } }
+{ 0x47f158c0, 0xc534, 0x43a1, \
+{ 0x84, 0x15, 0x8b, 0x17, 0x70, 0x6e, 0x2f, 0xbc } }
class nsIDOMCompositionListener : public nsIDOMEventListener {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMCOMPOSITIONLISTENER_IID)
NS_IMETHOD HandleStartComposition(nsIDOMEvent* aCompositionEvent) = 0;
NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent) = 0;
- NS_IMETHOD HandleQueryComposition(nsIDOMEvent* aCompositionEvent) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMCompositionListener,
NS_IDOMCOMPOSITIONLISTENER_IID)
#endif // nsIDOMCompositionListener_h__
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -106,23 +106,16 @@ nsDOMGeoPositionError::~nsDOMGeoPosition
NS_IMETHODIMP
nsDOMGeoPositionError::GetCode(PRInt16 *aCode)
{
NS_ENSURE_ARG_POINTER(aCode);
*aCode = mCode;
return NS_OK;
}
-NS_IMETHODIMP
-nsDOMGeoPositionError::GetMessage(nsAString & aMessage)
-{
- aMessage.Truncate();
- return NS_OK;
-}
-
void
nsDOMGeoPositionError::NotifyCallback(nsIDOMGeoPositionErrorCallback* aCallback)
{
if (!aCallback)
return;
// Ensure that the proper context is on the stack (bug 452762)
nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
@@ -707,42 +700,63 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
PRUint32 i;
for (i = 0; i < tmp->mPendingCallbacks.Length(); ++i)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mPendingCallbacks[i], nsIGeolocationRequest)
for (i = 0; i < tmp->mWatchingCallbacks.Length(); ++i)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWatchingCallbacks[i], nsIGeolocationRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-nsGeolocation::nsGeolocation(nsIDOMWindow* aContentDom)
+nsGeolocation::nsGeolocation()
: mUpdateInProgress(PR_FALSE)
{
- // Remember the window
- nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContentDom);
- if (window)
- mOwner = do_GetWeakReference(window->GetCurrentInnerWindow());
-
- // Grab the uri of the document
- nsCOMPtr<nsIDOMDocument> domdoc;
- aContentDom->GetDocument(getter_AddRefs(domdoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
- if (doc)
- doc->NodePrincipal()->GetURI(getter_AddRefs(mURI));
-
- mService = nsGeolocationService::GetInstance();
- if (mService)
- mService->AddLocator(this);
}
nsGeolocation::~nsGeolocation()
{
if (mService)
Shutdown();
}
+nsresult
+nsGeolocation::Init(nsIDOMWindow* aContentDom)
+{
+ // Remember the window
+ if (aContentDom) {
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContentDom);
+ if (!window)
+ return NS_ERROR_FAILURE;
+
+ mOwner = do_GetWeakReference(window->GetCurrentInnerWindow());
+ if (!mOwner)
+ return NS_ERROR_FAILURE;
+
+ // Grab the uri of the document
+ nsCOMPtr<nsIDOMDocument> domdoc;
+ aContentDom->GetDocument(getter_AddRefs(domdoc));
+ nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
+ if (!doc)
+ return NS_ERROR_FAILURE;
+
+ doc->NodePrincipal()->GetURI(getter_AddRefs(mURI));
+
+ if (!mURI)
+ return NS_ERROR_FAILURE;
+ }
+
+ // If no aContentDom was passed into us, we are being used
+ // by chrome/c++ and have no mOwner, no mURI, and no need
+ // to prompt.
+ mService = nsGeolocationService::GetInstance();
+ if (mService)
+ mService->AddLocator(this);
+
+ return NS_OK;
+}
+
void
nsGeolocation::Shutdown()
{
// Shutdown and release all callbacks
for (PRUint32 i = 0; i< mPendingCallbacks.Length(); i++)
mPendingCallbacks[i]->Shutdown();
mPendingCallbacks.Clear();
@@ -786,17 +800,17 @@ nsGeolocation::Update(nsIDOMGeoPosition
// function can only be called on the primary thread, we
// can lock this method with a member var.
if (mUpdateInProgress)
return;
mUpdateInProgress = PR_TRUE;
- if (!OwnerStillExists())
+ if (!WindowOwnerStillExists())
{
Shutdown();
return;
}
// notify anyone that has been waiting
for (PRUint32 i = 0; i< mPendingCallbacks.Length(); i++)
mPendingCallbacks[i]->SendLocation(aSomewhere);
@@ -814,95 +828,124 @@ nsGeolocation::GetCurrentPosition(nsIDOM
nsIDOMGeoPositionErrorCallback *errorCallback,
nsIDOMGeoPositionOptions *options)
{
NS_ENSURE_ARG_POINTER(callback);
if (sGeoEnabled == PR_FALSE)
return NS_ERROR_NOT_AVAILABLE;
- nsCOMPtr<nsIGeolocationPrompt> prompt = do_GetService(NS_GEOLOCATION_PROMPT_CONTRACTID);
- if (prompt == nsnull)
+ if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this, callback, errorCallback, options);
+ if (!request)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (NS_FAILED(request->Init()))
+ return NS_ERROR_FAILURE; // this as OKAY. not sure why we wouldn't throw. xxx dft
+
+ if (mOwner) {
+ nsCOMPtr<nsIGeolocationPrompt> prompt = do_GetService(NS_GEOLOCATION_PROMPT_CONTRACTID);
+ if (prompt == nsnull)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ prompt->Prompt(request);
+
+ mPendingCallbacks.AppendElement(request);
+
+ return NS_OK;
+ }
+
+ if (!nsContentUtils::IsCallerChrome())
+ return NS_ERROR_FAILURE;
+
+ request->Allow();
+
+ mPendingCallbacks.AppendElement(request);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
+ nsIDOMGeoPositionErrorCallback *errorCallback,
+ nsIDOMGeoPositionOptions *options,
+ PRInt32 *_retval NS_OUTPARAM)
+{
+
+ NS_ENSURE_ARG_POINTER(callback);
+
+ if (sGeoEnabled == PR_FALSE)
return NS_ERROR_NOT_AVAILABLE;
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
return NS_ERROR_NOT_AVAILABLE;
nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this, callback, errorCallback, options);
if (!request)
return NS_ERROR_OUT_OF_MEMORY;
if (NS_FAILED(request->Init()))
- return NS_OK;
-
- prompt->Prompt(request);
+ return NS_ERROR_FAILURE; // this as OKAY. not sure why we wouldn't throw. xxx dft
- // What if you have a location provider that only sends a location once, then stops.? fix.
- mPendingCallbacks.AppendElement(request);
- return NS_OK;
-}
+ if (mOwner) {
+ nsCOMPtr<nsIGeolocationPrompt> prompt = do_GetService(NS_GEOLOCATION_PROMPT_CONTRACTID);
+ if (prompt == nsnull)
+ return NS_ERROR_NOT_AVAILABLE;
-NS_IMETHODIMP
-nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
- nsIDOMGeoPositionErrorCallback *aErrorCallback,
- nsIDOMGeoPositionOptions *aOptions,
- PRInt32 *_retval NS_OUTPARAM)
-{
- NS_ENSURE_ARG_POINTER(aCallback);
+ prompt->Prompt(request);
- if (sGeoEnabled == PR_FALSE)
- return NS_ERROR_NOT_AVAILABLE;
-
- nsCOMPtr<nsIGeolocationPrompt> prompt = do_GetService(NS_GEOLOCATION_PROMPT_CONTRACTID);
- if (prompt == nsnull)
- return NS_ERROR_NOT_AVAILABLE;
+ // need to hand back an index/reference.
+ mWatchingCallbacks.AppendElement(request);
+ *_retval = mWatchingCallbacks.Length() - 1;
- if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
- return NS_ERROR_NOT_AVAILABLE;
+ return NS_OK;
+ }
- nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this, aCallback, aErrorCallback, aOptions);
- if (!request)
- return NS_ERROR_OUT_OF_MEMORY;
+ if (!nsContentUtils::IsCallerChrome())
+ return NS_ERROR_FAILURE;
- if (NS_FAILED(request->Init()))
- return NS_OK;
-
- prompt->Prompt(request);
+ request->Allow();
// need to hand back an index/reference.
mWatchingCallbacks.AppendElement(request);
*_retval = mWatchingCallbacks.Length() - 1;
+
return NS_OK;
}
NS_IMETHODIMP
nsGeolocation::ClearWatch(PRInt32 aWatchId)
{
PRUint32 count = mWatchingCallbacks.Length();
if (aWatchId < 0 || count == 0 || aWatchId > count)
- return NS_ERROR_FAILURE;
+ return NS_OK;
mWatchingCallbacks[aWatchId]->MarkCleared();
return NS_OK;
}
PRBool
-nsGeolocation::OwnerStillExists()
+nsGeolocation::WindowOwnerStillExists()
{
+ // an owner was never set when nsGeolocation
+ // was created, which means that this object
+ // is being used without a window.
+ if (mOwner == nsnull)
+ return PR_TRUE;
+
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mOwner);
- if (!window)
- return PR_FALSE;
-
if (window)
{
PRBool closed = PR_FALSE;
window->GetClosed(&closed);
if (closed)
return PR_FALSE;
+
+ nsPIDOMWindow* outer = window->GetOuterWindow();
+ if (!outer || outer->GetCurrentInnerWindow() != window)
+ return PR_FALSE;
}
- nsPIDOMWindow* outer = window->GetOuterWindow();
- if (!outer || outer->GetCurrentInnerWindow() != window)
- return PR_FALSE;
-
return PR_TRUE;
}
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -170,17 +170,19 @@ class nsGeolocation : public nsIDOMGeoGe
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMGEOGEOLOCATION
NS_DECL_CYCLE_COLLECTION_CLASS(nsGeolocation)
- nsGeolocation(nsIDOMWindow* contentDom);
+ nsGeolocation();
+
+ nsresult Init(nsIDOMWindow* contentDom=nsnull);
// Called by the geolocation device to notify that a location has changed.
void Update(nsIDOMGeoPosition* aPosition);
// Returns true if any of the callbacks are repeating
PRBool HasActiveCallbacks();
// Remove request from all callbacks arrays
@@ -191,17 +193,17 @@ public:
// Getter for the URI that this nsGeolocation was loaded from
nsIURI* GetURI() { return mURI; }
// Getter for the window that this nsGeolocation is owned by
nsIWeakReference* GetOwner() { return mOwner; }
// Check to see if the widnow still exists
- PRBool OwnerStillExists();
+ PRBool WindowOwnerStillExists();
private:
~nsGeolocation();
// Two callback arrays. The first |mPendingCallbacks| holds objects for only
// one callback and then they are released/removed from the array. The second
// |mWatchingCallbacks| holds objects until the object is explictly removed or
--- a/dom/src/threads/nsDOMThreadService.cpp
+++ b/dom/src/threads/nsDOMThreadService.cpp
@@ -326,17 +326,17 @@ public:
ClearQueue();
}
void PutRunnable(nsIRunnable* aRunnable,
PRIntervalTime aTimeoutInterval,
PRBool aClearQueue) {
NS_ASSERTION(aRunnable, "Null pointer!");
- // No need to enter the monitor because we should already be in it.
+ PR_ASSERT_CURRENT_THREAD_IN_MONITOR(gDOMThreadService->mMonitor);
if (NS_LIKELY(!aTimeoutInterval)) {
NS_ADDREF(aRunnable);
mRunnables.Push(aRunnable);
}
else {
NS_ASSERTION(!mCloseRunnable, "More than one close runnable?!");
if (aClearQueue) {
@@ -376,16 +376,21 @@ public:
NS_ERROR("nsDOMThreadService didn't give us a context! Are we out of memory?");
return NS_ERROR_FAILURE;
}
NS_ASSERTION(!JS_GetGlobalObject(cx), "Shouldn't have a global!");
JS_SetContextPrivate(cx, mWorker);
+ // Go ahead and trigger the operation callback for this context before we
+ // try to run any JS. That way we'll be sure to cancel or suspend as soon as
+ // possible if the compilation takes too long.
+ JS_TriggerOperationCallback(cx);
+
PRBool killWorkerWhenDone;
// Tell the worker which context it will be using
if (mWorker->SetGlobalForContext(cx)) {
RunQueue(cx, &killWorkerWhenDone);
// Code in XPConnect assumes that the context's global object won't be
// replaced outside of a request.
@@ -428,18 +433,16 @@ protected:
void ClearQueue() {
nsCOMPtr<nsIRunnable> runnable;
while ((runnable = dont_AddRef((nsIRunnable*)mRunnables.PopFront()))) {
// Loop until all the runnables are dead.
}
}
void RunQueue(JSContext* aCx, PRBool* aCloseRunnableSet) {
- PRBool operationCallbackTriggered = PR_FALSE;
-
while (1) {
nsCOMPtr<nsIRunnable> runnable;
{
nsAutoMonitor mon(gDOMThreadService->mMonitor);
runnable = dont_AddRef((nsIRunnable*)mRunnables.PopFront());
if (!runnable && mCloseRunnable) {
@@ -464,25 +467,16 @@ protected:
#endif
*aCloseRunnableSet = mKillWorkerWhenDone;
gDOMThreadService->WorkerComplete(this);
mon.NotifyAll();
return;
}
}
- if (!operationCallbackTriggered) {
- // Make sure that our operation callback is set to run before starting.
- // That way we are sure to suspend this worker if needed.
- JS_TriggerOperationCallback(aCx);
-
- // Only need to do this the first time.
- operationCallbackTriggered = PR_TRUE;
- }
-
// Clear out any old cruft hanging around in the regexp statics.
JS_ClearRegExpStatics(aCx);
runnable->Run();
}
NS_NOTREACHED("Shouldn't ever get here!");
}
@@ -501,16 +495,17 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorke
/*******************************************************************************
* JS environment function and callbacks
*/
JSBool
DOMWorkerOperationCallback(JSContext* aCx)
{
nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(aCx);
+ NS_ASSERTION(worker, "This must never be null!");
PRBool wasSuspended = PR_FALSE;
PRBool extraThreadAllowed = PR_FALSE;
jsrefcount suspendDepth = 0;
for (;;) {
// Kill execution if we're canceled.
if (worker->IsCanceled()) {
@@ -822,16 +817,26 @@ void
nsDOMThreadService::Cleanup()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
// This will either be called at 'xpcom-shutdown' or earlier if the call to
// Init fails somehow. We can therefore assume that all services will still
// be available here.
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ NS_ASSERTION(!mPools.Count(), "Live workers left!");
+ mPools.Clear();
+
+ NS_ASSERTION(!mSuspendedWorkers.Length(), "Suspended workers left!");
+ mSuspendedWorkers.Clear();
+ }
+
if (gObserverService) {
gObserverService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
NS_RELEASE(gObserverService);
UnregisterPrefCallbacks();
}
// The thread pool holds a circular reference to this service through its
@@ -848,21 +853,16 @@ nsDOMThreadService::Cleanup()
JS_GC(safeContext);
}
NS_RELEASE(gThreadJSContextStack);
}
// These must be released after the thread pool is shut down.
NS_IF_RELEASE(gJSRuntimeService);
NS_IF_RELEASE(gWorkerSecurityManager);
-
- nsAutoMonitor mon(mMonitor);
- NS_ASSERTION(!mPools.Count(), "Live workers left!");
-
- mPools.Clear();
}
nsresult
nsDOMThreadService::Dispatch(nsDOMWorker* aWorker,
nsIRunnable* aRunnable,
PRIntervalTime aTimeoutInterval,
PRBool aClearQueue)
{
@@ -939,31 +939,47 @@ nsDOMThreadService::SetWorkerTimeout(nsD
if (mWorkersInProgress.Get(aWorker, getter_AddRefs(workerRunnable))) {
workerRunnable->SetCloseRunnableTimeout(aTimeoutInterval);
}
}
void
nsDOMThreadService::WorkerComplete(nsDOMWorkerRunnable* aRunnable)
{
-
- // No need to be in the monitor here because we should already be in it.
+ PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
#ifdef DEBUG
nsRefPtr<nsDOMWorker>& debugWorker = aRunnable->mWorker;
nsRefPtr<nsDOMWorkerRunnable> runnable;
NS_ASSERTION(mWorkersInProgress.Get(debugWorker, getter_AddRefs(runnable)) &&
runnable == aRunnable,
"Removing a worker that isn't in our hashtable?!");
#endif
mWorkersInProgress.Remove(aRunnable->mWorker);
}
+PRBool
+nsDOMThreadService::QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable)
+{
+ nsAutoMonitor mon(mMonitor);
+
+#ifdef DEBUG
+ {
+ // Make sure that the runnable is in mWorkersInProgress.
+ nsRefPtr<nsDOMWorkerRunnable> current;
+ mWorkersInProgress.Get(aRunnable->mWorker, getter_AddRefs(current));
+ NS_ASSERTION(current == aRunnable, "Something crazy wrong here!");
+ }
+#endif
+
+ return mSuspendedWorkers.AppendElement(aRunnable) ? PR_TRUE : PR_FALSE;
+}
+
/* static */
JSContext*
nsDOMThreadService::CreateJSContext()
{
JSRuntime* rt;
gJSRuntimeService->GetRuntime(&rt);
NS_ENSURE_TRUE(rt, nsnull);
@@ -1027,63 +1043,113 @@ nsDOMThreadService::GetPoolForGlobal(nsI
}
return pool.forget();
}
void
nsDOMThreadService::TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool)
{
- nsAutoMonitor mon(mMonitor);
+ PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
// See if we need to trigger the operation callback on any currently running
// contexts.
PRUint32 contextCount = mJSContexts.Length();
for (PRUint32 index = 0; index < contextCount; index++) {
JSContext*& cx = mJSContexts[index];
nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(cx);
if (worker && worker->Pool() == aPool) {
JS_TriggerOperationCallback(cx);
}
}
}
void
+nsDOMThreadService::RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool)
+{
+ PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mMonitor);
+
+ PRUint32 count = mSuspendedWorkers.Length();
+ if (!count) {
+ // Nothing to do here.
+ return;
+ }
+
+ nsTArray<nsDOMWorkerRunnable*> others(count);
+
+ for (PRUint32 index = 0; index < count; index++) {
+ nsDOMWorkerRunnable* runnable = mSuspendedWorkers[index];
+
+#ifdef DEBUG
+ {
+ // Make sure that the runnable never left mWorkersInProgress.
+ nsRefPtr<nsDOMWorkerRunnable> current;
+ mWorkersInProgress.Get(runnable->mWorker, getter_AddRefs(current));
+ NS_ASSERTION(current == runnable, "Something crazy wrong here!");
+ }
+#endif
+
+ if (runnable->mWorker->Pool() == aPool) {
+#ifdef DEBUG
+ nsresult rv =
+#endif
+ mThreadPool->Dispatch(runnable, NS_DISPATCH_NORMAL);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "This shouldn't ever fail!");
+ }
+ else {
+ others.AppendElement(runnable);
+ }
+ }
+
+ mSuspendedWorkers.SwapElements(others);
+}
+
+void
nsDOMThreadService::CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
{
NS_ASSERTION(aGlobalObject, "Null pointer!");
nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_TRUE);
if (pool) {
pool->Cancel();
+
+ nsAutoMonitor mon(mMonitor);
+
TriggerOperationCallbackForPool(pool);
+ RescheduleSuspendedWorkerForPool(pool);
}
}
void
nsDOMThreadService::SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
{
NS_ASSERTION(aGlobalObject, "Null pointer!");
nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_FALSE);
if (pool) {
pool->Suspend();
+
+ nsAutoMonitor mon(mMonitor);
TriggerOperationCallbackForPool(pool);
}
}
void
nsDOMThreadService::ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
{
NS_ASSERTION(aGlobalObject, "Null pointer!");
nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_FALSE);
if (pool) {
pool->Resume();
+
+ nsAutoMonitor mon(mMonitor);
+
TriggerOperationCallbackForPool(pool);
+ RescheduleSuspendedWorkerForPool(pool);
}
}
void
nsDOMThreadService::NoteEmptyPool(nsDOMWorkerPool* aPool)
{
NS_ASSERTION(aPool, "Null pointer!");
--- a/dom/src/threads/nsDOMThreadService.h
+++ b/dom/src/threads/nsDOMThreadService.h
@@ -135,16 +135,17 @@ private:
static JSContext* CreateJSContext();
already_AddRefed<nsDOMWorkerPool>
GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
PRBool aRemove);
void TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool);
+ void RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool);
void NoteEmptyPool(nsDOMWorkerPool* aPool);
void TimeoutReady(nsDOMWorkerTimeout* aTimeout);
nsresult RegisterWorker(nsDOMWorker* aWorker,
nsIScriptGlobalObject* aGlobalObject);
@@ -156,16 +157,18 @@ private:
void RegisterPrefCallbacks();
void UnregisterPrefCallbacks();
static int PrefCallback(const char* aPrefName,
void* aClosure);
static PRUint32 GetWorkerCloseHandlerTimeoutMS();
+ PRBool QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable);
+
// Our internal thread pool.
nsCOMPtr<nsIThreadPool> mThreadPool;
// Maps nsIScriptGlobalObject* to nsDOMWorkerPool.
nsRefPtrHashtable<nsISupportsHashKey, nsDOMWorkerPool> mPools;
// mMonitor protects all access to mWorkersInProgress and
// mCreationsInProgress.
@@ -173,16 +176,20 @@ private:
// A map from nsDOMWorkerThread to nsDOMWorkerRunnable.
nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerRunnable> mWorkersInProgress;
// A list of active JSContexts that we've created. Always protected with
// mMonitor.
nsTArray<JSContext*> mJSContexts;
+ // A list of worker runnables that were never started because the worker was
+ // suspended. Always protected with mMonitor.
+ nsTArray<nsDOMWorkerRunnable*> mSuspendedWorkers;
+
nsString mAppName;
nsString mAppVersion;
nsString mPlatform;
nsString mUserAgent;
PRBool mNavigatorStringsLoaded;
};
--- a/dom/src/threads/test/closeOnGC_worker.js
+++ b/dom/src/threads/test/closeOnGC_worker.js
@@ -1,5 +1,7 @@
onclose = function() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "closeOnGC_server.sjs", false);
xhr.send();
};
+
+postMessage("ready");
--- a/dom/src/threads/test/test_closeOnGC.html
+++ b/dom/src/threads/test/test_closeOnGC.html
@@ -15,21 +15,23 @@
function CC() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
var worker = new Worker("closeOnGC_worker.js");
- worker = null;
-
- CC();
+ worker.onmessage = function(event) {
+ is(event.data, "ready");
+ worker = null;
+ }
var interval = setInterval(function() {
+ dump("xxxben interval\n");
var xhr = new XMLHttpRequest();
xhr.open("GET", "closeOnGC_server.sjs", false);
xhr.send();
if (xhr.responseText != "closed") {
CC();
return;
}
clearInterval(interval);
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug456151.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=456151
+-->
+<head>
+ <title>Test for Bug 456151</title>
+ <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=456151">Mozilla Bug 456151</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 456151 **/
+var intercepted = false;
+
+// Set up our new addEventListener
+var proto = HTMLParagraphElement.prototype;
+proto.oldAdd = proto.addEventListener;
+proto.addEventListener = function(ev, list, capt) {
+ intercepted = true;
+ this.oldAdd(ev, list, capt);
+}
+proto.oldRemove = proto.removeEventListener;
+proto.removeEventListener = function(ev, list, capt) {
+ intercepted = true;
+ this.oldRemove(ev, list, capt);
+}
+
+var called = false;
+
+var func = function() { called = true; };
+$("display").addEventListener("click", func, false);
+is(intercepted, true, "Should have interecepted addEventListener call");
+
+sendMouseEvent({type: "click"}, "display");
+is(called, true, "Should have called event listener");
+
+interecepted = false;
+called = false;
+
+$("display").removeEventListener("click", func, false);
+is(intercepted, true, "Should have interecepted removeEventListener call");
+
+sendMouseEvent({type: "click"}, "display");
+is(called, false, "Should have removed event listener");
+
+// And now some simple sanity tests
+var recursion = false;
+var x = document.createElement("span");
+HTMLSpanElement.prototype.addEventListener =
+ function(a, b, c) {
+ return x.addEventListener(a,b,c);
+ }
+try {
+ x.addEventListener("click", function() { called = true; }, false);
+} catch (e) {
+ recursion = e.message.match(/recursion/);
+}
+SimpleTest.isDeeply(recursion, ["recursion"], "Caught infinite recursion");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -54,12 +54,13 @@ include $(topsrcdir)/config/rules.mk
domstorage_global.js \
focus_window2.xul \
focus_frameset.html \
child_focus_frame.html \
test_focus_switchbinding.xul \
test_focus.xul \
window_focus.xul \
test_focused_link_scroll.xul \
+ test_geolocation.xul \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_geolocation.xul
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+ Test for Geolocation in chrome
+ -->
+<window id="sample-window" width="400" height="400"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <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>
+SimpleTest.waitForExplicitFinish();
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+var geolocation = Cc["@mozilla.org/geolocation;1"].getService(Ci.nsIDOMGeoGeolocation);
+geolocation.getCurrentPosition(done, error);
+
+function error(error)
+{
+ ok(0, "error occured trying to get geolocation from chrome");
+ SimpleTest.finish();
+ newwindow.close();
+}
+function done(position)
+{
+ ok(position, "geolocation was found from chrome");
+ SimpleTest.finish();
+ newwindow.close();
+}
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
+
+</window>
--- a/dom/tests/mochitest/geolocation/Makefile.in
+++ b/dom/tests/mochitest/geolocation/Makefile.in
@@ -53,16 +53,18 @@ include $(topsrcdir)/config/rules.mk
test_manyWindows.html \
test_allowCurrent.html \
test_allowWatch.html \
test_cancelCurrent.html \
test_cancelWatch.html \
test_clearWatch.html \
test_clearWatch_invalid.html \
test_timeoutWatch.html \
+ test_windowClose.html \
+ windowTest.html \
geolocation_common.js \
geolocation.html \
test_optional_api_params.html \
network_geolocation.sjs \
$(NULL)
libs:: $(_TEST_FILES)
--- a/dom/tests/mochitest/geolocation/test_clearWatch_invalid.html
+++ b/dom/tests/mochitest/geolocation/test_clearWatch_invalid.html
@@ -18,31 +18,21 @@ https://bugzilla.mozilla.org/show_bug.cg
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 463039 **/
// there are no watches, so this should always throw
for (x=-10; x<10; x++) {
- try {
- navigator.geolocation.clearWatch(x);
- ok(0, "clearWatch should throw");
- } catch (ex) {
- ok(1, "clearWatch with a bad value did throw");
- }
+ navigator.geolocation.clearWatch(x);
+ ok(1, "clearWatch should not throw");
}
// lets try something huge
-try {
- navigator.geolocation.clearWatch(Number.MAX_VALUE);
- ok(0, "clearWatch should throw");
-} catch (ex) {
- ok(1, "clearWatch with a bad value did throw");
-}
-
-
+navigator.geolocation.clearWatch(Number.MAX_VALUE);
+ok(1, "clearWatch should not throw");
</script>
</pre>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/geolocation/test_windowClose.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=493615
+-->
+<head>
+ <title>Test for geolocation in chrome </title>
+ <script type="text/javascript" src="/MochiKit/packed.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="geolocation_common.js"></script>
+
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=493615">Mozilla Bug 493615</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function done() {
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.open("windowTest.html");
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/geolocation/windowTest.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=493615