From f63afecd3ea046cd9373fd30424b1185ac18a862 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 7 Feb 2013 18:18:12 -0800 Subject: [PATCH 01/45] Bug 841558 - Don't exactly mark tagged NULL pointers; r=sfink --HG-- extra : rebase_source : 062760866d171948b2f866910ebd764521ed3f6f --- js/src/gc/Marking.h | 7 +++++++ js/src/gc/RootMarking.cpp | 2 +- js/src/vm/ObjectImpl-inl.h | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 8d8a934d571..1d22291d95f 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -109,6 +109,13 @@ DeclMarker(TypeObject, types::TypeObject) #undef DeclMarker +/* Return true if the pointer is NULL, or if it is a tagged pointer to NULL. */ +JS_ALWAYS_INLINE bool +IsNullTaggedPointer(void *p) +{ + return uintptr_t(p) < 32; +} + /*** Externally Typed Marking ***/ /* diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 1f94b71b13f..7a38e3373e8 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -46,7 +46,7 @@ static inline void MarkExactStackRoot(JSTracer *trc, Rooted *rooter, ThingRootKind kind) { void **addr = (void **)rooter->address(); - if (!*addr) + if (IsNullTaggedPointer(*addr)) return; if (kind == THING_ROOT_OBJECT && *addr == Proxy::LazyProto) diff --git a/js/src/vm/ObjectImpl-inl.h b/js/src/vm/ObjectImpl-inl.h index 4999ec60e44..ef44585df8a 100644 --- a/js/src/vm/ObjectImpl-inl.h +++ b/js/src/vm/ObjectImpl-inl.h @@ -359,7 +359,7 @@ js::ObjectImpl::writeBarrierPre(ObjectImpl *obj) * This would normally be a null test, but TypeScript::global uses 0x1 as a * special value. */ - if (uintptr_t(obj) < 32) + if (IsNullTaggedPointer(obj)) return; Zone *zone = obj->zone(); @@ -376,7 +376,7 @@ js::ObjectImpl::writeBarrierPre(ObjectImpl *obj) js::ObjectImpl::writeBarrierPost(ObjectImpl *obj, void *addr) { #ifdef JSGC_GENERATIONAL - if (uintptr_t(obj) < 32) + if (IsNullTaggedPointer(obj)) return; obj->runtime()->gcStoreBuffer.putCell((Cell **)addr); #endif From dd189456f3606749d78f032ee004f8c9e06b26d8 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Mon, 4 Mar 2013 15:42:11 -0800 Subject: [PATCH 02/45] Bug 839313: Add regression test for JS shell 'it.customNative' fix. r=waldo --- js/src/jit-test/tests/basic/bug839313.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 js/src/jit-test/tests/basic/bug839313.js diff --git a/js/src/jit-test/tests/basic/bug839313.js b/js/src/jit-test/tests/basic/bug839313.js new file mode 100644 index 00000000000..6eddcc0cfb1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug839313.js @@ -0,0 +1,3 @@ +// Bug 839313: Verify that 'it' does not leave JS_AddValueRoot roots lying around. +var dbg = new Debugger; +it.customNative = assertEq; From 1ea5c7163f734730457dede1ff864759b6aef8f0 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 4 Mar 2013 23:15:53 +0000 Subject: [PATCH 03/45] Bug 847002 - Add a crash if layer manager is null so we don't run off into garbage code. r=mattwoodrow --- layout/base/nsPresShell.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 2b754747692..fb2ce60d700 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5512,6 +5512,12 @@ PresShell::Paint(nsView* aViewToPaint, aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager); NS_ASSERTION(layerManager, "Must be in paint event"); + if (!layerManager) { + // Crash so we get a good stack on how this code is getting triggered. + // See bug 847002 for details. + MOZ_CRASH(); + } + // Whether or not we should set first paint when painting is // suppressed is debatable. For now we'll do it because // B2G relies on first paint to configure the viewport and From 8631e44d322ae2cbb4c0e36b992e1051ad2ea8ec Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Thu, 14 Feb 2013 10:33:16 -0500 Subject: [PATCH 04/45] bug 846487 - remove remaining usage of some nsIDOMFooElement r=Ms2Ger --- accessible/src/html/HTMLTableAccessible.cpp | 11 +++--- content/html/content/src/HTMLTableElement.cpp | 10 ++++++ content/html/content/src/HTMLTableElement.h | 8 +---- content/html/document/src/nsHTMLDocument.h | 1 - editor/libeditor/html/nsHTMLDataTransfer.cpp | 22 ++++-------- .../src/nsWebBrowserPersist.cpp | 36 +++++-------------- layout/base/nsCSSFrameConstructor.cpp | 2 -- layout/generic/nsBlockFrame.cpp | 1 - layout/generic/nsBlockReflowContext.cpp | 2 -- layout/tables/nsTableCellFrame.cpp | 1 - layout/tables/nsTableColFrame.cpp | 1 - layout/tables/nsTableColGroupFrame.cpp | 1 - layout/tables/nsTableFrame.cpp | 1 - 13 files changed, 29 insertions(+), 68 deletions(-) diff --git a/accessible/src/html/HTMLTableAccessible.cpp b/accessible/src/html/HTMLTableAccessible.cpp index adf0d23b3ae..aded0a65dd3 100644 --- a/accessible/src/html/HTMLTableAccessible.cpp +++ b/accessible/src/html/HTMLTableAccessible.cpp @@ -3,10 +3,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/DebugOnly.h" - #include "HTMLTableAccessible.h" +#include "mozilla/DebugOnly.h" + #include "Accessible-inl.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" @@ -18,6 +18,7 @@ #include "States.h" #include "TreeWalker.h" +#include "mozilla/dom/HTMLTableElement.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIDOMRange.h" @@ -25,10 +26,6 @@ #include "nsINameSpaceManager.h" #include "nsIDOMNodeList.h" #include "nsIDOMHTMLCollection.h" -#include "nsIDOMHTMLTableCellElement.h" -#include "nsIDOMHTMLTableElement.h" -#include "nsIDOMHTMLTableRowElement.h" -#include "nsIDOMHTMLTableSectionElement.h" #include "nsIDocument.h" #include "nsIMutableArray.h" #include "nsIPresShell.h" @@ -455,7 +452,7 @@ HTMLTableAccessible::Caption() void HTMLTableAccessible::Summary(nsString& aSummary) { - nsCOMPtr table(do_QueryInterface(mContent)); + dom::HTMLTableElement* table = dom::HTMLTableElement::FromContent(mContent); if (table) table->GetSummary(aSummary); diff --git a/content/html/content/src/HTMLTableElement.cpp b/content/html/content/src/HTMLTableElement.cpp index 65a6bfc35c2..caa63dfc93f 100644 --- a/content/html/content/src/HTMLTableElement.cpp +++ b/content/html/content/src/HTMLTableElement.cpp @@ -10,6 +10,7 @@ #include "nsAttrValueInlines.h" #include "nsRuleData.h" #include "nsHTMLStyleSheet.h" +#include "nsMappedAttributes.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/HTMLCollectionBinding.h" #include "mozilla/dom/HTMLTableElementBinding.h" @@ -1211,6 +1212,15 @@ HTMLTableElement::BuildInheritedAttributes() } } +void +HTMLTableElement::ReleaseInheritedAttributes() +{ + if (mTableInheritedAttributes && + mTableInheritedAttributes != TABLE_ATTRS_DIRTY) + NS_RELEASE(mTableInheritedAttributes); + mTableInheritedAttributes = TABLE_ATTRS_DIRTY; +} + nsresult HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, diff --git a/content/html/content/src/HTMLTableElement.h b/content/html/content/src/HTMLTableElement.h index 94b5ac7075f..7480cf5d000 100644 --- a/content/html/content/src/HTMLTableElement.h +++ b/content/html/content/src/HTMLTableElement.h @@ -9,7 +9,6 @@ #include "nsIDOMHTMLTableElement.h" #include "mozilla/dom/HTMLTableCaptionElement.h" #include "mozilla/dom/HTMLTableSectionElement.h" -#include "nsMappedAttributes.h" namespace mozilla { namespace dom { @@ -224,12 +223,7 @@ protected: // to be recalculated. nsMappedAttributes *mTableInheritedAttributes; void BuildInheritedAttributes(); - void ReleaseInheritedAttributes() { - if (mTableInheritedAttributes && - mTableInheritedAttributes != TABLE_ATTRS_DIRTY) - NS_RELEASE(mTableInheritedAttributes); - mTableInheritedAttributes = TABLE_ATTRS_DIRTY; - } + void ReleaseInheritedAttributes(); }; } // namespace dom diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 0f33e20052a..d6f0f498495 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -9,7 +9,6 @@ #include "nsDocument.h" #include "nsIHTMLDocument.h" #include "nsIDOMHTMLDocument.h" -#include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLCollection.h" #include "nsIScriptElement.h" #include "jsapi.h" diff --git a/editor/libeditor/html/nsHTMLDataTransfer.cpp b/editor/libeditor/html/nsHTMLDataTransfer.cpp index 77ebb9e4664..3e5a76d9c0b 100644 --- a/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -39,7 +39,6 @@ #include "nsIDOMDocumentFragment.h" #include "nsIDOMElement.h" #include "nsIDOMHTMLAnchorElement.h" -#include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLEmbedElement.h" #include "nsIDOMHTMLFrameElement.h" #include "nsIDOMHTMLIFrameElement.h" @@ -48,9 +47,6 @@ #include "nsIDOMHTMLLinkElement.h" #include "nsIDOMHTMLObjectElement.h" #include "nsIDOMHTMLScriptElement.h" -#include "nsIDOMHTMLTableCellElement.h" -#include "nsIDOMHTMLTableElement.h" -#include "nsIDOMHTMLTableRowElement.h" #include "nsIDOMNode.h" #include "nsIDOMRange.h" #include "nsIDocument.h" @@ -737,30 +733,24 @@ nsHTMLEditor::GetAttributeToModifyOnNode(nsIDOMNode *aNode, nsAString &aAttr) } NS_NAMED_LITERAL_STRING(bgStr, "background"); - nsCOMPtr nodeAsBody = do_QueryInterface(aNode); - if (nodeAsBody) - { + nsCOMPtr element = do_QueryInterface(aNode); + if (element && element->IsHTML(nsGkAtoms::body)) { aAttr = bgStr; return NS_OK; } - nsCOMPtr nodeAsTable = do_QueryInterface(aNode); - if (nodeAsTable) - { + if (element && element->IsHTML(nsGkAtoms::table)) { aAttr = bgStr; return NS_OK; } - nsCOMPtr nodeAsTableRow = do_QueryInterface(aNode); - if (nodeAsTableRow) - { + if (element && element->IsHTML(nsGkAtoms::tr)) { aAttr = bgStr; return NS_OK; } - nsCOMPtr nodeAsTableCell = do_QueryInterface(aNode); - if (nodeAsTableCell) - { + if (element && + (element->IsHTML(nsGkAtoms::td) || element->IsHTML(nsGkAtoms::th))) { aAttr = bgStr; return NS_OK; } diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 90f3093cb8b..1a760593701 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -55,10 +55,6 @@ #include "nsIDOMNodeFilter.h" #include "nsIDOMProcessingInstruction.h" -#include "nsIDOMHTMLBodyElement.h" -#include "nsIDOMHTMLTableElement.h" -#include "nsIDOMHTMLTableRowElement.h" -#include "nsIDOMHTMLTableCellElement.h" #include "nsIDOMHTMLAnchorElement.h" #include "nsIDOMHTMLAreaElement.h" #include "nsIDOMHTMLImageElement.h" @@ -2734,30 +2730,22 @@ nsresult nsWebBrowserPersist::OnWalkDOMNode(nsIDOMNode *aNode) } #endif // MOZ_MEDIA - nsCOMPtr nodeAsBody = do_QueryInterface(aNode); - if (nodeAsBody) - { + if (content->IsHTML(nsGkAtoms::body)) { StoreURIAttribute(aNode, "background"); return NS_OK; } - nsCOMPtr nodeAsTable = do_QueryInterface(aNode); - if (nodeAsTable) - { + if (content->IsHTML(nsGkAtoms::table)) { StoreURIAttribute(aNode, "background"); return NS_OK; } - nsCOMPtr nodeAsTableRow = do_QueryInterface(aNode); - if (nodeAsTableRow) - { + if (content->IsHTML(nsGkAtoms::tr)) { StoreURIAttribute(aNode, "background"); return NS_OK; } - nsCOMPtr nodeAsTableCell = do_QueryInterface(aNode); - if (nodeAsTableCell) - { + if (content->IsHTML(nsGkAtoms::td) || content->IsHTML(nsGkAtoms::th)) { StoreURIAttribute(aNode, "background"); return NS_OK; } @@ -3024,9 +3012,7 @@ nsWebBrowserPersist::CloneNodeWithFixedUpAttributes( return rv; } - nsCOMPtr nodeAsBody = do_QueryInterface(aNodeIn); - if (nodeAsBody) - { + if (content->IsHTML(nsGkAtoms::body)) { rv = GetNodeToFixup(aNodeIn, aNodeOut); if (NS_SUCCEEDED(rv) && *aNodeOut) { @@ -3035,9 +3021,7 @@ nsWebBrowserPersist::CloneNodeWithFixedUpAttributes( return rv; } - nsCOMPtr nodeAsTable = do_QueryInterface(aNodeIn); - if (nodeAsTable) - { + if (content->IsHTML(nsGkAtoms::table)) { rv = GetNodeToFixup(aNodeIn, aNodeOut); if (NS_SUCCEEDED(rv) && *aNodeOut) { @@ -3046,9 +3030,7 @@ nsWebBrowserPersist::CloneNodeWithFixedUpAttributes( return rv; } - nsCOMPtr nodeAsTableRow = do_QueryInterface(aNodeIn); - if (nodeAsTableRow) - { + if (content->IsHTML(nsGkAtoms::tr)) { rv = GetNodeToFixup(aNodeIn, aNodeOut); if (NS_SUCCEEDED(rv) && *aNodeOut) { @@ -3057,9 +3039,7 @@ nsWebBrowserPersist::CloneNodeWithFixedUpAttributes( return rv; } - nsCOMPtr nodeAsTableCell = do_QueryInterface(aNodeIn); - if (nodeAsTableCell) - { + if (content->IsHTML(nsGkAtoms::td) || content->IsHTML(nsGkAtoms::th)) { rv = GetNodeToFixup(aNodeIn, aNodeOut); if (NS_SUCCEEDED(rv) && *aNodeOut) { diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index f6d3ee8a3e8..b2345d67a62 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -30,8 +30,6 @@ #include "nsTableColGroupFrame.h" #include "nsTableColFrame.h" #include "nsIDOMHTMLDocument.h" -#include "nsIDOMHTMLTableColElement.h" -#include "nsIDOMHTMLTableCaptionElem.h" #include "nsHTMLParts.h" #include "nsIPresShell.h" #include "nsUnicharUtils.h" diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 3823b3b9fb0..c9e1727f1a5 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -63,7 +63,6 @@ #include "nsBidiPresUtils.h" #endif // IBMBIDI -#include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" static const int MIN_LINES_NEEDING_CURSOR = 20; diff --git a/layout/generic/nsBlockReflowContext.cpp b/layout/generic/nsBlockReflowContext.cpp index 395f3c925b3..0ba60df214f 100644 --- a/layout/generic/nsBlockReflowContext.cpp +++ b/layout/generic/nsBlockReflowContext.cpp @@ -16,8 +16,6 @@ #include "nsContainerFrame.h" #include "nsBlockFrame.h" #include "nsLineBox.h" -#include "nsIDOMHTMLTableCellElement.h" -#include "nsIDOMHTMLBodyElement.h" #include "nsGkAtoms.h" #include "nsCOMPtr.h" #include "nsLayoutUtils.h" diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index e1a8731f244..2a66161675b 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -20,7 +20,6 @@ #include "nsGkAtoms.h" #include "nsIPresShell.h" #include "nsCOMPtr.h" -#include "nsIDOMHTMLTableCellElement.h" #include "nsIServiceManager.h" #include "nsIDOMNode.h" #include "nsINameSpaceManager.h" diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp index 59e48950e1c..7d2e8183a2a 100644 --- a/layout/tables/nsTableColFrame.cpp +++ b/layout/tables/nsTableColFrame.cpp @@ -12,7 +12,6 @@ #include "nsGkAtoms.h" #include "nsCSSRendering.h" #include "nsIContent.h" -#include "nsIDOMHTMLTableColElement.h" #define COL_TYPE_BITS (NS_FRAME_STATE_BIT(28) | \ NS_FRAME_STATE_BIT(29) | \ diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index 5adf5dad20d..23ee2c48c33 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -5,7 +5,6 @@ #include "nsTableColGroupFrame.h" #include "nsTableColFrame.h" #include "nsTableFrame.h" -#include "nsIDOMHTMLTableColElement.h" #include "nsStyleContext.h" #include "nsStyleConsts.h" #include "nsPresContext.h" diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 24ffec25455..90b7dacfe3b 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -33,7 +33,6 @@ #include "nsIPresShell.h" #include "nsIDOMElement.h" #include "nsIDOMHTMLElement.h" -#include "nsIDOMHTMLBodyElement.h" #include "nsFrameManager.h" #include "nsError.h" #include "nsAutoPtr.h" From 615bf8538fd525fd25717ba9066ead7fb71e8fb7 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 4 Mar 2013 19:04:59 -0500 Subject: [PATCH 05/45] Bug 799142 - Make sure that the allocator for nsTimerEvent objects stays around long enough to deallocate all outstanding objects of that type; r=bsmedberg --- xpcom/threads/TimerThread.h | 6 ++++++ xpcom/threads/nsTimerImpl.cpp | 28 ++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/xpcom/threads/TimerThread.h b/xpcom/threads/TimerThread.h index ea795b91c78..294017c7500 100644 --- a/xpcom/threads/TimerThread.h +++ b/xpcom/threads/TimerThread.h @@ -11,6 +11,7 @@ #include "nsIThread.h" #include "nsTimerImpl.h" +#include "nsThreadUtils.h" #include "nsTArray.h" @@ -49,6 +50,11 @@ public: void DoBeforeSleep(); void DoAfterSleep(); + bool IsOnTimerThread() const + { + return mThread == NS_GetCurrentThread(); + } + private: ~TimerThread(); diff --git a/xpcom/threads/nsTimerImpl.cpp b/xpcom/threads/nsTimerImpl.cpp index 25c4c04358f..d814668819b 100644 --- a/xpcom/threads/nsTimerImpl.cpp +++ b/xpcom/threads/nsTimerImpl.cpp @@ -96,6 +96,11 @@ public: : mTimer(timer), mGeneration(generation) { // timer is already addref'd for us MOZ_COUNT_CTOR(nsTimerEvent); + + MOZ_ASSERT(gThread->IsOnTimerThread(), + "nsTimer must always be allocated on the timer thread"); + + PR_ATOMIC_INCREMENT(&sAllocatorUsers); } #ifdef DEBUG_TIMERS @@ -104,30 +109,41 @@ public: static void Init(); static void Shutdown(); + static void DeleteAllocatorIfNeeded(); static void* operator new(size_t size) CPP_THROW_NEW { return sAllocator->Alloc(size); } void operator delete(void* p) { sAllocator->Free(p, sizeof(nsTimerEvent)); + DeleteAllocatorIfNeeded(); } private: + nsTimerEvent(); // Not implemented ~nsTimerEvent() { #ifdef DEBUG if (mTimer) NS_WARNING("leaking reference to nsTimerImpl"); #endif MOZ_COUNT_DTOR(nsTimerEvent); + + MOZ_ASSERT(!sCanDeleteAllocator || sAllocatorUsers > 0, + "This will result in us attempting to deallocate the nsTimerEvent allocator twice"); + PR_ATOMIC_DECREMENT(&sAllocatorUsers); } nsTimerImpl *mTimer; int32_t mGeneration; static TimerEventAllocator* sAllocator; + static int32_t sAllocatorUsers; + static bool sCanDeleteAllocator; }; TimerEventAllocator* nsTimerEvent::sAllocator = nullptr; +int32_t nsTimerEvent::sAllocatorUsers = 0; +bool nsTimerEvent::sCanDeleteAllocator = false; NS_IMPL_THREADSAFE_QUERY_INTERFACE1(nsTimerImpl, nsITimer) NS_IMPL_THREADSAFE_ADDREF(nsTimerImpl) @@ -541,8 +557,16 @@ void nsTimerEvent::Init() void nsTimerEvent::Shutdown() { - delete sAllocator; - sAllocator = nullptr; + sCanDeleteAllocator = true; + DeleteAllocatorIfNeeded(); +} + +void nsTimerEvent::DeleteAllocatorIfNeeded() +{ + if (sCanDeleteAllocator && sAllocatorUsers == 0) { + delete sAllocator; + sAllocator = nullptr; + } } NS_IMETHODIMP nsTimerEvent::Run() From d7fb4ee81ab0f22462019f96371168dd3e1d87a2 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Tue, 5 Mar 2013 11:32:33 +1100 Subject: [PATCH 06/45] Bug 847094 - test-only fix for intermittent browser_social_chatwindowfocus test error. r=me. --- .../social/browser_social_chatwindowfocus.js | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/browser/base/content/test/social/browser_social_chatwindowfocus.js b/browser/base/content/test/social/browser_social_chatwindowfocus.js index 0ed94782f83..7ecc9ca5e8a 100644 --- a/browser/base/content/test/social/browser_social_chatwindowfocus.js +++ b/browser/base/content/test/social/browser_social_chatwindowfocus.js @@ -248,6 +248,19 @@ var tests = { // cause focus to move between all elements in our chat window before moving // to the next chat window. testTab: function(next) { + function sendTabAndWaitForFocus(chat, eltid, callback) { + // ideally we would use the 'focus' event here, but that doesn't work + // as expected for the iframe - the iframe itself never gets the focus + // event (apparently the sub-document etc does.) + // So just poll for the correct element getting focus... + let doc = chat.iframe.contentDocument; + EventUtils.sendKey("tab"); + waitForCondition(function() { + let elt = eltid ? doc.getElementById(eltid) : doc.documentElement; + return doc.activeElement == elt; + }, callback, "element " + eltid + " never got focus"); + } + let chatbar = SocialChatBar.chatbar; startTestAndWaitForSidebar(function(port) { openChatViaSidebarMessage(port, {id: 1}, function() { @@ -259,22 +272,27 @@ var tests = { ok(isChatFocused(chat2), "new chat is focused"); // Our chats have 3 focusable elements, so it takes 4 TABs to move // to the new chat. - EventUtils.sendKey("tab"); - ok(isChatFocused(chat2), "new chat still focused after first tab"); - is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1", - "first input field has focus"); - EventUtils.sendKey("tab"); - ok(isChatFocused(chat2), "new chat still focused after tab"); - is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2", - "second input field has focus"); - EventUtils.sendKey("tab"); - ok(isChatFocused(chat2), "new chat still focused after tab"); - is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe", - "iframe has focus"); - // this tab now should move to the next chat. - EventUtils.sendKey("tab"); - ok(isChatFocused(chat1), "first chat is focused"); - next(); + sendTabAndWaitForFocus(chat2, "input1", function() { + is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1", + "first input field has focus"); + ok(isChatFocused(chat2), "new chat still focused after first tab"); + sendTabAndWaitForFocus(chat2, "input2", function() { + ok(isChatFocused(chat2), "new chat still focused after tab"); + is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2", + "second input field has focus"); + sendTabAndWaitForFocus(chat2, "iframe", function() { + ok(isChatFocused(chat2), "new chat still focused after tab"); + is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe", + "iframe has focus"); + // this tab now should move to the next chat, but focus the + // document element itself (hence the null eltid) + sendTabAndWaitForFocus(chat1, null, function() { + ok(isChatFocused(chat1), "first chat is focused"); + next(); + }); + }); + }); + }); }); }); }); From 74ff81131a64ec6c7b177f6b440edb9d412955ea Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Tue, 5 Mar 2013 11:32:33 +1100 Subject: [PATCH 07/45] Bug 840872 - log an error if we fail to create a chat window. r=felipe --- browser/base/content/browser-social.js | 17 +++++++++-------- toolkit/components/social/MozSocialAPI.jsm | 13 ++++++++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index dedbbbf245c..693af842583 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -351,14 +351,15 @@ let SocialChatBar = { return !!this.chatbar.firstElementChild; }, openChat: function(aProvider, aURL, aCallback, aMode) { - if (this.isAvailable) { - this.chatbar.openChat(aProvider, aURL, aCallback, aMode); - // We only want to focus the chat if it is as a result of user input. - let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - if (dwu.isHandlingUserInput) - this.chatbar.focus(); - } + if (!this.isAvailable) + return false; + this.chatbar.openChat(aProvider, aURL, aCallback, aMode); + // We only want to focus the chat if it is as a result of user input. + let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + if (dwu.isHandlingUserInput) + this.chatbar.focus(); + return true; }, update: function() { let command = document.getElementById("Social:FocusChat"); diff --git a/toolkit/components/social/MozSocialAPI.jsm b/toolkit/components/social/MozSocialAPI.jsm index 2e0d3137a88..bb1f7ca4dc5 100644 --- a/toolkit/components/social/MozSocialAPI.jsm +++ b/toolkit/components/social/MozSocialAPI.jsm @@ -265,12 +265,19 @@ function findChromeWindowForChats(preferredWindow) { this.openChatWindow = function openChatWindow(chromeWindow, provider, url, callback, mode) { chromeWindow = findChromeWindowForChats(chromeWindow); - if (!chromeWindow) + if (!chromeWindow) { + Cu.reportError("Failed to open a social chat window - no host window could be found."); return; + } let fullURI = provider.resolveUri(url); - if (!provider.isSameOrigin(fullURI)) + if (!provider.isSameOrigin(fullURI)) { + Cu.reportError("Failed to open a social chat window - the requested URL is not the same origin as the provider."); return; - chromeWindow.SocialChatBar.openChat(provider, fullURI.spec, callback, mode); + } + if (!chromeWindow.SocialChatBar.openChat(provider, fullURI.spec, callback, mode)) { + Cu.reportError("Failed to open a social chat window - the chatbar is not available in the target window."); + return; + } // getAttention is ignored if the target window is already foreground, so // we can call it unconditionally. chromeWindow.getAttention(); From aa3bf62e8bec74e6dad30be45acd6b01cfdc8d66 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Tue, 5 Mar 2013 11:32:34 +1100 Subject: [PATCH 08/45] Bug 814986 - specify a max-height of 0px for the chatbar. r=felipe --- browser/base/content/browser.css | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index aac71d75489..ec4a580874a 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -627,4 +627,5 @@ chatbox { chatbar { -moz-binding: url("chrome://browser/content/socialchat.xml#chatbar"); height: 0; + max-height: 0; } From a74b6b9a5eb5ee67d3c553a3bc89f2a78432ac59 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 4 Mar 2013 16:44:31 -0800 Subject: [PATCH 09/45] Bug 845482 - Init scissor box values on offscreen context init - r=bjacob --- content/canvas/src/WebGLContext.cpp | 1 - gfx/gl/GLContext.cpp | 2 +- gfx/gl/GLContext.h | 10 ++++------ gfx/gl/GLContextProviderCGL.mm | 1 - gfx/gl/GLContextProviderEGL.cpp | 9 +++------ gfx/gl/GLContextProviderGLX.cpp | 2 -- gfx/gl/GLContextProviderWGL.cpp | 1 - 7 files changed, 8 insertions(+), 18 deletions(-) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 47547d1b8c1..35455eb6332 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -564,7 +564,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height) // we'll end up displaying random memory gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); - gl->fViewport(0, 0, mWidth, mHeight); gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl->fClearDepth(1.0f); gl->fClearStencil(0); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 3065aab736b..af7ead1fa9b 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -574,7 +574,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } // We're ready for final setup. - InitFramebuffers(); + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); if (mCaps.any) DetermineCaps(); diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index ace0440f12f..a56c503b97e 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -606,11 +606,6 @@ public: return ret; } - void InitFramebuffers() { - MakeCurrent(); - BindFB(0); - } - private: void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { switch (precisiontype) { @@ -1173,7 +1168,10 @@ public: if (!CreateScreenBuffer(size, caps)) return false; - InitFramebuffers(); + MakeCurrent(); + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); + fScissor(0, 0, size.width, size.height); + fViewport(0, 0, size.width, size.height); mCaps = mScreen->Caps(); UpdateGLFormats(caps); diff --git a/gfx/gl/GLContextProviderCGL.mm b/gfx/gl/GLContextProviderCGL.mm index e0ab11e29e8..1db033c630d 100644 --- a/gfx/gl/GLContextProviderCGL.mm +++ b/gfx/gl/GLContextProviderCGL.mm @@ -113,7 +113,6 @@ public: if (!InitWithPrefix("gl", true)) return false; - InitFramebuffers(); return true; } diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp index 5b229bf3aaf..5e96d41b432 100644 --- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -348,8 +348,8 @@ public: } SetupLookupFunction(); - - bool ok = InitWithPrefix("gl", true); + if (!InitWithPrefix("gl", true)) + return false; PR_STATIC_ASSERT(sizeof(GLint) >= sizeof(int32_t)); mMaxTextureImageSize = INT32_MAX; @@ -358,10 +358,7 @@ public: sEGLLibrary.HasKHRImageTexture2D() && IsExtensionSupported(OES_EGL_image); - if (ok) - InitFramebuffers(); - - return ok; + return true; } bool IsDoubleBuffered() { diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index 71a086a8be5..5aee0af7a30 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -864,8 +864,6 @@ TRY_AGAIN_NO_SHARING: if (!IsExtensionSupported(EXT_framebuffer_object)) return false; - InitFramebuffers(); - return true; } diff --git a/gfx/gl/GLContextProviderWGL.cpp b/gfx/gl/GLContextProviderWGL.cpp index 609e987d7ae..34c51876d08 100644 --- a/gfx/gl/GLContextProviderWGL.cpp +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -319,7 +319,6 @@ public: if (!InitWithPrefix("gl", true)) return false; - InitFramebuffers(); return true; } From 7f79074ea8ac1827bc3d081c3cf8ce69fcd82cd1 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 4 Mar 2013 16:44:31 -0800 Subject: [PATCH 10/45] Bug 845636 - WebGL uniform1i should generate INVALID_VALUE for invalid texture units - r=bjacob --- content/canvas/src/WebGLContext.h | 3 ++ content/canvas/src/WebGLContextGL.cpp | 57 +++++++++++++++++++++ content/canvas/src/WebGLContextValidate.cpp | 17 ++++++ 3 files changed, 77 insertions(+) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index e3f2993becd..cad66fa8b9a 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -764,6 +764,9 @@ public: bool ValidateUniformSetter(const char* name, WebGLUniformLocation *location_object, GLint& location); void ValidateProgram(WebGLProgram *prog); bool ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object); + bool ValidateSamplerUniformSetter(const char* info, + WebGLUniformLocation *location, + WebGLint value); void VertexAttrib1f(WebGLuint index, WebGLfloat x0); void VertexAttrib2f(WebGLuint index, WebGLfloat x0, WebGLfloat x1); diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 573572a2acc..3455ea6555e 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -3673,12 +3673,17 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE } + void WebGLContext::Uniform1i(WebGLUniformLocation *location_object, WebGLint a1) { GLint location; if (!ValidateUniformSetter("Uniform1i", location_object, location)) return; + + if (!ValidateSamplerUniformSetter("Uniform1i", location_object, a1)) + return; + MakeContextCurrent(); gl->fUniform1i(location, a1); } @@ -3690,6 +3695,13 @@ WebGLContext::Uniform2i(WebGLUniformLocation *location_object, WebGLint a1, GLint location; if (!ValidateUniformSetter("Uniform2i", location_object, location)) return; + + if (!ValidateSamplerUniformSetter("Uniform2i", location_object, a1) || + !ValidateSamplerUniformSetter("Uniform2i", location_object, a2)) + { + return; + } + MakeContextCurrent(); gl->fUniform2i(location, a1, a2); } @@ -3701,6 +3713,14 @@ WebGLContext::Uniform3i(WebGLUniformLocation *location_object, WebGLint a1, GLint location; if (!ValidateUniformSetter("Uniform3i", location_object, location)) return; + + if (!ValidateSamplerUniformSetter("Uniform3i", location_object, a1) || + !ValidateSamplerUniformSetter("Uniform3i", location_object, a2) || + !ValidateSamplerUniformSetter("Uniform3i", location_object, a3)) + { + return; + } + MakeContextCurrent(); gl->fUniform3i(location, a1, a2, a3); } @@ -3712,6 +3732,15 @@ WebGLContext::Uniform4i(WebGLUniformLocation *location_object, WebGLint a1, GLint location; if (!ValidateUniformSetter("Uniform4i", location_object, location)) return; + + if (!ValidateSamplerUniformSetter("Uniform4i", location_object, a1) || + !ValidateSamplerUniformSetter("Uniform4i", location_object, a2) || + !ValidateSamplerUniformSetter("Uniform4i", location_object, a3) || + !ValidateSamplerUniformSetter("Uniform4i", location_object, a4)) + { + return; + } + MakeContextCurrent(); gl->fUniform4i(location, a1, a2, a3, a4); } @@ -3769,6 +3798,10 @@ WebGLContext::Uniform1iv_base(WebGLUniformLocation *location_object, numElementsToUpload, arrayLength)) { return; } + + if (!ValidateSamplerUniformSetter("Uniform1iv", location_object, data[0])) + return; + MakeContextCurrent(); gl->fUniform1iv(location, numElementsToUpload, data); } @@ -3783,6 +3816,13 @@ WebGLContext::Uniform2iv_base(WebGLUniformLocation *location_object, numElementsToUpload, arrayLength)) { return; } + + if (!ValidateSamplerUniformSetter("Uniform2iv", location_object, data[0]) || + !ValidateSamplerUniformSetter("Uniform2iv", location_object, data[1])) + { + return; + } + MakeContextCurrent(); gl->fUniform2iv(location, numElementsToUpload, data); } @@ -3797,6 +3837,14 @@ WebGLContext::Uniform3iv_base(WebGLUniformLocation *location_object, numElementsToUpload, arrayLength)) { return; } + + if (!ValidateSamplerUniformSetter("Uniform3iv", location_object, data[0]) || + !ValidateSamplerUniformSetter("Uniform3iv", location_object, data[1]) || + !ValidateSamplerUniformSetter("Uniform3iv", location_object, data[2])) + { + return; + } + MakeContextCurrent(); gl->fUniform3iv(location, numElementsToUpload, data); } @@ -3811,6 +3859,15 @@ WebGLContext::Uniform4iv_base(WebGLUniformLocation *location_object, numElementsToUpload, arrayLength)) { return; } + + if (!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[0]) || + !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[1]) || + !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[2]) || + !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[3])) + { + return; + } + MakeContextCurrent(); gl->fUniform4iv(location, numElementsToUpload, data); } diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index eaf8683b5d5..a282118f324 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -688,6 +688,23 @@ WebGLContext::ValidateUniformLocation(const char* info, WebGLUniformLocation *lo return true; } +bool +WebGLContext::ValidateSamplerUniformSetter(const char* info, WebGLUniformLocation *location, WebGLint value) +{ + if (location->Info().type != SH_SAMPLER_2D && + location->Info().type != SH_SAMPLER_CUBE) + { + return true; + } + + if (value >= 0 && value < mGLMaxTextureUnits) + return true; + + ErrorInvalidValue("%s: this uniform location is a sampler, but %d is not a valid texture unit", + info, value); + return false; +} + bool WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength) { From ba31d85ba506f3b75ccc389305b842a10bea27b7 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 4 Mar 2013 16:44:32 -0800 Subject: [PATCH 11/45] Bug 845368 - Generic vertex attribs should have a size of 4 - r=bjacob --- content/canvas/src/WebGLContextGL.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 3455ea6555e..e23fea9e6ea 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2850,6 +2850,15 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname, return JS::Int32Value(mAttribBuffers[index].stride); case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE: + { + if (!ValidateAttribIndex(index, "enableVertexAttribArray")) + return JS::NullValue(); + + if (!mAttribBuffers[index].enabled) + return JS::Int32Value(4); + + // Don't break; fall through. + } case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE: { GLint i = 0; From f0c8853de68cffa5d9e95768b071352639ec4c06 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Feb 2013 18:53:49 -0800 Subject: [PATCH 12/45] Bug 847210 - Remove nsNodeInfo::sNodeInfoPool and use vanilla allocation for nsNodeInfo objects. r=smaug. --HG-- extra : rebase_source : 667a818984e7ce6d22669861992a06e832755dfb --- content/base/public/nsINodeInfo.h | 3 +- content/base/src/nsINode.cpp | 6 +- content/base/src/nsNodeInfo.cpp | 60 +------------------ content/base/src/nsNodeInfo.h | 29 +++------ content/base/src/nsNodeInfoManager.cpp | 12 ++-- .../xul/templates/src/nsContentSupportMap.h | 1 - content/xul/templates/src/nsContentTestNode.h | 1 - .../templates/src/nsRDFConInstanceTestNode.h | 1 - .../src/nsXULTemplateQueryProcessorRDF.h | 1 - .../templates/src/nsXULTemplateResultSetRDF.h | 1 - layout/build/nsLayoutStatics.cpp | 1 - 11 files changed, 21 insertions(+), 95 deletions(-) diff --git a/content/base/public/nsINodeInfo.h b/content/base/public/nsINodeInfo.h index d7dc1d6db6d..b701429be21 100644 --- a/content/base/public/nsINodeInfo.h +++ b/content/base/public/nsINodeInfo.h @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index 33330e9bfda..d9e81ccc8a6 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -1,5 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=79: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -2032,7 +2032,7 @@ nsINode::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const // Measurement of the following members may be added later if DMD finds it is // worthwhile: - // - mNodeInfo (Nb: allocated in nsNodeInfo.cpp with a nsFixedSizeAllocator) + // - mNodeInfo // - mSlots // // The following members are not measured: diff --git a/content/base/src/nsNodeInfo.cpp b/content/base/src/nsNodeInfo.cpp index 4ff1ed65cc5..02aed019555 100644 --- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -24,7 +25,6 @@ #include "nsReadableUtils.h" #include "nsAutoPtr.h" #include NEW_H -#include "nsFixedSizeAllocator.h" #include "prprf.h" #include "nsIDocument.h" #include "nsGkAtoms.h" @@ -32,43 +32,6 @@ using namespace mozilla; -static const size_t kNodeInfoPoolSizes[] = { - sizeof(nsNodeInfo) -}; - -static const int32_t kNodeInfoPoolInitialSize = sizeof(nsNodeInfo) * 64; - -// static -nsFixedSizeAllocator* nsNodeInfo::sNodeInfoPool = nullptr; - -// static -nsNodeInfo* -nsNodeInfo::Create(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID, - uint16_t aNodeType, nsIAtom *aExtraName, - nsNodeInfoManager *aOwnerManager) -{ - if (!sNodeInfoPool) { - sNodeInfoPool = new nsFixedSizeAllocator(); - if (!sNodeInfoPool) - return nullptr; - - nsresult rv = sNodeInfoPool->Init("NodeInfo Pool", kNodeInfoPoolSizes, - 1, kNodeInfoPoolInitialSize); - if (NS_FAILED(rv)) { - delete sNodeInfoPool; - sNodeInfoPool = nullptr; - return nullptr; - } - } - - // Create a new one - void* place = sNodeInfoPool->Alloc(sizeof(nsNodeInfo)); - return place ? - new (place) nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, - aOwnerManager) : - nullptr; -} - nsNodeInfo::~nsNodeInfo() { mOwnerManager->RemoveNodeInfo(this); @@ -234,28 +197,11 @@ nsNodeInfo::NamespaceEquals(const nsAString& aNamespaceURI) const return nsINodeInfo::NamespaceEquals(nsid); } -// static -void -nsNodeInfo::ClearCache() -{ - // Clear our cache. - delete sNodeInfoPool; - sNodeInfoPool = nullptr; -} - void nsNodeInfo::LastRelease() { nsRefPtr kungFuDeathGrip = mOwnerManager; - this->~nsNodeInfo(); - - // The refcount balancing and destructor re-entrancy protection - // code in Release() sets mRefCnt to 1 so we have to set it to 0 - // here to prevent leaks - mRefCnt = 0; - - NS_ASSERTION(sNodeInfoPool, "No NodeInfoPool when deleting NodeInfo!!!"); - sNodeInfoPool->Free(this, sizeof(nsNodeInfo)); + delete this; } bool diff --git a/content/base/src/nsNodeInfo.h b/content/base/src/nsNodeInfo.h index 4a9905d587a..b96b579320e 100644 --- a/content/base/src/nsNodeInfo.h +++ b/content/base/src/nsNodeInfo.h @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -20,8 +21,6 @@ #include "nsIDOMNode.h" #include "nsGkAtoms.h" -class nsFixedSizeAllocator; - class nsNodeInfo : public nsINodeInfo { public: @@ -33,39 +32,27 @@ public: virtual bool NamespaceEquals(const nsAString& aNamespaceURI) const; // nsNodeInfo - // Create objects with Create public: /* * aName and aOwnerManager may not be null. */ - static nsNodeInfo *Create(nsIAtom *aName, nsIAtom *aPrefix, - int32_t aNamespaceID, uint16_t aNodeType, - nsIAtom *aExtraName, - nsNodeInfoManager *aOwnerManager); -private: - nsNodeInfo(); // Unimplemented - nsNodeInfo(const nsNodeInfo& aOther); // Unimplemented nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID, uint16_t aNodeType, nsIAtom *aExtraName, nsNodeInfoManager *aOwnerManager); + +private: + nsNodeInfo(); // Unimplemented + nsNodeInfo(const nsNodeInfo& aOther); // Unimplemented protected: virtual ~nsNodeInfo(); public: - /** - * Call before shutdown to clear the cache and free memory for this class. - */ - static void ClearCache(); - bool CanSkip(); private: - static nsFixedSizeAllocator* sNodeInfoPool; - /** - * This method gets called by Release() when it's time to delete - * this object, instead of always deleting the object we'll put the - * object in the cache unless the cache is already full. + * This method gets called by Release() when it's time to delete + * this object. */ void LastRelease(); }; diff --git a/content/base/src/nsNodeInfoManager.cpp b/content/base/src/nsNodeInfoManager.cpp index 743a80db419..8b84f466f4d 100644 --- a/content/base/src/nsNodeInfoManager.cpp +++ b/content/base/src/nsNodeInfoManager.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -220,10 +221,9 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, } nsRefPtr newNodeInfo = - nsNodeInfo::Create(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, - this); + new nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this); NS_ENSURE_TRUE(newNodeInfo, nullptr); - + PLHashEntry *he; he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo); NS_ENSURE_TRUE(he, nullptr); @@ -266,13 +266,11 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix, return NS_OK; } - nsCOMPtr nameAtom = do_GetAtom(aName); NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY); nsRefPtr newNodeInfo = - nsNodeInfo::Create(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, - this); + new nsNodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this); NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); PLHashEntry *he; diff --git a/content/xul/templates/src/nsContentSupportMap.h b/content/xul/templates/src/nsContentSupportMap.h index 708bd06bb9d..6b0dc7c0e2e 100644 --- a/content/xul/templates/src/nsContentSupportMap.h +++ b/content/xul/templates/src/nsContentSupportMap.h @@ -7,7 +7,6 @@ #define nsContentSupportMap_h__ #include "pldhash.h" -#include "nsFixedSizeAllocator.h" #include "nsTemplateMatch.h" /** diff --git a/content/xul/templates/src/nsContentTestNode.h b/content/xul/templates/src/nsContentTestNode.h index 009b5aa6f13..7d50686839e 100644 --- a/content/xul/templates/src/nsContentTestNode.h +++ b/content/xul/templates/src/nsContentTestNode.h @@ -8,7 +8,6 @@ #include "nscore.h" #include "nsRuleNetwork.h" -#include "nsFixedSizeAllocator.h" #include "nsIAtom.h" #include "nsIDOMDocument.h" diff --git a/content/xul/templates/src/nsRDFConInstanceTestNode.h b/content/xul/templates/src/nsRDFConInstanceTestNode.h index c7a3b55a745..426982a1560 100644 --- a/content/xul/templates/src/nsRDFConInstanceTestNode.h +++ b/content/xul/templates/src/nsRDFConInstanceTestNode.h @@ -7,7 +7,6 @@ #define nsRDFConInstanceTestNode_h__ #include "nscore.h" -#include "nsFixedSizeAllocator.h" #include "nsRDFTestNode.h" #include "nsIRDFResource.h" #include "nsIRDFDataSource.h" diff --git a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h index 806a13a22e7..d272c9f1b1a 100644 --- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h @@ -18,7 +18,6 @@ #include "nsICollation.h" #include "nsCollationCID.h" -#include "nsFixedSizeAllocator.h" #include "nsResourceSet.h" #include "nsRuleNetwork.h" #include "nsRDFQuery.h" diff --git a/content/xul/templates/src/nsXULTemplateResultSetRDF.h b/content/xul/templates/src/nsXULTemplateResultSetRDF.h index f8f8450a301..43d5a7296e8 100644 --- a/content/xul/templates/src/nsXULTemplateResultSetRDF.h +++ b/content/xul/templates/src/nsXULTemplateResultSetRDF.h @@ -6,7 +6,6 @@ #ifndef nsXULTemplateResultSetRDF_h__ #define nsXULTemplateResultSetRDF_h__ -#include "nsFixedSizeAllocator.h" #include "nsISimpleEnumerator.h" #include "nsRuleNetwork.h" #include "nsRDFQuery.h" diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 25459052a07..1b1d7ce5250 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -330,7 +330,6 @@ nsLayoutStatics::Shutdown() nsAttrValue::Shutdown(); nsContentUtils::Shutdown(); - nsNodeInfo::ClearCache(); nsLayoutStylesheetCache::Shutdown(); NS_NameSpaceManagerShutdown(); From aa6a4878fc7140ae18e866c29533da75caf27642 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Mon, 4 Mar 2013 13:21:24 -0800 Subject: [PATCH 13/45] Bug 846096: Remove SimpleTest.expectAssertions() calls annotating assertions from bug 846096. --- layout/base/tests/test_bug93077-6.html | 5 ----- layout/base/tests/test_mozPaintCount.html | 4 ---- layout/base/tests/test_reftests_with_caret.html | 4 ---- layout/base/tests/test_remote_frame.html | 4 ---- layout/base/tests/test_scroll_selection_into_view.html | 4 ---- toolkit/content/tests/chrome/test_bug624329.xul | 2 -- toolkit/content/tests/chrome/test_bug792324.xul | 2 -- toolkit/content/tests/chrome/test_button.xul | 2 -- toolkit/content/tests/chrome/test_closemenu_attribute.xul | 2 -- toolkit/content/tests/chrome/test_colorpicker_popup.xul | 2 -- toolkit/content/tests/chrome/test_contextmenu_list.xul | 2 -- 11 files changed, 33 deletions(-) diff --git a/layout/base/tests/test_bug93077-6.html b/layout/base/tests/test_bug93077-6.html index 85615ad9916..08cdb6c7fd8 100644 --- a/layout/base/tests/test_bug93077-6.html +++ b/layout/base/tests/test_bug93077-6.html @@ -20,11 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=93077

Top

 
+
+  
+  
+  Mozilla Bug 783129
+  
+  
+
+  
+  
+
diff --git a/content/events/src/nsEventDispatcher.cpp b/content/events/src/nsEventDispatcher.cpp
index 8f6e00ff6eb..60bb3ae79b3 100644
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -866,6 +866,8 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
   if (aEventType.LowerCaseEqualsLiteral("commandevent") ||
       aEventType.LowerCaseEqualsLiteral("commandevents"))
     return NS_NewDOMCommandEvent(aDOMEvent, aPresContext, nullptr);
+  if (aEventType.LowerCaseEqualsLiteral("elementreplace"))
+    return NS_NewDOMElementReplaceEvent(aDOMEvent, aPresContext, nullptr);
   if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") ||
       aEventType.LowerCaseEqualsLiteral("datacontainerevents"))
     return NS_NewDOMDataContainerEvent(aDOMEvent, aPresContext, nullptr);
diff --git a/content/html/content/src/HTMLUnknownElement.cpp b/content/html/content/src/HTMLUnknownElement.cpp
index e0495c55817..8e2fbae261b 100644
--- a/content/html/content/src/HTMLUnknownElement.cpp
+++ b/content/html/content/src/HTMLUnknownElement.cpp
@@ -3,6 +3,7 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsDocument.h"
 #include "HTMLUnknownElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 
@@ -18,7 +19,19 @@ JSObject*
 HTMLUnknownElement::WrapNode(JSContext *aCx, JSObject *aScope,
                                bool *aTriedToWrap)
 {
-  return HTMLUnknownElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+  JSObject* obj =
+    HTMLUnknownElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+  if (obj && Substring(NodeName(), 0, 2).LowerCaseEqualsLiteral("x-")) {
+    // If we have a registered x-tag then we fix the prototype.
+    JSAutoCompartment ac(aCx, obj);
+    nsDocument* document = static_cast(OwnerDoc());
+    JSObject* prototype = document->GetCustomPrototype(LocalName());
+    if (prototype) {
+      NS_ENSURE_TRUE(JS_WrapObject(aCx, &prototype), nullptr);
+      NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
+    }
+  }
+  return obj;
 }
 
 // QueryInterface implementation for HTMLUnknownElement
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index 41aba47ea5b..6f7af9045c7 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2044,6 +2044,8 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
+    DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDocumentRegister,
+                                        nsDocument::RegisterEnabled())
     DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
diff --git a/dom/interfaces/core/Makefile.in b/dom/interfaces/core/Makefile.in
index 9e087be0e05..6bfe8ef44e6 100644
--- a/dom/interfaces/core/Makefile.in
+++ b/dom/interfaces/core/Makefile.in
@@ -29,6 +29,7 @@ SDK_XPIDLSRCS =                                 \
 	nsIDOMNodeList.idl			\
 	nsIDOMProcessingInstruction.idl		\
 	nsIDOMText.idl				\
+	nsIDocumentRegister.idl		\
 	$(NULL)
 XPIDLSRCS =                                     \
 	nsIDOMDOMStringList.idl			\
diff --git a/dom/interfaces/core/nsIDocumentRegister.idl b/dom/interfaces/core/nsIDocumentRegister.idl
new file mode 100644
index 00000000000..701eb9936ba
--- /dev/null
+++ b/dom/interfaces/core/nsIDocumentRegister.idl
@@ -0,0 +1,16 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(e35935bd-ebae-4e0d-93bf-efa93ab14c05)]
+interface nsIDocumentRegister : nsISupports
+{
+  [optional_argc,
+   implicit_jscontext] jsval   register(in DOMString name,
+                                        [optional] in jsval options)
+                                 raises(DOMException);
+};
+
diff --git a/dom/interfaces/events/Makefile.in b/dom/interfaces/events/Makefile.in
index 2d85f87c6f4..454f85c6d00 100644
--- a/dom/interfaces/events/Makefile.in
+++ b/dom/interfaces/events/Makefile.in
@@ -48,6 +48,7 @@ XPIDLSRCS =					\
 	nsIDOMUserProximityEvent.idl            \
 	nsIDOMDeviceOrientationEvent.idl        \
 	nsIDOMDeviceMotionEvent.idl		\
+	nsIDOMElementReplaceEvent.idl		\
 	nsIDOMScrollAreaEvent.idl		\
 	nsIDOMTransitionEvent.idl		\
 	nsIDOMAnimationEvent.idl		\
diff --git a/dom/interfaces/events/nsIDOMElementReplaceEvent.idl b/dom/interfaces/events/nsIDOMElementReplaceEvent.idl
new file mode 100644
index 00000000000..8303829ef6c
--- /dev/null
+++ b/dom/interfaces/events/nsIDOMElementReplaceEvent.idl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEvent.idl"
+
+interface nsIDOMElement;
+
+[scriptable, builtinclass, uuid(19a31767-54bf-4044-8769-cd172e37eca2)]
+interface nsIDOMElementReplaceEvent : nsIDOMEvent
+{
+  readonly attribute nsIDOMElement upgrade;
+
+  void initElementReplaceEvent(in DOMString typeArg,
+                               in boolean canBubbleArg,
+                               in boolean canCancelArg,
+                               in nsIDOMElement upgrade);
+};
+
+dictionary ElementReplaceEventInit : EventInit
+{
+  nsIDOMElement upgrade;
+};
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
index 9e5765a5197..60d1fc95831 100644
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -64,6 +64,7 @@ var interfaceNamesInGlobalScope =
     "HTMLOptionElement",
     "Pkcs11",
     "NotifyAudioAvailableEvent",
+    "ElementReplaceEvent",
     "Array",
     "SVGZoomAndPan",
     "XULPopupElement",
diff --git a/dom/tests/mochitest/moz.build b/dom/tests/mochitest/moz.build
index 5950b3efc2b..87c1f15e419 100644
--- a/dom/tests/mochitest/moz.build
+++ b/dom/tests/mochitest/moz.build
@@ -21,6 +21,7 @@ DIRS += [
     'storageevent',
     'pointerlock',
     'webapps',
+    'webcomponents',
 ]
 
 #needs IPC support, also tests do not run successfully in Firefox for now
diff --git a/dom/tests/mochitest/webcomponents/Makefile.in b/dom/tests/mochitest/webcomponents/Makefile.in
new file mode 100644
index 00000000000..aabdefe0590
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/Makefile.in
@@ -0,0 +1,18 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir	= @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_FILES	= \
+		test_document_register.html \
+		test_document_register_lifecycle.html \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/dom/tests/mochitest/webcomponents/moz.build b/dom/tests/mochitest/webcomponents/moz.build
new file mode 100644
index 00000000000..58ce5e27339
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/moz.build
@@ -0,0 +1,5 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
diff --git a/dom/tests/mochitest/webcomponents/test_document_register.html b/dom/tests/mochitest/webcomponents/test_document_register.html
new file mode 100644
index 00000000000..45dbf9e3e1f
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_document_register.html
@@ -0,0 +1,90 @@
+
+
+
+
+  Test for document.register using custom prototype
+  
+
+
+
+
+
+
+Bug 783129
+
+
+
+ + diff --git a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html new file mode 100644 index 00000000000..2b93cb992a2 --- /dev/null +++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html @@ -0,0 +1,49 @@ + + + + + Test for document.register lifecycle callback + + + + + + + +Bug 783129 + +
+
+ + diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 6540a374abf..796db001843 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -228,6 +228,12 @@ partial interface Document { void mozExitPointerLock (); }; +//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register +partial interface Document { + [Throws, Pref="dom.webcomponents.enabled"] + object register(DOMString name, optional ElementRegistrationOptions options); +}; + // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#sec-document-interface partial interface Document { readonly attribute boolean hidden; diff --git a/dom/webidl/WebComponents.webidl b/dom/webidl/WebComponents.webidl new file mode 100644 index 00000000000..4d946b4e16f --- /dev/null +++ b/dom/webidl/WebComponents.webidl @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface DocumentFragment; + +callback LifecycleCreatedCallback = void(); + +dictionary LifecycleCallbacks { + LifecycleCreatedCallback? created = null; +}; + +dictionary ElementRegistrationOptions { + object? prototype = null; + LifecycleCallbacks lifecycle; +}; + diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 1a13a79493e..2e7493b9043 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -217,6 +217,7 @@ webidl_files = \ TreeWalker.webidl \ URL.webidl \ ValidityState.webidl \ + WebComponents.webidl \ WebSocket.webidl \ UndoManager.webidl \ URLUtils.webidl \ diff --git a/js/xpconnect/src/event_impl_gen.conf.in b/js/xpconnect/src/event_impl_gen.conf.in index 19180f629ac..8edc838cc4d 100644 --- a/js/xpconnect/src/event_impl_gen.conf.in +++ b/js/xpconnect/src/event_impl_gen.conf.in @@ -39,6 +39,7 @@ simple_events = [ 'MozVoicemailEvent', 'USSDReceivedEvent', #endif + 'ElementReplaceEvent', 'MozSmsEvent', 'DeviceStorageChangeEvent', 'PopupBlockedEvent', From fe30ab027600f1b7bbc741f2cdd70e2a79b9e596 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 3 Mar 2013 16:02:11 -0800 Subject: [PATCH 18/45] Bug 847236 - Simplify the dead nsEventTargetChainItem objects cache. r=smaug. --HG-- extra : rebase_source : 05e8756f0270ac7ed0b10f1ceb2f2825fa7bc6ae --- content/events/src/nsEventDispatcher.cpp | 153 ++++++++--------------- layout/build/nsLayoutStatics.cpp | 4 +- 2 files changed, 55 insertions(+), 102 deletions(-) diff --git a/content/events/src/nsEventDispatcher.cpp b/content/events/src/nsEventDispatcher.cpp index 60bb3ae79b3..203eb1e6248 100644 --- a/content/events/src/nsEventDispatcher.cpp +++ b/content/events/src/nsEventDispatcher.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -12,7 +13,6 @@ #include "nsError.h" #include "nsMutationEvent.h" #include NEW_H -#include "nsFixedSizeAllocator.h" #include "nsINode.h" #include "nsPIDOMWindow.h" #include "nsFrameLoader.h" @@ -27,8 +27,6 @@ using namespace mozilla; #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1) #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2) -static nsEventTargetChainItem* gCachedETCI = nullptr; - // nsEventTargetChainItem represents a single item in the event target chain. class nsEventTargetChainItem { @@ -36,25 +34,32 @@ private: nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr); + // This is the ETCI recycle pool, which is used to avoid some malloc/free + // churn. It's implemented as a linked list. + static nsEventTargetChainItem* sEtciRecyclePool; + static uint32_t sNumRecycledEtcis; + static const uint32_t kMaxNumRecycledEtcis = 128; + public: - static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator, - nsIDOMEventTarget* aTarget, + static nsEventTargetChainItem* Create(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr) { + // Allocate from the ETCI recycle pool if possible. void* place = nullptr; - if (gCachedETCI) { - place = gCachedETCI; - gCachedETCI = gCachedETCI->mNext; + if (sNumRecycledEtcis > 0) { + MOZ_ASSERT(sEtciRecyclePool); + place = sEtciRecyclePool; + sEtciRecyclePool = sEtciRecyclePool->mNext; + --sNumRecycledEtcis; } else { - place = aAllocator->Alloc(sizeof(nsEventTargetChainItem)); + place = malloc(sizeof(nsEventTargetChainItem)); } return place ? ::new (place) nsEventTargetChainItem(aTarget, aChild) : nullptr; } - static void Destroy(nsFixedSizeAllocator* aAllocator, - nsEventTargetChainItem* aItem) + static void Destroy(nsEventTargetChainItem* aItem) { // ::Destroy deletes ancestor chain. nsEventTargetChainItem* item = aItem; @@ -62,16 +67,30 @@ public: item->mChild->mParent = nullptr; item->mChild = nullptr; } + // Put destroyed ETCIs into the recycle pool if it's not already full. while (item) { nsEventTargetChainItem* parent = item->mParent; item->~nsEventTargetChainItem(); - item->mNext = gCachedETCI; - gCachedETCI = item; - --sCurrentEtciCount; + if (sNumRecycledEtcis < kMaxNumRecycledEtcis) { + item->mNext = sEtciRecyclePool; + sEtciRecyclePool = item; + ++sNumRecycledEtcis; + } else { + free(item); + } item = parent; } } + static void ShutdownRecyclePool() + { + while (sEtciRecyclePool) { + nsEventTargetChainItem* tmp = sEtciRecyclePool; + sEtciRecyclePool = sEtciRecyclePool->mNext; + free(tmp); + } + } + bool IsValid() { NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!"); @@ -205,7 +224,7 @@ public: nsEventTargetChainItem* mChild; union { nsEventTargetChainItem* mParent; - // This is used only when caching ETCI objects. + // This is used only when recycling ETCIs. nsEventTargetChainItem* mNext; }; uint16_t mFlags; @@ -220,8 +239,8 @@ public: static uint32_t sCurrentEtciCount; }; -uint32_t nsEventTargetChainItem::sMaxEtciCount = 0; -uint32_t nsEventTargetChainItem::sCurrentEtciCount = 0; +nsEventTargetChainItem* nsEventTargetChainItem::sEtciRecyclePool = nullptr; +uint32_t nsEventTargetChainItem::sNumRecycledEtcis = 0; nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild) @@ -231,10 +250,6 @@ nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget, if (mChild) { mChild->mParent = this; } - - if (++sCurrentEtciCount > sMaxEtciCount) { - sMaxEtciCount = sCurrentEtciCount; - } } nsresult @@ -378,69 +393,13 @@ nsEventTargetChainItem::HandleEventTargetChain( return NS_OK; } -#define NS_CHAIN_POOL_SIZE 128 - -class ChainItemPool { -public: - ChainItemPool() { - if (!sEtciPool) { - sEtciPool = new nsFixedSizeAllocator(); - if (sEtciPool) { - static const size_t kBucketSizes[] = { sizeof(nsEventTargetChainItem) }; - static const int32_t kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); - static const int32_t kInitialPoolSize = - sizeof(nsEventTargetChainItem) * NS_CHAIN_POOL_SIZE; - nsresult rv = sEtciPool->Init("EventTargetChainItem Pool", kBucketSizes, - kNumBuckets, kInitialPoolSize); - if (NS_FAILED(rv)) { - delete sEtciPool; - sEtciPool = nullptr; - } - } - } - if (sEtciPool) { - ++sEtciPoolUsers; - } - } - - ~ChainItemPool() { - if (sEtciPool) { - --sEtciPoolUsers; - } - if (!sEtciPoolUsers) { - if (nsEventTargetChainItem::MaxEtciCount() > NS_CHAIN_POOL_SIZE) { - gCachedETCI = nullptr; - delete sEtciPool; - sEtciPool = nullptr; - nsEventTargetChainItem::ResetMaxEtciCount(); - } - } - } - - static void Shutdown() - { - if (!sEtciPoolUsers) { - gCachedETCI = nullptr; - delete sEtciPool; - sEtciPool = nullptr; - nsEventTargetChainItem::ResetMaxEtciCount(); - } - } - - nsFixedSizeAllocator* GetPool() { return sEtciPool; } - - static nsFixedSizeAllocator* sEtciPool; - static int32_t sEtciPoolUsers; -}; - -nsFixedSizeAllocator* ChainItemPool::sEtciPool = nullptr; -int32_t ChainItemPool::sEtciPoolUsers = 0; - -void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); } +void NS_ShutdownEventTargetChainItemRecyclePool() +{ + nsEventTargetChainItem::ShutdownRecyclePool(); +} nsEventTargetChainItem* -EventTargetChainItemForChromeTarget(ChainItemPool& aPool, - nsINode* aNode, +EventTargetChainItemForChromeTarget(nsINode* aNode, nsEventTargetChainItem* aChild = nullptr) { if (!aNode->IsInDoc()) { @@ -451,12 +410,11 @@ EventTargetChainItemForChromeTarget(ChainItemPool& aPool, NS_ENSURE_TRUE(piTarget, nullptr); nsEventTargetChainItem* etci = - nsEventTargetChainItem::Create(aPool.GetPool(), - piTarget->GetTargetForEventTargetChain(), + nsEventTargetChainItem::Create(piTarget->GetTargetForEventTargetChain(), aChild); NS_ENSURE_TRUE(etci, nullptr); if (!etci->IsValid()) { - nsEventTargetChainItem::Destroy(aPool.GetPool(), etci); + nsEventTargetChainItem::Destroy(etci); return nullptr; } return etci; @@ -551,16 +509,13 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, // If we have a PresContext, make sure it doesn't die before // event dispatching is finished. nsRefPtr kungFuDeathGrip(aPresContext); - ChainItemPool pool; - NS_ENSURE_TRUE(pool.GetPool(), NS_ERROR_OUT_OF_MEMORY); // Create the event target chain item for the event target. nsEventTargetChainItem* targetEtci = - nsEventTargetChainItem::Create(pool.GetPool(), - target->GetTargetForEventTargetChain()); + nsEventTargetChainItem::Create(target->GetTargetForEventTargetChain()); NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY); if (!targetEtci->IsValid()) { - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); + nsEventTargetChainItem::Destroy(targetEtci); return NS_ERROR_FAILURE; } @@ -603,8 +558,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) { // Event target couldn't handle the event. Try to propagate to chrome. - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); - targetEtci = EventTargetChainItemForChromeTarget(pool, content); + nsEventTargetChainItem::Destroy(targetEtci); + targetEtci = EventTargetChainItemForChromeTarget(content); NS_ENSURE_STATE(targetEtci); targetEtci->PreHandleEvent(preVisitor); } @@ -617,8 +572,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, while (preVisitor.mParentTarget) { nsIDOMEventTarget* parentTarget = preVisitor.mParentTarget; nsEventTargetChainItem* parentEtci = - nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget, - topEtci); + nsEventTargetChainItem::Create(preVisitor.mParentTarget, topEtci); if (!parentEtci) { rv = NS_ERROR_OUT_OF_MEMORY; break; @@ -640,15 +594,14 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, if (preVisitor.mCanHandle) { topEtci = parentEtci; } else { - nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci); + nsEventTargetChainItem::Destroy(parentEtci); parentEtci = nullptr; if (preVisitor.mAutomaticChromeDispatch && content) { // Even if the current target can't handle the event, try to // propagate to chrome. nsCOMPtr disabledTarget = do_QueryInterface(parentTarget); if (disabledTarget) { - parentEtci = EventTargetChainItemForChromeTarget(pool, - disabledTarget, + parentEtci = EventTargetChainItemForChromeTarget(disabledTarget, topEtci); if (parentEtci) { parentEtci->PreHandleEvent(preVisitor); @@ -679,7 +632,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, aCallback, false, &pusher); - + preVisitor.mEventStatus = postVisitor.mEventStatus; // If the DOM event was created during event flow. if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) { @@ -689,7 +642,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, } } - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); + nsEventTargetChainItem::Destroy(targetEtci); targetEtci = nullptr; aEvent->mFlags.mIsBeingDispatched = false; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 1b1d7ce5250..0ef327cc584 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -112,7 +112,7 @@ using namespace mozilla::system; #include "mozilla/dom/time/DateCacheCleaner.h" #include "nsIMEStateManager.h" -extern void NS_ShutdownChainItemPool(); +extern void NS_ShutdownEventTargetChainItemRecyclePool(); using namespace mozilla; using namespace mozilla::dom; @@ -368,7 +368,7 @@ nsLayoutStatics::Shutdown() nsRegion::ShutdownStatic(); - NS_ShutdownChainItemPool(); + NS_ShutdownEventTargetChainItemRecyclePool(); nsFrameList::Shutdown(); From 14d9c7186dac0d7cdcacb19116090565ad3c09be Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Mon, 4 Mar 2013 18:38:24 -0800 Subject: [PATCH 19/45] Bug 840128 - Android client for Bagheera. r=nalexander --- mobile/android/base/android-services-files.mk | 4 + .../background/bagheera/BagheeraClient.java | 247 ++++++++++++++++++ .../bagheera/BagheeraRequestDelegate.java | 13 + .../bagheera/BoundedByteArrayEntity.java | 88 +++++++ .../background/bagheera/DeflateHelper.java | 78 ++++++ .../base/background/common/log/Logger.java | 12 + mobile/android/services/java-sources.mn | 4 + 7 files changed, 446 insertions(+) create mode 100644 mobile/android/base/background/bagheera/BagheeraClient.java create mode 100644 mobile/android/base/background/bagheera/BagheeraRequestDelegate.java create mode 100644 mobile/android/base/background/bagheera/BoundedByteArrayEntity.java create mode 100644 mobile/android/base/background/bagheera/DeflateHelper.java diff --git a/mobile/android/base/android-services-files.mk b/mobile/android/base/android-services-files.mk index 63fe1e5ced6..af79a364821 100644 --- a/mobile/android/base/android-services-files.mk +++ b/mobile/android/base/android-services-files.mk @@ -20,6 +20,10 @@ SYNC_JAVA_FILES := \ background/announcements/AnnouncementsService.java \ background/announcements/AnnouncementsStartReceiver.java \ background/BackgroundService.java \ + background/bagheera/BagheeraClient.java \ + background/bagheera/BagheeraRequestDelegate.java \ + background/bagheera/BoundedByteArrayEntity.java \ + background/bagheera/DeflateHelper.java \ background/common/log/Logger.java \ background/common/log/writers/AndroidLevelCachingLogWriter.java \ background/common/log/writers/AndroidLogWriter.java \ diff --git a/mobile/android/base/background/bagheera/BagheeraClient.java b/mobile/android/base/background/bagheera/BagheeraClient.java new file mode 100644 index 00000000000..77a7b5fac1a --- /dev/null +++ b/mobile/android/base/background/bagheera/BagheeraClient.java @@ -0,0 +1,247 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.background.bagheera; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.GeneralSecurityException; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.regex.Pattern; + +import org.mozilla.gecko.sync.net.BaseResource; +import org.mozilla.gecko.sync.net.BaseResourceDelegate; +import org.mozilla.gecko.sync.net.Resource; + +import ch.boye.httpclientandroidlib.HttpEntity; +import ch.boye.httpclientandroidlib.HttpResponse; +import ch.boye.httpclientandroidlib.client.ClientProtocolException; +import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; +import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; +import ch.boye.httpclientandroidlib.protocol.HTTP; + +/** + * Provides encapsulated access to a Bagheera document server. + * The two permitted operations are: + * * Delete a document. + * * Upload a document, optionally deleting an expired document. + */ +public class BagheeraClient { + + protected final String serverURI; + protected final Executor executor; + protected static final Pattern URI_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]+$"); + + protected static String PROTOCOL_VERSION = "1.0"; + protected static String SUBMIT_PATH = "/submit/"; + + /** + * Instantiate a new client pointing at the provided server. + * {@link #deleteDocument(String, String, BagheeraRequestDelegate)} and + * {@link #uploadJSONDocument(String, String, String, String, BagheeraRequestDelegate)} + * both accept delegate arguments; the {@link Executor} provided to this + * constructor will be used to invoke callbacks on those delegates. + * + * @param serverURI + * the destination server URI. + * @param executor + * the executor which will be used to invoke delegate callbacks. + */ + public BagheeraClient(final String serverURI, final Executor executor) { + if (serverURI == null) { + throw new IllegalArgumentException("Must provide a server URI."); + } + if (executor == null) { + throw new IllegalArgumentException("Must provide a non-null executor."); + } + this.serverURI = serverURI.endsWith("/") ? serverURI : serverURI + "/"; + this.executor = executor; + } + + /** + * Instantiate a new client pointing at the provided server. + * Delegate callbacks will be invoked on a new background thread. + * + * See {@link #BagheeraClient(String, Executor)} for more details. + * + * @param serverURI + * the destination server URI. + */ + public BagheeraClient(final String serverURI) { + this(serverURI, Executors.newSingleThreadExecutor()); + } + + /** + * Delete the specified document from the server. + * The delegate's callbacks will be invoked by the BagheeraClient's executor. + */ + public void deleteDocument(final String namespace, + final String id, + final BagheeraRequestDelegate delegate) throws URISyntaxException { + if (namespace == null) { + throw new IllegalArgumentException("Must provide namespace."); + } + if (id == null) { + throw new IllegalArgumentException("Must provide id."); + } + + final BaseResource resource = makeResource(namespace, id); + resource.delegate = new BagheeraResourceDelegate(resource, delegate); + resource.delete(); + } + + /** + * Upload a JSON document to a Bagheera server. The delegate's callbacks will + * be invoked in tasks run by the client's executor. + * + * @param namespace + * the namespace, such as "test" + * @param id + * the document ID, which is typically a UUID. + * @param payload + * a document, typically JSON-encoded. + * @param oldID + * an optional ID which denotes a document to supersede. Can be null. + * @param delegate + * the delegate whose methods should be invoked on success or + * failure. + */ + public void uploadJSONDocument(final String namespace, + final String id, + final String payload, + final String oldID, + final BagheeraRequestDelegate delegate) throws URISyntaxException { + if (namespace == null) { + throw new IllegalArgumentException("Must provide namespace."); + } + if (id == null) { + throw new IllegalArgumentException("Must provide id."); + } + if (payload == null) { + throw new IllegalArgumentException("Must provide payload."); + } + + final BaseResource resource = makeResource(namespace, id); + final HttpEntity deflatedBody = DeflateHelper.deflateBody(payload); + + resource.delegate = new BagheeraUploadResourceDelegate(resource, oldID, delegate); + resource.post(deflatedBody); + } + + public static boolean isValidURIComponent(final String in) { + return URI_PATTERN.matcher(in).matches(); + } + + protected BaseResource makeResource(final String namespace, final String id) throws URISyntaxException { + if (!isValidURIComponent(namespace)) { + throw new URISyntaxException(namespace, "Illegal namespace name. Must be alphanumeric + [_-]."); + } + + if (!isValidURIComponent(id)) { + throw new URISyntaxException(id, "Illegal id value. Must be alphanumeric + [_-]."); + } + + final String uri = this.serverURI + PROTOCOL_VERSION + SUBMIT_PATH + + namespace + "/" + id; + return new BaseResource(uri); + } + + public class BagheeraResourceDelegate extends BaseResourceDelegate { + private static final int DEFAULT_SOCKET_TIMEOUT_MSEC = 5 * 60 * 1000; // Five minutes. + protected BagheeraRequestDelegate delegate; + + public BagheeraResourceDelegate(Resource resource) { + super(resource); + } + + public BagheeraResourceDelegate(final Resource resource, + final BagheeraRequestDelegate delegate) { + this(resource); + this.delegate = delegate; + } + + @Override + public int socketTimeout() { + return DEFAULT_SOCKET_TIMEOUT_MSEC; + } + + @Override + public void handleHttpResponse(HttpResponse response) { + final int status = response.getStatusLine().getStatusCode(); + switch (status) { + case 200: + case 201: + invokeHandleSuccess(status, response); + return; + default: + invokeHandleFailure(status, response); + } + } + + protected void invokeHandleError(final Exception e) { + executor.execute(new Runnable() { + @Override + public void run() { + delegate.handleError(e); + } + }); + } + + protected void invokeHandleFailure(final int status, final HttpResponse response) { + executor.execute(new Runnable() { + @Override + public void run() { + delegate.handleFailure(status, response); + } + }); + } + + protected void invokeHandleSuccess(final int status, final HttpResponse response) { + executor.execute(new Runnable() { + @Override + public void run() { + delegate.handleSuccess(status, response); + } + }); + } + + @Override + public void handleHttpProtocolException(final ClientProtocolException e) { + invokeHandleError(e); + } + + @Override + public void handleHttpIOException(IOException e) { + invokeHandleError(e); + } + + @Override + public void handleTransportException(GeneralSecurityException e) { + invokeHandleError(e); + } + } + + public final class BagheeraUploadResourceDelegate extends BagheeraResourceDelegate { + private static final String HEADER_OBSOLETE_DOCUMENT = "X-Obsolete-Document"; + private static final String COMPRESSED_CONTENT_TYPE = "application/json+zlib; charset=utf-8"; + protected String obsoleteDocumentID; + + public BagheeraUploadResourceDelegate(Resource resource, + String obsoleteDocumentID, + BagheeraRequestDelegate delegate) { + super(resource, delegate); + this.obsoleteDocumentID = obsoleteDocumentID; + } + + @Override + public void addHeaders(HttpRequestBase request, DefaultHttpClient client) { + super.addHeaders(request, client); + request.setHeader(HTTP.CONTENT_TYPE, COMPRESSED_CONTENT_TYPE); + if (this.obsoleteDocumentID != null) { + request.addHeader(HEADER_OBSOLETE_DOCUMENT, this.obsoleteDocumentID); + } + } + } +} diff --git a/mobile/android/base/background/bagheera/BagheeraRequestDelegate.java b/mobile/android/base/background/bagheera/BagheeraRequestDelegate.java new file mode 100644 index 00000000000..3fa4f9de432 --- /dev/null +++ b/mobile/android/base/background/bagheera/BagheeraRequestDelegate.java @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.background.bagheera; + +import ch.boye.httpclientandroidlib.HttpResponse; + +public interface BagheeraRequestDelegate { + void handleSuccess(int status, HttpResponse response); + void handleError(Exception e); + void handleFailure(int status, HttpResponse response); +} diff --git a/mobile/android/base/background/bagheera/BoundedByteArrayEntity.java b/mobile/android/base/background/bagheera/BoundedByteArrayEntity.java new file mode 100644 index 00000000000..c802d38a8b0 --- /dev/null +++ b/mobile/android/base/background/bagheera/BoundedByteArrayEntity.java @@ -0,0 +1,88 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.background.bagheera; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import ch.boye.httpclientandroidlib.entity.AbstractHttpEntity; +import ch.boye.httpclientandroidlib.entity.ByteArrayEntity; + +/** + * An entity that acts like {@link ByteArrayEntity}, but exposes a window onto + * the byte array that is a subsection of the array. The purpose of this is to + * allow a smaller entity to be created without having to resize the source + * array. + */ +public class BoundedByteArrayEntity extends AbstractHttpEntity implements + Cloneable { + protected final byte[] content; + protected final int start; + protected final int end; + protected final int length; + + /** + * Create a new entity that behaves exactly like a {@link ByteArrayEntity} + * created with a copy of b truncated to ( + * end - start) bytes, starting at start. + * + * @param b the byte array to use. + * @param start the start index. + * @param end the end index. + */ + public BoundedByteArrayEntity(final byte[] b, final int start, final int end) { + if (b == null) { + throw new IllegalArgumentException("Source byte array may not be null."); + } + + if (end < start || + start < 0 || + end < 0 || + start > b.length || + end > b.length) { + throw new IllegalArgumentException("Bounds out of range."); + } + this.content = b; + this.start = start; + this.end = end; + this.length = end - start; + } + + @Override + public boolean isRepeatable() { + return true; + } + + @Override + public long getContentLength() { + return this.length; + } + + @Override + public InputStream getContent() { + return new ByteArrayInputStream(this.content, this.start, this.length); + } + + @Override + public void writeTo(final OutputStream outstream) throws IOException { + if (outstream == null) { + throw new IllegalArgumentException("Output stream may not be null."); + } + outstream.write(this.content); + outstream.flush(); + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} \ No newline at end of file diff --git a/mobile/android/base/background/bagheera/DeflateHelper.java b/mobile/android/base/background/bagheera/DeflateHelper.java new file mode 100644 index 00000000000..a325e1f42ce --- /dev/null +++ b/mobile/android/base/background/bagheera/DeflateHelper.java @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.background.bagheera; + +import java.io.UnsupportedEncodingException; +import java.util.zip.Deflater; + +import ch.boye.httpclientandroidlib.HttpEntity; + +public class DeflateHelper { + /** + * Conservative upper bound for zlib size, equivalent to the first few lines + * in zlib's deflateBound function. + * + * Includes zlib header. + * + * @param sourceLen + * the number of bytes to compress. + * @return the number of bytes to allocate for the compressed output. + */ + public static int deflateBound(final int sourceLen) { + return sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5 + 6; + } + + /** + * Deflate the input into the output array, returning the number of bytes + * written to output. + */ + public static int deflate(byte[] input, byte[] output) { + final Deflater deflater = new Deflater(); + deflater.setInput(input); + deflater.finish(); + + final int length = deflater.deflate(output); + deflater.end(); + return length; + } + + /** + * Deflate the input, returning an HttpEntity that offers an accurate window + * on the output. + * + * Note that this method does not trim the output array. (Test code can use + * {@link TestDeflation#deflateTrimmed(byte[])}.) + * + * Trimming would be more efficient for long-term space use, but we expect this + * entity to be transient. + * + * Note also that deflate can require more space than the input. + * {@link #deflateBound(int)} tells us the most it will use. + * + * @param bytes the input to deflate. + * @return the deflated input as an entity. + */ + @SuppressWarnings("javadoc") + public static HttpEntity deflateBytes(final byte[] bytes) { + // We would like to use DeflaterInputStream here, but it's minSDK=9, and we + // still target 8. It would also force us to use chunked Transfer-Encoding, + // so perhaps it's for the best! + + final byte[] out = new byte[deflateBound(bytes.length)]; + final int outLength = deflate(bytes, out); + return new BoundedByteArrayEntity(out, 0, outLength); + } + + public static HttpEntity deflateBody(final String payload) { + final byte[] bytes; + try { + bytes = payload.getBytes("UTF-8"); + } catch (UnsupportedEncodingException ex) { + // This will never happen. Thanks, Java! + throw new RuntimeException(ex); + } + return deflateBytes(bytes); + } +} \ No newline at end of file diff --git a/mobile/android/base/background/common/log/Logger.java b/mobile/android/base/background/common/log/Logger.java index fcd064a4693..2575717eb03 100644 --- a/mobile/android/base/background/common/log/Logger.java +++ b/mobile/android/base/background/common/log/Logger.java @@ -4,6 +4,7 @@ package org.mozilla.gecko.background.common.log; +import java.io.PrintWriter; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; @@ -12,6 +13,7 @@ import org.mozilla.gecko.background.common.GlobalConstants; import org.mozilla.gecko.background.common.log.writers.AndroidLevelCachingLogWriter; import org.mozilla.gecko.background.common.log.writers.AndroidLogWriter; import org.mozilla.gecko.background.common.log.writers.LogWriter; +import org.mozilla.gecko.background.common.log.writers.PrintLogWriter; import org.mozilla.gecko.background.common.log.writers.SimpleTagLogWriter; import org.mozilla.gecko.background.common.log.writers.ThreadLocalTagLogWriter; @@ -117,6 +119,16 @@ public class Logger { logWriters.addAll(Logger.defaultLogWriters()); } + /** + * Start writing log output to stdout. + *

+ * Use resetLogging to stop logging to stdout. + */ + public static synchronized void startLoggingToConsole() { + setThreadLogTag("Test"); + startLoggingTo(new PrintLogWriter(new PrintWriter(System.out, true))); + } + // Synchronized version for other classes to use. public static synchronized boolean shouldLogVerbose(String logTag) { for (LogWriter logWriter : logWriters) { diff --git a/mobile/android/services/java-sources.mn b/mobile/android/services/java-sources.mn index 631267cf80b..d3a2c77dc93 100644 --- a/mobile/android/services/java-sources.mn +++ b/mobile/android/services/java-sources.mn @@ -8,6 +8,10 @@ background/announcements/AnnouncementsFetchResourceDelegate.java background/announcements/AnnouncementsService.java background/announcements/AnnouncementsStartReceiver.java background/BackgroundService.java +background/bagheera/BagheeraClient.java +background/bagheera/BagheeraRequestDelegate.java +background/bagheera/BoundedByteArrayEntity.java +background/bagheera/DeflateHelper.java background/common/log/Logger.java background/common/log/writers/AndroidLevelCachingLogWriter.java background/common/log/writers/AndroidLogWriter.java From 6e5475a4fb96409e36265a8ec60bed5e3ea8f87b Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 4 Mar 2013 14:33:03 -0800 Subject: [PATCH 20/45] Bug 836943: Part 0 - Make sure IndexedDB attempts to initialize the storage service on the main thread. r=bent --- dom/indexedDB/IndexedDatabaseManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index 0ed273593a2..3f92a4b1253 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -418,6 +418,11 @@ IndexedDatabaseManager::GetOrCreate() nsCOMPtr obs = GetObserverService(); NS_ENSURE_TRUE(obs, nullptr); + // Must initialize the storage service on the main thread. + nsCOMPtr ss = + do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); + NS_ENSURE_TRUE(ss, nullptr); + // We need this callback to know when to shut down all our threads. rv = obs->AddObserver(instance, PROFILE_BEFORE_CHANGE_OBSERVER_ID, false); NS_ENSURE_SUCCESS(rv, nullptr); From 0757cacfc9815f68daef2b96d6bd0a1b61116696 Mon Sep 17 00:00:00 2001 From: Mike de Boer Date: Mon, 4 Mar 2013 12:50:06 +0100 Subject: [PATCH 21/45] Bug 833939 - Initialize gLogConsoleErrors to FALSE, also in debug builds. r=bsmedberg --- toolkit/xre/nsAppRunner.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 836d9ab0dde..72b36f35268 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1062,12 +1062,7 @@ static nsresult AppInfoConstructor(nsISupports* aOuter, QueryInterface(aIID, aResult); } -bool gLogConsoleErrors -#ifdef DEBUG - = true; -#else - = false; -#endif +bool gLogConsoleErrors = false; #define NS_ENSURE_TRUE_LOG(x, ret) \ PR_BEGIN_MACRO \ From ecd0c885f4860cafbfe2dcf58f967829e2454e2d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 4 Mar 2013 21:41:47 -0500 Subject: [PATCH 22/45] Bug 839913 - Fix HTMLAreaElement's stringifier. r=bz --- content/html/content/src/HTMLAreaElement.h | 5 +++++ content/html/content/test/Makefile.in | 1 + content/html/content/test/test_bug839913.html | 14 ++++++++++++++ dom/webidl/HTMLAreaElement.webidl | 7 ++++++- 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 content/html/content/test/test_bug839913.html diff --git a/content/html/content/src/HTMLAreaElement.h b/content/html/content/src/HTMLAreaElement.h index effc99018a1..80ddd0c94e9 100644 --- a/content/html/content/src/HTMLAreaElement.h +++ b/content/html/content/src/HTMLAreaElement.h @@ -155,6 +155,11 @@ public: SetHTMLBoolAttr(nsGkAtoms::nohref, aValue, aError); } + void Stringify(nsAString& aResult) + { + GetHref(aResult); + } + protected: virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE; diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index f604b34e8bd..309111abb64 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -270,6 +270,7 @@ MOCHITEST_FILES = \ test_bug827126.html \ test_bug827426.html \ test_bug838582.html \ + test_bug839913.html \ test_bug841466.html \ test_iframe_sandbox_inheritance.html \ file_iframe_sandbox_a_if1.html \ diff --git a/content/html/content/test/test_bug839913.html b/content/html/content/test/test_bug839913.html new file mode 100644 index 00000000000..37aef87cd22 --- /dev/null +++ b/content/html/content/test/test_bug839913.html @@ -0,0 +1,14 @@ + + +Test for HTMLAreaElement's stringifier + + +

+ diff --git a/dom/webidl/HTMLAreaElement.webidl b/dom/webidl/HTMLAreaElement.webidl index 5d6d96969c2..b891630aed6 100644 --- a/dom/webidl/HTMLAreaElement.webidl +++ b/dom/webidl/HTMLAreaElement.webidl @@ -21,7 +21,12 @@ interface HTMLAreaElement : HTMLElement { [SetterThrows] attribute DOMString shape; [SetterThrows] - stringifier attribute DOMString href; + // No support for stringifier attributes yet + //[SetterThrows] + //stringifier attribute DOMString href; + stringifier; + [SetterThrows] + attribute DOMString href; [SetterThrows] attribute DOMString target; [SetterThrows] From 18ed8b2501990d376b3705385e473bb40cd124dd Mon Sep 17 00:00:00 2001 From: EKR Date: Thu, 21 Feb 2013 08:52:30 -0800 Subject: [PATCH 23/45] Bug 843644 - DNS resolution for STUN servers. r=abr --- media/mtransport/build/Makefile.in | 1 + media/mtransport/nricectx.cpp | 41 +++- media/mtransport/nricectx.h | 44 ++-- media/mtransport/nriceresolverfake.cpp | 186 +++++++++++++++++ media/mtransport/nriceresolverfake.h | 122 +++++++++++ media/mtransport/objs.mk | 1 + media/mtransport/standalone/Makefile.in | 1 + media/mtransport/test/ice_unittest.cpp | 108 ++++++++-- media/mtransport/third_party/nICEr/nicer.gyp | 2 + .../third_party/nICEr/src/ice/ice_candidate.c | 194 +++++++++++++++--- .../third_party/nICEr/src/ice/ice_candidate.h | 5 +- .../nICEr/src/ice/ice_candidate_pair.c | 2 +- .../third_party/nICEr/src/ice/ice_component.c | 14 +- .../third_party/nICEr/src/ice/ice_ctx.c | 26 ++- .../third_party/nICEr/src/ice/ice_ctx.h | 16 +- .../third_party/nICEr/src/net/nr_resolver.c | 85 ++++++++ .../third_party/nICEr/src/net/nr_resolver.h | 95 +++++++++ .../nICEr/src/net/transport_addr.c | 26 ++- .../nICEr/src/net/transport_addr.h | 2 + 19 files changed, 892 insertions(+), 79 deletions(-) create mode 100644 media/mtransport/nriceresolverfake.cpp create mode 100644 media/mtransport/nriceresolverfake.h create mode 100644 media/mtransport/third_party/nICEr/src/net/nr_resolver.c create mode 100644 media/mtransport/third_party/nICEr/src/net/nr_resolver.h diff --git a/media/mtransport/build/Makefile.in b/media/mtransport/build/Makefile.in index 52463e010fc..03c6ca8ae9c 100644 --- a/media/mtransport/build/Makefile.in +++ b/media/mtransport/build/Makefile.in @@ -31,6 +31,7 @@ EXPORTS_mtransport = \ ../dtlsidentity.h \ ../nricectx.h \ ../nricemediastream.h \ + ../nriceresolverfake.h \ ../transportflow.h \ ../transportlayer.h \ ../transportlayerdtls.h \ diff --git a/media/mtransport/nricectx.cpp b/media/mtransport/nricectx.cpp index 07c44889862..416a294c915 100644 --- a/media/mtransport/nricectx.cpp +++ b/media/mtransport/nricectx.cpp @@ -159,7 +159,27 @@ static nr_ice_crypto_vtbl nr_ice_crypto_nss_vtbl = { -// NrIceCtx + +nsresult NrIceStunServer::ToNicerStruct(nr_ice_stun_server *server) const { + int r; + + if (has_addr_) { + r = nr_praddr_to_transport_addr(&addr_, &server->u.addr, 0); + if (r) { + return NS_ERROR_FAILURE; + } + server->type=NR_ICE_STUN_SERVER_TYPE_ADDR; + } + else { + MOZ_ASSERT(sizeof(server->u.dnsname.host) > host_.size()); + PL_strncpyz(server->u.dnsname.host, host_.c_str(), + sizeof(server->u.dnsname.host)); + server->u.dnsname.port = port_; + server->type=NR_ICE_STUN_SERVER_TYPE_DNSNAME; + } + + return NS_OK; +} // Handler callbacks int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream, @@ -364,17 +384,15 @@ nsresult NrIceCtx::SetStunServers(const std::vector& ScopedDeleteArray servers( new nr_ice_stun_server[stun_servers.size()]); - int r; for (size_t i=0; i < stun_servers.size(); ++i) { - r = nr_praddr_to_transport_addr(&stun_servers[i].addr(), - &servers[i].addr, 0); - if (r) { + nsresult rv = stun_servers[i].ToNicerStruct(&servers[i]); + if (NS_FAILED(rv)) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set STUN server for '" << name_ << "'"); return NS_ERROR_FAILURE; } } - r = nr_ice_ctx_set_stun_servers(ctx_, servers, stun_servers.size()); + int r = nr_ice_ctx_set_stun_servers(ctx_, servers, stun_servers.size()); if (r) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set STUN server for '" << name_ << "'"); return NS_ERROR_FAILURE; @@ -383,6 +401,17 @@ nsresult NrIceCtx::SetStunServers(const std::vector& return NS_OK; } +nsresult NrIceCtx::SetResolver(nr_resolver *resolver) { + int r = nr_ice_ctx_set_resolver(ctx_, resolver); + + if (r) { + MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set resolver for '" << name_ << "'"); + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + nsresult NrIceCtx::StartGathering() { int r = nr_ice_initialize(ctx_, &NrIceCtx::initialized_cb, this); diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h index 9fe8b1e0906..ac1940c6296 100644 --- a/media/mtransport/nricectx.h +++ b/media/mtransport/nricectx.h @@ -64,26 +64,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "m_cpp_utils.h" -namespace mozilla { - -typedef void* NR_SOCKET; typedef struct nr_ice_ctx_ nr_ice_ctx; typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx; typedef struct nr_ice_media_stream_ nr_ice_media_stream; typedef struct nr_ice_handler_ nr_ice_handler; typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl; typedef struct nr_ice_cand_pair_ nr_ice_cand_pair; +typedef struct nr_ice_stun_server_ nr_ice_stun_server; +typedef struct nr_resolver_ nr_resolver; + +namespace mozilla { + +typedef void* NR_SOCKET; class NrIceMediaStream; - struct NrIceStunServer { public: - NrIceStunServer(const PRNetAddr& addr) { + NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) { memcpy(&addr_, &addr, sizeof(addr)); } - // Convenience function to allow you to pass an IP addr as a string + // The main function to use. Will take either an address or a hostname. static NrIceStunServer* Create(const std::string& addr, uint16_t port) { ScopedDeletePtr server( new NrIceStunServer()); @@ -94,23 +96,35 @@ struct NrIceStunServer { return server.forget(); } - - const PRNetAddr& addr() const { return addr_; } + nsresult ToNicerStruct(nr_ice_stun_server *server) const; private: NrIceStunServer() : addr_() {} nsresult Init(const std::string& addr, uint16_t port) { PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_); - if (status != PR_SUCCESS) - return NS_ERROR_INVALID_ARG; + if (status == PR_SUCCESS) { + // Parseable as an address + addr_.inet.port = PR_htons(port); + port_ = port; + has_addr_ = true; + return NS_OK; + } + else if (host_.size() < 256) { + // Apparently this is a hostname. + host_ = addr; + port_ = port; + has_addr_ = false; + return NS_OK; + } - addr_.inet.port = PR_htons(port); - - return NS_OK; + return NS_ERROR_FAILURE; } + bool has_addr_; + std::string host_; + uint16_t port_; PRNetAddr addr_; }; @@ -168,6 +182,10 @@ class NrIceCtx { // (if at all). nsresult SetStunServers(const std::vector& stun_servers); + // Provide the resolution provider. Must be called before + // StartGathering. + nsresult SetResolver(nr_resolver *resolver); + // Start ICE gathering nsresult StartGathering(); diff --git a/media/mtransport/nriceresolverfake.cpp b/media/mtransport/nriceresolverfake.cpp new file mode 100644 index 00000000000..289f4cc6e1f --- /dev/null +++ b/media/mtransport/nriceresolverfake.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +// Original author: ekr@rtfm.com + +// Some of this code is cut-and-pasted from nICEr. Copyright is: + +/* +Copyright (c) 2007, Adobe Systems, Incorporated +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems, Network Resonance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "nspr.h" +#include "prnetdb.h" + +#include "mozilla/Assertions.h" + +extern "C" { +#include "nr_api.h" +#include "async_timer.h" +#include "nr_resolver.h" +#include "transport_addr.h" +} + +#include "nriceresolverfake.h" +#include "nr_socket_prsock.h" + +namespace mozilla { + +NrIceResolverFake::NrIceResolverFake() : + vtbl_(new nr_resolver_vtbl), addrs_(), delay_ms_(100), + allocated_resolvers_(0) { + vtbl_->destroy = &NrIceResolverFake::destroy; + vtbl_->resolve = &NrIceResolverFake::resolve; + vtbl_->cancel = &NrIceResolverFake::cancel; +} + +NrIceResolverFake::~NrIceResolverFake() { + MOZ_ASSERT(allocated_resolvers_ == 0); + delete vtbl_; +} + + +nr_resolver *NrIceResolverFake::AllocateResolver() { + nr_resolver *resolver; + + int r = nr_resolver_create_int((void *)this, + vtbl_, &resolver); + MOZ_ASSERT(!r); + if(r) + return nullptr; + + ++allocated_resolvers_; + + return resolver; +} + +void NrIceResolverFake::DestroyResolver() { + --allocated_resolvers_; +} + +int NrIceResolverFake::destroy(void **objp) { + if (!objp || !*objp) + return 0; + + NrIceResolverFake *fake = static_cast(*objp); + *objp = 0; + + fake->DestroyResolver(); + + return 0; +} + +int NrIceResolverFake::resolve(void *obj, + nr_resolver_resource *resource, + int (*cb)(void *cb_arg, + nr_transport_addr *addr), + void *cb_arg, + void **handle) { + int r,_status; + + MOZ_ASSERT(obj); + NrIceResolverFake *fake = static_cast(obj); + + MOZ_ASSERT(fake->allocated_resolvers_ > 0); + + PendingResolution *pending = new PendingResolution(fake, + resource->domain_name, + resource->port ? + resource->port : 3478, + cb, cb_arg); + + if ((r=NR_ASYNC_TIMER_SET(fake->delay_ms_,NrIceResolverFake::resolve_cb, + (void *)pending, &pending->timer_handle_))) { + delete pending; + ABORT(r); + } + *handle = pending; + + _status=0; +abort: + return(_status); +} + +void NrIceResolverFake::resolve_cb(NR_SOCKET s, int how, void *cb_arg) { + MOZ_ASSERT(cb_arg); + PendingResolution *pending = static_cast(cb_arg); + + const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_); + + if (addr) { + nr_transport_addr transport_addr; + + int r = nr_praddr_to_transport_addr(addr, &transport_addr, 0); + MOZ_ASSERT(!r); + if (r) + goto abort; + + r=nr_transport_addr_set_port(&transport_addr, pending->port_); + MOZ_ASSERT(!r); + if (r) + goto abort; + + /* Fill in the address string */ + r=nr_transport_addr_fmt_addr_string(&transport_addr); + MOZ_ASSERT(!r); + if (r) + goto abort; + + pending->cb_(pending->cb_arg_, &transport_addr); + delete pending; + return; + } + +abort: + // Resolution failed. + pending->cb_(pending->cb_arg_, nullptr); + + delete pending; +} + +int NrIceResolverFake::cancel(void *obj, void *handle) { + MOZ_ASSERT(obj); + MOZ_ASSERT(static_cast(obj)->allocated_resolvers_ > 0); + + PendingResolution *pending = static_cast(handle); + + NR_async_timer_cancel(pending->timer_handle_); + delete pending; + + return(0); +} + + +} // End of namespace mozilla diff --git a/media/mtransport/nriceresolverfake.h b/media/mtransport/nriceresolverfake.h new file mode 100644 index 00000000000..bebe57d3f42 --- /dev/null +++ b/media/mtransport/nriceresolverfake.h @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +// Original author: ekr@rtfm.com + +// Some of this code is cut-and-pasted from nICEr. Copyright is: + +/* +Copyright (c) 2007, Adobe Systems, Incorporated +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems, Network Resonance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef nriceresolverfake_h__ +#define nriceresolverfake_h__ + +#include +#include + +#include "nspr.h" +#include "prnetdb.h" +#include "mozilla/NullPtr.h" + +typedef struct nr_resolver_ nr_resolver; +typedef struct nr_resolver_vtbl_ nr_resolver_vtbl; +typedef struct nr_transport_addr_ nr_transport_addr; +typedef struct nr_resolver_resource_ nr_resolver_resource; + +namespace mozilla { + +class NrIceResolverFake { + public: + NrIceResolverFake(); + ~NrIceResolverFake(); + + void SetAddr(const std::string& hostname, const PRNetAddr& addr) { + addrs_[hostname] = addr; + } + + nr_resolver *AllocateResolver(); + + void DestroyResolver(); + +private: + // Implementations of vtbl functions + static int destroy(void **objp); + static int resolve(void *obj, + nr_resolver_resource *resource, + int (*cb)(void *cb_arg, + nr_transport_addr *addr), + void *cb_arg, + void **handle); + static void resolve_cb(NR_SOCKET s, int how, void *cb_arg); + static int cancel(void *obj, void *handle); + + // Get an address. + const PRNetAddr *Resolve(const std::string& hostname) { + if (!addrs_.count(hostname)) + return nullptr; + + return &addrs_[hostname]; + } + + + struct PendingResolution { + PendingResolution(NrIceResolverFake *resolver, + const std::string& hostname, + uint16_t port, + int (*cb)(void *cb_arg, nr_transport_addr *addr), + void *cb_arg) : + resolver_(resolver), + hostname_(hostname), + port_(port), + cb_(cb), cb_arg_(cb_arg) {} + + NrIceResolverFake *resolver_; + std::string hostname_; + uint16_t port_; + int (*cb_)(void *cb_arg, nr_transport_addr *addr); + void *cb_arg_; + void *timer_handle_; + }; + + nr_resolver_vtbl* vtbl_; + std::map addrs_; + uint32_t delay_ms_; + int allocated_resolvers_; +}; + +} // End of namespace mozilla + +#endif diff --git a/media/mtransport/objs.mk b/media/mtransport/objs.mk index 2a731dcb0dd..49b26177621 100644 --- a/media/mtransport/objs.mk +++ b/media/mtransport/objs.mk @@ -66,6 +66,7 @@ MTRANSPORT_LCPPSRCS = \ dtlsidentity.cpp \ nricectx.cpp \ nricemediastream.cpp \ + nriceresolverfake.cpp \ nr_socket_prsock.cpp \ nr_timer.cpp \ transportflow.cpp \ diff --git a/media/mtransport/standalone/Makefile.in b/media/mtransport/standalone/Makefile.in index 65e6b099a43..ec191def8d2 100644 --- a/media/mtransport/standalone/Makefile.in +++ b/media/mtransport/standalone/Makefile.in @@ -27,6 +27,7 @@ EXPORTS_mtransport = \ ../dtlsidentity.h \ ../nricectx.h \ ../nricemediastream.h \ + ../nriceresolverfake.h \ ../transportflow.h \ ../transportlayer.h \ ../transportlayerdtls.h \ diff --git a/media/mtransport/test/ice_unittest.cpp b/media/mtransport/test/ice_unittest.cpp index 1afe12ab4c3..fcec0364191 100644 --- a/media/mtransport/test/ice_unittest.cpp +++ b/media/mtransport/test/ice_unittest.cpp @@ -24,6 +24,7 @@ #include "logging.h" #include "nricectx.h" #include "nricemediastream.h" +#include "nriceresolverfake.h" #include "mtransport_test_utils.h" #include "runnable_utils.h" @@ -36,6 +37,11 @@ MtransportTestUtils *test_utils; bool stream_added = false; +const std::string kDefaultStunServerAddress((char *)"23.21.150.121"); +const std::string kDefaultStunServerHostname((char *)"stun-server.invalid"); +const std::string kBogusStunServerHostname((char *)"stun-server-nonexistent.invalid"); +const uint16_t kDefaultStunServerPort=3478; + namespace { enum TrickleMode { TRICKLE_NONE, TRICKLE_DEFERRED }; @@ -53,6 +59,7 @@ class IceTestPeer : public sigslot::has_slots<> { ice_complete_(false), received_(0), sent_(0), + fake_resolver_(), remote_(nullptr) { ice_ctx_->SignalGatheringCompleted.connect(this, &IceTestPeer::GatheringComplete); @@ -63,6 +70,10 @@ class IceTestPeer : public sigslot::has_slots<> { test_utils->sts_target()->Dispatch(WrapRunnable(this, &IceTestPeer::Shutdown), NS_DISPATCH_SYNC); + + // Give the ICE destruction callback time to fire before + // we destroy the resolver. + PR_Sleep(1000); } void AddStream(int components) { @@ -79,14 +90,30 @@ class IceTestPeer : public sigslot::has_slots<> { stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived); } - void Gather() { - nsresult res; - + void SetStunServer(const std::string addr, uint16_t port) { std::vector stun_servers; - ScopedDeletePtr server(NrIceStunServer::Create( - std::string((char *)"216.93.246.14"), 3478)); + ScopedDeletePtr server(NrIceStunServer::Create(addr, + port)); stun_servers.push_back(*server); ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers))); + } + + void AddAddressToResolver(const std::string hostname, + const std::string address) { + PRNetAddr addr; + PRStatus status = PR_StringToNetAddr(address.c_str(), &addr); + ASSERT_EQ(PR_SUCCESS, status); + + fake_resolver_.SetAddr(hostname, addr); + } + + void SetResolver() { + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver( + fake_resolver_.AllocateResolver()))); + } + + void Gather() { + nsresult res; test_utils->sts_target()->Dispatch( WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res), @@ -242,12 +269,35 @@ class IceTestPeer : public sigslot::has_slots<> { bool ice_complete_; size_t received_; size_t sent_; + NrIceResolverFake fake_resolver_; IceTestPeer *remote_; }; -class IceTest : public ::testing::Test { +class IceGatherTest : public ::testing::Test { public: - IceTest() : initted_(false) {} + void SetUp() { + peer_ = new IceTestPeer("P1", true, false); + peer_->AddStream(1); + peer_->AddAddressToResolver(kDefaultStunServerHostname, + kDefaultStunServerAddress); + } + + void SetResolver() { + peer_->SetResolver(); + } + + void Gather() { + peer_->Gather(); + + ASSERT_TRUE_WAIT(peer_->gathering_complete(), 10000); + } + protected: + mozilla::ScopedDeletePtr peer_; +}; + +class IceConnectTest : public ::testing::Test { + public: + IceConnectTest() : initted_(false) {} void SetUp() { nsresult rv; @@ -271,6 +321,8 @@ class IceTest : public ::testing::Test { bool Gather(bool wait) { Init(false); + p1_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort); + p2_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort); p1_->Gather(); p2_->Gather(); @@ -315,7 +367,7 @@ class IceTest : public ::testing::Test { p1_->Connect(p2_, TRICKLE_NONE, true); p2_->Connect(p1_, TRICKLE_NONE, false); test_utils->sts_target()->Dispatch(WrapRunnable(this, - &IceTest::CloseP1), + &IceConnectTest::CloseP1), NS_DISPATCH_SYNC); p2_->StartChecks(); @@ -344,32 +396,56 @@ class IceTest : public ::testing::Test { } // end namespace -TEST_F(IceTest, TestGather) { +TEST_F(IceGatherTest, TestGatherStunServerIpAddress) { + peer_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort); + peer_->SetResolver(); + Gather(); +} + +TEST_F(IceGatherTest, TestGatherStunServerHostname) { + peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort); + peer_->SetResolver(); + Gather(); +} + +TEST_F(IceGatherTest, TestGatherStunBogusHostname) { + peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort); + peer_->SetResolver(); + Gather(); +} + +TEST_F(IceGatherTest, TestGatherStunServerHostnameNoResolver) { + peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort); + Gather(); +} + + +TEST_F(IceConnectTest, TestGather) { AddStream("first", 1); ASSERT_TRUE(Gather(true)); } -TEST_F(IceTest, TestGatherAutoPrioritize) { +TEST_F(IceConnectTest, TestGatherAutoPrioritize) { Init(false); AddStream("first", 1); ASSERT_TRUE(Gather(true)); } -TEST_F(IceTest, TestConnect) { +TEST_F(IceConnectTest, TestConnect) { AddStream("first", 1); ASSERT_TRUE(Gather(true)); Connect(); } -TEST_F(IceTest, TestConnectAutoPrioritize) { +TEST_F(IceConnectTest, TestConnectAutoPrioritize) { Init(false); AddStream("first", 1); ASSERT_TRUE(Gather(true)); Connect(); } -TEST_F(IceTest, TestConnectTrickleOneStreamOneComponent) { +TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) { AddStream("first", 1); ASSERT_TRUE(Gather(true)); ConnectTrickle(); @@ -378,7 +454,7 @@ TEST_F(IceTest, TestConnectTrickleOneStreamOneComponent) { ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000); } -TEST_F(IceTest, TestConnectTrickleTwoStreamsOneComponent) { +TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) { AddStream("first", 1); AddStream("second", 1); ASSERT_TRUE(Gather(true)); @@ -390,14 +466,14 @@ TEST_F(IceTest, TestConnectTrickleTwoStreamsOneComponent) { } -TEST_F(IceTest, TestSendReceive) { +TEST_F(IceConnectTest, TestSendReceive) { AddStream("first", 1); ASSERT_TRUE(Gather(true)); Connect(); SendReceive(); } -TEST_F(IceTest, TestConnectShutdownOneSide) { +TEST_F(IceConnectTest, TestConnectShutdownOneSide) { AddStream("first", 1); ASSERT_TRUE(Gather(true)); ConnectThenDelete(); diff --git a/media/mtransport/third_party/nICEr/nicer.gyp b/media/mtransport/third_party/nICEr/nicer.gyp index fed0bb8d35d..b62e06132d4 100644 --- a/media/mtransport/third_party/nICEr/nicer.gyp +++ b/media/mtransport/third_party/nICEr/nicer.gyp @@ -63,6 +63,8 @@ "./src/ice/ice_socket.h", # Net + "./src/net/nr_resolver.c", + "./src/net/nr_resolver.h", "./src/net/nr_socket.c", "./src/net/nr_socket.h", #"./src/net/nr_socket_local.c", diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c index 279ed4cf945..42a13708b07 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c @@ -63,12 +63,15 @@ static char *RCSSTRING __UNUSED__="$Id: ice_candidate.c,v 1.2 2008/04/28 17:59:0 static int next_automatic_preference = 224; +static int nr_ice_candidate_initialize2(nr_ice_candidate *cand); static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand); -static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg); +static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand); static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg); #ifdef USE_TURN -static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg); +static int nr_ice_start_relay_turn(nr_ice_candidate *cand); static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg); +static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr); + #endif /* USE_TURN */ char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0}; @@ -81,16 +84,39 @@ static const char *nr_ctype_name(nr_ice_candidate_type ctype) { return nr_ice_candidate_type_names[ctype]; } -int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp) +static int nr_ice_candidate_format_stun_label(char *label, size_t size, nr_ice_candidate *cand) + { + int _status; + + *label = 0; + switch(cand->stun_server->type) { + case NR_ICE_STUN_SERVER_TYPE_ADDR: + snprintf(label, size, "%s(%s|%s)", nr_ctype_name(cand->type), cand->base.as_string, + cand->stun_server->u.addr.as_string); + break; + case NR_ICE_STUN_SERVER_TYPE_DNSNAME: + snprintf(label, size, "%s(%s|%s:%u)", nr_ctype_name(cand->type), cand->base.as_string, + cand->stun_server->u.dnsname.host, cand->stun_server->u.dnsname.port); + break; + default: + assert(0); + ABORT(R_BAD_ARGS); + } + + _status=0; + abort: + return(_status); + } + +int nr_ice_candidate_create(nr_ice_ctx *ctx,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp) { nr_ice_candidate *cand=0; nr_ice_candidate *tmp=0; int r,_status; + char label[512]; if(!(cand=RCALLOC(sizeof(nr_ice_candidate)))) ABORT(R_NO_MEMORY); - if(!(cand->label=r_strdup(label))) - ABORT(R_NO_MEMORY); cand->state=NR_ICE_CAND_STATE_CREATED; cand->ctx=ctx; cand->isock=isock; @@ -101,12 +127,36 @@ int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,n cand->component=comp; cand->stream=comp->stream; - r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): creating candidate %s with type %s", - ctx->label,label,nr_ctype_name(ctype)); - /* Extract the addr as the base */ if(r=nr_socket_getaddr(cand->isock->sock,&cand->base)) ABORT(r); + + switch(ctype) { + case HOST: + snprintf(label, sizeof(label), "host(%s)", cand->base.as_string); + break; + + case SERVER_REFLEXIVE: + if(r=nr_ice_candidate_format_stun_label(label, sizeof(label),cand)) + ABORT(r); + break; + + case RELAYED: + if(r=nr_ice_candidate_format_stun_label(label, sizeof(label),cand)) + ABORT(r); + break; + + case PEER_REFLEXIVE: + snprintf(label, sizeof(label), "prflx"); + break; + + default: + assert(0); /* Can't happen */ + ABORT(R_BAD_ARGS); + } + if(!(cand->label=r_strdup(label))) + ABORT(R_NO_MEMORY); + if(r=nr_ice_get_foundation(ctx,cand)) ABORT(r); if(r=nr_ice_candidate_compute_priority(cand)) @@ -122,21 +172,25 @@ int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,n if(ctype==RELAYED) cand->u.relayed.turn_sock=osock; + /* Add the candidate to the isock list*/ TAILQ_INSERT_TAIL(&isock->candidates,cand,entry_sock); + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): created candidate %s with type %s", + ctx->label,cand->label,nr_ctype_name(ctype)); + *candp=cand; _status=0; abort: if (_status){ + r_log(LOG_ICE,LOG_ERR,"ICE(%s): Failed to create candidate of type %s", ctx->label,nr_ctype_name(ctype)); nr_ice_candidate_destroy(&cand); } return(_status); } - /* Create a peer reflexive candidate */ int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp) { @@ -205,6 +259,9 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp) NR_async_timer_cancel(cand->delay_timer); NR_async_timer_cancel(cand->ready_cb_timer); + if(cand->resolver_handle){ + nr_resolver_cancel(cand->ctx->resolver,cand->resolver_handle); + } RFREE(cand->foundation); RFREE(cand->label); @@ -344,7 +401,7 @@ static void nr_ice_candidate_fire_ready_cb(NR_SOCKET s, int how, void *cb_arg) int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg) { int r,_status; - + int protocol=NR_RESOLVE_PROTOCOL_STUN; cand->done_cb=ready_cb; cand->cb_arg=cb_arg; @@ -361,14 +418,111 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo break; #ifdef USE_TURN case RELAYED: - if(r=nr_ice_start_relay_turn(cand,ready_cb,cb_arg)) + protocol=NR_RESOLVE_PROTOCOL_TURN; + /* Fall through */ +#endif + case SERVER_REFLEXIVE: + cand->state=NR_ICE_CAND_STATE_INITIALIZING; + + if(cand->stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR) { + /* Just copy the address */ + if (r=nr_transport_addr_copy(&cand->stun_server_addr, + &cand->stun_server->u.addr)) { + r_log(LOG_ICE,LOG_ERR,"ICE-CANDIDATE(%s): Could not copy STUN server addr", cand->label); + ABORT(r); + } + + if(r=nr_ice_candidate_initialize2(cand)) + ABORT(r); + } + else { + nr_resolver_resource resource; + resource.domain_name=cand->stun_server->u.dnsname.host; + resource.port=cand->stun_server->u.dnsname.port; + resource.stun_turn=protocol; + resource.transport_protocol=IPPROTO_UDP; /* We don't support TCP yet */ + + /* Try to resolve */ + if(!cand->ctx->resolver) { + r_log(LOG_ICE, LOG_ERR, "Can't use DNS names without a resolver"); + ABORT(R_BAD_ARGS); + } + + if(r=nr_resolver_resolve(cand->ctx->resolver, + &resource, + nr_ice_candidate_resolved_cb, + (void *)cand, + &cand->resolver_handle)){ + r_log(LOG_ICE,LOG_ERR,"ICE-CANDIDATE(%s): Could not resolve domain name",cand->label); + ABORT(r); + } + } + break; + default: + ABORT(R_INTERNAL); + } + + _status=0; + abort: + if(_status && _status!=R_WOULDBLOCK) + cand->state=NR_ICE_CAND_STATE_FAILED; + return(_status); + } + + +static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr) + { + nr_ice_candidate *cand=cb_arg; + int r,_status; + + cand->resolver_handle=0; + + if(addr){ + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): resolved candidate %s. addr=%s", + cand->ctx->label,cand->label,addr->as_string); + } + else { + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): failed to resolve candidate %s.", + cand->ctx->label,cand->label); + ABORT(R_NOT_FOUND); + } + + /* Copy the address */ + if(r=nr_transport_addr_copy(&cand->stun_server_addr,addr)) + ABORT(r); + + /* Now start initializing */ + if(r=nr_ice_candidate_initialize2(cand)) + ABORT(r); + + _status=0; + abort: + if(_status && _status!=R_WOULDBLOCK) { + cand->state=NR_ICE_CAND_STATE_FAILED; + cand->done_cb(0,0,cand->cb_arg); + } + return(_status); + } + +static int nr_ice_candidate_initialize2(nr_ice_candidate *cand) + { + int r,_status; + + switch(cand->type){ + case HOST: + assert(0); /* Can't happen */ + ABORT(R_INTERNAL); + break; +#ifdef USE_TURN + case RELAYED: + if(r=nr_ice_start_relay_turn(cand)) ABORT(r); ABORT(R_WOULDBLOCK); break; #endif /* USE_TURN */ case SERVER_REFLEXIVE: /* Need to start stun */ - if(r=nr_ice_srvrflx_start_stun(cand,ready_cb,cb_arg)) + if(r=nr_ice_srvrflx_start_stun(cand)) ABORT(r); cand->osock=cand->isock->sock; ABORT(R_WOULDBLOCK); @@ -412,17 +566,12 @@ static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_ar return; } -static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg) +static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand) { int r,_status; - cand->done_cb=ready_cb; - cand->cb_arg=cb_arg; - - cand->state=NR_ICE_CAND_STATE_INITIALIZING; - if(r=nr_stun_client_ctx_create(cand->label, cand->isock->sock, - &cand->stun_server->addr, cand->stream->ctx->gather_rto, + &cand->stun_server_addr, cand->stream->ctx->gather_rto, &cand->u.srvrflx.stun)) ABORT(r); @@ -472,19 +621,16 @@ static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg) return; } -static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg) +static int nr_ice_start_relay_turn(nr_ice_candidate *cand) { int r,_status; if(r=nr_turn_client_ctx_create(cand->label, cand->isock->sock, cand->osock, - &cand->stun_server->addr, cand->stream->ctx->gather_rto, + &cand->stun_server->u.addr, cand->stream->ctx->gather_rto, &cand->u.relayed.turn)) ABORT(r); - cand->done_cb=ready_cb; - cand->cb_arg=cb_arg; - NR_ASYNC_TIMER_SET(cand->stream->ctx->stun_delay,nr_ice_start_relay_turn_timer_cb,cand,&cand->delay_timer); cand->stream->ctx->stun_delay += cand->stream->ctx->Ta; diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h index 0503214a7ac..8af1737bef5 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h @@ -65,8 +65,9 @@ struct nr_ice_candidate_ { char *foundation; /* Foundation for the candidate (S 4) */ UINT4 priority; /* The priority value (S 5.4 */ nr_ice_stun_server *stun_server; - + nr_transport_addr stun_server_addr; /* Resolved STUN server address */ void *delay_timer; + void *resolver_handle; /* Holding data for STUN and TURN */ union { @@ -97,7 +98,7 @@ struct nr_ice_candidate_ { extern char *nr_ice_candidate_type_names[]; -int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,char *label, nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp); +int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp); int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg); int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr); int nr_ice_candidate_destroy(nr_ice_candidate **candp); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c index a5100b9775b..e851a9f4a1f 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c @@ -285,7 +285,7 @@ static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg) /* OK, nothing found, must be peer reflexive */ if(!cand){ - if(r=nr_ice_candidate_create(pair->pctx->ctx,"prflx", + if(r=nr_ice_candidate_create(pair->pctx->ctx, pair->local->component,pair->local->isock,pair->local->osock, PEER_REFLEXIVE,0,pair->local->component->component_id,&cand)) ABORT(r); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.c b/media/mtransport/third_party/nICEr/src/ice/ice_component.c index 94f1ac923cf..ffb17ae6bec 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c @@ -159,9 +159,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon ABORT(r); /* Create one host candidate */ - - snprintf(label, sizeof(label), "host(%s)", addrs[i].as_string); - if(r=nr_ice_candidate_create(ctx,label,component,isock,sock,HOST,0, + if(r=nr_ice_candidate_create(ctx,component,isock,sock,HOST,0, component->component_id,&cand)) ABORT(r); @@ -171,8 +169,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon /* And a srvrflx candidate for each STUN server */ for(j=0;jstun_server_ct;j++){ - snprintf(label, sizeof(label), "srvrflx(%s|%s)", addrs[i].as_string, ctx->stun_servers[j].addr.as_string); - if(r=nr_ice_candidate_create(ctx,label,component, + if(r=nr_ice_candidate_create(ctx,component, isock,sock,SERVER_REFLEXIVE, &ctx->stun_servers[j],component->component_id,&cand)) ABORT(r); @@ -188,8 +185,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon nr_ice_candidate *srvflx_cand; /* srvrflx */ - snprintf(label, sizeof(label), "srvrflx(%s|%s)", addrs[i].as_string, ctx->turn_servers[j].turn_server.addr.as_string); - if(r=nr_ice_candidate_create(ctx,label,component, + if(r=nr_ice_candidate_create(ctx,component, isock,sock,SERVER_REFLEXIVE, &ctx->turn_servers[j].turn_server,component->component_id,&cand)) ABORT(r); @@ -204,8 +200,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon /* relayed*/ if(r=nr_socket_turn_create(sock, 0, &turn_sock)) ABORT(r); - snprintf(label, sizeof(label), "turn-relayed(%s|%s)", addrs[i].as_string, ctx->turn_servers[j].turn_server.addr.as_string); - if(r=nr_ice_candidate_create(ctx,label,component, + if(r=nr_ice_candidate_create(ctx,component, isock,turn_sock,RELAYED, &ctx->turn_servers[j].turn_server,component->component_id,&cand)) ABORT(r); @@ -248,6 +243,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon if(cand->state!=NR_ICE_CAND_STATE_INITIALIZING){ if(r=nr_ice_candidate_initialize(cand,nr_ice_initialize_finished_cb,ctx)){ if(r!=R_WOULDBLOCK){ + ctx->uninitialized_candidates--; cand->state=NR_ICE_CAND_STATE_FAILED; } } diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c index 97090b83f08..3f0b72ef8a3 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c @@ -86,7 +86,7 @@ int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out) ABORT(r); addr_int=inet_addr(addr); if(addr_int==INADDR_NONE){ - r_log(LOG_ICE,LOG_ERR,"Invalid address %s",addr); + r_log(LOG_ICE,LOG_ERR,"Invalid address %s;",addr); ABORT(R_BAD_ARGS); } if(r=NR_reg_get2_uint2(child,"port",&port)) { @@ -95,10 +95,10 @@ int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out) port = 3478; } if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP, - &servers[i].addr)) + &servers[i].u.addr)) ABORT(r); servers[i].index=i; - + servers[i].type = NR_ICE_STUN_SERVER_TYPE_ADDR; RFREE(addr); addr=0; } @@ -156,6 +156,22 @@ int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int return(_status); } +int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver) + { + int _status; + + if (ctx->resolver) { + ABORT(R_ALREADY); + } + + ctx->resolver = resolver; + + _status=0; + abort: + return(_status); + } + + #ifdef USE_TURN int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out) { @@ -188,7 +204,7 @@ int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out) port = 3478; } if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP, - &servers[i].turn_server.addr)) + &servers[i].turn_server.u.addr)) ABORT(r); if(r=NR_reg_get2_uint4(child,NR_ICE_REG_TURN_SRV_BANDWIDTH,&servers[i].bandwidth_kbps)) @@ -363,6 +379,8 @@ static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg) RFREE(id1); } + nr_resolver_destroy(&ctx->resolver); + RFREE(ctx); } diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h index f3069d09660..120b6b9290e 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h @@ -42,12 +42,23 @@ extern "C" { /* Not good practice but making includes simpler */ #include "transport_addr.h" #include "nr_socket.h" +#include "nr_resolver.h" #include "stun_client_ctx.h" #include "stun_server_ctx.h" #include "turn_client_ctx.h" +#define NR_ICE_STUN_SERVER_TYPE_ADDR 1 +#define NR_ICE_STUN_SERVER_TYPE_DNSNAME 2 + typedef struct nr_ice_stun_server_ { - nr_transport_addr addr; + int type; + union { + nr_transport_addr addr; + struct { + char host[256]; /* Limit from RFC 1034, plus a 0 byte */ + UINT2 port; + } dnsname; + } u; int index; } nr_ice_stun_server; @@ -114,6 +125,8 @@ struct nr_ice_ctx_ { nr_ice_turn_server *turn_servers; /* The list of turn servers */ int turn_server_ct; + nr_resolver *resolver; /* The resolver to use */ + nr_ice_foundation_head foundations; nr_ice_media_stream_head streams; /* Media streams */ @@ -149,6 +162,7 @@ int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg); int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx); int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers, int ct); int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct); +int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver); extern int LOG_ICE; diff --git a/media/mtransport/third_party/nICEr/src/net/nr_resolver.c b/media/mtransport/third_party/nICEr/src/net/nr_resolver.c new file mode 100644 index 00000000000..4dbf1bbe913 --- /dev/null +++ b/media/mtransport/third_party/nICEr/src/net/nr_resolver.c @@ -0,0 +1,85 @@ +/* +Copyright (c) 2007, Adobe Systems, Incorporated +Copyright (c) 2013, Mozilla + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems, Network Resonance, Mozilla nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "nr_resolver.h" + +int nr_resolver_create_int(void *obj, nr_resolver_vtbl *vtbl, nr_resolver **resolverp) +{ + int _status; + nr_resolver *resolver=0; + + if (!(resolver=RCALLOC(sizeof(nr_resolver)))) + ABORT(R_NO_MEMORY); + + resolver->obj=obj; + resolver->vtbl=vtbl; + + *resolverp=resolver; + _status=0; +abort: + return(_status); +} + +int nr_resolver_destroy(nr_resolver **resolverp) +{ + nr_resolver *resolver; + + if(!resolverp || !*resolverp) + return(0); + + resolver=*resolverp; + *resolverp=0; + + resolver->vtbl->destroy(&resolver->obj); + + RFREE(resolver); + + return(0); +} + +int nr_resolver_resolve(nr_resolver *resolver, + nr_resolver_resource *resource, + int (*cb)(void *cb_arg, nr_transport_addr *addr), + void *cb_arg, + void **handle) +{ + return resolver->vtbl->resolve(resolver->obj, resource, cb, cb_arg, handle); +} + +int nr_resolver_cancel(nr_resolver *resolver, void *handle) +{ + return resolver->vtbl->cancel(resolver->obj, handle); +} diff --git a/media/mtransport/third_party/nICEr/src/net/nr_resolver.h b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h new file mode 100644 index 00000000000..d53388feb03 --- /dev/null +++ b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h @@ -0,0 +1,95 @@ +/* +Copyright (c) 2007, Adobe Systems, Incorporated +Copyright (c) 2013, Mozilla + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems, Network Resonance, Mozilla nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _nr_resolver_h +#define _nr_resolver_h + +#include "transport_addr.h" + +#define NR_RESOLVE_PROTOCOL_STUN 1 +#define NR_RESOLVE_PROTOCOL_TURN 2 + +typedef struct nr_resolver_resource_ { + char *domain_name; + UINT2 port; + int stun_turn; + UCHAR transport_protocol; +} nr_resolver_resource; + +typedef struct nr_resolver_vtbl_ { + int (*destroy)(void **obj); + int (*resolve)(void *obj, + nr_resolver_resource *resource, + int (*cb)(void *cb_arg, nr_transport_addr *addr), + void *cb_arg, + void **handle); + int (*cancel)(void *obj, void *handle); +} nr_resolver_vtbl; + +typedef struct nr_resolver_ { + void *obj; + nr_resolver_vtbl *vtbl; +} nr_resolver; + + +/* + The convention here is that the provider of this interface + must generate a void *obj, and a vtbl and then call + nr_resolver_create_int() to allocate the generic wrapper + object. + + The vtbl must contain implementations for all the functions + listed. + + The nr_resolver_destroy() function (and hence vtbl->destroy) + will be called when the consumer of the resolver is done + with it. That is the signal that it is safe to clean up + the resources associated with obj. No other function will + be called afterwards. +*/ +int nr_resolver_create_int(void *obj, nr_resolver_vtbl *vtbl, + nr_resolver **resolverp); +int nr_resolver_destroy(nr_resolver **resolverp); + +/* Request resolution of a domain */ +int nr_resolver_resolve(nr_resolver *resolver, + nr_resolver_resource *resource, + int (*cb)(void *cb_arg, nr_transport_addr *addr), + void *cb_arg, + void **handle); + +/* Cancel a requested resolution. No callback will fire. */ +int nr_resolver_cancel(nr_resolver *resolver, void *handle); +#endif diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.c b/media/mtransport/third_party/nICEr/src/net/transport_addr.c index 1ce52e47fab..82250504c7b 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr.c +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.c @@ -52,7 +52,7 @@ static char *RCSSTRING __UNUSED__="$Id: transport_addr.c,v 1.2 2008/04/28 17:59: #include "nr_api.h" #include "transport_addr.h" -static int fmt_addr_string(nr_transport_addr *addr) +int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr) { int _status; /* Max length for normalized IPv6 address string represntation is 39 */ @@ -109,7 +109,7 @@ int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int saddr_len, int pro else ABORT(R_BAD_ARGS); - if(r=fmt_addr_string(addr)) + if(r=nr_transport_addr_fmt_addr_string(addr)) ABORT(r); _status=0; @@ -144,7 +144,7 @@ int nr_ip4_port_to_transport_addr(UINT4 ip4, UINT2 port, int protocol, nr_transp addr->addr=(struct sockaddr *)&addr->u.addr4; addr->addr_len=sizeof(struct sockaddr_in); - if(r=fmt_addr_string(addr)) + if(r=nr_transport_addr_fmt_addr_string(addr)) ABORT(r); _status=0; @@ -215,6 +215,26 @@ int nr_transport_addr_get_port(nr_transport_addr *addr, int *port) return(_status); } +int nr_transport_addr_set_port(nr_transport_addr *addr, int port) + { + int _status; + + switch(addr->ip_version){ + case NR_IPV4: + addr->u.addr4.sin_port=htons(port); + break; + case NR_IPV6: + addr->u.addr6.sin6_port=htons(port); + break; + default: + ABORT(R_INTERNAL); + } + + _status=0; + abort: + return(_status); + } + int nr_transport_addr_get_ip4(nr_transport_addr *addr, UINT4 *ip4p) { int _status; diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.h b/media/mtransport/third_party/nICEr/src/net/transport_addr.h index 53ce4925c1a..64cf9ef7fc5 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr.h +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.h @@ -89,6 +89,8 @@ int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int int nr_transport_addr_is_wildcard(nr_transport_addr *addr); int nr_transport_addr_is_loopback(nr_transport_addr *addr); int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from); +int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr); +int nr_transport_addr_set_port(nr_transport_addr *addr, int port); #endif From 9657e1ff304a002b883ac0e7f7df9997c1a55ef2 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 4 Mar 2013 21:53:52 -0500 Subject: [PATCH 24/45] Backed out changeset 3ba8ed8f13de (bug 839913) for bustage. --- content/html/content/src/HTMLAreaElement.h | 5 ----- content/html/content/test/Makefile.in | 1 - content/html/content/test/test_bug839913.html | 14 -------------- dom/webidl/HTMLAreaElement.webidl | 7 +------ 4 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 content/html/content/test/test_bug839913.html diff --git a/content/html/content/src/HTMLAreaElement.h b/content/html/content/src/HTMLAreaElement.h index 80ddd0c94e9..effc99018a1 100644 --- a/content/html/content/src/HTMLAreaElement.h +++ b/content/html/content/src/HTMLAreaElement.h @@ -155,11 +155,6 @@ public: SetHTMLBoolAttr(nsGkAtoms::nohref, aValue, aError); } - void Stringify(nsAString& aResult) - { - GetHref(aResult); - } - protected: virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE; diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index 309111abb64..f604b34e8bd 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -270,7 +270,6 @@ MOCHITEST_FILES = \ test_bug827126.html \ test_bug827426.html \ test_bug838582.html \ - test_bug839913.html \ test_bug841466.html \ test_iframe_sandbox_inheritance.html \ file_iframe_sandbox_a_if1.html \ diff --git a/content/html/content/test/test_bug839913.html b/content/html/content/test/test_bug839913.html deleted file mode 100644 index 37aef87cd22..00000000000 --- a/content/html/content/test/test_bug839913.html +++ /dev/null @@ -1,14 +0,0 @@ - - -Test for HTMLAreaElement's stringifier - - -
- diff --git a/dom/webidl/HTMLAreaElement.webidl b/dom/webidl/HTMLAreaElement.webidl index b891630aed6..5d6d96969c2 100644 --- a/dom/webidl/HTMLAreaElement.webidl +++ b/dom/webidl/HTMLAreaElement.webidl @@ -21,12 +21,7 @@ interface HTMLAreaElement : HTMLElement { [SetterThrows] attribute DOMString shape; [SetterThrows] - // No support for stringifier attributes yet - //[SetterThrows] - //stringifier attribute DOMString href; - stringifier; - [SetterThrows] - attribute DOMString href; + stringifier attribute DOMString href; [SetterThrows] attribute DOMString target; [SetterThrows] From d4ed118909427c7419f30ce8fa773db1856a9612 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Tue, 5 Mar 2013 14:42:22 +1300 Subject: [PATCH 25/45] Bug 845639 - Remove stagefright blocklisting for Sony Xperia Ion - r=bjacob --HG-- extra : rebase_source : a5859cad3437a67724d0041b25ef0829d680a7d3 --- widget/android/GfxInfo.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp index 58062173624..a1e3a748bb0 100644 --- a/widget/android/GfxInfo.cpp +++ b/widget/android/GfxInfo.cpp @@ -396,7 +396,12 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature, } else if (CompareVersions(mOSVersion.get(), "4.1.0") < 0) { + // Whitelist: + // All Samsung ICS devices + // All Galaxy nexus ICS devices + // Sony Xperia Ion (LT28) ICS devices bool isWhitelisted = + cModel.Equals("LT28h", nsCaseInsensitiveCStringComparator()) || cManufacturer.Equals("samsung", nsCaseInsensitiveCStringComparator()) || cModel.Equals("galaxy nexus", nsCaseInsensitiveCStringComparator()); // some Galaxy Nexus have manufacturer=amazon From 97e6f743293688244ee3b5701918c5f581d31b0d Mon Sep 17 00:00:00 2001 From: Yoshi Huang Date: Tue, 5 Mar 2013 11:21:26 +0800 Subject: [PATCH 26/45] Bug 847770 : B2G RIL: typos in ICCRecordHelper.readANR and readEmail. r=hsinyi --- dom/system/gonk/ril_worker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 81eaa529545..cc5626bc39f 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -10315,7 +10315,7 @@ let ICCRecordHelper = { * @param onerror Callback to be called when error. */ readEmail: function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) { - function callback(optoins) { + function callback(options) { let strLen = Buf.readUint32(); let octetLen = strLen / 2; let email = null; @@ -10362,7 +10362,7 @@ let ICCRecordHelper = { * @param onerror Callback to be called when error. */ readANR: function readANR(fileId, fileType, recordNumber, onsuccess, onerror) { - function callback(optoins) { + function callback(options) { let strLen = Buf.readUint32(); let octetLen = strLen / 2; let number = null; From 137a7403a74bdf7bf6d92e3bbbf793a12f1a5596 Mon Sep 17 00:00:00 2001 From: Sunny Date: Mon, 4 Mar 2013 22:40:11 -0500 Subject: [PATCH 27/45] Bug 817381 - Add sThreadCount and sTelemetryMaxThreadCount to count the number of maximum concurrent threads in a download session and implemented Telemetry for the same. r=biesi --- netwerk/base/src/BackgroundFileSaver.cpp | 25 ++++++++++++++++++++ netwerk/base/src/BackgroundFileSaver.h | 15 ++++++++++++ toolkit/components/telemetry/Histograms.json | 5 ++++ 3 files changed, 45 insertions(+) diff --git a/netwerk/base/src/BackgroundFileSaver.cpp b/netwerk/base/src/BackgroundFileSaver.cpp index 1b07c65208a..9cd69361343 100644 --- a/netwerk/base/src/BackgroundFileSaver.cpp +++ b/netwerk/base/src/BackgroundFileSaver.cpp @@ -16,6 +16,7 @@ #include "nsXPCOMStrings.h" #include "BackgroundFileSaver.h" +#include "mozilla/Telemetry.h" namespace mozilla { namespace net { @@ -67,6 +68,9 @@ private: //////////////////////////////////////////////////////////////////////////////// //// BackgroundFileSaver +uint32_t BackgroundFileSaver::sThreadCount = 0; +uint32_t BackgroundFileSaver::sTelemetryMaxThreadCount = 0; + BackgroundFileSaver::BackgroundFileSaver() : mControlThread(nullptr) , mWorkerThread(nullptr) @@ -117,6 +121,8 @@ BackgroundFileSaver::virtualDestroyNSSReference() nsresult BackgroundFileSaver::Init() { + MOZ_ASSERT(NS_IsMainThread(), "This should be called on the main thread"); + nsresult rv; rv = NS_NewPipe2(getter_AddRefs(mPipeInputStream), @@ -130,6 +136,11 @@ BackgroundFileSaver::Init() rv = NS_NewThread(getter_AddRefs(mWorkerThread)); NS_ENSURE_SUCCESS(rv, rv); + sThreadCount++; + if (sThreadCount > sTelemetryMaxThreadCount) { + sTelemetryMaxThreadCount = sThreadCount; + } + return NS_OK; } @@ -600,6 +611,8 @@ BackgroundFileSaver::NotifyTargetChange(nsIFile *aTarget) nsresult BackgroundFileSaver::NotifySaveComplete() { + MOZ_ASSERT(NS_IsMainThread(), "This should be called on the main thread"); + nsresult status; { MutexAutoLock lock(mLock); @@ -619,6 +632,18 @@ BackgroundFileSaver::NotifySaveComplete() // reference to it through the event object. mWorkerThread->Shutdown(); + sThreadCount--; + + // When there are no more active downloads, we consider the download session + // finished. We record the maximum number of concurrent downloads reached + // during the session in a telemetry histogram, and we reset the maximum + // thread counter for the next download session + if (sThreadCount == 0) { + Telemetry::Accumulate(Telemetry::BACKGROUNDFILESAVER_THREAD_COUNT, + sTelemetryMaxThreadCount); + sTelemetryMaxThreadCount = 0; + } + return NS_OK; } diff --git a/netwerk/base/src/BackgroundFileSaver.h b/netwerk/base/src/BackgroundFileSaver.h index 1e743962876..1e03dad8454 100644 --- a/netwerk/base/src/BackgroundFileSaver.h +++ b/netwerk/base/src/BackgroundFileSaver.h @@ -53,6 +53,21 @@ public: */ void virtualDestroyNSSReference(); + /** + * Number of worker threads that are currently running. + */ + static uint32_t sThreadCount; + + /** + * Maximum number of worker threads reached during the current download session, + * used for telemetry. + * + * When there are no more worker threads running, we consider the download + * session finished, and this counter is reset. + */ + static uint32_t sTelemetryMaxThreadCount; + + protected: virtual ~BackgroundFileSaver(); diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 4e2e1fb2f37..6691b4447e6 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -23,6 +23,11 @@ "extended_statistics_ok": true, "description": "time spent updating accessibility (ms)" }, + "BACKGROUNDFILESAVER_THREAD_COUNT": { + "kind": "enumerated", + "n_values": 21, + "description": "Maximum number of concurrent threads reached during a given download session" + }, "CYCLE_COLLECTOR": { "kind": "exponential", "high": "10000", From a3a261f28243866ef3f27642973b41e7bd050697 Mon Sep 17 00:00:00 2001 From: Raymond Lee Date: Tue, 5 Mar 2013 11:26:16 +0800 Subject: [PATCH 28/45] Bug 847527 - Fix typo in metro/base/tests/Makefile.in. r=mbrubeck --- browser/metro/base/tests/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/metro/base/tests/Makefile.in b/browser/metro/base/tests/Makefile.in index 5b6d1104e47..5b1ed7178da 100644 --- a/browser/metro/base/tests/Makefile.in +++ b/browser/metro/base/tests/Makefile.in @@ -31,7 +31,7 @@ BROWSER_TESTS = \ $(NULL) BROWSER_TEST_RESOURCES = \ - res\image01.png \ + res/image01.png \ $(NULL) libs:: $(BROWSER_TESTS) From e3dcee067cd9a79d61e487509f88abe7b8170daa Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 4 Mar 2013 22:46:22 -0500 Subject: [PATCH 29/45] Backed out changeset 74eaeeec2b9d (bug 847236) for crashes on a CLOSED TREE. --- content/events/src/nsEventDispatcher.cpp | 153 +++++++++++++++-------- layout/build/nsLayoutStatics.cpp | 4 +- 2 files changed, 102 insertions(+), 55 deletions(-) diff --git a/content/events/src/nsEventDispatcher.cpp b/content/events/src/nsEventDispatcher.cpp index 203eb1e6248..60bb3ae79b3 100644 --- a/content/events/src/nsEventDispatcher.cpp +++ b/content/events/src/nsEventDispatcher.cpp @@ -1,5 +1,4 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -13,6 +12,7 @@ #include "nsError.h" #include "nsMutationEvent.h" #include NEW_H +#include "nsFixedSizeAllocator.h" #include "nsINode.h" #include "nsPIDOMWindow.h" #include "nsFrameLoader.h" @@ -27,6 +27,8 @@ using namespace mozilla; #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1) #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2) +static nsEventTargetChainItem* gCachedETCI = nullptr; + // nsEventTargetChainItem represents a single item in the event target chain. class nsEventTargetChainItem { @@ -34,32 +36,25 @@ private: nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr); - // This is the ETCI recycle pool, which is used to avoid some malloc/free - // churn. It's implemented as a linked list. - static nsEventTargetChainItem* sEtciRecyclePool; - static uint32_t sNumRecycledEtcis; - static const uint32_t kMaxNumRecycledEtcis = 128; - public: - static nsEventTargetChainItem* Create(nsIDOMEventTarget* aTarget, + static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator, + nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr) { - // Allocate from the ETCI recycle pool if possible. void* place = nullptr; - if (sNumRecycledEtcis > 0) { - MOZ_ASSERT(sEtciRecyclePool); - place = sEtciRecyclePool; - sEtciRecyclePool = sEtciRecyclePool->mNext; - --sNumRecycledEtcis; + if (gCachedETCI) { + place = gCachedETCI; + gCachedETCI = gCachedETCI->mNext; } else { - place = malloc(sizeof(nsEventTargetChainItem)); + place = aAllocator->Alloc(sizeof(nsEventTargetChainItem)); } return place ? ::new (place) nsEventTargetChainItem(aTarget, aChild) : nullptr; } - static void Destroy(nsEventTargetChainItem* aItem) + static void Destroy(nsFixedSizeAllocator* aAllocator, + nsEventTargetChainItem* aItem) { // ::Destroy deletes ancestor chain. nsEventTargetChainItem* item = aItem; @@ -67,30 +62,16 @@ public: item->mChild->mParent = nullptr; item->mChild = nullptr; } - // Put destroyed ETCIs into the recycle pool if it's not already full. while (item) { nsEventTargetChainItem* parent = item->mParent; item->~nsEventTargetChainItem(); - if (sNumRecycledEtcis < kMaxNumRecycledEtcis) { - item->mNext = sEtciRecyclePool; - sEtciRecyclePool = item; - ++sNumRecycledEtcis; - } else { - free(item); - } + item->mNext = gCachedETCI; + gCachedETCI = item; + --sCurrentEtciCount; item = parent; } } - static void ShutdownRecyclePool() - { - while (sEtciRecyclePool) { - nsEventTargetChainItem* tmp = sEtciRecyclePool; - sEtciRecyclePool = sEtciRecyclePool->mNext; - free(tmp); - } - } - bool IsValid() { NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!"); @@ -224,7 +205,7 @@ public: nsEventTargetChainItem* mChild; union { nsEventTargetChainItem* mParent; - // This is used only when recycling ETCIs. + // This is used only when caching ETCI objects. nsEventTargetChainItem* mNext; }; uint16_t mFlags; @@ -239,8 +220,8 @@ public: static uint32_t sCurrentEtciCount; }; -nsEventTargetChainItem* nsEventTargetChainItem::sEtciRecyclePool = nullptr; -uint32_t nsEventTargetChainItem::sNumRecycledEtcis = 0; +uint32_t nsEventTargetChainItem::sMaxEtciCount = 0; +uint32_t nsEventTargetChainItem::sCurrentEtciCount = 0; nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild) @@ -250,6 +231,10 @@ nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget, if (mChild) { mChild->mParent = this; } + + if (++sCurrentEtciCount > sMaxEtciCount) { + sMaxEtciCount = sCurrentEtciCount; + } } nsresult @@ -393,13 +378,69 @@ nsEventTargetChainItem::HandleEventTargetChain( return NS_OK; } -void NS_ShutdownEventTargetChainItemRecyclePool() -{ - nsEventTargetChainItem::ShutdownRecyclePool(); -} +#define NS_CHAIN_POOL_SIZE 128 + +class ChainItemPool { +public: + ChainItemPool() { + if (!sEtciPool) { + sEtciPool = new nsFixedSizeAllocator(); + if (sEtciPool) { + static const size_t kBucketSizes[] = { sizeof(nsEventTargetChainItem) }; + static const int32_t kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); + static const int32_t kInitialPoolSize = + sizeof(nsEventTargetChainItem) * NS_CHAIN_POOL_SIZE; + nsresult rv = sEtciPool->Init("EventTargetChainItem Pool", kBucketSizes, + kNumBuckets, kInitialPoolSize); + if (NS_FAILED(rv)) { + delete sEtciPool; + sEtciPool = nullptr; + } + } + } + if (sEtciPool) { + ++sEtciPoolUsers; + } + } + + ~ChainItemPool() { + if (sEtciPool) { + --sEtciPoolUsers; + } + if (!sEtciPoolUsers) { + if (nsEventTargetChainItem::MaxEtciCount() > NS_CHAIN_POOL_SIZE) { + gCachedETCI = nullptr; + delete sEtciPool; + sEtciPool = nullptr; + nsEventTargetChainItem::ResetMaxEtciCount(); + } + } + } + + static void Shutdown() + { + if (!sEtciPoolUsers) { + gCachedETCI = nullptr; + delete sEtciPool; + sEtciPool = nullptr; + nsEventTargetChainItem::ResetMaxEtciCount(); + } + } + + nsFixedSizeAllocator* GetPool() { return sEtciPool; } + + static nsFixedSizeAllocator* sEtciPool; + static int32_t sEtciPoolUsers; +}; + +nsFixedSizeAllocator* ChainItemPool::sEtciPool = nullptr; +int32_t ChainItemPool::sEtciPoolUsers = 0; + +void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); } nsEventTargetChainItem* -EventTargetChainItemForChromeTarget(nsINode* aNode, +EventTargetChainItemForChromeTarget(ChainItemPool& aPool, + nsINode* aNode, nsEventTargetChainItem* aChild = nullptr) { if (!aNode->IsInDoc()) { @@ -410,11 +451,12 @@ EventTargetChainItemForChromeTarget(nsINode* aNode, NS_ENSURE_TRUE(piTarget, nullptr); nsEventTargetChainItem* etci = - nsEventTargetChainItem::Create(piTarget->GetTargetForEventTargetChain(), + nsEventTargetChainItem::Create(aPool.GetPool(), + piTarget->GetTargetForEventTargetChain(), aChild); NS_ENSURE_TRUE(etci, nullptr); if (!etci->IsValid()) { - nsEventTargetChainItem::Destroy(etci); + nsEventTargetChainItem::Destroy(aPool.GetPool(), etci); return nullptr; } return etci; @@ -509,13 +551,16 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, // If we have a PresContext, make sure it doesn't die before // event dispatching is finished. nsRefPtr kungFuDeathGrip(aPresContext); + ChainItemPool pool; + NS_ENSURE_TRUE(pool.GetPool(), NS_ERROR_OUT_OF_MEMORY); // Create the event target chain item for the event target. nsEventTargetChainItem* targetEtci = - nsEventTargetChainItem::Create(target->GetTargetForEventTargetChain()); + nsEventTargetChainItem::Create(pool.GetPool(), + target->GetTargetForEventTargetChain()); NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY); if (!targetEtci->IsValid()) { - nsEventTargetChainItem::Destroy(targetEtci); + nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); return NS_ERROR_FAILURE; } @@ -558,8 +603,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) { // Event target couldn't handle the event. Try to propagate to chrome. - nsEventTargetChainItem::Destroy(targetEtci); - targetEtci = EventTargetChainItemForChromeTarget(content); + nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); + targetEtci = EventTargetChainItemForChromeTarget(pool, content); NS_ENSURE_STATE(targetEtci); targetEtci->PreHandleEvent(preVisitor); } @@ -572,7 +617,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, while (preVisitor.mParentTarget) { nsIDOMEventTarget* parentTarget = preVisitor.mParentTarget; nsEventTargetChainItem* parentEtci = - nsEventTargetChainItem::Create(preVisitor.mParentTarget, topEtci); + nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget, + topEtci); if (!parentEtci) { rv = NS_ERROR_OUT_OF_MEMORY; break; @@ -594,14 +640,15 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, if (preVisitor.mCanHandle) { topEtci = parentEtci; } else { - nsEventTargetChainItem::Destroy(parentEtci); + nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci); parentEtci = nullptr; if (preVisitor.mAutomaticChromeDispatch && content) { // Even if the current target can't handle the event, try to // propagate to chrome. nsCOMPtr disabledTarget = do_QueryInterface(parentTarget); if (disabledTarget) { - parentEtci = EventTargetChainItemForChromeTarget(disabledTarget, + parentEtci = EventTargetChainItemForChromeTarget(pool, + disabledTarget, topEtci); if (parentEtci) { parentEtci->PreHandleEvent(preVisitor); @@ -632,7 +679,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, aCallback, false, &pusher); - + preVisitor.mEventStatus = postVisitor.mEventStatus; // If the DOM event was created during event flow. if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) { @@ -642,7 +689,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, } } - nsEventTargetChainItem::Destroy(targetEtci); + nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); targetEtci = nullptr; aEvent->mFlags.mIsBeingDispatched = false; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 0ef327cc584..1b1d7ce5250 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -112,7 +112,7 @@ using namespace mozilla::system; #include "mozilla/dom/time/DateCacheCleaner.h" #include "nsIMEStateManager.h" -extern void NS_ShutdownEventTargetChainItemRecyclePool(); +extern void NS_ShutdownChainItemPool(); using namespace mozilla; using namespace mozilla::dom; @@ -368,7 +368,7 @@ nsLayoutStatics::Shutdown() nsRegion::ShutdownStatic(); - NS_ShutdownEventTargetChainItemRecyclePool(); + NS_ShutdownChainItemPool(); nsFrameList::Shutdown(); From 6fe682381f848882cea477a57a9aced5c8d6219d Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 4 Mar 2013 23:04:51 -0500 Subject: [PATCH 30/45] Bug 845960 - Fix a crash resulted from a missing nullcheck for the optional failure callback of decodeAudioData; r=bzbarsky --- content/media/webaudio/MediaBufferDecoder.cpp | 6 ++++-- content/media/webaudio/test/Makefile.in | 1 + .../media/webaudio/test/test_bug845960.html | 20 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 content/media/webaudio/test/test_bug845960.html diff --git a/content/media/webaudio/MediaBufferDecoder.cpp b/content/media/webaudio/MediaBufferDecoder.cpp index a0ddd3b00dd..f5811ea1df4 100644 --- a/content/media/webaudio/MediaBufferDecoder.cpp +++ b/content/media/webaudio/MediaBufferDecoder.cpp @@ -868,8 +868,10 @@ WebAudioDecodeJob::OnFailure(ErrorCode aErrorCode) // Ignore errors in calling the callback, since there is not much that we can // do about it here. - ErrorResult rv; - mFailureCallback->Call(rv); + if (mFailureCallback) { + ErrorResult rv; + mFailureCallback->Call(rv); + } mContext->RemoveFromDecodeQueue(this); } diff --git a/content/media/webaudio/test/Makefile.in b/content/media/webaudio/test/Makefile.in index 9db3aea4a32..5bc37735a44 100644 --- a/content/media/webaudio/test/Makefile.in +++ b/content/media/webaudio/test/Makefile.in @@ -15,6 +15,7 @@ MOCHITEST_FILES := \ test_bug808374.html \ test_bug827541.html \ test_bug839753.html \ + test_bug845960.html \ test_AudioBuffer.html \ test_AudioContext.html \ test_AudioListener.html \ diff --git a/content/media/webaudio/test/test_bug845960.html b/content/media/webaudio/test/test_bug845960.html new file mode 100644 index 00000000000..1f06889c48b --- /dev/null +++ b/content/media/webaudio/test/test_bug845960.html @@ -0,0 +1,20 @@ + + + + Crashtest for bug 845960 + + + + +
+
+
+ + From 1a5143de5ede9dbe281dc423b52e3e41fb4f7be8 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Mon, 4 Mar 2013 20:21:12 -0800 Subject: [PATCH 31/45] Bug 548763 followup - add missing include --- widget/cocoa/nsMacDockSupport.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/widget/cocoa/nsMacDockSupport.mm b/widget/cocoa/nsMacDockSupport.mm index 9c8a90338c8..9b86d21e83a 100644 --- a/widget/cocoa/nsMacDockSupport.mm +++ b/widget/cocoa/nsMacDockSupport.mm @@ -6,6 +6,7 @@ #import #import +#include "nsComponentManagerUtils.h" #include "nsMacDockSupport.h" #include "nsObjCExceptions.h" From 6bc6665342fba3a6daaca696e79c0b5378b2548c Mon Sep 17 00:00:00 2001 From: William Chen Date: Mon, 4 Mar 2013 20:30:13 -0800 Subject: [PATCH 32/45] Bug 847773 - Added override for GetWrapperCache with smart pointer argument to resolve ambiguity in templates. r=bz --- content/base/src/nsDocument.cpp | 2 +- dom/bindings/BindingUtils.h | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 7d4e1f45c52..18d9c10c975 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -5059,7 +5059,7 @@ nsDocument::Register(JSContext* aCx, const nsAString& aName, // Don't abort the upgrade algorithm if the callback throws an // exception. ErrorResult dummy; - aOptions.mLifecycle.mCreated->Call(newElement.get(), dummy); + aOptions.mLifecycle.mCreated->Call(newElement, dummy); } nsCOMPtr ptEvent = do_QueryInterface(event); diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 08bd54ccf3c..d863a830fe1 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -696,6 +696,15 @@ GetWrapperCache(void* p) return NULL; } +// Helper template for smart pointers to resolve ambiguity between +// GetWrappeCache(void*) and GetWrapperCache(const ParentObject&). +template