From 54cdabf82d6737b95390ba91589d5f3baa53bf35 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Thu, 30 Jun 2011 10:17:48 -0300 Subject: [PATCH 1/7] Bug 665880 - [highlighter] If a node is highlighted, a <> exception is raised; r=rcampbell,gavin.sharp --- browser/base/content/inspector.js | 19 +++--- .../base/content/test/inspector/Makefile.in | 1 + .../inspector/browser_inspector_bug_665880.js | 62 +++++++++++++++++++ 3 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 browser/base/content/test/inspector/browser_inspector_bug_665880.js diff --git a/browser/base/content/inspector.js b/browser/base/content/inspector.js index c432e3cad174..618f2f179cad 100644 --- a/browser/base/content/inspector.js +++ b/browser/base/content/inspector.js @@ -732,15 +732,18 @@ var InspectorUI = { } if (node instanceof GetSVGDocument) { - // then the node is a frame - if (index == 0) { - if (!this.embeddedBrowserParents) - this.embeddedBrowserParents = {}; - let skipChild = node.getSVGDocument().documentElement; - this.embeddedBrowserParents[skipChild] = node; - return skipChild; // the node's SVGElement + let svgDocument = node.getSVGDocument(); + if (svgDocument) { + // then the node is a frame + if (index == 0) { + if (!this.embeddedBrowserParents) + this.embeddedBrowserParents = {}; + let skipChild = svgDocument.documentElement; + this.embeddedBrowserParents[skipChild] = node; + return skipChild; // the node's SVGElement + } + return null; } - return null; } let child = null; diff --git a/browser/base/content/test/inspector/Makefile.in b/browser/base/content/test/inspector/Makefile.in index 156850c8ea73..00905f99673a 100644 --- a/browser/base/content/test/inspector/Makefile.in +++ b/browser/base/content/test/inspector/Makefile.in @@ -54,6 +54,7 @@ _BROWSER_FILES = \ browser_inspector_treePanel_output.js \ browser_inspector_treePanel_input.html \ browser_inspector_treePanel_result.html \ + browser_inspector_bug_665880.js \ $(NULL) libs:: $(_BROWSER_FILES) diff --git a/browser/base/content/test/inspector/browser_inspector_bug_665880.js b/browser/base/content/test/inspector/browser_inspector_bug_665880.js new file mode 100644 index 000000000000..29b2f17eae50 --- /dev/null +++ b/browser/base/content/test/inspector/browser_inspector_bug_665880.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + + +function test() +{ + waitForExplicitFinish(); + + let doc; + let objectNode; + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function() { + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + doc = content.document; + waitForFocus(setupObjectInspectionTest, content); + }, true); + + content.location = "data:text/html,

foobar

"; + + function setupObjectInspectionTest() + { + objectNode = doc.querySelector("object"); + ok(objectNode, "we have the object node"); + Services.obs.addObserver(runObjectInspectionTest, + INSPECTOR_NOTIFICATIONS.OPENED, false); + InspectorUI.toggleInspectorUI(); + } + + function runObjectInspectionTest() + { + Services.obs.removeObserver(runObjectInspectionTest, + INSPECTOR_NOTIFICATIONS.OPENED); + + executeSoon(function() { + Services.obs.addObserver(performTestComparison, + INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false); + + InspectorUI.inspectNode(objectNode); + }); + } + + function performTestComparison() + { + Services.obs.removeObserver(performTestComparison, + INSPECTOR_NOTIFICATIONS.HIGHLIGHTING); + + is(InspectorUI.selection, objectNode, "selection matches node"); + + Services.obs.addObserver(finishUp, + INSPECTOR_NOTIFICATIONS.CLOSED, false); + InspectorUI.closeInspectorUI(); + } + + + function finishUp() { + Services.obs.removeObserver(finishUp, INSPECTOR_NOTIFICATIONS.CLOSED); + doc = objectNode = null; + gBrowser.removeCurrentTab(); + finish(); + } +} From 7e94825de1f3d9728ea35206d46ea624f3001359 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Fri, 1 Jul 2011 12:55:05 +0200 Subject: [PATCH 2/7] Fix for bug 667315 (Make unknown handler forward to new handler). r=sicking. --- content/xslt/crashtests/667315.xml | 11 + content/xslt/crashtests/crashtests.list | 1 + content/xslt/src/xslt/txExecutionState.h | 1 + content/xslt/src/xslt/txUnknownHandler.cpp | 193 ++++++++++++------ content/xslt/src/xslt/txUnknownHandler.h | 10 +- content/xslt/tests/mochitest/Makefile.in | 1 + .../xslt/tests/mochitest/test_bug667315.html | 47 +++++ 7 files changed, 193 insertions(+), 71 deletions(-) create mode 100644 content/xslt/crashtests/667315.xml create mode 100644 content/xslt/tests/mochitest/test_bug667315.html diff --git a/content/xslt/crashtests/667315.xml b/content/xslt/crashtests/667315.xml new file mode 100644 index 000000000000..7a560ba3bdea --- /dev/null +++ b/content/xslt/crashtests/667315.xml @@ -0,0 +1,11 @@ + + + +]> + + +

a

+ +
+
diff --git a/content/xslt/crashtests/crashtests.list b/content/xslt/crashtests/crashtests.list index 4a0524a1fd09..4bd655daa704 100644 --- a/content/xslt/crashtests/crashtests.list +++ b/content/xslt/crashtests/crashtests.list @@ -13,3 +13,4 @@ load 545927.html load 601543.html load 603844.html load 602115.html +load 667315.xml diff --git a/content/xslt/src/xslt/txExecutionState.h b/content/xslt/src/xslt/txExecutionState.h index 8dc665b9cc13..e9c943a362ce 100644 --- a/content/xslt/src/xslt/txExecutionState.h +++ b/content/xslt/src/xslt/txExecutionState.h @@ -163,6 +163,7 @@ public: txAXMLEventHandler* mOutputHandler; txAXMLEventHandler* mResultHandler; + nsAutoPtr mObsoleteHandler; txAOutputHandlerFactory* mOutputHandlerFactory; nsAutoPtr mTemplateParams; diff --git a/content/xslt/src/xslt/txUnknownHandler.cpp b/content/xslt/src/xslt/txUnknownHandler.cpp index 24313fa4053e..677d423e071a 100644 --- a/content/xslt/src/xslt/txUnknownHandler.cpp +++ b/content/xslt/src/xslt/txUnknownHandler.cpp @@ -43,7 +43,8 @@ #include "txAtoms.h" txUnknownHandler::txUnknownHandler(txExecutionState* aEs) - : mEs(aEs) + : mEs(aEs), + mFlushed(PR_FALSE) { MOZ_COUNT_CTOR_INHERITED(txUnknownHandler, txBufferingHandler); } @@ -53,92 +54,145 @@ txUnknownHandler::~txUnknownHandler() MOZ_COUNT_DTOR_INHERITED(txUnknownHandler, txBufferingHandler); } +nsresult +txUnknownHandler::attribute(nsIAtom* aPrefix, nsIAtom* aLocalName, + nsIAtom* aLowercaseLocalName, PRInt32 aNsID, + const nsString& aValue) +{ + return mFlushed ? + mEs->mResultHandler->attribute(aPrefix, aLocalName, + aLowercaseLocalName, aNsID, aValue) : + txBufferingHandler::attribute(aPrefix, aLocalName, + aLowercaseLocalName, aNsID, aValue); +} + +nsresult +txUnknownHandler::attribute(nsIAtom* aPrefix, const nsSubstring& aLocalName, + const PRInt32 aNsID, const nsString& aValue) +{ + return mFlushed ? + mEs->mResultHandler->attribute(aPrefix, aLocalName, aNsID, aValue) : + txBufferingHandler::attribute(aPrefix, aLocalName, aNsID, aValue); +} + +nsresult +txUnknownHandler::characters(const nsSubstring& aData, PRBool aDOE) +{ + return mFlushed ? + mEs->mResultHandler->characters(aData, aDOE) : + txBufferingHandler::characters(aData, aDOE); +} + +nsresult +txUnknownHandler::comment(const nsString& aData) +{ + return mFlushed ? + mEs->mResultHandler->comment(aData) : + txBufferingHandler::comment(aData); +} + nsresult txUnknownHandler::endDocument(nsresult aResult) { - if (NS_FAILED(aResult)) { - return NS_OK; + if (!mFlushed) { + if (NS_FAILED(aResult)) { + return NS_OK; + } + + // This is an unusual case, no output method has been set and we + // didn't create a document element. Switching to XML output mode + // anyway. + + // Make sure that mEs->mResultHandler == this is true, otherwise we'll + // leak mEs->mResultHandler in createHandlerAndFlush. + NS_ASSERTION(mEs->mResultHandler == this, + "We're leaking mEs->mResultHandler."); + + nsresult rv = createHandlerAndFlush(PR_FALSE, EmptyString(), + kNameSpaceID_None); + NS_ENSURE_SUCCESS(rv, rv); } - // This is an unusual case, no output method has been set and we - // didn't create a document element. Switching to XML output mode - // anyway. + return mEs->mResultHandler->endDocument(aResult); +} - // Make sure that mEs->mResultHandler == this is true, otherwise we'll - // leak mEs->mResultHandler in createHandlerAndFlush and we'll crash on - // the last line (delete this). - NS_ASSERTION(mEs->mResultHandler == this, - "We're leaking mEs->mResultHandler and are going to crash."); +nsresult +txUnknownHandler::endElement() +{ + return mFlushed ? + mEs->mResultHandler->endElement() : + txBufferingHandler::endElement(); +} - nsresult rv = createHandlerAndFlush(PR_FALSE, EmptyString(), - kNameSpaceID_None); - NS_ENSURE_SUCCESS(rv, rv); +nsresult +txUnknownHandler::processingInstruction(const nsString& aTarget, + const nsString& aData) +{ + return mFlushed ? + mEs->mResultHandler->processingInstruction(aTarget, aData) : + txBufferingHandler::processingInstruction(aTarget, aData); +} - rv = mEs->mResultHandler->endDocument(aResult); - - delete this; - - return rv; +nsresult +txUnknownHandler::startDocument() +{ + return mFlushed ? + mEs->mResultHandler->startDocument() : + txBufferingHandler::startDocument(); } nsresult txUnknownHandler::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName, nsIAtom* aLowercaseLocalName, PRInt32 aNsID) { - // Make sure that mEs->mResultHandler == this is true, otherwise we'll - // leak mEs->mResultHandler in createHandlerAndFlush and we may crash - // later on trying to delete this handler again. - NS_ASSERTION(mEs->mResultHandler == this, - "We're leaking mEs->mResultHandler."); + if (!mFlushed) { + // Make sure that mEs->mResultHandler == this is true, otherwise we'll + // leak mEs->mResultHandler in createHandlerAndFlush. + NS_ASSERTION(mEs->mResultHandler == this, + "We're leaking mEs->mResultHandler."); - nsCOMPtr owner; - if (!aLowercaseLocalName) { - owner = TX_ToLowerCaseAtom(aLocalName); - NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY); - - aLowercaseLocalName = owner; + nsCOMPtr owner; + if (!aLowercaseLocalName) { + owner = TX_ToLowerCaseAtom(aLocalName); + NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY); + + aLowercaseLocalName = owner; + } + + PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix && + aLowercaseLocalName == txHTMLAtoms::html; + + // Use aLocalName and not aLowercaseLocalName in case the output + // handler cares about case. For eHTMLOutput the handler will hardcode + // to 'html' anyway. + nsresult rv = createHandlerAndFlush(htmlRoot, + nsDependentAtomString(aLocalName), + aNsID); + NS_ENSURE_SUCCESS(rv, rv); } - PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix && - aLowercaseLocalName == txHTMLAtoms::html; - - // Use aLocalName and not aLowercaseLocalName in case the output - // handler cares about case. For eHTMLOutput the handler will hardcode - // to 'html' anyway. - nsresult rv = createHandlerAndFlush(htmlRoot, - nsDependentAtomString(aLocalName), - aNsID); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mEs->mResultHandler->startElement(aPrefix, aLocalName, - aLowercaseLocalName, aNsID); - - delete this; - - return rv; + return mEs->mResultHandler->startElement(aPrefix, aLocalName, + aLowercaseLocalName, aNsID); } nsresult txUnknownHandler::startElement(nsIAtom* aPrefix, const nsSubstring& aLocalName, const PRInt32 aNsID) { - // Make sure that mEs->mResultHandler == this is true, otherwise we'll - // leak mEs->mResultHandler in createHandlerAndFlush and we may crash - // later on trying to delete this handler again. - NS_ASSERTION(mEs->mResultHandler == this, - "We're leaking mEs->mResultHandler."); + if (!mFlushed) { + // Make sure that mEs->mResultHandler == this is true, otherwise we'll + // leak mEs->mResultHandler in createHandlerAndFlush. + NS_ASSERTION(mEs->mResultHandler == this, + "We're leaking mEs->mResultHandler."); - PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix && - aLocalName.Equals(NS_LITERAL_STRING("html"), - txCaseInsensitiveStringComparator()); - nsresult rv = createHandlerAndFlush(htmlRoot, aLocalName, aNsID); - NS_ENSURE_SUCCESS(rv, rv); + PRBool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix && + aLocalName.Equals(NS_LITERAL_STRING("html"), + txCaseInsensitiveStringComparator()); + nsresult rv = createHandlerAndFlush(htmlRoot, aLocalName, aNsID); + NS_ENSURE_SUCCESS(rv, rv); + } - rv = mEs->mResultHandler->startElement(aPrefix, aLocalName, aNsID); - - delete this; - - return rv; + return mEs->mResultHandler->startElement(aPrefix, aLocalName, aNsID); } nsresult txUnknownHandler::createHandlerAndFlush(PRBool aHTMLRoot, @@ -159,11 +213,18 @@ nsresult txUnknownHandler::createHandlerAndFlush(PRBool aHTMLRoot, getter_Transfers(handler)); NS_ENSURE_SUCCESS(rv, rv); - rv = mBuffer->flushToHandler(handler); - NS_ENSURE_SUCCESS(rv, rv); - mEs->mOutputHandler = handler; mEs->mResultHandler = handler.forget(); + // Let the executionstate delete us. We need to stay alive because we might + // need to forward hooks to mEs->mResultHandler if someone is currently + // flushing a buffer to mEs->mResultHandler. + mEs->mObsoleteHandler = this; - return NS_OK; + mFlushed = PR_TRUE; + + // Let go of out buffer as soon as we're done flushing it, we're not going + // to need it anymore from this point on (all hooks get forwarded to + // mEs->mResultHandler. + nsAutoPtr buffer(mBuffer); + return buffer->flushToHandler(mEs->mResultHandler); } diff --git a/content/xslt/src/xslt/txUnknownHandler.h b/content/xslt/src/xslt/txUnknownHandler.h index 7a62aa7a0d62..0cc26db92042 100644 --- a/content/xslt/src/xslt/txUnknownHandler.h +++ b/content/xslt/src/xslt/txUnknownHandler.h @@ -50,11 +50,7 @@ public: txUnknownHandler(txExecutionState* aEs); virtual ~txUnknownHandler(); - nsresult endDocument(nsresult aResult); - nsresult startElement(nsIAtom* aPrefix, nsIAtom* aName, - nsIAtom* aLowercaseName, PRInt32 aNsID); - nsresult startElement(nsIAtom* aPrefix, const nsSubstring& aLocalName, - const PRInt32 aNsID); + TX_DECL_TXAXMLEVENTHANDLER private: nsresult createHandlerAndFlush(PRBool aHTMLRoot, @@ -67,6 +63,10 @@ private: * The right fix may need a txOutputFormat here. */ txExecutionState* mEs; + + // If mFlushed is true then we've replaced mEs->mResultHandler with a + // different handler and we should forward to that handler. + PRBool mFlushed; }; #endif /* txUnknownHandler_h___ */ diff --git a/content/xslt/tests/mochitest/Makefile.in b/content/xslt/tests/mochitest/Makefile.in index be7750cb67a8..be1d8356ad55 100644 --- a/content/xslt/tests/mochitest/Makefile.in +++ b/content/xslt/tests/mochitest/Makefile.in @@ -55,6 +55,7 @@ _TEST_FILES = test_bug319374.xhtml \ test_bug566629.html \ test_bug566629.xhtml \ test_bug603159.html \ + test_bug667315.html \ test_exslt_regex.html \ $(NULL) diff --git a/content/xslt/tests/mochitest/test_bug667315.html b/content/xslt/tests/mochitest/test_bug667315.html new file mode 100644 index 000000000000..1cfd6778054c --- /dev/null +++ b/content/xslt/tests/mochitest/test_bug667315.html @@ -0,0 +1,47 @@ + + + + + Test for Bug 667315 + + + + + +Mozilla Bug 667315 +

+ +
+
+
+ + From c76c86d25531c26a89534255bdcbea4a538f12f0 Mon Sep 17 00:00:00 2001 From: Igor Bazarny Date: Mon, 4 Jul 2011 11:30:43 +0200 Subject: [PATCH 3/7] Bug 668513 - make the w3c tests for navigationtiming pass r=smaug --HG-- extra : rebase_source : 791001cf9c9fa54448d9f5f25cf92de4b8cc8d5e --- docshell/base/nsDocShell.cpp | 4 +- docshell/test/Makefile.in | 3 + docshell/test/bug668513_redirect.html | 1 + .../test/bug668513_redirect.html^headers^ | 2 + docshell/test/test_bug668513.html | 114 ++++++++++++++++++ dom/base/nsDOMNavigationTiming.cpp | 5 +- dom/base/nsDOMNavigationTiming.h | 1 + 7 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 docshell/test/bug668513_redirect.html create mode 100644 docshell/test/bug668513_redirect.html^headers^ create mode 100644 docshell/test/test_bug668513.html diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 38199031497b..4c03e8f454ae 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -677,7 +677,9 @@ ConvertLoadTypeToNavigationType(PRUint32 aLoadType) case LOAD_NORMAL_BYPASS_CACHE: case LOAD_NORMAL_BYPASS_PROXY: case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE: + case LOAD_NORMAL_REPLACE: case LOAD_LINK: + case LOAD_STOP_CONTENT: result = nsIDOMPerformanceNavigation::TYPE_NAVIGATE; break; case LOAD_HISTORY: @@ -690,8 +692,6 @@ ConvertLoadTypeToNavigationType(PRUint32 aLoadType) case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: result = nsIDOMPerformanceNavigation::TYPE_RELOAD; break; - case LOAD_NORMAL_REPLACE: - case LOAD_STOP_CONTENT: case LOAD_STOP_CONTENT_AND_REPLACE: case LOAD_REFRESH: case LOAD_BYPASS_HISTORY: diff --git a/docshell/test/Makefile.in b/docshell/test/Makefile.in index 0fd0597b5142..9d2b8fb710e6 100644 --- a/docshell/test/Makefile.in +++ b/docshell/test/Makefile.in @@ -113,6 +113,9 @@ _TEST_FILES = \ file_bug662170.html \ test_bug570341.html \ bug570341_recordevents.html \ + test_bug668513.html \ + bug668513_redirect.html \ + bug668513_redirect.html^headers^ \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) diff --git a/docshell/test/bug668513_redirect.html b/docshell/test/bug668513_redirect.html new file mode 100644 index 000000000000..1b8f66c63150 --- /dev/null +++ b/docshell/test/bug668513_redirect.html @@ -0,0 +1 @@ +This document is redirected to a blank document. diff --git a/docshell/test/bug668513_redirect.html^headers^ b/docshell/test/bug668513_redirect.html^headers^ new file mode 100644 index 000000000000..0e785833c67c --- /dev/null +++ b/docshell/test/bug668513_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 302 Moved Temporarily +Location: navigation/blank.html diff --git a/docshell/test/test_bug668513.html b/docshell/test/test_bug668513.html new file mode 100644 index 000000000000..863c25cf03bc --- /dev/null +++ b/docshell/test/test_bug668513.html @@ -0,0 +1,114 @@ + + + + + Test for Bug 668513 + + + + + + +Mozilla Bug 668513 +
+ +
+

+ +
+
+
+ + diff --git a/dom/base/nsDOMNavigationTiming.cpp b/dom/base/nsDOMNavigationTiming.cpp index 34bc1ac10310..942a3c72c464 100644 --- a/dom/base/nsDOMNavigationTiming.cpp +++ b/dom/base/nsDOMNavigationTiming.cpp @@ -64,6 +64,7 @@ nsDOMNavigationTiming::Clear() mFetchStart = 0; mRedirectStart = 0; mRedirectEnd = 0; + mRedirectCount = 0; mBeforeUnloadStart = 0; mUnloadStart = 0; mUnloadEnd = 0; @@ -156,6 +157,7 @@ PRBool nsDOMNavigationTiming::ReportRedirects() { if (mRedirectCheck == NOT_CHECKED) { + mRedirectCount = mRedirects.Count(); if (mRedirects.Count() == 0) { mRedirectCheck = NO_REDIRECTS; } else { @@ -166,6 +168,7 @@ nsDOMNavigationTiming::ReportRedirects() nsresult rv = ssm->CheckSameOriginURI(curr, mLoadedURI, PR_FALSE); if (!NS_SUCCEEDED(rv)) { mRedirectCheck = CHECK_FAILED; + mRedirectCount = 0; break; } } @@ -243,7 +246,7 @@ nsDOMNavigationTiming::GetRedirectCount(PRUint16* aRedirectCount) { *aRedirectCount = 0; if (ReportRedirects()) { - *aRedirectCount = mRedirects.Count(); + *aRedirectCount = mRedirectCount; } return NS_OK; } diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h index 4fd3679c3eaf..d08aa175962c 100644 --- a/dom/base/nsDOMNavigationTiming.h +++ b/dom/base/nsDOMNavigationTiming.h @@ -95,6 +95,7 @@ private: NO_REDIRECTS, CHECK_FAILED} RedirectCheckState; RedirectCheckState mRedirectCheck; + PRInt16 mRedirectCount; nsDOMPerformanceNavigationType mNavigationType; DOMTimeMilliSec mNavigationStart; From 9fdec57a7b827aaa5127c18a938754dcb24eaa1d Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Mon, 4 Jul 2011 11:47:09 +0200 Subject: [PATCH 4/7] bug 621558 - Disable IPv6 for the 300ms-delayed backup connection to improve the user experience of people with broken IPv6 connectivity (i.e. implement Chrome's "Happy Eyeballs" strategy) r=mcmanus --- netwerk/base/public/nsISocketTransport.idl | 8 +++++++- netwerk/base/src/nsSocketTransport2.cpp | 2 ++ netwerk/dns/nsDNSService2.cpp | 8 ++++---- netwerk/dns/nsDNSService2.h | 2 +- netwerk/dns/nsIDNSService.idl | 5 +++++ netwerk/protocol/http/nsHttpConnectionMgr.cpp | 17 ++++++++++++++--- netwerk/protocol/http/nsHttpConnectionMgr.h | 3 ++- 7 files changed, 35 insertions(+), 10 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index 2997f05e9498..9c2ea3571e2b 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -138,7 +138,7 @@ interface nsISocketTransport : nsITransport /** * connectionFlags is a bitmask that can be used to modify underlying - * behavior of the socket connection. + * behavior of the socket connection. See the flags below. */ attribute unsigned long connectionFlags; @@ -159,6 +159,12 @@ interface nsISocketTransport : nsITransport */ const unsigned long ANONYMOUS_CONNECT = (1 << 1); + /** + * If set, we will skip all IPv6 addresses the host may have and only + * connect to IPv4 ones. + */ + const unsigned long DISABLE_IPV6 = (1 << 2); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 62e87045bc40..50291cedc739 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -942,6 +942,8 @@ nsSocketTransport::ResolveHost() PRUint32 dnsFlags = 0; if (mConnectionFlags & nsSocketTransport::BYPASS_CACHE) dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; + if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) + dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; SendStatus(STATUS_RESOLVING); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nsnull, diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index 57d13953b6c5..72a2c7f7f73d 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -462,7 +462,7 @@ nsDNSService::AsyncResolve(const nsACString &hostname, listener = listenerProxy; } - PRUint16 af = GetAFForLookup(*hostPtr); + PRUint16 af = GetAFForLookup(*hostPtr, flags); nsDNSAsyncRequest *req = new nsDNSAsyncRequest(res, *hostPtr, listener, flags, af); @@ -520,7 +520,7 @@ nsDNSService::Resolve(const nsACString &hostname, PR_EnterMonitor(mon); nsDNSSyncRequest syncReq(mon); - PRUint16 af = GetAFForLookup(*hostPtr); + PRUint16 af = GetAFForLookup(*hostPtr, flags); rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), flags, af, &syncReq); if (NS_SUCCEEDED(rv)) { @@ -580,9 +580,9 @@ nsDNSService::Observe(nsISupports *subject, const char *topic, const PRUnichar * } PRUint16 -nsDNSService::GetAFForLookup(const nsACString &host) +nsDNSService::GetAFForLookup(const nsACString &host, PRUint32 flags) { - if (mDisableIPv6) + if (mDisableIPv6 || (flags & RESOLVE_DISABLE_IPV6)) return PR_AF_INET; MutexAutoLock lock(mLock); diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h index d5fbbefbca55..728b3c01ecd1 100644 --- a/netwerk/dns/nsDNSService2.h +++ b/netwerk/dns/nsDNSService2.h @@ -55,7 +55,7 @@ public: ~nsDNSService(); private: - PRUint16 GetAFForLookup(const nsACString &host); + PRUint16 GetAFForLookup(const nsACString &host, PRUint32 flags); nsRefPtr mResolver; nsCOMPtr mIDN; diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index ea51f10c6838..8a2a15c366f0 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -120,4 +120,9 @@ interface nsIDNSService : nsISupports * return errors if prefetching is disabled by configuration. */ const unsigned long RESOLVE_SPECULATE = (1 << 4); + + /** + * If set, only IPv4 addresses will be returned from resolve/asyncResolve. + */ + const unsigned long RESOLVE_DISABLE_IPV6 = (1 << 5); }; diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 3cc0cb2b32bf..bc85cf243759 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -1291,7 +1291,8 @@ nsresult nsHttpConnectionMgr:: nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, nsIAsyncInputStream **instream, - nsIAsyncOutputStream **outstream) + nsIAsyncOutputStream **outstream, + PRBool isBackup) { nsresult rv; @@ -1320,6 +1321,14 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, if (mTransaction->Caps() & NS_HTTP_LOAD_ANONYMOUS) tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT; + // For backup connections, we disable IPv6. That's because some users have + // broken IPv6 connectivity (leading to very long timeouts), and disabling + // IPv6 on the backup connection gives them a much better user experience + // with dual-stack hosts, though they still pay the 250ms delay for each new + // connection. This strategy is also known as "happy eyeballs". + if (isBackup) + tmpFlags |= nsISocketTransport::DISABLE_IPV6; + socketTransport->SetConnectionFlags(tmpFlags); socketTransport->SetQoSBits(gHttpHandler->GetQoSBits()); @@ -1358,7 +1367,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::SetupPrimaryStreams() { nsresult rv = SetupStreams(getter_AddRefs(mSocketTransport), getter_AddRefs(mStreamIn), - getter_AddRefs(mStreamOut)); + getter_AddRefs(mStreamOut), + PR_FALSE); LOG(("nsHalfOpenSocket::SetupPrimaryStream [this=%p ent=%s rv=%x]", this, mEnt->mConnInfo->Host(), rv)); if (NS_FAILED(rv)) { @@ -1376,7 +1386,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupStreams() { nsresult rv = SetupStreams(getter_AddRefs(mBackupTransport), getter_AddRefs(mBackupStreamIn), - getter_AddRefs(mBackupStreamOut)); + getter_AddRefs(mBackupStreamOut), + PR_TRUE); LOG(("nsHalfOpenSocket::SetupBackupStream [this=%p ent=%s rv=%x]", this, mEnt->mConnInfo->Host(), rv)); if (NS_FAILED(rv)) { diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index b8e7f395fe37..695cd8f8b92c 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -211,7 +211,8 @@ private: nsresult SetupStreams(nsISocketTransport **, nsIAsyncInputStream **, - nsIAsyncOutputStream **); + nsIAsyncOutputStream **, + PRBool isBackup); nsresult SetupPrimaryStreams(); nsresult SetupBackupStreams(); void SetupBackupTimer(); From 08e9ef88ed867d05f18829126e8f69de49f4f578 Mon Sep 17 00:00:00 2001 From: Jezreel Ng Date: Mon, 4 Jul 2011 12:51:47 +0200 Subject: [PATCH 5/7] Bug 465186 - When detaching a tab, open the new window at the drop location. r=dao/smaug --HG-- extra : rebase_source : 8145e9a0fcc4bf96fc5f66c2fdbbad13ca25c90e --- browser/base/content/tabbrowser.xml | 57 +++++++++++++++++++++++++++-- dom/base/nsGlobalWindow.cpp | 3 +- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index ac2d018b6929..2a4d346b5c0b 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -2005,13 +2005,18 @@ in the current window, in which case this will do nothing. --> + @@ -3298,6 +3303,16 @@ let canvas = tabPreviews.capture(tab, false); dt.setDragImage(canvas, 0, 0); + + let bo = this.mTabstrip.boxObject; + let paddingStart = this.mTabstrip.scrollboxPaddingStart; + // _dragOffset[X|Y] give the coordinates that the mouse should be + // positioned relative to the corner of the new window created upon + // dragend such that the mouse appears to have the same position + // relative to the corner of the dragged tab. + tab._dragOffsetX = event.screenX - tab.boxObject.screenX + paddingStart + bo.screenX - window.screenX; + tab._dragOffsetY = event.screenY - tab.boxObject.screenY + bo.screenY - window.screenY; + event.stopPropagation(); ]]> @@ -3477,6 +3492,11 @@ } } } + + // these offsets are only used in dragend, but we need to free them here + // as well + delete draggedTab._dragOffsetX; + delete draggedTab._dragOffsetY; ]]> wX && eX < (wX + window.outerWidth)) { @@ -3498,13 +3519,43 @@ // also avoid detaching if the the tab was dropped too close to // the tabbar (half a tab) let endScreenY = bo.screenY + 1.5 * bo.height; - let eY = event.screenY; if (eY < endScreenY && eY > window.screenY) return; } var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - this.tabbrowser.replaceTabWithWindow(draggedTab); + // screen.availLeft et. al. only check the screen that this window is on, + // but we want to look at the screen the tab is being dropped onto. + var sm = Cc["@mozilla.org/gfx/screenmanager;1"]. + getService(Ci.nsIScreenManager); + var whichScreen = sm.screenForRect(eX, eY, 1, 1); + var sX = {}, sY = {}, sW = {}, sH = {}; + whichScreen.GetAvailRect(sX, sY, sW, sH); + // ensure new window entirely within screen + var winWidth = Math.min(window.outerWidth, sW.value); + var winHeight = Math.min(window.outerHeight, sH.value); + var aLeft = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value), sX.value + sW.value - winWidth); + var aTop = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value), sY.value + sH.value - winHeight); + + delete draggedTab._dragOffsetX; + delete draggedTab._dragOffsetY; + + if (this.tabbrowser.tabs.length == 1) { + // resize _before_ move to ensure the window fits the new screen. if + // the window is too large for its screen, the window manager may do + // automatic repositioning. + window.resizeTo(winWidth, winHeight); + window.moveTo(aLeft, aTop); + window.focus(); + } + else + this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: aLeft, + screenY: aTop, +#ifndef XP_WIN + outerWidth: winWidth, + outerHeight: winHeight +#endif + }); event.stopPropagation(); ]]> diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index d404812c0d1b..537efbb77667 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2579,7 +2579,8 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor) } else if (msg == NS_MOUSE_BUTTON_DOWN && NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) { gMouseDown = PR_TRUE; - } else if (msg == NS_MOUSE_BUTTON_UP && + } else if ((msg == NS_MOUSE_BUTTON_UP || + msg == NS_DRAGDROP_END) && NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) { gMouseDown = PR_FALSE; if (gDragServiceDisabled) { From 0a103765fb19ac4e92440f85abff04d4d2139f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Mon, 4 Jul 2011 12:54:41 +0200 Subject: [PATCH 6/7] Addressing review comments for bug 465186 --HG-- extra : rebase_source : d433b763a715eeb11845e1bc111dbcf66ea732a4 --- browser/base/content/tabbrowser.xml | 41 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 2a4d346b5c0b..d6d5f28bd6be 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -3304,14 +3304,15 @@ let canvas = tabPreviews.capture(tab, false); dt.setDragImage(canvas, 0, 0); - let bo = this.mTabstrip.boxObject; - let paddingStart = this.mTabstrip.scrollboxPaddingStart; - // _dragOffset[X|Y] give the coordinates that the mouse should be + // _dragOffsetX/Y give the coordinates that the mouse should be // positioned relative to the corner of the new window created upon // dragend such that the mouse appears to have the same position // relative to the corner of the dragged tab. - tab._dragOffsetX = event.screenX - tab.boxObject.screenX + paddingStart + bo.screenX - window.screenX; - tab._dragOffsetY = event.screenY - tab.boxObject.screenY + bo.screenY - window.screenY; + function clientX(ele) ele.getBoundingClientRect().left; + let tabOffsetX = clientX(tab) - + clientX(this.children[0].pinned ? this.children[0] : this); + tab._dragOffsetX = event.screenX - window.screenX - tabOffsetX; + tab._dragOffsetY = event.screenY - window.screenY; event.stopPropagation(); ]]> @@ -3526,16 +3527,18 @@ var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); // screen.availLeft et. al. only check the screen that this window is on, // but we want to look at the screen the tab is being dropped onto. - var sm = Cc["@mozilla.org/gfx/screenmanager;1"]. - getService(Ci.nsIScreenManager); - var whichScreen = sm.screenForRect(eX, eY, 1, 1); - var sX = {}, sY = {}, sW = {}, sH = {}; - whichScreen.GetAvailRect(sX, sY, sW, sH); + var sX = {}, sY = {}, sWidth = {}, sHeight = {}; + Cc["@mozilla.org/gfx/screenmanager;1"] + .getService(Ci.nsIScreenManager) + .screenForRect(eX, eY, 1, 1) + .GetAvailRect(sX, sY, sWidth, sHeight); // ensure new window entirely within screen - var winWidth = Math.min(window.outerWidth, sW.value); - var winHeight = Math.min(window.outerHeight, sH.value); - var aLeft = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value), sX.value + sW.value - winWidth); - var aTop = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value), sY.value + sH.value - winHeight); + var winWidth = Math.min(window.outerWidth, sWidth.value); + var winHeight = Math.min(window.outerHeight, sHeight.value); + var left = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value), + sX.value + sWidth.value - winWidth); + var top = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value), + sY.value + sHeight.value - winHeight); delete draggedTab._dragOffsetX; delete draggedTab._dragOffsetY; @@ -3545,17 +3548,17 @@ // the window is too large for its screen, the window manager may do // automatic repositioning. window.resizeTo(winWidth, winHeight); - window.moveTo(aLeft, aTop); + window.moveTo(left, top); window.focus(); - } - else - this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: aLeft, - screenY: aTop, + } else { + this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left, + screenY: top, #ifndef XP_WIN outerWidth: winWidth, outerHeight: winHeight #endif }); + } event.stopPropagation(); ]]> From 74aecf92be35134a165e20531641ee08503c6672 Mon Sep 17 00:00:00 2001 From: Serge Gautherie Date: Mon, 4 Jul 2011 14:28:04 +0200 Subject: [PATCH 7/7] Bug 642420 - (Bv1) XPFE autocomplete.xml: restore explicit , but at start instead of at end. r=neil. --- xpfe/components/autocomplete/resources/content/autocomplete.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xpfe/components/autocomplete/resources/content/autocomplete.xml b/xpfe/components/autocomplete/resources/content/autocomplete.xml index e10cdfbadf38..dd463006a441 100644 --- a/xpfe/components/autocomplete/resources/content/autocomplete.xml +++ b/xpfe/components/autocomplete/resources/content/autocomplete.xml @@ -14,6 +14,8 @@ + +